From 505a0e33420f6b37d261ae681fe8422ad859dce5 Mon Sep 17 00:00:00 2001 From: Travis Sluka Date: Fri, 21 May 2021 14:05:49 -0600 Subject: [PATCH] tagged Release/2021.5.0 (#78) * remove Model class, no longer needed (#1) * remove makeobs (#2) * remove makeobs.x, no longer needed * remove Model class, no longer needed (#1) * Implement Geometry class (#3) * ctest passed for Geometry class * Modified test CMakeLists.txt * Travis's suggested changes completed by Ligang * Travis's suggested changes completed by Ligang * add dummy serializeable interfaces (#5) * add serializable interfaces to State (#8) * replace boost::shared_ptr with std::shared_ptr (#9) * change jcsda repo locations (#10) * Implement state class (#11) * Temporary implememting class State for Travis to check. * Updated State.cc * Updating class State * Updating class State. * Updating class State. * Updating class State. * Finished class State, passed all test. * Passed all test for class State. * fix binary path Co-authored-by: Travis Sluka * Finished class Increment. (#17) * Finished class Increment. * Finished class increment. * Updated increment.yml for class increment. * Updated for class Increment. * add test observations (#22) Merged. * Changed float to double for JEDI, read/write netCDF with float for consistency. (#24) * Create Fields base class for Increment/State (#25) * add MPI support (#26) * add missing ModelAux stubs (#27) * Feature/rename (#28) * rename to umdsst * switch to public jedi repo locations * fix travisci * Implement GetValues (#29) * start GetValues * add level(1) to fields * getvalues working? * Merge class LinearGetValues (#31) * Implemented class LinearGetValues, passed all tests. * minor change of a comment. * add hofx_nomodel test (#32) * add hofx_nomodel test * remove use of external OOPS_TRAPFPE env var, deal with that later * Finished bugfix/ConertToCelsius. (#41) * Finished feature class Covariance. (#42) * fix print in getvalues/lineargetvalues (#45) * Finished Feature/dirac.x (#43) * Implementing dirac.x. * Finished feature dirac.x. * Finishing feature/dirac.x. Co-authored-by: Travis Sluka * Fixed conversion between Celsius and Kelvin. (#46) * Fixed conversion between Celsius and Kelvin. * Finished bugfix/C_K_conversion. * update for ufo::locations change (#47) * Finished Feature/staticbinit.x (#48) * Implementing staticbinit.x * Finished feature/staticbinit.x * Finished feature/staticbinit.x 2nd Time. * keep up with JEDI (#49) * Finished Feature/var.x (#50) * Implementing feature/var.x. * Implementing feature/var.x. * Implementing var.x * Finished feature/var.x. * Finished feature/var.x. * Feature/add mask field (#51) * added landmask.nc * Finished feature/addMaskField. * Finished feature/addMaskField. * Finished feature/addMaskField. * Remove hardcoded 180 and 360. * Finished feature/useLandmask. (#55) * Finished feature/useLandmask. * Finished feature/useLandmask. * Finished feature/useLandmask. * add eckit::Configuration to LinearGetValues constructor (#59) * Add support for horizontally varying correlation lengths (#58) * clean old bump files on test run * manually specify correlation lengths * fix coding norms * fix dependencies of errorcovariance test * add StdDev variable change (#60) * feature/addQC finished (#62) * Finished AddQC, Solved problems with passing vector of pointers of FieldImpl from C to Fortran. * Finishing feature/addQC. * Feature/better landmask (#63) * Test improved landmask. * Finished feature/betterLandmask. * Finished feature/betterLandmask. * update for oops hofx3d (#64) * Misc updates (#65) * convert corr length from gaussian to GC * add "default" var change * update reference answers * fix docker on travisci (#66) * remove GeneralizedDepartures (#67) Approved. * Bugfix/grid issues (#68) * invert lat on netcdf I/O * landmask is explicitly applied to background * flood the test background file * fix landmask/grid in yamls * update reference answers * add cycling script (#69) * Create Model2GeoVaLs class (#70) * fields working for any number of fields * implement Model2GeoVaLs * remove ggmask from Geometry * cleanup * Rossby radius based horizontal correlation lengths (#73) * rossby radius based corr loc, using dummy RR values * kd interpolation in geometry * using rossby radius in covariance * fix tests and coding norms * document interptogeom * add .dat to lfs * fix compile error * support for modules with new ecbuild (#76) * support for module with new ecbuild * use public atlas/fckit * Feature/experiment - Added some initial background of 0.25x0.25 grid. (#77) * Added some 0.25x0.25 files. * Added new initial background for 20120101. * Updated for some initial background of 0.25x025 grid. * Updated initial background of 0.25x0.25 grid. * Updated yml files with correct renamed file names. * Updated to have correct file names. * update most recent stable repo tags Co-authored-by: Logan (Ligang) Chen --- .gitattributes | 4 +- .github/Dockerfile | 11 +- .travis.yml | 19 +- CMakeLists.txt | 106 +---- README.md | 22 +- bundle/.gitignore | 2 +- bundle/CMakeLists.txt | 51 +- ...lags.cmake => umdsst_compiler_flags.cmake} | 0 cycling/config/staticbinit.yaml | 40 ++ cycling/config/var.yaml | 92 ++++ cycling/cycle.sh | 155 +++++++ src/CMakeLists.txt | 4 +- src/mains/CMakeLists.txt | 26 +- src/mains/ConvertState.cc | 4 +- src/mains/Dirac.cc | 10 +- src/mains/{HofXNoModel.cc => HofX3D.cc} | 6 +- src/mains/MakeObs.cc | 17 - src/mains/StaticBInit.cc | 6 +- src/mains/Var.cc | 6 +- src/oisst/CMakeLists.txt | 33 -- src/oisst/Covariance/Covariance.cc | 72 --- src/oisst/Geometry/Geometry.cc | 52 --- src/oisst/GetValues/CMakeLists.txt | 6 - src/oisst/GetValues/GetValues.cc | 59 --- src/oisst/GetValues/LinearGetValues.cc | 84 ---- src/oisst/Increment/Increment.cc | 191 -------- src/oisst/Increment/Increment.h | 96 ---- src/oisst/Model/CMakeLists.txt | 4 - src/oisst/Model/Model.cc | 71 --- src/oisst/Model/Model.h | 57 --- src/oisst/State/State.cc | 126 ----- src/oisst/State/State.h | 83 ---- src/oisst/Traits.h | 44 -- src/umdsst/CMakeLists.txt | 48 ++ .../Covariance/CMakeLists.txt | 2 +- src/umdsst/Covariance/Covariance.cc | 166 +++++++ src/{oisst => umdsst}/Covariance/Covariance.h | 16 +- src/umdsst/Fields/CMakeLists.txt | 4 + src/umdsst/Fields/Fields.cc | 436 ++++++++++++++++++ src/umdsst/Fields/Fields.h | 87 ++++ src/{oisst => umdsst}/Geometry/CMakeLists.txt | 2 +- src/umdsst/Geometry/Geometry.cc | 248 ++++++++++ src/{oisst => umdsst}/Geometry/Geometry.h | 43 +- src/umdsst/GetValues/CMakeLists.txt | 14 + src/umdsst/GetValues/GeoVaLsWrapper.f90 | 71 +++ src/umdsst/GetValues/GeoVaLsWrapper.h | 55 +++ src/umdsst/GetValues/GeoVaLsWrapperAD.f90 | 57 +++ src/umdsst/GetValues/GeoVaLsWrapperAD.h | 44 ++ src/umdsst/GetValues/GetValues.cc | 86 ++++ src/{oisst => umdsst}/GetValues/GetValues.h | 40 +- src/umdsst/GetValues/LinearGetValues.cc | 119 +++++ .../GetValues/LinearGetValues.h | 30 +- src/umdsst/GetValues/LocationsWrapper.h | 47 ++ .../Increment/CMakeLists.txt | 2 +- src/umdsst/Increment/Increment.cc | 261 +++++++++++ src/umdsst/Increment/Increment.h | 68 +++ .../LinearVariableChange/CMakeLists.txt | 4 + src/umdsst/LinearVariableChange/StdDev.cc | 74 +++ src/umdsst/LinearVariableChange/StdDev.h | 47 ++ src/{oisst => umdsst}/ModelAux/CMakeLists.txt | 2 +- .../ModelAux/ModelAuxControl.cc | 10 +- .../ModelAux/ModelAuxControl.h | 19 +- .../ModelAux/ModelAuxCovariance.cc | 10 +- .../ModelAux/ModelAuxCovariance.h | 14 +- .../ModelAux/ModelAuxIncrement.cc | 10 +- .../ModelAux/ModelAuxIncrement.h | 28 +- src/{oisst => umdsst}/State/CMakeLists.txt | 2 +- src/umdsst/State/State.cc | 61 +++ src/umdsst/State/State.h | 56 +++ src/umdsst/Traits.h | 44 ++ src/umdsst/VariableChange/CMakeLists.txt | 4 + src/umdsst/VariableChange/Model2GeoVaLs.cc | 64 +++ src/umdsst/VariableChange/Model2GeoVaLs.h | 37 ++ test/CMakeLists.txt | 218 +++++++-- test/Data/19850101_regridded_sst_1x1.nc | 3 + test/Data/20100101_regridded_sst_0.25x0.25.nc | 3 + test/Data/20120101_regridded_sst_0.25x0.25.nc | 3 + test/Data/landmask_0.25x0.25.nc | 3 + test/Data/landmask_1x1.nc | 3 + test/Data/obs_sst.nc | 3 + test/Data/rossby_radius.dat | 3 + test/executables/TestErrorCovariance.cc | 4 +- test/executables/TestGeometry.cc | 4 +- test/executables/TestGetValues.cc | 4 +- test/executables/TestIncrement.cc | 4 +- test/executables/TestLinearGetValues.cc | 4 +- ...stModel.cc => TestLinearVariableChange.cc} | 9 +- test/executables/TestModelAuxControl.cc | 4 +- test/executables/TestModelAuxCovariance.cc | 4 +- test/executables/TestModelAuxIncrement.cc | 4 +- test/executables/TestState.cc | 4 +- test/test_wrapper.sh | 46 ++ test/testinput/dirac.yml | 50 ++ test/testinput/errorcovariance.yml | 23 +- test/testinput/geometry.yml | 9 +- test/testinput/getvalues.yml | 13 +- test/testinput/hofx3d.yml | 31 ++ test/testinput/increment.yml | 15 +- test/testinput/lineargetvalues.yml | 12 +- test/testinput/linearvarchange_stddev.yml | 20 + test/testinput/model.yml | 19 - test/testinput/state.yml | 28 +- test/testinput/staticbinit.yml | 37 ++ test/testinput/var.yml | 82 ++++ test/testref/dirac.ref | 2 + test/testref/hofx3d.ref | 4 + test/testref/staticbinit.ref | 1 + test/testref/var.ref | 9 + 108 files changed, 3320 insertions(+), 1356 deletions(-) rename cmake/{oisst_compiler_flags.cmake => umdsst_compiler_flags.cmake} (100%) create mode 100644 cycling/config/staticbinit.yaml create mode 100644 cycling/config/var.yaml create mode 100755 cycling/cycle.sh rename src/mains/{HofXNoModel.cc => HofX3D.cc} (79%) delete mode 100644 src/mains/MakeObs.cc delete mode 100644 src/oisst/CMakeLists.txt delete mode 100644 src/oisst/Covariance/Covariance.cc delete mode 100644 src/oisst/Geometry/Geometry.cc delete mode 100644 src/oisst/GetValues/CMakeLists.txt delete mode 100644 src/oisst/GetValues/GetValues.cc delete mode 100644 src/oisst/GetValues/LinearGetValues.cc delete mode 100644 src/oisst/Increment/Increment.cc delete mode 100644 src/oisst/Increment/Increment.h delete mode 100644 src/oisst/Model/CMakeLists.txt delete mode 100644 src/oisst/Model/Model.cc delete mode 100644 src/oisst/Model/Model.h delete mode 100644 src/oisst/State/State.cc delete mode 100644 src/oisst/State/State.h delete mode 100644 src/oisst/Traits.h create mode 100644 src/umdsst/CMakeLists.txt rename src/{oisst => umdsst}/Covariance/CMakeLists.txt (61%) create mode 100644 src/umdsst/Covariance/Covariance.cc rename src/{oisst => umdsst}/Covariance/Covariance.h (80%) create mode 100644 src/umdsst/Fields/CMakeLists.txt create mode 100644 src/umdsst/Fields/Fields.cc create mode 100644 src/umdsst/Fields/Fields.h rename src/{oisst => umdsst}/Geometry/CMakeLists.txt (58%) create mode 100644 src/umdsst/Geometry/Geometry.cc rename src/{oisst => umdsst}/Geometry/Geometry.h (51%) create mode 100644 src/umdsst/GetValues/CMakeLists.txt create mode 100644 src/umdsst/GetValues/GeoVaLsWrapper.f90 create mode 100644 src/umdsst/GetValues/GeoVaLsWrapper.h create mode 100644 src/umdsst/GetValues/GeoVaLsWrapperAD.f90 create mode 100644 src/umdsst/GetValues/GeoVaLsWrapperAD.h create mode 100644 src/umdsst/GetValues/GetValues.cc rename src/{oisst => umdsst}/GetValues/GetValues.h (60%) create mode 100644 src/umdsst/GetValues/LinearGetValues.cc rename src/{oisst => umdsst}/GetValues/LinearGetValues.h (70%) create mode 100644 src/umdsst/GetValues/LocationsWrapper.h rename src/{oisst => umdsst}/Increment/CMakeLists.txt (59%) create mode 100644 src/umdsst/Increment/Increment.cc create mode 100644 src/umdsst/Increment/Increment.h create mode 100644 src/umdsst/LinearVariableChange/CMakeLists.txt create mode 100644 src/umdsst/LinearVariableChange/StdDev.cc create mode 100644 src/umdsst/LinearVariableChange/StdDev.h rename src/{oisst => umdsst}/ModelAux/CMakeLists.txt (86%) rename src/{oisst => umdsst}/ModelAux/ModelAuxControl.cc (87%) rename src/{oisst => umdsst}/ModelAux/ModelAuxControl.h (71%) rename src/{oisst => umdsst}/ModelAux/ModelAuxCovariance.cc (90%) rename src/{oisst => umdsst}/ModelAux/ModelAuxCovariance.h (82%) rename src/{oisst => umdsst}/ModelAux/ModelAuxIncrement.cc (93%) rename src/{oisst => umdsst}/ModelAux/ModelAuxIncrement.h (64%) rename src/{oisst => umdsst}/State/CMakeLists.txt (53%) create mode 100644 src/umdsst/State/State.cc create mode 100644 src/umdsst/State/State.h create mode 100644 src/umdsst/Traits.h create mode 100644 src/umdsst/VariableChange/CMakeLists.txt create mode 100644 src/umdsst/VariableChange/Model2GeoVaLs.cc create mode 100644 src/umdsst/VariableChange/Model2GeoVaLs.h create mode 100644 test/Data/19850101_regridded_sst_1x1.nc create mode 100644 test/Data/20100101_regridded_sst_0.25x0.25.nc create mode 100644 test/Data/20120101_regridded_sst_0.25x0.25.nc create mode 100644 test/Data/landmask_0.25x0.25.nc create mode 100644 test/Data/landmask_1x1.nc create mode 100644 test/Data/obs_sst.nc create mode 100644 test/Data/rossby_radius.dat rename test/executables/{TestModel.cc => TestLinearVariableChange.cc} (63%) create mode 100755 test/test_wrapper.sh create mode 100644 test/testinput/dirac.yml create mode 100644 test/testinput/hofx3d.yml create mode 100644 test/testinput/linearvarchange_stddev.yml delete mode 100644 test/testinput/model.yml create mode 100644 test/testinput/staticbinit.yml create mode 100644 test/testinput/var.yml create mode 100644 test/testref/dirac.ref create mode 100644 test/testref/hofx3d.ref create mode 100644 test/testref/staticbinit.ref create mode 100644 test/testref/var.ref diff --git a/.gitattributes b/.gitattributes index 194ed45..9793855 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,4 @@ +*.dat filter=lfs diff=lfs merge=lfs -text *.nc filter=lfs diff=lfs merge=lfs -text -*.nc4 filter=lfs diff=lfs merge=lfs -text \ No newline at end of file +*.nc4 filter=lfs diff=lfs merge=lfs -text +*.dat filter=lfs diff=lfs merge=lfs -text diff --git a/.github/Dockerfile b/.github/Dockerfile index 2552117..67af72f 100644 --- a/.github/Dockerfile +++ b/.github/Dockerfile @@ -1,17 +1,14 @@ - FROM jcsda/docker-gnu-openmpi-dev:latest -RUN groupadd jcsda -g 9999 \ - && adduser jcsdauser \ - && mkdir -p /jcsda \ - && chown -R jcsdauser:jcsda /jcsda \ +RUN mkdir -p /jcsda \ + && chown -R jedi:jedi /jcsda \ && chmod 6755 /jcsda -USER jcsdauser +USER jedi COPY default-mca-params.conf /jcsda/mca-params.conf RUN mkdir -p ~/.openmpi \ && cp /jcsda/mca-params.conf ~/.openmpi/ -CMD ["/bin/bash"] \ No newline at end of file +CMD ["/bin/bash"] diff --git a/.travis.yml b/.travis.yml index 62ef9ae..c5b67e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,15 @@ before_install: script: - | - # build/test code - docker exec jcsda_container bash \ - -c 'cd /jcsda/build && ecbuild /jcsda/src/bundle && cd oisst && make -j 4' - docker exec jcsda_container bash \ - -c 'cd /jcsda/build/oisst && ctest' - -after_success: + # build code + docker exec -it jcsda_container bash \ + -c 'cd /jcsda/build && ecbuild -DBUILD_FCKIT=ON -DBUILD_ATLAS=ON /jcsda/src/bundle && cd umdsst && make -j 4; exit $?' \ + || travis_terminate 1 + +- | + # test code + docker exec -it jcsda_container bash \ + -c 'cd /jcsda/build/umdsst && ctest --output-on-failure' \ + || travis_terminate 1 + +after_success: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ba100b..2e0bf54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,122 +4,46 @@ # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. ################################################################################ -# OISST +# UMDSST ################################################################################ +cmake_minimum_required( VERSION 3.12 ) +project( umdsst VERSION 2021.5.0 LANGUAGES C CXX Fortran) -cmake_minimum_required( VERSION 3.8 FATAL_ERROR ) - -project( oisst C CXX Fortran) - -set( CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}) - -set( ENABLE_OS_TESTS OFF CACHE BOOL "Disable OS tests" FORCE ) -set( ENABLE_LARGE_FILE_SUPPORT OFF CACHE BOOL "Disable testing of large file support" FORCE ) -set( ENABLE_MPI ON CACHE BOOL "Compile with MPI" ) - +find_package(ecbuild 3.3.2 QUIET) include( ecbuild_system NO_POLICY_SCOPE ) - -ecbuild_requires_macro_version( 2.5 ) - - -################################################################################ -# Project -################################################################################ - ecbuild_declare_project() -ecbuild_enable_fortran( REQUIRED ) -ecbuild_add_cxx11_flags() - -set( OISST_LINKER_LANGUAGE CXX ) +list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +include( umdsst_compiler_flags ) ################################################################################ # Dependencies ################################################################################ -# Boost Headers -set( Boost_MINIMUM_VERSION "1.47" ) -include_directories( ${Boost_INCLUDE_DIR} ) - -# NetCDF find_package( NetCDF REQUIRED COMPONENTS Fortran ) -include_directories( ${NETCDF_INCLUDE_DIRS} ) - -# eckit -ecbuild_use_package( PROJECT eckit VERSION 1.1.0 REQUIRED ) -include_directories( ${ECKIT_INCLUDE_DIRS} ) -link_libraries( ${ECKIT_LIBRARIES} ) - -# fckit -ecbuild_use_package( PROJECT fckit VERSION 0.4.1 REQUIRED ) -include_directories( ${FCKIT_INCLUDE_DIRS} ) - -# atlas -ecbuild_use_package( PROJECT atlas VERSION 0.18.1 REQUIRED ) -include_directories( ${ATLAS_INCLUDE_DIRS} ) - -# oops -ecbuild_use_package( PROJECT oops VERSION 0.1.0 REQUIRED ) -include_directories( ${OOPS_INCLUDE_DIRS} ) -add_definitions(-DATLASIFIED=1) - -# saber -ecbuild_use_package( PROJECT saber VERSION 0.0.1 REQUIRED ) -include_directories( ${SABER_INCLUDE_DIRS} ) - -# ioda -ecbuild_use_package( PROJECT ioda VERSION 0.1.0 REQUIRED ) -include_directories( ${IODA_INCLUDE_DIRS} ) - -# ufo -ecbuild_use_package( PROJECT ufo VERSION 0.1.0 REQUIRED ) -include_directories( ${UFO_INCLUDE_DIRS} ) - -# MPI -ecbuild_find_mpi( COMPONENTS CXX Fortran REQUIRED ) -ecbuild_include_mpi() -link_libraries(${MPI_CXX_LIBRARIES} ${MPI_Fortran_LIBRARIES}) - - -################################################################################ -# Export package info -################################################################################ -list( APPEND OISST_TPLS atlas atlas_f LAPACK MPI NetCDF ) - -set( OISST_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src - ${CMAKE_CURRENT_BINARY_DIR}/src - ${CMAKE_Fortran_MODULE_DIRECTORY} ) -set( OISST_LIBRARIES oisst ) - -get_directory_property( OISST_DEFINITIONS COMPILE_DEFINITIONS ) - -foreach( _tpl ${OISST_TPLS} ) -string( TOUPPER ${_tpl} TPL ) -list( APPEND OISST_EXTRA_DEFINITIONS ${${TPL}_DEFINITIONS} ${${TPL}_TPL_DEFINITIONS} ) -list( APPEND OISST_EXTRA_INCLUDE_DIRS ${${TPL}_INCLUDE_DIRS} ${${TPL}_TPL_INCLUDE_DIRS} ) -list( APPEND OISST_EXTRA_LIBRARIES ${${TPL}_LIBRARIES} ${${TPL}_TPL_LIBRARIES} ) -endforeach() +find_package( eckit 1.11.6 REQUIRED) +find_package( fckit 0.7.0 REQUIRED) +find_package( atlas 0.20.2 REQUIRED) +find_package( oops 1.0.0 REQUIRED) +find_package( saber 1.0.0 REQUIRED) +find_package( ioda 1.0.0 REQUIRED) +find_package( ufo 1.0.0 REQUIRED) ################################################################################ # Sources ################################################################################ -include( oisst_compiler_flags ) -include_directories( ${OISST_INCLUDE_DIRS} ${OISST_EXTRA_INCLUDE_DIRS} ) - +set( UMDSST_LINKER_LANGUAGE CXX ) add_subdirectory( src ) add_subdirectory( test ) -if(ECBUILD_INSTALL_FORTRAN_MODULES) - install(DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/${CMAKE_CFG_INTDIR} DESTINATION ${INSTALL_INCLUDE_DIR} ) -endif() ################################################################################ # Finalise configuration ################################################################################ # prepares a tar.gz of the sources and/or binaries -ecbuild_install_project( NAME oisst ) +ecbuild_install_project( NAME umdsst ) # print the summary of the configuration ecbuild_print_summary() diff --git a/README.md b/README.md index 4b46961..d11c71e 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,21 @@ -[![Build Status](https://travis-ci.org/UMD-AOSC/OISSTv3.svg?branch=develop)](https://travis-ci.org/UMD-AOSC/OISSTv3) +[![Build Status](https://travis-ci.org/UMD-AOSC/UMD-SST.svg?branch=develop)](https://travis-ci.org/UMD-AOSC/UMD-SST) -# OISSTv3 +# UMD-SST -Prototype for the Optimal Interpolation Sea Surface Temperature v3 (OISSTv3) +Testbed sea surface temperature analysis system. -A variational data assmilation system built on the JCSDA Joint Effort for Data Assimilation Integration (JEDI). This project is just beginning, and further documentation will be created as the project proresses. +A variational data assmilation system built on the JCSDA Joint Effort for Data Assimilation Integration (JEDI). This project is just beginning, and further documentation will be created as the project progresses. ## Getting Started The following steps assume you already have one of the JEDI containers setup and working on your computer. See the [JEDI Documentation](https://jointcenterforsatellitedataassimilation-jedi-docs.readthedocs-hosted.com/en/latest/) for additional details on how to do this. -> ***NOTE: until JEDI is publicly released, anyone trying to build OISSTv3 must have access to the private JEDI repositories!*** - -To build OISSTv3 and run the continuous integration tests: +To build UMD-SST and run the continuous integration tests: ``` -git clone https://github.com/UMD-AOSC/OISSTv3.git oisst.src -mkdir -p oisst.build -cd oisst.build -ecbuild ../oisst.src/bundle -cd oisst +git clone https://github.com/UMD-AOSC/UMD-SST.git umdsst.src +mkdir -p umdsst.build +cd umdsst.build +ecbuild ../umdsst.src/bundle +cd umdsst make -j ctest ``` diff --git a/bundle/.gitignore b/bundle/.gitignore index aa7988d..ddf2504 100644 --- a/bundle/.gitignore +++ b/bundle/.gitignore @@ -6,4 +6,4 @@ ioda/ oops/ saber/ ufo/ -oisst \ No newline at end of file +umdsst \ No newline at end of file diff --git a/bundle/CMakeLists.txt b/bundle/CMakeLists.txt index 951023d..66c3208 100644 --- a/bundle/CMakeLists.txt +++ b/bundle/CMakeLists.txt @@ -4,34 +4,47 @@ # WHICH CAN BE OBTAINED AT HTTP://WWW.APACHE.ORG/LICENSES/LICENSE-2.0. # -# OISST-BUNDLE +# UMDSST-BUNDLE # -project( OISST-bundle C CXX Fortran ) +cmake_minimum_required( VERSION 3.12 ) +project( umdsst-bundle VERSION 2021.5.0 LANGUAGES C CXX Fortran ) -cmake_minimum_required( VERSION 3.8 FATAL_ERROR ) +find_package( ecbuild 3.3.2 QUIET) include( ecbuild_bundle ) - -set( ECBUILD_DEFAULT_BUILD_TYPE RelWithDebInfo ) -set( ENABLE_MPI ON CACHE BOOL "Compile with MPI" ) - ecbuild_bundle_initialize() -ecbuild_requires_macro_version( 2.7 ) -# Optional repositories -option( BUILD_ECKIT "download and build eckit (not needed if in a jedi container)" ) + +#=================================================================================================== +# ECMWF repos that you probably dont need to build yourself because they should be in the +# jedi-stack and containers +#=================================================================================================== +option(BUILD_ECKIT "download and build eckit (not needed if in a jedi container)") if ( BUILD_ECKIT ) - ecbuild_bundle( PROJECT eckit GIT "https://github.com/JCSDA/eckit.git" UPDATE BRANCH release-stable ) + ecbuild_bundle( PROJECT eckit GIT "https://github.com/ecmwf/eckit.git" UPDATE TAG b3adb28 ) endif () +option(BUILD_FCKIT "download and build fckit (not needed if in a jedi container)") +if (BUILD_FCKIT) + ecbuild_bundle( PROJECT fckit GIT "https://github.com/jcsda/fckit.git" UPDATE TAG 8502aae ) + # TODO: replace with https://github.com/ecmwf/fckit.git TAG 0.9.2 +endif() + +option(BUILD_ATLAS "download and build atlas (not needed if in a jedi container)") +if (BUILD_ATLAS) + ecbuild_bundle( PROJECT atlas GIT "https://github.com/jcsda/atlas.git" UPDATE TAG e0b7709 ) + # TODO: repalce with https://github.com/ecmwf/atlas.git TAG 0.24.1 +endif() + + +#=================================================================================================== # required repositories -ecbuild_bundle( PROJECT fckit GIT "https://github.com/JCSDA/fckit.git" UPDATE BRANCH release-stable ) -ecbuild_bundle( PROJECT atlas GIT "https://github.com/JCSDA/atlas.git" UPDATE BRANCH release-stable ) -ecbuild_bundle( PROJECT oops GIT "https://github.com/JCSDA/oops.git" UPDATE BRANCH develop ) -ecbuild_bundle( PROJECT saber GIT "https://github.com/JCSDA/saber.git" UPDATE BRANCH develop ) -ecbuild_bundle( PROJECT ioda GIT "https://github.com/JCSDA/ioda.git" UPDATE BRANCH develop ) -ecbuild_bundle( PROJECT ioda-converters GIT "https://github.com/JCSDA/ioda-converters.git" UPDATE BRANCH develop ) -ecbuild_bundle( PROJECT ufo GIT "https://github.com/JCSDA/ufo.git" UPDATE BRANCH develop ) -ecbuild_bundle( PROJECT oisst SOURCE ../) +#=================================================================================================== +ecbuild_bundle( PROJECT oops GIT "https://github.com/jcsda/oops.git" UPDATE TAG 8f517dd ) +ecbuild_bundle( PROJECT saber GIT "https://github.com/jcsda/saber.git" UPDATE TAG 0422a16 ) +ecbuild_bundle( PROJECT ioda GIT "https://github.com/jcsda/ioda.git" UPDATE TAG 04880ef ) +ecbuild_bundle( PROJECT ioda-converters GIT "https://github.com/jcsda/ioda-converters.git" UPDATE TAG ab0a195 ) +ecbuild_bundle( PROJECT ufo GIT "https://github.com/jcsda/ufo.git" UPDATE TAG eb2e70f ) +ecbuild_bundle( PROJECT umdsst SOURCE ../) ecbuild_bundle_finalize() diff --git a/cmake/oisst_compiler_flags.cmake b/cmake/umdsst_compiler_flags.cmake similarity index 100% rename from cmake/oisst_compiler_flags.cmake rename to cmake/umdsst_compiler_flags.cmake diff --git a/cycling/config/staticbinit.yaml b/cycling/config/staticbinit.yaml new file mode 100644 index 0000000..25aca30 --- /dev/null +++ b/cycling/config/staticbinit.yaml @@ -0,0 +1,40 @@ +geometry: + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: landmask.nc + rossby radius file: rossby_radius.dat + +analysis variables: &vars [sea_surface_temperature] + +background: + state variables: *vars + date: 2018-04-15T00:00:00Z # date doesn't matter here, just pick something + filename: bkg.nc + +background error: + covariance model: umdsstCovar + bump: + verbosity: main + datadir: bump + prefix: bump_sst + method: cor + strategy: specific_univariate + mask_check: 1 + network: 1 + new_nicas: 1 + ntry: 3 + resol: 6.0 + mpicom: 2 + nc1max: 100000 + + correlation lengths: + base value: 0.0 + rossby mult: 1.0 + min grid mult: 1.5 + #min value: 25.0e3 + #max value: + diff --git a/cycling/config/var.yaml b/cycling/config/var.yaml new file mode 100644 index 0000000..4eed828 --- /dev/null +++ b/cycling/config/var.yaml @@ -0,0 +1,92 @@ +cost function: + cost type: 3D-Var + window begin: __DA_WINDOW_START__ + window length: PT24H + analysis variables: &vars [sea_surface_temperature] + + geometry: &geometry + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: landmask.nc + + background: + state variables: *vars + date: __ANA_DATE__ + filename: bkg.nc + kelvin: true + + background error: + covariance model: BUMP + bump: + verbosity: main + datadir: bump + prefix: bump_sst + method: cor + strategy: specific_univariate + mask_check: 1 + network: 1 + load_nicas: 1 + mpicom: 2 + + variable changes: + - variable change: umdsstStdDev + input variables: *vars + output variables: *vars + fixed: 1.0 + + observations: + - obs error: + covariance model: diagonal + obs operator: + name: Identity + obs space: + name: sea_surface_temperature + obsdatain: + obsfile: obs_ioda.nc + simulated variables: [sea_surface_temperature] + obsdataout: + obsfile: obs_out/obs.nc + obs filters: + - filter: PreQC # only keep obs with the best 2 qc levels from original data file + maxvalue: 1 + - filter: BlackList # assign initial error value + action: + name: assign error + error parameter: 1.0 + - filter: Domain Check # land check + where: + - variable: {name: sea_area_fraction@GeoVaLs} + minvalue: 1.0 + - filter: Background Check + absolute threshold: 5.0 + - filter: Bounds Check + minvalue: 0.0 # ignore obs that are close to freezing, for now + maxvalue: 40.0 + +variational: + minimizer: + algorithm: DRIPCG + + iterations: + - diagnostics: + departures: ombg + gradient norm reduction: 1.0e-3 + ninner: 200 + geometry: *geometry + test: on + online diagnostics: + write increment: true + increment: + filename: inc.nc + +final: + diagnostics: + departures: oman + +output: + filename: ana.nc + kelvin: true diff --git a/cycling/cycle.sh b/cycling/cycle.sh new file mode 100755 index 0000000..7daa141 --- /dev/null +++ b/cycling/cycle.sh @@ -0,0 +1,155 @@ +#!/bin/bash +set -eu + +#------------------------------------------------------------------------------- +# user configurables that should be set before running +#------------------------------------------------------------------------------- + +EXP_DIR=$(readlink -f .) # assume experiment directory is the directory + # that this script is in + +EXP_START_DATE=20160101Z12 # start date, in YYYYMMDDZHH format +EXP_END_DATE=20160131Z12 # end date, in YYYYMMDDZHH format + +# location of root UMD-SST source directory +# (not needed by this script, other than the subsequent default IC/landmask locations) +UMDSST_SRC_DIR=/home/tsluka/work/umdsst/umd-sst.src + +# location of the UMD-SST binary files +UMDSST_BIN_DIR=/home/tsluka/work/umdsst/umd-sst.release/bin + +# observation locations, note that %Y %m %d %H will be replaced with the +# date/time of each cycle +OBS_FILE=$EXP_DIR/obs/%Y%m%d%H0000-ESACCI-L3C_GHRSST-SSTskin-AVHRR19_G-CDR2.1_night-v02.0-fv01.0.nc + +OBS_THINNING=0.8 # percent of obs to discard (range: 0.0 - 1.0 ) + +# initial background used for the first cycle +IC_FILE=$UMDSST_SRC_DIR/test/Data/19850101_regridded_sst.nc + +# land mask file +LANDMASK_FILE=$UMDSST_SRC_DIR/test/Data/landmask.nc + +ROSSBYRADIUS_FILE=$UMDSST_SRC_DIR/test/Data/rossby_radius.dat + +# temporary working files, that are deleted after each cycle is finished +SCRATCH_DIR=$EXP_DIR/SCRATCH + +#------------------------------------------------------------------------------- +# END of user configurables +#------------------------------------------------------------------------------- + + +# you probably dont need to edit anything below here... + +# define some other variables used by this script +export OMP_NUM_THREADS=1 # OpenMP isn't working correctly, disable +DA_WINDOW_LEN=24 # assuming a fixed window of 1 day, for now + +#================================================================================ +#================================================================================ +# Start of loop +#================================================================================ +#================================================================================ +export TIMEFORMAT='%1Rs' +date_fmt="%Y-%m-%dT%H:%M:%SZ" +cycle_avg_count=0 +cycle_avg_runtime=0 +while true; do + cycle_start=$(date +%s) + + # determine where the experiment left off and if this is the first cycle + cycle_status_file=$EXP_DIR/cycle_status + if [[ ! -e $cycle_status_file ]]; then + cycle_start_date=$(date -ud "$EXP_START_DATE" +$date_fmt) + init=1 + else + cycle_start_date=$(cat $cycle_status_file) + init=0 + fi + + # are we done with the experiment? + if [[ $(date -ud "$cycle_start_date" +%Y%m%d%H) -gt \ + $(date -ud "$EXP_END_DATE" +%Y%m%d%H) ]]; then + echo "Done with the experiment. Last date: $cycle_start_date" + exit 0 + fi + + # variables that depend on the cycle date + ANA_DATE=$(date -ud "$cycle_start_date" +$date_fmt) + DA_WINDOW_HW=$(( DA_WINDOW_LEN/2 )) + DA_WINDOW_START=$(date -ud "$ANA_DATE - $DA_WINDOW_HW hours" +$date_fmt) + NEXT_DATE=$(date -ud "$ANA_DATE + $DA_WINDOW_LEN hours" +$date_fmt) + PREV_DATE_YMDH=$(date -ud "$ANA_DATE - $DA_WINDOW_LEN hours" +"%Y%m%d%H") + ANA_DATE_YMDH=$(date -ud "$ANA_DATE" +"%Y%m%d%H") + SCRATCH_DIR_CYCLE=$SCRATCH_DIR/$ANA_DATE_YMDH + + echo "" + echo "======================================================================" + echo "analysis date: $ANA_DATE" + echo "======================================================================" + + # setup working directory + [[ -d "$SCRATCH_DIR_CYCLE" ]] && rm -r $SCRATCH_DIR_CYCLE + mkdir -p $SCRATCH_DIR_CYCLE + cd $SCRATCH_DIR_CYCLE + ln -s $LANDMASK_FILE landmask.nc + ln -s $ROSSBYRADIUS_FILE rossby_radius.dat + + # link in the most recent background state + if [[ "$init" == 1 ]]; then + ln -s $IC_FILE bkg.nc + else + ln -s $EXP_DIR/ana/ana.$PREV_DATE_YMDH.nc bkg.nc + fi + + # initialize bump if not already done so + BUMP_DIR=$EXP_DIR/bump + if [[ ! -d "$BUMP_DIR" ]]; then + echo "Initializing BUMP..." + mkdir bump + cp $EXP_DIR/config/staticbinit.yaml . + mpirun $UMDSST_BIN_DIR/umdsst_staticbinit.x staticbinit.yaml + mv bump $BUMP_DIR + fi + ln -s $BUMP_DIR bump + + # run ioda converter + obs_file=$(date -ud "$ANA_DATE" +$OBS_FILE) + $UMDSST_BIN_DIR/gds2_sst2ioda.py -i $obs_file -o obs_ioda.nc \ + -d $ANA_DATE_YMDH --sst -t $OBS_THINNING + + # run the var + mkdir -p obs_out + cp $EXP_DIR/config/var.yaml . + sed -i "s/__DA_WINDOW_START__/${DA_WINDOW_START}/g" var.yaml + sed -i "s/__ANA_DATE__/${ANA_DATE}/g" var.yaml + mpirun $UMDSST_BIN_DIR/umdsst_var.x var.yaml + + # move the output files + ana_file=$EXP_DIR/ana/ana.${ANA_DATE_YMDH}.nc + mkdir -p $(dirname $ana_file) + mv ana.nc $ana_file + + inc_file=$EXP_DIR/inc/inc.${ANA_DATE_YMDH}.nc + mkdir -p $(dirname $inc_file) + mv inc.nc $inc_file + + # moving observation output stats as is + # TODO: concatenate into a single file per platform + obs_out_dir=$EXP_DIR/obs_out/${ANA_DATE_YMDH} + mkdir -p $obs_out_dir + mv obs_out/*.nc $obs_out_dir + + # done with this day of the cycle, cleanup and prepare for the next cycle + rm -rf $SCRATCH_DIR_CYCLE + echo "$NEXT_DATE" > $cycle_status_file + + # update statistics on average cycle runtime + cycle_end=$(date +%s) + cycle_runtime=$((cycle_end-cycle_start )) + cycle_avg_runtime=$(((cycle_avg_runtime*cycle_avg_count+cycle_runtime)/(cycle_avg_count+1) )) + cycle_avg_count=$((cycle_avg_count+1)) + echo "Cycle runtime: $cycle_runtime seconds" + echo "Cycle runtime avg: $cycle_avg_runtime seconds" +done \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 53e3594..51bcf3a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -add_subdirectory( oisst ) +add_subdirectory( umdsst ) add_subdirectory( mains ) # Add the CPP coding norms test @@ -9,7 +9,7 @@ if(NOT CPPLINT_PY) set(CPPLINT_PY ${CMAKE_BINARY_DIR}/bin/cpplint.py) endif() -ecbuild_add_test( TARGET oisst_coding_norms +ecbuild_add_test( TARGET umdsst_coding_norms TYPE SCRIPT COMMAND ${CPPLINT_PY} ARGS --quiet --recursive ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/src/mains/CMakeLists.txt b/src/mains/CMakeLists.txt index 1adda1f..119f63b 100644 --- a/src/mains/CMakeLists.txt +++ b/src/mains/CMakeLists.txt @@ -1,23 +1,19 @@ -ecbuild_add_executable( TARGET oisst_convertstate.x +ecbuild_add_executable( TARGET umdsst_convertstate.x SOURCES ConvertState.cc - LIBS oisst ) + LIBS umdsst ) -ecbuild_add_executable( TARGET oisst_dirac.x +ecbuild_add_executable( TARGET umdsst_dirac.x SOURCES Dirac.cc - LIBS oisst ) + LIBS umdsst ) -ecbuild_add_executable( TARGET oisst_hofx_nomodel.x - SOURCES HofXNoModel.cc - LIBS oisst ) +ecbuild_add_executable( TARGET umdsst_hofx3d.x + SOURCES HofX3D.cc + LIBS umdsst ) -ecbuild_add_executable( TARGET oisst_makeobs.x - SOURCES MakeObs.cc - LIBS oisst ) - -ecbuild_add_executable( TARGET oisst_staticbinit.x +ecbuild_add_executable( TARGET umdsst_staticbinit.x SOURCES StaticBInit.cc - LIBS oisst ) + LIBS umdsst ) -ecbuild_add_executable( TARGET oisst_var.x +ecbuild_add_executable( TARGET umdsst_var.x SOURCES Var.cc - LIBS oisst ) + LIBS umdsst ) diff --git a/src/mains/ConvertState.cc b/src/mains/ConvertState.cc index 15b67f6..1633f72 100644 --- a/src/mains/ConvertState.cc +++ b/src/mains/ConvertState.cc @@ -6,13 +6,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/ConvertState.h" #include "oops/runs/Run.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - oops::ConvertState convertstate; + oops::ConvertState convertstate; return run.execute(convertstate); } diff --git a/src/mains/Dirac.cc b/src/mains/Dirac.cc index 3318fdc..5436d72 100644 --- a/src/mains/Dirac.cc +++ b/src/mains/Dirac.cc @@ -5,15 +5,17 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Dirac.h" #include "oops/runs/Run.h" -// #include "saber/oops/instantiateLocalizationFactory.h" +// #include "saber/oops/instantiateLocalizationFactory.h" +#include "saber/oops/instantiateCovarFactory.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - // saber::instantiateLocalizationFactory(); - oops::Dirac dir; + // saber::instantiateLocalizationFactory(); + saber::instantiateCovarFactory(); + oops::Dirac dir; return run.execute(dir); } diff --git a/src/mains/HofXNoModel.cc b/src/mains/HofX3D.cc similarity index 79% rename from src/mains/HofXNoModel.cc rename to src/mains/HofX3D.cc index f48d887..285786a 100644 --- a/src/mains/HofXNoModel.cc +++ b/src/mains/HofX3D.cc @@ -5,8 +5,8 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" -#include "oops/runs/HofXNoModel.h" +#include "umdsst/Traits.h" +#include "oops/runs/HofX3D.h" #include "oops/runs/Run.h" #include "ufo/instantiateObsFilterFactory.h" #include "ufo/ObsTraits.h" @@ -14,6 +14,6 @@ int main(int argc, char ** argv) { oops::Run run(argc, argv); ufo::instantiateObsFilterFactory(); - oops::HofXNoModel hofx; + oops::HofX3D hofx; return run.execute(hofx); } diff --git a/src/mains/MakeObs.cc b/src/mains/MakeObs.cc deleted file mode 100644 index 5274685..0000000 --- a/src/mains/MakeObs.cc +++ /dev/null @@ -1,17 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR. - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#include "oisst/Traits.h" -#include "oops/runs/MakeObs.h" -#include "oops/runs/Run.h" -#include "ufo/ObsTraits.h" - -int main(int argc, char ** argv) { - oops::Run run(argc, argv); - oops::MakeObs makeobs; - return run.execute(makeobs); -} diff --git a/src/mains/StaticBInit.cc b/src/mains/StaticBInit.cc index 6283e71..98c74f6 100644 --- a/src/mains/StaticBInit.cc +++ b/src/mains/StaticBInit.cc @@ -5,12 +5,14 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "oops/runs/StaticBInit.h" +#include "saber/oops/instantiateCovarFactory.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - oops::StaticBInit bmat; + saber::instantiateCovarFactory(); + oops::StaticBInit bmat; return run.execute(bmat); } diff --git a/src/mains/Var.cc b/src/mains/Var.cc index 8946449..95b6b47 100644 --- a/src/mains/Var.cc +++ b/src/mains/Var.cc @@ -5,15 +5,17 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "oops/runs/Variational.h" #include "ufo/instantiateObsFilterFactory.h" #include "ufo/ObsTraits.h" +#include "saber/oops/instantiateCovarFactory.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); ufo::instantiateObsFilterFactory(); - oops::Variational var; + saber::instantiateCovarFactory(); + oops::Variational var; return run.execute(var); } diff --git a/src/oisst/CMakeLists.txt b/src/oisst/CMakeLists.txt deleted file mode 100644 index 260b52c..0000000 --- a/src/oisst/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -#include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - -# the source code in this directory, -# all other files are handled through the subdirectory's respective CMakeLists.txt -list( APPEND oisst_src_files - Traits.h -) - -# a convenience frunction to make adding source files from subdirectories easier -# (To keep from having to use the full path every time) -function(oisst_target_sources) - foreach( src IN LISTS ARGN) - target_sources(oisst PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${src}) - endforeach() -endfunction() - -# the main library for this interface -ecbuild_add_library( TARGET oisst - SOURCES ${oisst_src_files} - LIBS ${NETCDF_LIBRARIES} - eckit eckit_mpi fckit oops ioda ufo - INSTALL_HEADERS LISTED - LINKER_LANGUAGE ${OISST_LINKER_LANGUAGE} - ) - -# add source code in the subdirectories -add_subdirectory(Covariance) -add_subdirectory(Geometry) -add_subdirectory(GetValues) -add_subdirectory(Increment) -add_subdirectory(Model) -add_subdirectory(ModelAux) -add_subdirectory(State) \ No newline at end of file diff --git a/src/oisst/Covariance/Covariance.cc b/src/oisst/Covariance/Covariance.cc deleted file mode 100644 index c71ca0e..0000000 --- a/src/oisst/Covariance/Covariance.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#include -#include - -#include "oisst/Covariance/Covariance.h" -#include "oisst/Geometry/Geometry.h" -#include "oisst/Increment/Increment.h" -#include "oisst/State/State.h" - -#include "eckit/config/Configuration.h" - -#include "oops/base/Variables.h" -#include "oops/util/abor1_cpp.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - Covariance::Covariance(const Geometry & geom, - const oops::Variables & vars, - const eckit::Configuration & conf, - const State & x1, const State & x2) { - util::abor1_cpp("Covariance::Covariance() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Covariance::~Covariance() { - util::abor1_cpp("Covariance::~Covariance() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Covariance::inverseMultiply(const Increment &, Increment &) const { - util::abor1_cpp("Covariance::inverseMultiply() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Covariance::multiply(const Increment & dxin, Increment & dxout) const { - util::abor1_cpp("Covariance::multiply() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Covariance::randomize(Increment &) const { - util::abor1_cpp("Covariance::randomize() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Covariance::print(std::ostream & os) const { - util::abor1_cpp("Covariance::print() needs to be implemented.", - __FILE__, __LINE__); - os << "(TODO, print diagnostic info about the Covariance here)" - << std::endl; - } - -// ---------------------------------------------------------------------------- - -} // namespace oisst diff --git a/src/oisst/Geometry/Geometry.cc b/src/oisst/Geometry/Geometry.cc deleted file mode 100644 index 2b84639..0000000 --- a/src/oisst/Geometry/Geometry.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#include "oisst/Geometry/Geometry.h" - -#include "eckit/config/Configuration.h" - -#include "oops/util/abor1_cpp.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - Geometry::Geometry(const eckit::Configuration & conf, - const eckit::mpi::Comm & comm) - : comm_(comm) { - util::abor1_cpp("Geometry::Geometry() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Geometry::Geometry(const Geometry & other) - : comm_(other.comm_) { - util::abor1_cpp("Geometry::Geometry() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Geometry::~Geometry() { - util::abor1_cpp("Geometry::~Geometry() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Geometry::print(std::ostream & os) const { - util::abor1_cpp("Geometry::print() needs to be implemented.", - __FILE__, __LINE__); - os << "Geometry: " - << "(TODO, print diagnostic info about the geometry here)" - << std::endl; - } - -// ---------------------------------------------------------------------------- - -} // namespace oisst diff --git a/src/oisst/GetValues/CMakeLists.txt b/src/oisst/GetValues/CMakeLists.txt deleted file mode 100644 index d86500a..0000000 --- a/src/oisst/GetValues/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -oisst_target_sources( - GetValues.cc - GetValues.h - LinearGetValues.cc - LinearGetValues.h -) \ No newline at end of file diff --git a/src/oisst/GetValues/GetValues.cc b/src/oisst/GetValues/GetValues.cc deleted file mode 100644 index 9390280..0000000 --- a/src/oisst/GetValues/GetValues.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#include "oisst/Geometry/Geometry.h" -#include "oisst/GetValues/GetValues.h" -#include "oisst/State/State.h" - -#include "eckit/config/Configuration.h" - -#include "oops/base/Variables.h" -#include "oops/util/abor1_cpp.h" - -#include "ufo/GeoVaLs.h" -#include "ufo/Locations.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - GetValues::GetValues(const Geometry & geom, - const ufo::Locations & locs) - : geom_(new Geometry(geom)), locs_(locs) { - util::abor1_cpp("GetValues::GetValues() needs to be implemented.", - __FILE__, __LINE__); - } - -// ----------------------------------------------------------------------------- - - GetValues::~GetValues() { - util::abor1_cpp("GetValues::~GetValues() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void GetValues::fillGeoVaLs(const State & state, - const util::DateTime & t1, - const util::DateTime & t2, - ufo::GeoVaLs & geovals) const { - util::abor1_cpp("GetValues::fillGeoVaLs() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void GetValues::print(std::ostream & os) const { - os << "insert diagnostic information about getvalues" - << std::endl; - util::abor1_cpp("GetValues::print() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - -} // namespace oisst diff --git a/src/oisst/GetValues/LinearGetValues.cc b/src/oisst/GetValues/LinearGetValues.cc deleted file mode 100644 index 4c9e857..0000000 --- a/src/oisst/GetValues/LinearGetValues.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - - -#include "oisst/GetValues/LinearGetValues.h" -#include "oisst/State/State.h" -#include "oisst/Geometry/Geometry.h" -#include "oisst/Increment/Increment.h" - -#include "eckit/config/Configuration.h" - -#include "oops/base/Variables.h" -#include "oops/util/abor1_cpp.h" - -#include "ufo/GeoVaLs.h" -#include "ufo/Locations.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - LinearGetValues::LinearGetValues(const Geometry & geom, - const ufo::Locations & locs) - : geom_( new Geometry(geom)), locs_(locs) { - util::abor1_cpp( - "LinearGetValues::LinearGetValues() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - LinearGetValues::~LinearGetValues() { - util::abor1_cpp( - "LinearGetValues::~LinearGetValues() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void LinearGetValues::fillGeoVaLsAD(Increment & inc, - const util::DateTime & t1, - const util::DateTime & t2, - const ufo::GeoVaLs & geovals) const { - util::abor1_cpp( - "LinearGetValues::fillGeoVaLsAD() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void LinearGetValues::fillGeoVaLsTL(const Increment & inc, - const util::DateTime & t1, - const util::DateTime & t2, - ufo::GeoVaLs & geovals) const { - util::abor1_cpp("LinearGetValues::fillGeoVaLsTL() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void LinearGetValues::setTrajectory(const State & state, - const util::DateTime & t1, - const util::DateTime & t2, - ufo::GeoVaLs & geovals) { - util::abor1_cpp("LinearGetValues::setTrajectory() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void LinearGetValues::print(std::ostream & os) const { - os << "insert diagnostic information about LinearGetValues" - << std::endl; - util::abor1_cpp("LinearGetValues::print() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - -} // namespace oisst diff --git a/src/oisst/Increment/Increment.cc b/src/oisst/Increment/Increment.cc deleted file mode 100644 index b2d2ccf..0000000 --- a/src/oisst/Increment/Increment.cc +++ /dev/null @@ -1,191 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#include - -#include "oisst/Geometry/Geometry.h" -#include "oisst/Increment/Increment.h" - -#include "oops/util/abor1_cpp.h" - -#include "ufo/GeoVaLs.h" -#include "ufo/Locations.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - Increment::Increment(const Geometry & geom, - const oops::Variables & vars, - const util::DateTime & vt) - : geom_(new Geometry(geom)), time_(vt), vars_(vars) { - util::abor1_cpp("Increment::Increment() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Increment::Increment(const Geometry & geom, const Increment & other) - : geom_(new Geometry(geom)), time_(other.time_), vars_(other.vars_) { - util::abor1_cpp("Increment::Increment() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Increment::Increment(const Increment & other, const bool copy) - : geom_(new Geometry(*other.geom_)), time_(other.time_), - vars_(other.vars_) { - util::abor1_cpp("Increment::Increment() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Increment::Increment(const Increment & other) - : geom_(new Geometry(*other.geom_)), time_(other.time_), - vars_(other.vars_) { - util::abor1_cpp("Increment::Increment() needs to be implemented.", - __FILE__, __LINE__); - } -// ---------------------------------------------------------------------------- - - Increment::~Increment() { - util::abor1_cpp("Increment::~Increment() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Increment & Increment::operator =(const Increment &) { - util::abor1_cpp("Increment::operator= needs to be implemented.", - __FILE__, __LINE__); - return *this; - } - -// ---------------------------------------------------------------------------- - - Increment & Increment::operator -=(const Increment &) { - util::abor1_cpp("Increment::operator-= needs to be implemented.", - __FILE__, __LINE__); - return *this; - } - -// ---------------------------------------------------------------------------- - - Increment & Increment::operator +=(const Increment &) { - util::abor1_cpp("Increment::operator+= needs to be implemented.", - __FILE__, __LINE__); - return *this; - } - -// ---------------------------------------------------------------------------- - - Increment & Increment::operator *=(const double &) { - util::abor1_cpp("Increment::operator*= needs to be implemented.", - __FILE__, __LINE__); - return *this; - } - -// ---------------------------------------------------------------------------- - - void Increment::accumul(const double & zz, const State & xx) { - util::abor1_cpp("Increment::accuml() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::axpy(const double &, const Increment &, const bool check) { - util::abor1_cpp("Increment::axpy() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::diff(const State & x1, const State & x2) { - util::abor1_cpp("Increment::diff() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - double Increment::dot_product_with(const Increment &) const { - util::abor1_cpp("Increment::dot_product_with() needs to be implemented.", - __FILE__, __LINE__); - return 0.0; - } - -// ---------------------------------------------------------------------------- - - double Increment::norm() const { - util::abor1_cpp("Increment::norm() needs to be implemented.", - __FILE__, __LINE__); - return 0.0; - } - -// ---------------------------------------------------------------------------- - - void Increment::random() { - util::abor1_cpp("Increment::random() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::schur_product_with(const Increment & ) { - util::abor1_cpp("Increment::schur_product_with() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::zero() { - util::abor1_cpp("Increment::zero() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::zero(const util::DateTime & time) { - zero(); - time_ = time; - } - -// ---------------------------------------------------------------------------- - - void Increment::dirac(const eckit::Configuration & conf) { - util::abor1_cpp("Increment::dirac() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::print(std::ostream & os) const { - os << "Increment: " - << "(TODO, print diagnostic info about the increment here)" - << std::endl; - util::abor1_cpp("Increment::print() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::read(const eckit::Configuration & conf) { - util::abor1_cpp("Increment::read() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Increment::write(const eckit::Configuration & conf) const { - util::abor1_cpp("Increment::write() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- -} // namespace oisst diff --git a/src/oisst/Increment/Increment.h b/src/oisst/Increment/Increment.h deleted file mode 100644 index 598d108..0000000 --- a/src/oisst/Increment/Increment.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR. - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - * In applying this licence, ECMWF does not waive the privileges and immunities - * granted to it by virtue of its status as an intergovernmental organisation nor - * does it submit to any jurisdiction. - */ - -#ifndef OISST_INCREMENT_INCREMENT_H_ -#define OISST_INCREMENT_INCREMENT_H_ - -#include -#include -#include - -#include - -#include "oops/base/Variables.h" -#include "oops/util/DateTime.h" -#include "oops/util/Printable.h" -#include "oops/base/GeneralizedDepartures.h" - -// forward declarations -namespace oops { - class Variables; -} -namespace ufo { - class GeoVaLs; - class Locations; -} -namespace oisst { - class Geometry; - class State; -} - -// ---------------------------------------------------------------------------- - -namespace oisst { - - // Increment class - class Increment : public oops::GeneralizedDepartures, - public util::Printable, - private util::ObjectCounter { - public: - static const std::string classname() {return "oisst::Increment";} - - // Constructor, destructor - Increment(const Geometry &, const oops::Variables &, - const util::DateTime &); - Increment(const Geometry &, const Increment &); - Increment(const Increment &, const bool); - Increment(const Increment &); - ~Increment(); - - // Math operators - Increment & operator =(const Increment &); - Increment & operator-=(const Increment &); - Increment & operator+=(const Increment &); - Increment & operator*=(const double &); - void accumul(const double &, const State &); - void axpy(const double &, const Increment &, const bool check = true); - void diff(const State &, const State &); - double dot_product_with(const Increment &) const; - double norm() const; - void random(); - void schur_product_with(const Increment &); - void zero(); - void zero(const util::DateTime &); - - // time manipulation - void updateTime(const util::Duration & dt) { time_ += dt; } - const util::DateTime & validTime() const { return time_; } - util::DateTime & validTime() { return time_; } - - // dirac - void dirac(const eckit::Configuration &); - - // other accessors - boost::shared_ptr geometry() const { return geom_; } - - // I/O - void read(const eckit::Configuration &); - void write(const eckit::Configuration &) const; - - private: - void print(std::ostream &) const; - - boost::shared_ptr geom_; - util::DateTime time_; - oops::Variables vars_; - }; -} // namespace oisst - -#endif // OISST_INCREMENT_INCREMENT_H_ diff --git a/src/oisst/Model/CMakeLists.txt b/src/oisst/Model/CMakeLists.txt deleted file mode 100644 index 37016e9..0000000 --- a/src/oisst/Model/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -oisst_target_sources( - Model.cc - Model.h -) \ No newline at end of file diff --git a/src/oisst/Model/Model.cc b/src/oisst/Model/Model.cc deleted file mode 100644 index cbd378f..0000000 --- a/src/oisst/Model/Model.cc +++ /dev/null @@ -1,71 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ -#include "oisst/Traits.h" -#include "oisst/Geometry/Geometry.h" -#include "oisst/Model/Model.h" -#include "oisst/ModelAux/ModelAuxControl.h" -#include "oisst/State/State.h" - -#include "oops/util/abor1_cpp.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - static oops::ModelMaker modelmaker_("OISST"); - -// ---------------------------------------------------------------------------- - - Model::Model(const Geometry & geom, const eckit::Configuration & conf) - : geom_(new Geometry(geom)), tstep_(conf.getString("tstep")), - vars_(conf, "model variables") { - util::abor1_cpp("Model::Model() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - Model::~Model() { - util::abor1_cpp("Model::~Model() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Model::initialize(State & xx) const { - util::abor1_cpp("Model::initialize() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Model::step(State & xx, const ModelAuxControl & xx_bias) const { - util::abor1_cpp("Model::step() needs to be implemented.", - __FILE__, __LINE__); - xx.validTime() += tstep_; - } - -// ---------------------------------------------------------------------------- - - void Model::finalize(State & xx) const { - util::abor1_cpp("Model::finalize() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void Model::print(std::ostream & os) const { - os << "Geometry: " - << "(TODO, print diagnostic info about the geometry here)" - << std::endl; - util::abor1_cpp("Model::print() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - -} // namespace oisst diff --git a/src/oisst/Model/Model.h b/src/oisst/Model/Model.h deleted file mode 100644 index cdc1402..0000000 --- a/src/oisst/Model/Model.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#ifndef OISST_MODEL_MODEL_H_ -#define OISST_MODEL_MODEL_H_ - -#include -#include - -#include "oops/util/Duration.h" -#include "oops/base/ModelBase.h" -#include "oops/base/Variables.h" -#include "oops/util/ObjectCounter.h" - -// forward declarations -namespace oisst { - class Geometry; - class ModelAuxControl; - struct Traits; -} - -// ---------------------------------------------------------------------------- - -namespace oisst { - - // Model class - class Model : public oops::ModelBase, - private util::ObjectCounter - { - public: - // constructors / destructor - Model(const Geometry &, const eckit::Configuration &); - ~Model(); - - // model stages - void initialize(State &) const; - void step(State &, const ModelAuxControl &) const; - void finalize(State &) const; - - // accessors - const util::Duration & timeResolution() const { return tstep_;} - const oops::Variables & variables() const { return vars_; } - - private: - void print(std::ostream &) const; - - const std::unique_ptr geom_; - util::Duration tstep_; - const oops::Variables vars_; - }; - -} // namespace oisst -#endif // OISST_MODEL_MODEL_H_ diff --git a/src/oisst/State/State.cc b/src/oisst/State/State.cc deleted file mode 100644 index ee63bf4..0000000 --- a/src/oisst/State/State.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#include "oisst/Geometry/Geometry.h" -#include "oisst/State/State.h" - -#include "eckit/config/Configuration.h" - -#include "oops/base/Variables.h" -#include "oops/util/abor1_cpp.h" - -#include "ufo/GeoVaLs.h" -#include "ufo/Locations.h" - -namespace oisst { - -// ---------------------------------------------------------------------------- - - State::State(const Geometry & geom, const eckit::Configuration & conf) - : geom_(new Geometry(geom)), time_(conf.getString("date")), - vars_(conf, "state variables") { - util::abor1_cpp("State::State() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - State::State(const Geometry & geom, const oops::Variables & vars, - const util::DateTime & time) - : geom_(new Geometry(geom)), time_(time), vars_(vars) { - util::abor1_cpp("State::State() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - State::State(const Geometry & geom, const State & other) - : geom_(new Geometry(geom)), time_(other.time_), vars_(other.vars_) { - // Change state resolution - util::abor1_cpp("State::State() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - State::State(const State & other) - : geom_(new Geometry(*other.geom_)), time_(other.time_), - vars_(other.vars_) { - util::abor1_cpp("State::State() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - State::~State() { - util::abor1_cpp("State::~State() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - State & State::operator+=(const Increment & dx) - { - util::abor1_cpp("State::operator+=(Increment) needs to be implemented.", - __FILE__, __LINE__); - return *this; - } - -// ---------------------------------------------------------------------------- - - void State::accumul(const double &, const State &) { - util::abor1_cpp("State::accumul() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - double State::norm() const { - util::abor1_cpp("State::norm() needs to be implemented.", - __FILE__, __LINE__); - return 0.0; - } - -// ---------------------------------------------------------------------------- - - void State::zero() { - util::abor1_cpp("State::zero() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void State::read(const eckit::Configuration & conf) { - util::abor1_cpp("State::read() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - void State::write(const eckit::Configuration & conf) const { - util::abor1_cpp("State::write() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - - boost::shared_ptr State::geometry() const {return geom_;} - -// ---------------------------------------------------------------------------- - - void State::print(std::ostream & os) const { - os << "insert diagnostic information about state here " - << "(min/max/mean for each state var?)" - << std::endl; - - util::abor1_cpp("State::print() needs to be implemented.", - __FILE__, __LINE__); - } - -// ---------------------------------------------------------------------------- - -} // namespace oisst diff --git a/src/oisst/State/State.h b/src/oisst/State/State.h deleted file mode 100644 index 06e0fcd..0000000 --- a/src/oisst/State/State.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#ifndef OISST_STATE_STATE_H_ -#define OISST_STATE_STATE_H_ - -#include -#include -#include - -#include - -#include "eckit/mpi/Comm.h" - -#include "oops/base/Variables.h" -#include "oops/util/DateTime.h" -#include "oops/util/ObjectCounter.h" -#include "oops/util/Printable.h" - -// forward declarations -namespace eckit { - class Configuration; -} -namespace ufo { - class GeoVaLs; - class Locations; -} -namespace oisst { - class Geometry; - class Increment; -} - -// ---------------------------------------------------------------------------- - -namespace oisst { - - // State class - class State : public util::Printable, - private util::ObjectCounter { - public: - static const std::string classname() {return "oisst::State";} - - // constructors, destructors - State(const Geometry &, const eckit::Configuration &); - State(const Geometry &, const oops::Variables &, - const util::DateTime &); - State(const Geometry &, const State &); - State(const State &); - ~State(); - - // math operators - State & operator+=(const Increment &); - void accumul(const double &, const State &); - double norm() const; - void zero(); - - // I/O - void read(const eckit::Configuration &); - void write(const eckit::Configuration &) const; - - // time manipulation - void updateTime(const util::Duration & dt) { time_ += dt; } - const util::DateTime & validTime() const { return time_; } - util::DateTime & validTime() { return time_; } - - // other accessors - boost::shared_ptr geometry() const; - const oops::Variables & variables() const { return vars_; } - - private: - void print(std::ostream &) const; - - boost::shared_ptr geom_; - oops::Variables vars_; - util::DateTime time_; - }; -} // namespace oisst - -#endif // OISST_STATE_STATE_H_ diff --git a/src/oisst/Traits.h b/src/oisst/Traits.h deleted file mode 100644 index 8688fb9..0000000 --- a/src/oisst/Traits.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * (C) Copyright 2019-2020 UCAR - * - * This software is licensed under the terms of the Apache Licence Version 2.0 - * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. - */ - -#ifndef OISST_TRAITS_H_ -#define OISST_TRAITS_H_ - -#include - -#include "oisst/Covariance/Covariance.h" -#include "oisst/Geometry/Geometry.h" -#include "oisst/GetValues/GetValues.h" -#include "oisst/GetValues/LinearGetValues.h" -#include "oisst/Increment/Increment.h" -#include "oisst/ModelAux/ModelAuxControl.h" -#include "oisst/ModelAux/ModelAuxCovariance.h" -#include "oisst/ModelAux/ModelAuxIncrement.h" -#include "oisst/State/State.h" - -namespace oisst { - - struct Traits{ - static std::string name() {return "oisst";} - static std::string nameCovar() {return "oisstCovar";} - static std::string nameCovar4D() {return "oisstCovar";} - - // Interfaces that oisst has to implement - // --------------------------------------------------- - typedef oisst::Covariance Covariance; - typedef oisst::Geometry Geometry; - typedef oisst::GetValues GetValues; - typedef oisst::Increment Increment; - typedef oisst::LinearGetValues LinearGetValues; - typedef oisst::ModelAuxControl ModelAuxControl; - typedef oisst::ModelAuxCovariance ModelAuxCovariance; - typedef oisst::ModelAuxIncrement ModelAuxIncrement; - typedef oisst::State State; - }; -} // namespace oisst - -#endif // OISST_TRAITS_H_ diff --git a/src/umdsst/CMakeLists.txt b/src/umdsst/CMakeLists.txt new file mode 100644 index 0000000..1ce29e7 --- /dev/null +++ b/src/umdsst/CMakeLists.txt @@ -0,0 +1,48 @@ +#include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) + +# the source code in this directory, +# all other files are handled through the subdirectory's respective CMakeLists.txt +list( APPEND umdsst_src_files + Traits.h +) + +# a convenience frunction to make adding source files from subdirectories easier +# (To keep from having to use the full path every time) +function(umdsst_target_sources) + foreach( src IN LISTS ARGN) + target_sources(umdsst PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${src}) + endforeach() +endfunction() + +find_package( NetCDF REQUIRED COMPONENTS CXX ) + +# the main library for this interface +ecbuild_add_library( TARGET umdsst + SOURCES ${umdsst_src_files} + INSTALL_HEADERS LISTED + LINKER_LANGUAGE ${UMDSST_LINKER_LANGUAGE} + ) +target_include_directories(umdsst PUBLIC + $ + $) + +target_compile_features( umdsst PUBLIC cxx_std_11 ) + +target_link_libraries( umdsst PUBLIC NetCDF::NetCDF_CXX ) +target_link_libraries( umdsst PUBLIC fckit ) +target_link_libraries( umdsst PUBLIC atlas ) +target_link_libraries( umdsst PUBLIC oops ) +target_link_libraries( umdsst PUBLIC saber ) +target_link_libraries( umdsst PUBLIC ioda ) +target_link_libraries( umdsst PUBLIC ufo ) + +# add source code in the subdirectories +add_subdirectory(Covariance) +add_subdirectory(Fields) +add_subdirectory(Geometry) +add_subdirectory(GetValues) +add_subdirectory(Increment) +add_subdirectory(LinearVariableChange) +add_subdirectory(ModelAux) +add_subdirectory(State) +add_subdirectory(VariableChange) \ No newline at end of file diff --git a/src/oisst/Covariance/CMakeLists.txt b/src/umdsst/Covariance/CMakeLists.txt similarity index 61% rename from src/oisst/Covariance/CMakeLists.txt rename to src/umdsst/Covariance/CMakeLists.txt index 706576a..d5525f1 100644 --- a/src/oisst/Covariance/CMakeLists.txt +++ b/src/umdsst/Covariance/CMakeLists.txt @@ -1,4 +1,4 @@ -oisst_target_sources( +umdsst_target_sources( Covariance.cc Covariance.h ) \ No newline at end of file diff --git a/src/umdsst/Covariance/Covariance.cc b/src/umdsst/Covariance/Covariance.cc new file mode 100644 index 0000000..f9db5c3 --- /dev/null +++ b/src/umdsst/Covariance/Covariance.cc @@ -0,0 +1,166 @@ +/* + * (C) Copyright 2019-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include +#include +#include +#include + +#include "umdsst/Covariance/Covariance.h" +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/Increment/Increment.h" +#include "umdsst/State/State.h" + +#include "eckit/config/Configuration.h" + +#include "oops/assimilation/GMRESR.h" +#include "oops/base/IdentityMatrix.h" +#include "oops/base/Variables.h" +#include "oops/util/abor1_cpp.h" +#include "oops/util/Logger.h" +#include "oops/util/missingValues.h" + +#include "saber/bump/type_bump.h" + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + Covariance::Covariance(const Geometry & geom, + const oops::Variables & vars, + const eckit::Configuration & conf, + const State & x1, const State & x2) { + oops::Log::trace() << "umdsst::Covariance::Covariance starting"<< std::endl; + + // setup BUMP + // -------------------------------------------- + eckit::LocalConfiguration bumpConf; + conf.get("bump", bumpConf); + const double msvalr = util::missingValue(msvalr); + bumpConf.set("msvalr", msvalr); + + eckit::LocalConfiguration gridConf; + std::string prefix; + bumpConf.get("prefix", prefix); + gridConf.set("prefix", prefix + "_00"); + gridConf.set("variables", vars.variables()); + gridConf.set("nv", vars.size()); + gridConf.set("nl", 1); + + oops::Log::info() << "Configuration: " << bumpConf << std::endl; + oops::Log::info() << "Grid " << 0 << ": " << gridConf << std::endl; + + saber::bump_create_f90(keyBump_, &geom.getComm(), + geom.atlasFunctionSpace()->get(), + geom.atlasFieldSet()->get(), + bumpConf, gridConf); + + // pass user generated fields to BUMP + // NOTE: assuming only 1 state variable + // -------------------------------------------- + assert(vars.size() == 1); + std::string param_name; + atlas::FieldSet param_fieldSet; + atlas::Field param_field = geom.atlasFunctionSpace()->createField( + atlas::option::levels(1) | atlas::option::name(vars[0])); + param_fieldSet.add(param_field); + auto param_view = atlas::array::make_view(param_field); + + // horizontal correlation lengths + if (conf.has("correlation lengths")) { + eckit::LocalConfiguration corrConf; + conf.get("correlation lengths", corrConf); + + // rh is calculated as follows : + // 1) rh = "base value" + rossby_radius * "rossby mult" + // 2) minimum value of "min grid mult" * grid_size is imposed + // 3) min/max are imposed based on "min value" and "max value" + // 4) converted from a gaussian sigma to Gaspari-Cohn cutoff distance + double baseValue = corrConf.getDouble("base value", 0.0); + double rossbyMult = corrConf.getDouble("rossby mult", 0.0); + double minGridMult = corrConf.getDouble("min grid mult", 0.0); + double minValue = corrConf.getDouble("min value", 0.0); + double maxValue = corrConf.getDouble("max value", + std::numeric_limits::max()); + + auto rossbyRadius = atlas::array::make_view( + geom.atlasFieldSet()->field("rossby_radius")); + auto area = atlas::array::make_view( + geom.atlasFieldSet()->field("area")); + + param_view.assign(baseValue); + for ( int i = 0; i < param_field.size(); i++ ) { + param_view(i, 0) += rossbyMult * rossbyRadius(i, 0); + param_view(i, 0) = std::max(param_view(i, 0), + minGridMult*sqrt(area(i, 0))); + param_view(i, 0) = std::max(param_view(i, 0), minValue); + param_view(i, 0) = std::min(param_view(i, 0), maxValue); + } + + // note: BUMP expects the length as a Gaspari-Cohn cutoff length, + // but we probably think of it as a Gaussian 1 sigma, so convert. + for ( int i = 0; i < param_field.size(); i++ ) { + param_view(i, 0) *= 3.57; // gaussian to GC factor + } + + param_name = "cor_rh"; + saber::bump_set_parameter_f90(keyBump_, param_name.size(), + param_name.c_str(), param_fieldSet.get()); + + // vertical lengths (leave at 1.0, because we have no vertical) + param_name = "cor_rv"; + param_view.assign(1.0); + saber::bump_set_parameter_f90(keyBump_, param_name.size(), + param_name.c_str(), param_fieldSet.get()); + } + + // Calculate static B and cleanup + // -------------------------------------------- + saber::bump_run_drivers_f90(keyBump_); + saber::bump_partial_dealloc_f90(keyBump_); + + oops::Log::trace() << "umdsst::Covariance::Covariance done" << std::endl; + } + +// ---------------------------------------------------------------------------- + + Covariance::~Covariance() { + oops::Log::trace() << "Covariance destructed!" << std::endl; + } + +// ---------------------------------------------------------------------------- + + void Covariance::inverseMultiply(const Increment & dxin, + Increment & dxout) const { + oops::IdentityMatrix Id; + dxout.zero(); + GMRESR(dxout, dxin, *this, Id, 10, 1.0e-3); + } + +// ---------------------------------------------------------------------------- + + void Covariance::multiply(const Increment & dxin, Increment & dxout) const { + dxout = dxin; + saber::bump_apply_nicas_f90(keyBump_, (*dxout.atlasFieldSet()).get()); + } + +// ---------------------------------------------------------------------------- + + void Covariance::randomize(Increment & dx) const { + dx.random(); + } + +// ---------------------------------------------------------------------------- + + void Covariance::print(std::ostream & os) const { + os << "(TODO, print diagnostic info about the Covariance here)" + << std::endl; + } + +// ---------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/oisst/Covariance/Covariance.h b/src/umdsst/Covariance/Covariance.h similarity index 80% rename from src/oisst/Covariance/Covariance.h rename to src/umdsst/Covariance/Covariance.h index 87739d6..2afb7c1 100644 --- a/src/oisst/Covariance/Covariance.h +++ b/src/umdsst/Covariance/Covariance.h @@ -5,8 +5,8 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_COVARIANCE_COVARIANCE_H_ -#define OISST_COVARIANCE_COVARIANCE_H_ +#ifndef UMDSST_COVARIANCE_COVARIANCE_H_ +#define UMDSST_COVARIANCE_COVARIANCE_H_ #include #include @@ -21,7 +21,7 @@ namespace eckit { namespace oops { class Variables; } -namespace oisst { +namespace umdsst { class Geometry; class Increment; class State; @@ -29,13 +29,13 @@ namespace oisst { // ---------------------------------------------------------------------------- -namespace oisst { +namespace umdsst { // Fields class class Covariance : public util::Printable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::Covariance";} + static const std::string classname() {return "umdsst::Covariance";} // constructors/destructors Covariance(const Geometry &, const oops::Variables &, @@ -50,8 +50,10 @@ namespace oisst { private: void print(std::ostream &) const; + + int keyBump_ = 0; }; -} // namespace oisst +} // namespace umdsst -#endif // OISST_COVARIANCE_COVARIANCE_H_ +#endif // UMDSST_COVARIANCE_COVARIANCE_H_ diff --git a/src/umdsst/Fields/CMakeLists.txt b/src/umdsst/Fields/CMakeLists.txt new file mode 100644 index 0000000..bf84dff --- /dev/null +++ b/src/umdsst/Fields/CMakeLists.txt @@ -0,0 +1,4 @@ +umdsst_target_sources( + Fields.cc + Fields.h +) \ No newline at end of file diff --git a/src/umdsst/Fields/Fields.cc b/src/umdsst/Fields/Fields.cc new file mode 100644 index 0000000..d9c641d --- /dev/null +++ b/src/umdsst/Fields/Fields.cc @@ -0,0 +1,436 @@ +/* + * (C) Copyright 2020-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include +#include + +#include "netcdf" + +#include "umdsst/Fields/Fields.h" +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/State/State.h" + +#include "atlas/array.h" +#include "atlas/field.h" +#include "atlas/option.h" + +#include "oops/mpi/mpi.h" +#include "oops/util/abor1_cpp.h" +#include "oops/util/Logger.h" +#include "oops/util/missingValues.h" + +using atlas::array::make_view; + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + Fields::Fields(const Geometry & geom, const oops::Variables & vars, + const util::DateTime & vt) + : geom_(new Geometry(geom)), missing_(util::missingValue(this->missing_)), + time_(vt), vars_(vars) { + // the constructor that gets called by everything (all State + // and Increment constructors ultimately end up here) + + atlasFieldSet_.reset(new atlas::FieldSet()); + for (int v = 0; v < vars_.size(); v++) { + std::string var = vars_[v]; + atlas::Field fld = geom_->atlasFunctionSpace()->createField( + atlas::option::levels(1) | + atlas::option::name(var)); + auto fd = make_view(fld); + fd.assign(0.0); + + atlasFieldSet_->add(fld); + } + } + +// ---------------------------------------------------------------------------- + + Fields::Fields(const Fields & other) + : Fields(*other.geom_, other.vars_, other.time_) { + // copy data from object other + *this = other; + } + +// ---------------------------------------------------------------------------- + Fields & Fields::operator =(const Fields & other) { + const int size = geom_->atlasFunctionSpace()->size(); + + for (int v = 0; v < vars_.size(); v++) { + std::string name = vars_[v]; + auto fd = make_view(atlasFieldSet_->field(name)); + auto fd_other = make_view(other.atlasFieldSet_->field(name)); + for (int j = 0; j < size; j++) + fd(j, 0) = fd_other(j, 0); + } + return *this; + } + +// ---------------------------------------------------------------------------- + + Fields & Fields::operator+=(const Fields &other) { + const int size = geom_->atlasFunctionSpace()->size(); + + for (int v = 0; v < vars_.size(); v++) { + std::string name = vars_[v]; + auto fd = make_view(atlasFieldSet_->field(name)); + auto fd_other = make_view(other.atlasFieldSet_->field(name)); + + for (int j = 0; j < size; j++) { + if (fd(j, 0) == missing_ || fd_other(j, 0) == other.missing_) + fd(j, 0) = missing_; + else + fd(j, 0) += fd_other(j, 0); + } + } + return *this; + } + +// ---------------------------------------------------------------------------- + + void Fields::accumul(const double &zz, const Fields &rhs) { + const size_t size = geom_->atlasFunctionSpace()->size(); + + for (int v = 0; v < vars_.size(); v++) { + std::string name = vars_[v]; + auto fd = make_view(atlasFieldSet_->field(name)); + auto fd_rhs = make_view(rhs.atlasFieldSet()->field(name)); + + for (size_t i = 0; i < size; i++) { + if (fd(i, 0) == missing_ || fd_rhs(i, 0) == missing_) + fd(i, 0) = missing_; + else + fd(i, 0) += zz*fd_rhs(i, 0); + } + } + } + +// ---------------------------------------------------------------------------- + + double Fields::norm() const { + const int size = geom_->atlasFunctionSpace()->size(); + int nValid = 0; + double norm = 0.0, s = 0.0; + + for (int v = 0; v < vars_.size(); v++) { + auto fd = make_view(atlasFieldSet_->field(v)); + + for (int i = 0; i < size; i++) { + if (fd(i, 0) != missing_) { + nValid += 1; + s += fd(i, 0)*fd(i, 0); + } + } + } + + // sum results across PEs + oops::mpi::world().allReduceInPlace(nValid, eckit::mpi::Operation::SUM); + oops::mpi::world().allReduceInPlace(s, eckit::mpi::Operation::SUM); + + if (nValid == 0) + norm = 0.0; + else + norm = sqrt(s/(1.0*nValid)); + + return norm; + } + +// ---------------------------------------------------------------------------- + + void Fields::zero() { + const int size = geom_->atlasFunctionSpace()->size(); + for (int v = 0; v < vars_.size(); v++) { + auto fd = make_view(atlasFieldSet_->field(v)); + fd.assign(0.0); + } + } + +// ---------------------------------------------------------------------------- + + void Fields::read(const eckit::Configuration & conf) { + // create a global field valid on the root PE + // Ligang: root PE by atlas::option::global() to specify? + atlas::Field globalSst = geom_->atlasFunctionSpace()->createField( + atlas::option::levels(1) | + atlas::option::global()); + + // following code block should execute on the root PE only + // Ligang: How do you do to decide which PEs to run with Atlas? + // Check the above Fields::norm() which sums results across PEs. + if ( globalSst.size() != 0 ) { + int time = 0, lon = 0, lat = 0; + std::string filename; + + auto fd = make_view(globalSst); + + // get filename + if (!conf.get("filename", filename)) + util::abor1_cpp("Fields::read(), Get filename failed.", + __FILE__, __LINE__); + + // open netCDF file + netCDF::NcFile file(filename.c_str(), netCDF::NcFile::read); + if (file.isNull()) + util::abor1_cpp("Fields::read(), Create netCDF file failed.", + __FILE__, __LINE__); + + // get file dimensions + time = static_cast(file.getDim("time").getSize()); + lon = static_cast(file.getDim("lon").getSize()); + lat = static_cast(file.getDim("lat").getSize()); + if (time != 1 || + lat != static_cast(geom_->atlasFunctionSpace()->grid().ny()) || + lon != static_cast((((atlas::RegularLonLatGrid&) // LC: no &? + (geom_->atlasFunctionSpace()->grid()))).nx()) ) { + util::abor1_cpp("Fields::read(), lat!=ny or lon!=nx", + __FILE__, __LINE__); + } + + // get sst data + netCDF::NcVar sstVar; + sstVar = file.getVar("sst"); + if (sstVar.isNull()) + util::abor1_cpp("Get sst var failed.", __FILE__, __LINE__); + float sstData[lat][lon]; + sstVar.getVar(sstData); // if used double, read-in data would be wrong. + + // mask missing values + const double epsilon = 1.0e-6; + const double missing_nc = -32768.0; + bool isKelvin = conf.getBool("kelvin", false); + for (int j = 0; j < lat; j++) + for (int i = 0; i < lon; i++) + if (abs(sstData[j][i]-(missing_nc)) < epsilon) { + sstData[j][i] = missing_; + // TODO(someone) missing values that aren't a part of the landmask + // should be filled in instead + } else { + // Kelvin to Celsius which JEDI use internally, will check if the + // units is Kelvin or Celsius in the future + if (isKelvin) + sstData[j][i] -= 273.15; + } + + // float to double + int idx = 0; + for (int j = lat-1; j >= 0; j--) + for (int i = 0; i < lon; i++) + fd(idx++, 0) = static_cast(sstData[j][i]); + } + + // scatter to the PEs + geom_->atlasFunctionSpace()->scatter( + globalSst, atlasFieldSet_->field("sea_surface_temperature")); + + // apply mask from read in landmask + if ( (*geom_->atlasFieldSet()).has_field("gmask") ) { + atlas::Field mask_field = (*geom_->atlasFieldSet())["gmask"]; + auto mask = make_view(mask_field); + auto fd = make_view(atlasFieldSet_->field(0)); + for (int i = 0; i < mask.size(); i++) { + if (mask(i, 0) == 0) + fd(i, 0) = missing_; + } + } + } + +// ---------------------------------------------------------------------------- + + void Fields::write(const eckit::Configuration & conf) const { + // gather from the PEs + atlas::Field globalSst = geom_->atlasFunctionSpace()->createField( + atlas::option::levels(1) | + atlas::option::global()); + geom_->atlasFunctionSpace()->gather( + atlasFieldSet_->field("sea_surface_temperature"), globalSst); + + // The following code block should execute on the root PE only + // Ligang: How do you do the above? Use the following if statement. + if ( globalSst.size() != 0 ) { + int lat, lon, time = 1; + std::string filename; + + // Ligang: debug, check conf +// oops::Log::info() << "In Fields::write(), conf = " << conf << std::endl; + + // get filename + if (!conf.get("filename", filename)) { + util::abor1_cpp("Fields::write(), Get filename failed.", + __FILE__, __LINE__); + } else { + oops::Log::info() << "Fields::write(), filename=" << filename + << std::endl; + } + + // create netCDF file + netCDF::NcFile file(filename.c_str(), netCDF::NcFile::replace); + if (file.isNull()) + util::abor1_cpp("Fields::write(), Create netCDF file failed.", + __FILE__, __LINE__); + + // define dims + lat = geom_->atlasFunctionSpace()->grid().ny(); + lon = ((atlas::RegularLonLatGrid) + (geom_->atlasFunctionSpace()->grid())).nx(); + + // unlimited dim if without size parameter, then it'll be 0, + // what about the size? + netCDF::NcDim timeDim = file.addDim("time", 1); + netCDF::NcDim latDim = file.addDim("lat" , lat); + netCDF::NcDim lonDim = file.addDim("lon" , lon); + if (timeDim.isNull() || latDim.isNull() || lonDim.isNull()) + util::abor1_cpp("Fields::write(), Define dims failed.", + __FILE__, __LINE__); + + std::vector dims; + dims.push_back(timeDim); + dims.push_back(latDim); + dims.push_back(lonDim); + + // Lignag: define coordinate vars "lat" and "lon" + // Ligang: define units atts for coordinate vars + + // inside UMDSSTv3/JEDI, use double, read/write use float + // to make it consistent with the netCDF files. + netCDF::NcVar sstVar = file.addVar(std::string("sst"), + netCDF::ncFloat, dims); + + // define units atts for data vars + const float fillvalue = -32768.0; + sstVar.putAtt("units", "K"); + sstVar.putAtt("_FillValue", netCDF::NcFloat(), fillvalue); + sstVar.putAtt("missing_value", netCDF::NcFloat(), fillvalue); + + // write data to the file + auto fd = make_view(globalSst); + float sstData[time][lat][lon]; + bool isKelvin = conf.getBool("kelvin", false); + int idx = 0; + for (int j = lat-1; j >= 0; j--) + for (int i = 0; i < lon; i++) { + if (fd(idx, 0) == missing_) { + sstData[0][j][i] = fillvalue; + } else { + // doulbe to float, also convert JEDI Celsius to Kelvin, in the + // future it should be able to handle both Kelvin and Celsius. + if (isKelvin) + sstData[0][j][i] = static_cast(fd(idx, 0)) + 273.15; + else + sstData[0][j][i] = static_cast(fd(idx, 0)); + } + idx++; + } + + sstVar.putVar(sstData); + + oops::Log::info() << "Fields::write(), Successfully write data to file!" + << std::endl; + } + } + +// ---------------------------------------------------------------------------- + + std::shared_ptr Fields::geometry() const { + return geom_; + } + +// ---------------------------------------------------------------------------- + + std::shared_ptr Fields::atlasFieldSet() const { + return atlasFieldSet_; + } + +// ---------------------------------------------------------------------------- + + void Fields::setAtlas(atlas::FieldSet * fs) const { + for (int v = 0; v < vars_.size(); v++) { + fs->add((*atlasFieldSet_)[v]); + } + } + +// ---------------------------------------------------------------------------- + + void Fields::toAtlas(atlas::FieldSet * fs_to) const { + const int size = geom_->atlasFunctionSpace()->size(); + + // Ligang: you will have segment fault with following delete/new code. + // if (fs_to) + // delete fs_to; + // fs_to = new atlas::FieldSet(); + + for (int i = 0; i < vars_.size(); i++) { + std::string var_name = vars_[i]; + if (!fs_to->has_field(var_name)) { + atlas::Field fld_to = geom_->atlasFunctionSpace()->createField( + atlas::option::levels(1) | + atlas::option::name(var_name)); + fs_to->add(fld_to); + } + auto fd_to = make_view(fs_to->field(var_name)); + + auto fd = make_view(atlasFieldSet_->field(var_name)); + for (int j = 0; j < size; j++) + fd_to(j, 0) = fd(j, 0); + } + } + +// ---------------------------------------------------------------------------- + + void Fields::fromAtlas(atlas::FieldSet * fs_from) { + const int size = geom_->atlasFunctionSpace()->size(); + + for (int i = 0; i < vars_.size(); i++) { + std::string var_name = vars_[i]; + + auto fd = make_view(atlasFieldSet_->field(var_name)); + auto fd_from = make_view(fs_from->field(var_name)); + for (int j = 0; j < size; j++) + fd(j, 0) = fd_from(j, 0); + } + } + +// ---------------------------------------------------------------------------- + + void Fields::print(std::ostream & os) const { + const int size = geom_->atlasFunctionSpace()->size(); + for (int v = 0; v < vars_.size(); v++) { + auto fd = make_view(atlasFieldSet_->field(v)); + double mean = 0.0, sum = 0.0, + min = std::numeric_limits::max(), + max = std::numeric_limits::min(); + int nValid = 0; + + for (int i = 0; i < size; i++) + if (fd(i, 0) != missing_) { + if (fd(i, 0) < min) min = fd(i, 0); + if (fd(i, 0) > max) max = fd(i, 0); + + sum += fd(i, 0); + nValid++; + } + + // gather results across PEs + oops::mpi::world().allReduceInPlace(nValid, eckit::mpi::Operation::SUM); + oops::mpi::world().allReduceInPlace(sum, eckit::mpi::Operation::SUM); + oops::mpi::world().allReduceInPlace(min, eckit::mpi::Operation::MIN); + oops::mpi::world().allReduceInPlace(max, eckit::mpi::Operation::MAX); + + if (nValid == 0) { + mean = 0.0; + oops::Log::debug() << "Field::print(), nValid == 0!" << std::endl; + } else { + mean = sum / (1.0*nValid); + } + + os << "min = " << min << ", max = " << max << ", mean = " << mean + << std::endl; + } + } +// ---------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/umdsst/Fields/Fields.h b/src/umdsst/Fields/Fields.h new file mode 100644 index 0000000..d0e7a21 --- /dev/null +++ b/src/umdsst/Fields/Fields.h @@ -0,0 +1,87 @@ +/* + * (C) Copyright 2020-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_FIELDS_FIELDS_H_ +#define UMDSST_FIELDS_FIELDS_H_ + +#include +#include + +#include "atlas/field.h" + +#include "oops/base/Variables.h" +#include "oops/util/DateTime.h" +#include "oops/util/Printable.h" +#include "oops/util/Serializable.h" + +// forward declarations +namespace umdsst { + class Geometry; + class State; +} + +namespace atlas { + class FieldSet; +} + +// ---------------------------------------------------------------------------- + +namespace umdsst { + + class Fields : public util::Serializable, + public util::Printable { + public: + // Constructors/destructors + Fields(const Geometry & , const oops::Variables & , + const util::DateTime &); + Fields(const Fields &); + ~Fields() {} + + // math operators + Fields & operator =(const Fields &); + Fields & operator+=(const Fields &); + void accumul(const double &, const Fields &); + double norm() const; + void zero(); + + // time manipulation + void updateTime(const util::Duration & dt) { time_ += dt; } + util::DateTime & validTime() { return time_; } + const util::DateTime & validTime() const { return time_; } + + // I/O + void read(const eckit::Configuration &); + void write(const eckit::Configuration &) const; + + // Serialization (not needed by our project) + size_t serialSize() const override { return 0; } + void serialize(std::vector &) const override {} + void deserialize(const std::vector &, size_t &) override {} + + // other accessors + std::shared_ptr atlasFieldSet() const; + std::shared_ptr geometry() const; + const oops::Variables & variables() const { return vars_; } + + // Ligang: 20210111, adjust for JEDI rep updates + void setAtlas(atlas::FieldSet *) const; + void toAtlas(atlas::FieldSet *) const; + void fromAtlas(atlas::FieldSet *); + + protected: + std::shared_ptr atlasFieldSet_; + std::shared_ptr geom_; + const double missing_; + util::DateTime time_; + oops::Variables vars_; + + private: + void print(std::ostream &) const override; + }; +} // namespace umdsst + +#endif // UMDSST_FIELDS_FIELDS_H_ diff --git a/src/oisst/Geometry/CMakeLists.txt b/src/umdsst/Geometry/CMakeLists.txt similarity index 58% rename from src/oisst/Geometry/CMakeLists.txt rename to src/umdsst/Geometry/CMakeLists.txt index a03a6cb..d144545 100644 --- a/src/oisst/Geometry/CMakeLists.txt +++ b/src/umdsst/Geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -oisst_target_sources( +umdsst_target_sources( Geometry.cc Geometry.h ) \ No newline at end of file diff --git a/src/umdsst/Geometry/Geometry.cc b/src/umdsst/Geometry/Geometry.cc new file mode 100644 index 0000000..ba5de8c --- /dev/null +++ b/src/umdsst/Geometry/Geometry.cc @@ -0,0 +1,248 @@ +/* + * (C) Copyright 2020-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include +#include +#include "netcdf" + +#include "umdsst/Geometry/Geometry.h" + +#include "eckit/container/KDTree.h" +#include "eckit/config/Configuration.h" + +#include "atlas/grid.h" +#include "atlas/array.h" +#include "atlas/field.h" +#include "atlas/option.h" +#include "atlas/functionspace.h" +#include "atlas/util/Config.h" + +#include "oops/util/abor1_cpp.h" +#include "oops/util/Logger.h" + +using atlas::array::make_view; + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + Geometry::Geometry(const eckit::Configuration & conf, + const eckit::mpi::Comm & comm) : comm_(comm) { + atlas::util::Config gridConfig(conf.getSubConfiguration("grid")); + atlas::RegularLonLatGrid atlasRllGrid(gridConfig); + + atlasFunctionSpace_.reset( + new atlas::functionspace::StructuredColumns(atlasRllGrid, + atlas::option::halo(0))); + + atlasFieldSet_.reset(new atlas::FieldSet()); + atlasFieldSet_->add(atlasFunctionSpace_->lonlat()); + + if (conf.has("landmask.filename")) { + oops::Log::debug() << "Geometry::Geometry(), before loading landmask." + << std::endl; + loadLandMask(conf); + + oops::Log::debug() << "Geometry::Geometry(), after loading landmask." + << std::endl; + } + + // add Field area + // Ligang: From Travis, Temporary approximation solution, for a global + // regular latlon grid, need to change if involved with other types of grid. + double dx = 2. * M_PI * atlas::util::DatumIFS::radius() + / atlasFunctionSpace()->grid().nxmax(); + auto lonlat_data = make_view(atlasFunctionSpace_->lonlat()); + atlas::Field area = atlasFunctionSpace_->createField( + atlas::option::levels(1) | atlas::option::name("area")); + auto area_data = make_view(area); + for (int i=0; i < atlasFunctionSpace_->size(); i++) { + area_data(i, 0) = dx*dx*cos(lonlat_data(i, 1)*M_PI/180.); + } + atlasFieldSet_->add(area); + + // add field for rossby radius + if (conf.has("rossby radius file")) { + readRossbyRadius(conf.getString("rossby radius file")); + } + } + +// ---------------------------------------------------------------------------- + + Geometry::Geometry(const Geometry & other) : comm_(other.comm_) { + atlasFunctionSpace_.reset(new + atlas::functionspace::StructuredColumns(other.atlasFunctionSpace_->grid(), + atlas::option::halo(0))); + + atlasFieldSet_.reset(new atlas::FieldSet()); +// atlasFieldSet_->add(atlasFunctionSpace_->lonlat()); + for (int i = 0; i < other.atlasFieldSet()->size(); i++) { + atlasFieldSet_->add((*other.atlasFieldSet())[i]); + } + } + +// ---------------------------------------------------------------------------- + + Geometry::~Geometry() {} + +// ---------------------------------------------------------------------------- + + void Geometry::loadLandMask(const eckit::Configuration &conf) { + // use an globalLandMask to read the data on root PE only. + atlas::Field globalLandMask = atlasFunctionSpace_->createField( + atlas::option::levels(1) | + atlas::option::name("gmask") | + atlas::option::global()); + auto fd = make_view(globalLandMask); + + // Ligang: read file only on the root PE. + if (globalLandMask.size() != 0) { + int lat = 0, lon = 0; + std::string filename; + + if (!conf.get("landmask.filename", filename)) + util::abor1_cpp("Geometry::loadLandMask(), Get filename failed.", + __FILE__, __LINE__); + else + oops::Log::info() << "In Geometry::loadLandMask(), filename = " + << filename << std::endl; + + // Open netCDF file + netCDF::NcFile file(filename.c_str(), netCDF::NcFile::read); + if (file.isNull()) + util::abor1_cpp("Geometry::loadLandMask(), Create netCDF file failed.", + __FILE__, __LINE__); + + // get file dimensions + lat = static_cast(file.getDim("lat").getSize()); + lon = static_cast(file.getDim("lon").getSize()); + + // get landmask data + netCDF::NcVar varLandMask; + varLandMask = file.getVar("landmask"); + if (varLandMask.isNull()) + util::abor1_cpp("Get var landmask failed.", __FILE__, __LINE__); + + int dataLandMask[lat][lon]; + varLandMask.getVar(dataLandMask); + + // TODO(someone) the netcdf lat dimension is likely inverted compared to + // the atlas grid. This should be explicitly checked. + int idx = 0; + for (int j = lat-1; j >= 0; j--) + for (int i = 0; i < lon; i++) + fd(idx++, 0) = dataLandMask[j][i]; + } + + atlas::Field fld = atlasFunctionSpace_->createField( + atlas::option::levels(1) | + atlas::option::name("gmask")); + atlasFieldSet_->add(fld); + + atlasFunctionSpace_->scatter(globalLandMask, + atlasFieldSet_->field("gmask")); + } + +// ---------------------------------------------------------------------------- + + void Geometry::print(std::ostream & os) const { + int nx, ny; + ny = static_cast(atlasFunctionSpace()->grid().ny()); + nx = static_cast( + ((atlas::RegularLonLatGrid&)(atlasFunctionSpace()->grid())).nx() ); + + os << "Geometry: nx = " << nx << ", ny = " << ny << std::endl; + + int nMaskedLand = 0, nUnmaskedOcean = 0, + nSize = atlasFunctionSpace_->size(); + auto fd = make_view(atlasFieldSet_->field("gmask")); + for (int j = 0; j < nSize; j++) { + if (fd(j, 0) == 1) + nUnmaskedOcean += 1; + else if (fd(j, 0) == 0) + nMaskedLand += 1; + else + util::abor1_cpp("Geometry::print(), landmask neither 1 nor 0.", + __FILE__, __LINE__); + } + os << "Geometry: # of unmasked ocean grid = " << nUnmaskedOcean + << ", # of masked land grid = " << nMaskedLand << std::endl; + } + +// ---------------------------------------------------------------------------- + + void Geometry::readRossbyRadius(const std::string & filename) { + std::ifstream infile(filename); + std::vector lonlat; + std::vector vals; + double lat, lon, x, val; + + while (infile >> lat >> lon >> x >> val) { + lonlat.push_back(eckit::geometry::Point2(lon, lat)); + vals.push_back(val*1.0e3); + } + + atlas::Field field = interpToGeom(lonlat, vals); + field.rename("rossby_radius"); + atlasFieldSet_->add(field); + } + +// ---------------------------------------------------------------------------- + + atlas::Field Geometry::interpToGeom( + const std::vector & srcLonLat, + const std::vector & srcVal) const + { + // Interpolate the values from the given lat/lons onto the grid that is + // represented by this geometry. Note that this assumes each PE is + // presenting an identical copy of srcLonLat and srcVal. + struct TreeTrait { + typedef eckit::geometry::Point3 Point; + typedef double Payload; + }; + typedef eckit::KDTreeMemory KDTree; + const int maxSearchPoints = 4; + + // Create a KD tree for fast lookup + std::vector srcPoints; + for (int i = 0; i < srcVal.size(); i++) { + KDTree::PointType xyz; + atlas::util::Earth::convertSphericalToCartesian(srcLonLat[i], xyz); + srcPoints.push_back(KDTree::Value(xyz, srcVal[i]) ); + } + KDTree kd; + kd.build(srcPoints.begin(), srcPoints.end()); + + // Interpolate (inverse distance weighted) + atlas::Field dstField = atlasFunctionSpace_->createField( + atlas::option::levels(1)); + auto dstView = make_view(dstField); + auto dstLonLat = make_view(atlasFunctionSpace_->lonlat()); + for (int i=0; i < atlasFunctionSpace_->size(); i++) { + eckit::geometry::Point2 dstPoint({dstLonLat(i, 0), dstLonLat(i, 1)}); + eckit::geometry::Point3 dstPoint3D; + atlas::util::Earth::convertSphericalToCartesian(dstPoint, dstPoint3D); + auto points = kd.kNearestNeighbours(dstPoint3D, maxSearchPoints); + double sumDist = 0.0; + double sumDistVal = 0.0; + for ( int n = 0; n < points.size(); n++ ) { + if ( points[n].distance() < 1.0e-6 ) { + sumDist = 1.0; + sumDistVal = points[n].payload(); + break; + } + double w = 1.0 / (points[n].distance()*points[n].distance()); + sumDist += w; + sumDistVal += w*points[n].payload(); + } + + dstView(i, 0) = sumDistVal / sumDist; + } + + return dstField; + } +} // namespace umdsst diff --git a/src/oisst/Geometry/Geometry.h b/src/umdsst/Geometry/Geometry.h similarity index 51% rename from src/oisst/Geometry/Geometry.h rename to src/umdsst/Geometry/Geometry.h index 36cf198..32c0f3e 100644 --- a/src/oisst/Geometry/Geometry.h +++ b/src/umdsst/Geometry/Geometry.h @@ -1,18 +1,22 @@ /* - * (C) Copyright 2019-2020 UCAR + * (C) Copyright 2020-2020 UCAR, University of Maryland * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_GEOMETRY_GEOMETRY_H_ -#define OISST_GEOMETRY_GEOMETRY_H_ +#ifndef UMDSST_GEOMETRY_GEOMETRY_H_ +#define UMDSST_GEOMETRY_GEOMETRY_H_ +#include #include #include +#include -#include "eckit/mpi/Comm.h" +#include "atlas/functionspace.h" +#include "atlas/field.h" +#include "eckit/mpi/Comm.h" #include "oops/util/ObjectCounter.h" #include "oops/util/Printable.h" @@ -20,25 +24,27 @@ namespace eckit { class Configuration; } -namespace oisst { +namespace umdsst { class GeometryIterator; } // ---------------------------------------------------------------------------- -namespace oisst { - +namespace umdsst { // Geometry class class Geometry : public util::Printable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::Geometry";} + static const std::string classname() {return "umdsst::Geometry";} // constructors and destructor explicit Geometry(const eckit::Configuration &, const eckit::mpi::Comm &); Geometry(const Geometry &); ~Geometry(); + // load landmask + void loadLandMask(const eckit::Configuration &); + // accessors const eckit::mpi::Comm & getComm() const {return comm_;} @@ -46,11 +52,26 @@ namespace oisst { // TODO(template_impl) GeometryIterator begin() const; // TODO(template_impl) GeometryIterator end() const; + atlas::functionspace::StructuredColumns* atlasFunctionSpace() const { + return atlasFunctionSpace_.get(); + } + + // Ligang: 20210111, adjust for JEDI rep updates. + atlas::FieldSet* atlasFieldSet() const { + return atlasFieldSet_.get(); + } + private: + atlas::Field interpToGeom(const std::vector &, + const std::vector &) const; + void readRossbyRadius(const std::string &); void print(std::ostream &) const; - const eckit::mpi::Comm & comm_; + + std::unique_ptr + atlasFunctionSpace_; + std::unique_ptr atlasFieldSet_; }; -} // namespace oisst +} // namespace umdsst -#endif // OISST_GEOMETRY_GEOMETRY_H_ +#endif // UMDSST_GEOMETRY_GEOMETRY_H_ diff --git a/src/umdsst/GetValues/CMakeLists.txt b/src/umdsst/GetValues/CMakeLists.txt new file mode 100644 index 0000000..97d25e1 --- /dev/null +++ b/src/umdsst/GetValues/CMakeLists.txt @@ -0,0 +1,14 @@ +umdsst_target_sources( + GetValues.cc + GetValues.h + LinearGetValues.cc + LinearGetValues.h + + # Note: these are temporary, and should be removed once + # Locations and GeoVaLs have a proper c++ interface + LocationsWrapper.h + GeoVaLsWrapper.h + GeoVaLsWrapper.f90 + GeoVaLsWrapperAD.h + GeoVaLsWrapperAD.f90 +) diff --git a/src/umdsst/GetValues/GeoVaLsWrapper.f90 b/src/umdsst/GetValues/GeoVaLsWrapper.f90 new file mode 100644 index 0000000..6cdcefa --- /dev/null +++ b/src/umdsst/GetValues/GeoVaLsWrapper.f90 @@ -0,0 +1,71 @@ +module geovals_wrapper + +use atlas_module +use iso_c_binding +use kinds +use ufo_geovals_mod_c, only: ufo_geovals_registry +use ufo_geovals_mod, only: ufo_geovals +use ufo_locations_mod +use datetime_mod, only: datetime, c_f_datetime + +implicit none + +contains + +subroutine geovals_wrapper_fill( c_key_geovals, c_locs, c_t1, c_t2, c_flds, nvar) & + bind(c, name="geovals_wrapper_fill_f90") + integer(c_int), intent(inout) :: c_key_geovals + type(c_ptr), value, intent(in) :: c_locs + type(c_ptr), intent(in) :: c_t1 + type(c_ptr), intent(in) :: c_t2 + integer(c_int), intent(in) :: nvar + type(c_ptr), dimension(*), intent(in) :: c_flds + + type(ufo_geovals), pointer :: geovals + type(ufo_locations) :: locs + type(datetime) :: t1, t2 + + type(atlas_field) :: field + real(kind_real), pointer:: field_data(:,:) + + logical(c_bool), allocatable :: time_mask(:) + + integer :: ivar, nval, i + + ! get fortran version fo the passed in C arguments + call ufo_geovals_registry%get(c_key_geovals, geovals) + locs = ufo_locations(c_locs) + call c_f_datetime(c_t1, t1) + call c_f_datetime(c_t2, t2) + + ! calculate time mask + allocate(time_mask(locs%nlocs())) + call locs%get_timemask(t1, t2, time_mask) + + ! initialize geovals + nval=1 + if (.not. geovals%linit) then + do ivar = 1, nvar + geovals%geovals(ivar)%nval = nval + allocate(geovals%geovals(ivar)%vals(nval, geovals%geovals(ivar)%nlocs)) + geovals%geovals(ivar)%vals = 0.0 + end do + geovals%linit = .true. + end if + + ! fill the geovals, obeying the time masking + do ivar = 1, nvar + ! write(*, *) "In Fortran geovals_wrapper_fill(), i_var=", ivar, ", nvar=", nvar + + field = atlas_field(c_flds(ivar)) + call field%data(field_data) + + do i=1, size(time_mask) + if (time_mask(i)) then + geovals%geovals(ivar)%vals(:,i) = field_data(:,i) + end if + end do + end do +end subroutine + +end module diff --git a/src/umdsst/GetValues/GeoVaLsWrapper.h b/src/umdsst/GetValues/GeoVaLsWrapper.h new file mode 100644 index 0000000..1172c98 --- /dev/null +++ b/src/umdsst/GetValues/GeoVaLsWrapper.h @@ -0,0 +1,55 @@ +/* + * (C) Copyright 2020-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_GETVALUES_GEOVALSWRAPPER_H_ +#define UMDSST_GETVALUES_GEOVALSWRAPPER_H_ + +#include + +#include "ufo/GeoVaLs.h" + +#include "oops/util/DateTime.h" +#include "ufo/Locations.h" + +namespace umdsst { + +extern "C" { + void geovals_wrapper_fill_f90(const int &, + const ufo::Locations &, + const util::DateTime **, + const util::DateTime **, + atlas::field::FieldImpl **, + const int & size); +} + + class GeoVaLsWrapper { + public: + explicit GeoVaLsWrapper(const ufo::GeoVaLs & geovals, + const ufo::Locations & locs) + : geovals_(&geovals), locs_(locs) {} + + void fill(const util::DateTime & t1, + const util::DateTime & t2, + const std::vector & fields) { + const util::DateTime * t1p = &t1; + const util::DateTime * t2p = &t2; + + std::vector flds; + for (int i = 0; i < fields.size(); i++) + flds.push_back((atlas::field::FieldImpl*)(fields[i].get())); + + geovals_wrapper_fill_f90(geovals_->toFortran(), locs_, + &t1p, &t2p, flds.data(), flds.size()); // flds.data() <=> ** ; + } + + private: + const ufo::GeoVaLs *geovals_; + const ufo::Locations locs_; + }; +} // namespace umdsst + +#endif // UMDSST_GETVALUES_GEOVALSWRAPPER_H_ diff --git a/src/umdsst/GetValues/GeoVaLsWrapperAD.f90 b/src/umdsst/GetValues/GeoVaLsWrapperAD.f90 new file mode 100644 index 0000000..f617f36 --- /dev/null +++ b/src/umdsst/GetValues/GeoVaLsWrapperAD.f90 @@ -0,0 +1,57 @@ +module geovals_wrapper_ad + +use atlas_module +use iso_c_binding +use kinds +use ufo_geovals_mod_c, only: ufo_geovals_registry +use ufo_geovals_mod, only: ufo_geovals +use ufo_locations_mod +use datetime_mod, only: datetime, c_f_datetime + +implicit none + +contains + +subroutine geovals_wrapper_ad_fill( c_key_geovals, c_locs, c_t1, c_t2, c_field) & + bind(c, name="geovals_wrapper_ad_fill_f90") + integer(c_int), intent(inout) :: c_key_geovals + type(c_ptr), value, intent(in) :: c_locs + type(c_ptr), intent(in) :: c_t1 + type(c_ptr), intent(in) :: c_t2 + type(c_ptr), value, intent(in) :: c_field + + type(ufo_geovals), pointer :: geovals + type(ufo_locations) :: locs + type(atlas_field) :: field + type(datetime) :: t1, t2 + real(kind_real), pointer:: field_data(:,:) + logical(c_bool), allocatable :: time_mask(:) + + integer :: ivar, nval, i + + ! get fortran version fo the passed in C arguments + call ufo_geovals_registry%get(c_key_geovals, geovals) + locs = ufo_locations(c_locs) + field = atlas_field(c_field) + call field%data(field_data) + call c_f_datetime(c_t1, t1) + call c_f_datetime(c_t2, t2) + + ! calculate time mask + allocate(time_mask(locs%nlocs())) + call locs%get_timemask(t1, t2, time_mask) + + ! initialize field_data + ivar=1 + nval=1 + field_data = 0.0 + + ! fill the field_data from geovals, obeying the time masking + do i=1, size(time_mask) + if (time_mask(i)) then + field_data(:,i) = geovals%geovals(ivar)%vals(:,i) + end if + end do +end subroutine + +end module diff --git a/src/umdsst/GetValues/GeoVaLsWrapperAD.h b/src/umdsst/GetValues/GeoVaLsWrapperAD.h new file mode 100644 index 0000000..6be5514 --- /dev/null +++ b/src/umdsst/GetValues/GeoVaLsWrapperAD.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2020-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_GETVALUES_GEOVALSWRAPPERAD_H_ +#define UMDSST_GETVALUES_GEOVALSWRAPPERAD_H_ + +#include "ufo/GeoVaLs.h" +#include "ufo/Locations.h" + +namespace umdsst { + + extern "C" { + void geovals_wrapper_ad_fill_f90(const int &, + const ufo::Locations &, + const util::DateTime **, + const util::DateTime **, + const atlas::field::FieldImpl *); + } + + class GeoVaLsWrapperAD { + public: + explicit GeoVaLsWrapperAD(const ufo::GeoVaLs & geovals, + const ufo::Locations & locs) + : geovals_(&geovals), locs_(locs) {} + + void fill(const util::DateTime & t1, + const util::DateTime & t2, + const atlas::Field & fld) { + const util::DateTime * t1p = &t1; + const util::DateTime * t2p = &t2; + geovals_wrapper_ad_fill_f90(geovals_->toFortran(), locs_, + &t1p, &t2p, fld.get()); + } + private: + const ufo::GeoVaLs *geovals_; + const ufo::Locations locs_; + }; +} // namespace umdsst + +#endif // UMDSST_GETVALUES_GEOVALSWRAPPERAD_H_ diff --git a/src/umdsst/GetValues/GetValues.cc b/src/umdsst/GetValues/GetValues.cc new file mode 100644 index 0000000..0442634 --- /dev/null +++ b/src/umdsst/GetValues/GetValues.cc @@ -0,0 +1,86 @@ +/* + * (C) Copyright 2019-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include + +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/GetValues/GetValues.h" +#include "umdsst/GetValues/GeoVaLsWrapper.h" +#include "umdsst/State/State.h" +#include "umdsst/VariableChange/Model2GeoVaLs.h" + +#include "eckit/config/Configuration.h" + +#include "oops/generic/InterpolatorUnstructured.h" +#include "oops/base/Variables.h" +#include "oops/util/abor1_cpp.h" +#include "oops/util/Logger.h" + +#include "ufo/GeoVaLs.h" +#include "ufo/Locations.h" + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + GetValues::GetValues(const Geometry & geom, + const ufo::Locations & locs, + const eckit::Configuration & config) + : geom_(new Geometry(geom)), locs_(locs), + model2geovals_(new Model2GeoVaLs(geom, config)) { + interpolator_.reset( new oops::InterpolatorUnstructured( + eckit::LocalConfiguration(), + *geom_->atlasFunctionSpace(), + locs_.atlasFunctionSpace())); + } + +// ----------------------------------------------------------------------------- + + GetValues::~GetValues() { } + +// ---------------------------------------------------------------------------- + + void GetValues::fillGeoVaLs(const State & state, + const util::DateTime & t1, + const util::DateTime & t2, + ufo::GeoVaLs & geovals) const { + oops::Variables vars = geovals.getVars(); + std::vector fields(vars.size()); + + // Do variable change if it has not already been done. + // TODO(travis): remove this once Yannick is done rearranging things in oops + std::unique_ptr varChangeState; + const State * state_ptr; + if (geovals.getVars() <= state.variables()) { + state_ptr = &state; + } else { + varChangeState.reset(new State(*geom_, geovals.getVars(), + state.validTime())); + model2geovals_->changeVar(state, *varChangeState); + state_ptr = varChangeState.get(); + } + + // interpolate + for (size_t i = 0; i < vars.size(); i++) { + fields[i] = locs_.atlasFunctionSpace()->createField( + atlas::option::levels(1)); + interpolator_->apply(state_ptr->atlasFieldSet()->field(vars[i]), + fields[i]); + } + + GeoVaLsWrapper(geovals, locs_.locs()).fill(t1, t2, fields); + } + +// ---------------------------------------------------------------------------- + + void GetValues::print(std::ostream & os) const { + os << "umdsst::GetValues" << std::endl; + } + +// ---------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/oisst/GetValues/GetValues.h b/src/umdsst/GetValues/GetValues.h similarity index 60% rename from src/oisst/GetValues/GetValues.h rename to src/umdsst/GetValues/GetValues.h index 8e22a7b..681a9fd 100644 --- a/src/oisst/GetValues/GetValues.h +++ b/src/umdsst/GetValues/GetValues.h @@ -5,14 +5,15 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_GETVALUES_GETVALUES_H_ -#define OISST_GETVALUES_GETVALUES_H_ +#ifndef UMDSST_GETVALUES_GETVALUES_H_ +#define UMDSST_GETVALUES_GETVALUES_H_ #include #include #include -#include +#include "umdsst/GetValues/LocationsWrapper.h" +#include "umdsst/GetValues/GeoVaLsWrapper.h" #include "oops/util/ObjectCounter.h" #include "oops/util/Printable.h" @@ -20,27 +21,38 @@ #include "ufo/Locations.h" // forward declarations +namespace umdsst { + class Geometry; + class State; + class Model2GeoVaLs; +} + +namespace eckit { + class Configuration; +} +namespace oops { + class InterpolatorUnstructured; +} namespace ufo { class GeoVaLs; class Locations; } -namespace oisst { - class Geometry; - class State; -} + // ---------------------------------------------------------------------------- -namespace oisst { +namespace umdsst { // GetValues class: interpolate state to observation locations class GetValues : public util::Printable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::GetValues";} + static const std::string classname() {return "umdsst::GetValues";} // constructors, destructors - GetValues(const Geometry &, const ufo::Locations & locs); + GetValues(const Geometry &, + const ufo::Locations & locs, + const eckit::Configuration & config); virtual ~GetValues(); // fills in geovals for all observations in the timeframe (t1, t2], @@ -52,9 +64,11 @@ namespace oisst { private: void print(std::ostream &) const; + std::unique_ptr model2geovals_; + std::unique_ptr interpolator_; std::shared_ptr geom_; - ufo::Locations locs_; + LocationsWrapper locs_; }; -} // namespace oisst +} // namespace umdsst -#endif // OISST_GETVALUES_GETVALUES_H_ +#endif // UMDSST_GETVALUES_GETVALUES_H_ diff --git a/src/umdsst/GetValues/LinearGetValues.cc b/src/umdsst/GetValues/LinearGetValues.cc new file mode 100644 index 0000000..2dcbc8b --- /dev/null +++ b/src/umdsst/GetValues/LinearGetValues.cc @@ -0,0 +1,119 @@ +/* + * (C) Copyright 2019-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + + +#include + +#include "umdsst/GetValues/LinearGetValues.h" +#include "umdsst/State/State.h" +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/Increment/Increment.h" +#include "umdsst/GetValues/GeoVaLsWrapper.h" +#include "umdsst/GetValues/GeoVaLsWrapperAD.h" + +#include "eckit/config/Configuration.h" + +#include "oops/generic/InterpolatorUnstructured.h" +#include "oops/base/Variables.h" +#include "oops/util/abor1_cpp.h" + +#include "ufo/GeoVaLs.h" +#include "ufo/Locations.h" + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + LinearGetValues::LinearGetValues(const Geometry & geom, + const ufo::Locations & locs, + const eckit::Configuration & config) + : geom_( new Geometry(geom)), locs_(locs) { + interpolator_.reset( new oops::InterpolatorUnstructured( + eckit::LocalConfiguration(), + *geom_->atlasFunctionSpace(), + locs_.atlasFunctionSpace()) ); + } + +// ---------------------------------------------------------------------------- + + LinearGetValues::~LinearGetValues() { } + +// ---------------------------------------------------------------------------- + + void LinearGetValues::fillGeoVaLsAD(Increment & inc, + const util::DateTime & t1, + const util::DateTime & t2, + const ufo::GeoVaLs & geovals) const { + oops::Variables vars = geovals.getVars(); + for (size_t i = 0; i < vars.size(); i++) { + // expect only sst for now + if (vars[i] != "sea_surface_temperature") + util::abor1_cpp("LinearGetValues::fillGeoVaLsAD,unkown state variable"); + + atlas::Field fgvl = locs_.atlasFunctionSpace()->createField( + atlas::option::levels(1)); + // copy from geovals to fin so it can be used in apply_ad; + GeoVaLsWrapperAD(geovals, locs_.locs()).fill(t1, t2, fgvl); + + interpolator_->apply_ad(fgvl, + inc.atlasFieldSet()->field("sea_surface_temperature")); + } + } + +// ---------------------------------------------------------------------------- + + void LinearGetValues::fillGeoVaLsTL(const Increment & inc, + const util::DateTime & t1, + const util::DateTime & t2, + ufo::GeoVaLs & geovals) const { + oops::Variables vars = geovals.getVars(); + std::vector fields(vars.size()); + for (size_t i = 0; i < vars.size(); i++) { + // expect only sst for now + if (vars[i] != "sea_surface_temperature") + util::abor1_cpp("LinearGetValues::fillGeoVaLsTL,unkown state variable"); + + fields[i] = locs_.atlasFunctionSpace()->createField( + atlas::option::levels(1)); + + interpolator_->apply( + inc.atlasFieldSet()->field("sea_surface_temperature"), fields[i]); + } + GeoVaLsWrapper(geovals, locs_.locs()).fill(t1, t2, fields); + } + +// ---------------------------------------------------------------------------- + + void LinearGetValues::setTrajectory(const State & state, + const util::DateTime & t1, + const util::DateTime & t2, + ufo::GeoVaLs & geovals) { + oops::Variables vars = geovals.getVars(); + std::vector fields(vars.size()); + for (size_t i = 0; i < vars.size(); i++) { + // expect only sst for now + if (vars[i] != "sea_surface_temperature") + util::abor1_cpp("LinearGetValues::setTrajectory,unkown state variable"); + + fields[i] = locs_.atlasFunctionSpace()->createField( + atlas::option::levels(1)); + + interpolator_->apply( + state.atlasFieldSet()->field("sea_surface_temperature"), fields[i]); + } + GeoVaLsWrapper(geovals, locs_.locs()).fill(t1, t2, fields); + } + +// ---------------------------------------------------------------------------- + + void LinearGetValues::print(std::ostream & os) const { + os << "umdsst::LinearGetValues" << std::endl; + } + +// ---------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/oisst/GetValues/LinearGetValues.h b/src/umdsst/GetValues/LinearGetValues.h similarity index 70% rename from src/oisst/GetValues/LinearGetValues.h rename to src/umdsst/GetValues/LinearGetValues.h index dde33ea..fc38a37 100644 --- a/src/oisst/GetValues/LinearGetValues.h +++ b/src/umdsst/GetValues/LinearGetValues.h @@ -5,14 +5,15 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_GETVALUES_LINEARGETVALUES_H_ -#define OISST_GETVALUES_LINEARGETVALUES_H_ +#ifndef UMDSST_GETVALUES_LINEARGETVALUES_H_ +#define UMDSST_GETVALUES_LINEARGETVALUES_H_ #include #include #include -#include +#include "umdsst/GetValues/LocationsWrapper.h" +// #include "umdsst/GetValues/GeoVaLsWrapper.h" #include "oops/util/ObjectCounter.h" #include "oops/util/Printable.h" @@ -20,12 +21,17 @@ #include "ufo/Locations.h" // forward declarations - +namespace eckit { + class Configuration; +} +namespace oops { + class InterpolatorUnstructured; +} namespace ufo { class GeoVaLs; class Locations; } -namespace oisst { +namespace umdsst { class Geometry; class Increment; class State; @@ -33,16 +39,17 @@ namespace oisst { // ---------------------------------------------------------------------------- -namespace oisst { +namespace umdsst { // GetValues class: interpolate state to observation locations class LinearGetValues : public util::Printable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::LinearGetValues";} + static const std::string classname() {return "umdsst::LinearGetValues";} // constructors, destructors - LinearGetValues(const Geometry &, const ufo::Locations &); + LinearGetValues(const Geometry &, const ufo::Locations &, + const eckit::Configuration &); virtual ~LinearGetValues(); // Forward and backward interpolation @@ -64,9 +71,10 @@ namespace oisst { private: void print(std::ostream &) const; + std::unique_ptr interpolator_; std::shared_ptr geom_; - ufo::Locations locs_; + LocationsWrapper locs_; }; -} // namespace oisst +} // namespace umdsst -#endif // OISST_GETVALUES_LINEARGETVALUES_H_ +#endif // UMDSST_GETVALUES_LINEARGETVALUES_H_ diff --git a/src/umdsst/GetValues/LocationsWrapper.h b/src/umdsst/GetValues/LocationsWrapper.h new file mode 100644 index 0000000..95c2e44 --- /dev/null +++ b/src/umdsst/GetValues/LocationsWrapper.h @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2020-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_GETVALUES_LOCATIONSWRAPPER_H_ +#define UMDSST_GETVALUES_LOCATIONSWRAPPER_H_ + +#include +#include + +#include "atlas/array.h" +#include "atlas/functionspace.h" + +#include "ufo/Locations.h" + +namespace umdsst { + + class LocationsWrapper { + public: + explicit LocationsWrapper(const ufo::Locations & locs) : locs_(locs) { + atlas::Field field("lonlat", + atlas::array::make_datatype(), + atlas::array::make_shape(locs.size(), 2) ); + auto fd = atlas::array::make_view(field); + for (int j = 0; j < locs.size(); j++) { + fd(j, 0) = locs.lons()[j]; + fd(j, 1) = locs.lats()[j]; + } + functionSpace_.reset(new atlas::functionspace::PointCloud(field)); + } + + const atlas::FunctionSpace & atlasFunctionSpace() const { + return *functionSpace_; + } + + const ufo::Locations & locs() const { return locs_; } + + private: + const ufo::Locations locs_; + std::unique_ptr functionSpace_; + }; +} // namespace umdsst + +#endif // UMDSST_GETVALUES_LOCATIONSWRAPPER_H_ diff --git a/src/oisst/Increment/CMakeLists.txt b/src/umdsst/Increment/CMakeLists.txt similarity index 59% rename from src/oisst/Increment/CMakeLists.txt rename to src/umdsst/Increment/CMakeLists.txt index b882fe2..bd03a1e 100644 --- a/src/oisst/Increment/CMakeLists.txt +++ b/src/umdsst/Increment/CMakeLists.txt @@ -1,4 +1,4 @@ -oisst_target_sources( +umdsst_target_sources( Increment.cc Increment.h ) \ No newline at end of file diff --git a/src/umdsst/Increment/Increment.cc b/src/umdsst/Increment/Increment.cc new file mode 100644 index 0000000..e8a417f --- /dev/null +++ b/src/umdsst/Increment/Increment.cc @@ -0,0 +1,261 @@ +/* + * (C) Copyright 2019-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include + +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/Increment/Increment.h" +#include "umdsst/State/State.h" + +#include "eckit/config/Configuration.h" + +#include "atlas/field.h" +#include "atlas/array.h" + +#include "oops/base/Variables.h" +#include "oops/mpi/mpi.h" +#include "oops/util/abor1_cpp.h" +#include "oops/util/Logger.h" +#include "oops/util/Random.h" + +using atlas::array::make_view; + + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + Increment::Increment(const Geometry & geom, + const oops::Variables & vars, + const util::DateTime & vt) + : Fields(geom, vars, vt) {} + +// ---------------------------------------------------------------------------- + + Increment::Increment(const Geometry & geom, const Increment & other) + : Fields(other) { + // it will normally be used for interpolation and change resolution. + // For now, just copy without interpolation. + } + +// ---------------------------------------------------------------------------- + + Increment::Increment(const Increment & other, const bool copy) + : Fields(*other.geom_, other.vars_, other.time_) { + if (copy) + *this = other; + } + +// ---------------------------------------------------------------------------- + + Increment::Increment(const Increment & other) + : Fields(other) {} + +// ---------------------------------------------------------------------------- + + Increment::~Increment() { } + +// ---------------------------------------------------------------------------- + + Increment & Increment::operator =(const Increment &other) { + // Ligang: Do we assume the geom_ and vars_ are the same, (so they are not + // empty)? For now yes, as all of the constructors allocate atlasFieldSet. + // so just assign the values of FieldSet. same for other math operators. + Fields::operator=(other); + return *this; + } + +// ---------------------------------------------------------------------------- + + Increment & Increment::operator -=(const Increment &other) { + const int size = geom_->atlasFunctionSpace()->size(); + + for (int i = 0; i < vars_.size(); i++) { + auto fd = make_view(atlasFieldSet_->field(0)); + auto fd_other = make_view(other.atlasFieldSet()->field(0)); + for (int j = 0; j < size; j++) + fd(j, 0) -= fd_other(j, 0); + } + + return *this; + } + +// ---------------------------------------------------------------------------- + + Increment & Increment::operator +=(const Increment &other) { + Fields::operator+=(other); + return *this; + } + +// ---------------------------------------------------------------------------- + + Increment & Increment::operator *=(const double &zz) { + auto fd = make_view(atlasFieldSet_->field(0)); + const int size = geom_->atlasFunctionSpace()->size(); + + for (int j = 0; j < size; j++) + fd(j, 0) *= zz; + + return *this; + } + +// ---------------------------------------------------------------------------- + + void Increment::axpy(const double &zz, const Increment &dx, const bool check) + { + ASSERT(!check || time_ == dx.validTime()); + // use accumul, because conceptually it is the same as axpy + // (axpy is for Increment, accumul is for State) + accumul(zz, dx); + } + +// ---------------------------------------------------------------------------- + + void Increment::diff(const State & x1, const State & x2) { + auto fd = make_view(atlasFieldSet_->field(0)); + auto fd_x1 = make_view(x1.atlasFieldSet()->field(0)); + auto fd_x2 = make_view(x2.atlasFieldSet()->field(0)); + + const int size = geom_->atlasFunctionSpace()->size(); + + for (int i = 0; i < size; i++) + fd(i, 0) = fd_x1(i, 0) - fd_x2(i, 0); + } + +// ---------------------------------------------------------------------------- + + double Increment::dot_product_with(const Increment &other) const { + auto fd = make_view(atlasFieldSet_->field(0)); + auto fd_other = make_view(other.atlasFieldSet()->field(0)); + + const int size = geom_->atlasFunctionSpace()->size(); + double dp = 0.0; + + // Ligang: will be updated with missing_value process! + for (int i = 0; i < size; i++) + dp += fd(i, 0)*fd_other(i, 0); + + // sum results across PEs + oops::mpi::world().allReduceInPlace(dp, eckit::mpi::Operation::SUM); + + return dp; + } + +// ---------------------------------------------------------------------------- + + void Increment::ones() { + auto fd = make_view(atlasFieldSet_->field(0)); + fd.assign(1.0); + } + +// ---------------------------------------------------------------------------- + + void Increment::random() { + auto fd = make_view(atlasFieldSet_->field(0)); + const int size = geom_->atlasFunctionSpace()->size(); + + util::NormalDistribution x(size, 0, 1.0, 1); + + for (int i = 0; i < size; i++) + fd(i, 0) = x[i]; + } + +// ---------------------------------------------------------------------------- + + void Increment::schur_product_with(const Increment &rhs ) { + auto fd = make_view(atlasFieldSet_->field(0)); + auto fd_rhs = make_view(rhs.atlasFieldSet()->field(0)); + + const int size = geom_->atlasFunctionSpace()->size(); + for (int i = 0; i < size; i++) + fd(i, 0) *= fd_rhs(i, 0); + } + +// ---------------------------------------------------------------------------- + + void Increment::schur_product_with_inv(const Increment &rhs ) { + auto fd = make_view(atlasFieldSet_->field(0)); + auto fd_rhs = make_view(rhs.atlasFieldSet()->field(0)); + + const int size = geom_->atlasFunctionSpace()->size(); + for (int i = 0; i < size; i++) + fd(i, 0) *= 1.0 / fd_rhs(i, 0); + } +// ---------------------------------------------------------------------------- + + void Increment::zero() { + // Need this wrapper because the overridden zero(time) would otherwise + // interfere + Fields::zero(); + } + +// ---------------------------------------------------------------------------- + + void Increment::zero(const util::DateTime & time) { + zero(); + time_ = time; + } + +// ---------------------------------------------------------------------------- + + void Increment::dirac(const eckit::Configuration & conf) { + // Ligang: Do NOT know what it is, may ask Jim. Idea of coding from JEDI. + std::vector ixdir(conf.getIntVector("ixdir")); + std::vector iydir(conf.getIntVector("iydir")); + + // check + ASSERT(ixdir.size() > 0 && ixdir.size() == iydir.size()); + const int dir_size = ixdir.size(); + + // Ligang: This is where we need the field_data to be 2D; + // How do we make it 2D? should be related to when create the field. + const int ny = static_cast(geom_->atlasFunctionSpace()->grid().ny()); + const int nx = static_cast( + ((atlas::RegularLonLatGrid&)(geom_->atlasFunctionSpace()->grid())).nx() ); + for (int i = 0; i < dir_size; i++) + ASSERT(ixdir[i] < nx && iydir[i] < ny); + + atlas::Field gi = geom_->atlasFunctionSpace()->global_index(); + atlas::Field ri = geom_->atlasFunctionSpace()->remote_index(); + auto fd_gi = make_view(gi); + auto fd_ri = make_view(ri); + + const int sz = geom_->atlasFunctionSpace()->size(); + + auto fd = make_view(atlasFieldSet_->field(0)); + for (int i = 0; i < dir_size; i++) { + // Ligang: 2D to 1D global_index, the 1D global_index starts from 1, which + // is normally oriented to user; while 1D remote_index and the 2D + // specification start from 0 and (0,0) (as in ncview), which is kind + // oriented to C++ programming. The relationship below is only for our + // simple case (grid), need to dig deep in how atlas store globa_indices. + int g_idx = iydir[i]*nx + ixdir[i] + 1; + + // Use if below to avoid unnecessary search. + if (fd_gi(0) <= g_idx && g_idx <= fd_gi(sz-1)) { + // Find the corresponding remote_index to the global g_idx on this CPU. + // If we know for sure the array fd_gi() is increasing, we can use more + // efficient algorithm for search. + int j_loc = 0; + for (j_loc = 0; j_loc < sz; j_loc++) { + if (fd_gi(j_loc) == g_idx) + break; + } + if (j_loc >= sz) { + util::abor1_cpp("Increment::dirac(), failed to find global idx.", + __FILE__, __LINE__); + } else { + // The arrays of globa/remote index should be matching. + int r_idx = fd_ri(j_loc); + fd(r_idx, 0) = 1.0; + } + } + } + } + +// ---------------------------------------------------------------------------- +} // namespace umdsst diff --git a/src/umdsst/Increment/Increment.h b/src/umdsst/Increment/Increment.h new file mode 100644 index 0000000..2a46d2c --- /dev/null +++ b/src/umdsst/Increment/Increment.h @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2020-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_INCREMENT_INCREMENT_H_ +#define UMDSST_INCREMENT_INCREMENT_H_ + +#include + +#include "umdsst/Fields/Fields.h" + +// forward declarations +namespace oops { + class Variables; +} +namespace ufo { + class GeoVaLs; + class Locations; +} +namespace umdsst { + class Geometry; + class State; +} + +// ---------------------------------------------------------------------------- + +namespace umdsst { + + // Increment class + class Increment : private util::ObjectCounter, + public umdsst::Fields { + public: + static const std::string classname() {return "umdsst::Increment";} + + // Constructor, destructor + Increment(const Geometry &, const oops::Variables &, + const util::DateTime &); + Increment(const Geometry &, const Increment &); + Increment(const Increment &, const bool); + Increment(const Increment &); + ~Increment(); + + // wrappers of methods that are fully implemented in Fields + Increment & operator+=(const Increment &); + + // Math operators + Increment & operator =(const Increment &); + Increment & operator-=(const Increment &); + Increment & operator*=(const double &); + void axpy(const double &, const Increment &, const bool check = true); + void diff(const State &, const State &); + double dot_product_with(const Increment &) const; + void ones(); + void random(); + void schur_product_with(const Increment &); + void schur_product_with_inv(const Increment &); + void zero(); + void zero(const util::DateTime &); + + // dirac + void dirac(const eckit::Configuration &); + }; +} // namespace umdsst + +#endif // UMDSST_INCREMENT_INCREMENT_H_ diff --git a/src/umdsst/LinearVariableChange/CMakeLists.txt b/src/umdsst/LinearVariableChange/CMakeLists.txt new file mode 100644 index 0000000..7d260c9 --- /dev/null +++ b/src/umdsst/LinearVariableChange/CMakeLists.txt @@ -0,0 +1,4 @@ +umdsst_target_sources( + StdDev.cc + StdDev.h +) \ No newline at end of file diff --git a/src/umdsst/LinearVariableChange/StdDev.cc b/src/umdsst/LinearVariableChange/StdDev.cc new file mode 100644 index 0000000..4b7291c --- /dev/null +++ b/src/umdsst/LinearVariableChange/StdDev.cc @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2021-2021 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include "umdsst/LinearVariableChange/StdDev.h" +#include "umdsst/State/State.h" +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/Traits.h" +#include "umdsst/Increment/Increment.h" + +#include "oops/interface/LinearVariableChange.h" +#include "oops/util/abor1_cpp.h" + +namespace umdsst { + +// ---------------------------------------------------------------------------- + +StdDev::StdDev(const State &bkg, const State &traj, const Geometry &geom, + const eckit::Configuration &conf) { + stddev_.reset(new Increment(geom, bkg.variables(), bkg.validTime())); + stddev_->ones(); + + if ( conf.has("fixed") ) { + // a single global fixed value + double val; + conf.get("fixed", val); + *stddev_ *= val; + } else { + util::abor1_cpp("StdDev::StdDev() no standard deviation " + "method specified", __FILE__, __LINE__); + } + + // TODO(someone) place the real horizontally varying background error + // standard deviation in stddev_ +} + +// ---------------------------------------------------------------------------- + +void StdDev::multiply(const Increment &dxin, Increment &dxout) const { + dxout = dxin; + dxout.schur_product_with(*stddev_); +} + +// ---------------------------------------------------------------------------- + +void StdDev::multiplyAD(const Increment &dxin, Increment &dxout) const { + multiply(dxin, dxout); +} + +// ---------------------------------------------------------------------------- + +void StdDev::multiplyInverse(const Increment &dxin, Increment &dxout) const { + dxout = dxin; + dxout.schur_product_with_inv(*stddev_); +} + +// ---------------------------------------------------------------------------- + +void StdDev::multiplyInverseAD(const Increment &dxin, Increment &dxout) const { + multiplyInverse(dxin, dxout); +} + +// ---------------------------------------------------------------------------- + +oops::LinearVariableChangeMaker > + makerLinearVariableChangeStdDev_("umdsstStdDev"); + +// ---------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/umdsst/LinearVariableChange/StdDev.h b/src/umdsst/LinearVariableChange/StdDev.h new file mode 100644 index 0000000..39b4979 --- /dev/null +++ b/src/umdsst/LinearVariableChange/StdDev.h @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2021-2021 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_LINEARVARIABLECHANGE_STDDEV_H_ +#define UMDSST_LINEARVARIABLECHANGE_STDDEV_H_ + +#include +#include + +#include "oops/util/Printable.h" + +// Forward Declaration +namespace eckit { + class Configuration; +} +namespace umdsst { + class Geometry; + class Increment; + class State; +} + +namespace umdsst { + +class StdDev: public util::Printable { + public: + static const std::string classname() {return "umdsst:StdDev";} + + explicit StdDev(const State &, const State &, const Geometry &, + const eckit::Configuration &); + + void multiply(const Increment &, Increment &) const; + void multiplyInverse(const Increment &, Increment &) const; + void multiplyAD(const Increment &, Increment &) const; + void multiplyInverseAD(const Increment &, Increment &) const; + + private: + void print(std::ostream &) const override {} + std::unique_ptr stddev_; +}; + +} // namespace umdsst + +#endif // UMDSST_LINEARVARIABLECHANGE_STDDEV_H_ diff --git a/src/oisst/ModelAux/CMakeLists.txt b/src/umdsst/ModelAux/CMakeLists.txt similarity index 86% rename from src/oisst/ModelAux/CMakeLists.txt rename to src/umdsst/ModelAux/CMakeLists.txt index 2b4fa08..6428f21 100644 --- a/src/oisst/ModelAux/CMakeLists.txt +++ b/src/umdsst/ModelAux/CMakeLists.txt @@ -1,4 +1,4 @@ -oisst_target_sources( +umdsst_target_sources( ModelAuxControl.cc ModelAuxControl.h ModelAuxCovariance.cc diff --git a/src/oisst/ModelAux/ModelAuxControl.cc b/src/umdsst/ModelAux/ModelAuxControl.cc similarity index 87% rename from src/oisst/ModelAux/ModelAuxControl.cc rename to src/umdsst/ModelAux/ModelAuxControl.cc index c9bf72a..fd773d8 100644 --- a/src/oisst/ModelAux/ModelAuxControl.cc +++ b/src/umdsst/ModelAux/ModelAuxControl.cc @@ -5,12 +5,12 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/ModelAux/ModelAuxControl.h" -#include "oisst/ModelAux/ModelAuxIncrement.h" +#include "umdsst/ModelAux/ModelAuxControl.h" +#include "umdsst/ModelAux/ModelAuxIncrement.h" #include "oops/util/abor1_cpp.h" -namespace oisst { +namespace umdsst { // ---------------------------------------------------------------------------- @@ -42,10 +42,10 @@ namespace oisst { // ---------------------------------------------------------------------------- void ModelAuxControl::print(std::ostream & os) const { - os << "oisst::ModelAuxControl not implemented" + os << "umdsst::ModelAuxControl not implemented" << std::endl; } // ---------------------------------------------------------------------------- -} // namespace oisst +} // namespace umdsst diff --git a/src/oisst/ModelAux/ModelAuxControl.h b/src/umdsst/ModelAux/ModelAuxControl.h similarity index 71% rename from src/oisst/ModelAux/ModelAuxControl.h rename to src/umdsst/ModelAux/ModelAuxControl.h index 2a1b753..a4319b0 100644 --- a/src/oisst/ModelAux/ModelAuxControl.h +++ b/src/umdsst/ModelAux/ModelAuxControl.h @@ -5,8 +5,8 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_MODELAUX_MODELAUXCONTROL_H_ -#define OISST_MODELAUX_MODELAUXCONTROL_H_ +#ifndef UMDSST_MODELAUX_MODELAUXCONTROL_H_ +#define UMDSST_MODELAUX_MODELAUXCONTROL_H_ #include #include @@ -18,20 +18,20 @@ namespace eckit { class Configuration; } -namespace oisst { +namespace umdsst { class Geometry; class ModelAuxIncrement; } //----------------------------------------------------------------------------- -namespace oisst { +namespace umdsst { // ModelAuxControl class class ModelAuxControl : public util::Printable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::ModelAuxControl";} + static const std::string classname() {return "umdsst::ModelAuxControl";} // constructors / destructor ModelAuxControl(const Geometry &, const eckit::Configuration &); @@ -39,11 +39,16 @@ namespace oisst { ModelAuxControl(const ModelAuxControl &, const bool); ~ModelAuxControl(); + // I/O + void read(const eckit::Configuration &) {} + void write(const eckit::Configuration &) const {} + // math operators ModelAuxControl & operator +=(const ModelAuxIncrement &); + double norm() const {return 0.0;} private: void print(std::ostream & os) const; }; -} // namespace oisst -#endif // OISST_MODELAUX_MODELAUXCONTROL_H_ +} // namespace umdsst +#endif // UMDSST_MODELAUX_MODELAUXCONTROL_H_ diff --git a/src/oisst/ModelAux/ModelAuxCovariance.cc b/src/umdsst/ModelAux/ModelAuxCovariance.cc similarity index 90% rename from src/oisst/ModelAux/ModelAuxCovariance.cc rename to src/umdsst/ModelAux/ModelAuxCovariance.cc index 467ed36..e2ce412 100644 --- a/src/oisst/ModelAux/ModelAuxCovariance.cc +++ b/src/umdsst/ModelAux/ModelAuxCovariance.cc @@ -5,14 +5,14 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Geometry/Geometry.h" -#include "oisst/ModelAux/ModelAuxCovariance.h" +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/ModelAux/ModelAuxCovariance.h" #include "eckit/config/Configuration.h" #include "oops/util/abor1_cpp.h" -namespace oisst { +namespace umdsst { // ---------------------------------------------------------------------------- @@ -52,10 +52,10 @@ namespace oisst { // ---------------------------------------------------------------------------- void ModelAuxCovariance::print(std::ostream & os) const { - os << "oisst::ModelAuxCovariance not implemented" + os << "umdsst::ModelAuxCovariance not implemented" << std::endl; } // ---------------------------------------------------------------------------- -} // namespace oisst +} // namespace umdsst diff --git a/src/oisst/ModelAux/ModelAuxCovariance.h b/src/umdsst/ModelAux/ModelAuxCovariance.h similarity index 82% rename from src/oisst/ModelAux/ModelAuxCovariance.h rename to src/umdsst/ModelAux/ModelAuxCovariance.h index 876c0d0..9c5f0a0 100644 --- a/src/oisst/ModelAux/ModelAuxCovariance.h +++ b/src/umdsst/ModelAux/ModelAuxCovariance.h @@ -5,8 +5,8 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_MODELAUX_MODELAUXCOVARIANCE_H_ -#define OISST_MODELAUX_MODELAUXCOVARIANCE_H_ +#ifndef UMDSST_MODELAUX_MODELAUXCOVARIANCE_H_ +#define UMDSST_MODELAUX_MODELAUXCOVARIANCE_H_ #include #include @@ -17,7 +17,7 @@ #include "oops/util/Printable.h" // forward declarations -namespace oisst { +namespace umdsst { class Geometry; class ModelAuxControl; class ModelAuxIncrement; @@ -25,12 +25,12 @@ namespace oisst { // ----------------------------------------------------------------------------- -namespace oisst { +namespace umdsst { class ModelAuxCovariance : public util::Printable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::ModelBiasCovariance";} + static const std::string classname() {return "umdsst::ModelBiasCovariance";} // Constructor, destructor ModelAuxCovariance(const eckit::Configuration &, const Geometry &); @@ -53,7 +53,7 @@ class ModelAuxCovariance : public util::Printable, // ----------------------------------------------------------------------------- -} // namespace oisst +} // namespace umdsst -#endif // OISST_MODELAUX_MODELAUXCOVARIANCE_H_ +#endif // UMDSST_MODELAUX_MODELAUXCOVARIANCE_H_ diff --git a/src/oisst/ModelAux/ModelAuxIncrement.cc b/src/umdsst/ModelAux/ModelAuxIncrement.cc similarity index 93% rename from src/oisst/ModelAux/ModelAuxIncrement.cc rename to src/umdsst/ModelAux/ModelAuxIncrement.cc index 428e089..a295afc 100644 --- a/src/oisst/ModelAux/ModelAuxIncrement.cc +++ b/src/umdsst/ModelAux/ModelAuxIncrement.cc @@ -5,12 +5,12 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/ModelAux/ModelAuxIncrement.h" -#include "oisst/ModelAux/ModelAuxControl.h" +#include "umdsst/ModelAux/ModelAuxIncrement.h" +#include "umdsst/ModelAux/ModelAuxControl.h" #include "oops/util/abor1_cpp.h" -namespace oisst { +namespace umdsst { // ---------------------------------------------------------------------------- @@ -81,10 +81,10 @@ namespace oisst { // ---------------------------------------------------------------------------- void ModelAuxIncrement::print(std::ostream & os) const { - os << "oisst::ModelAuxIncrement not implemented" + os << "umdsst::ModelAuxIncrement not implemented" << std::endl; } // ---------------------------------------------------------------------------- -} // namespace oisst +} // namespace umdsst diff --git a/src/oisst/ModelAux/ModelAuxIncrement.h b/src/umdsst/ModelAux/ModelAuxIncrement.h similarity index 64% rename from src/oisst/ModelAux/ModelAuxIncrement.h rename to src/umdsst/ModelAux/ModelAuxIncrement.h index 2072d6b..d17f378 100644 --- a/src/oisst/ModelAux/ModelAuxIncrement.h +++ b/src/umdsst/ModelAux/ModelAuxIncrement.h @@ -5,33 +5,36 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#ifndef OISST_MODELAUX_MODELAUXINCREMENT_H_ -#define OISST_MODELAUX_MODELAUXINCREMENT_H_ +#ifndef UMDSST_MODELAUX_MODELAUXINCREMENT_H_ +#define UMDSST_MODELAUX_MODELAUXINCREMENT_H_ #include #include +#include #include "oops/util/ObjectCounter.h" #include "oops/util/Printable.h" +#include "oops/util/Serializable.h" // forward declarations namespace eckit { class Configuration; } -namespace oisst { +namespace umdsst { class Geometry; class ModelAuxControl; } //----------------------------------------------------------------------------- -namespace oisst { +namespace umdsst { // ModelAuxControl class class ModelAuxIncrement : public util::Printable, + public util::Serializable, private util::ObjectCounter { public: - static const std::string classname() {return "oisst::ModelAuxIncrement";} + static const std::string classname() {return "umdsst::ModelAuxIncrement";} // constructors / destructor ModelAuxIncrement(const ModelAuxIncrement &, const eckit::Configuration &); @@ -49,8 +52,17 @@ namespace oisst { double norm() const; void zero(); + // I/O + void read(const eckit::Configuration &) {} + void write(const eckit::Configuration &) const {} + + // serialize and deserialize + size_t serialSize() const override {return 0;} + void serialize(std::vector &) const override {} + void deserialize(const std::vector &, size_t &) override {} + private: - void print(std::ostream &) const; + void print(std::ostream &) const override; }; -} // namespace oisst -#endif // OISST_MODELAUX_MODELAUXINCREMENT_H_ +} // namespace umdsst +#endif // UMDSST_MODELAUX_MODELAUXINCREMENT_H_ diff --git a/src/oisst/State/CMakeLists.txt b/src/umdsst/State/CMakeLists.txt similarity index 53% rename from src/oisst/State/CMakeLists.txt rename to src/umdsst/State/CMakeLists.txt index ab87f82..7a4d88d 100644 --- a/src/oisst/State/CMakeLists.txt +++ b/src/umdsst/State/CMakeLists.txt @@ -1,4 +1,4 @@ -oisst_target_sources( +umdsst_target_sources( State.cc State.h ) \ No newline at end of file diff --git a/src/umdsst/State/State.cc b/src/umdsst/State/State.cc new file mode 100644 index 0000000..cdb77dc --- /dev/null +++ b/src/umdsst/State/State.cc @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2019-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/Increment/Increment.h" +#include "umdsst/State/State.h" + +#include "eckit/config/Configuration.h" + +#include "oops/base/Variables.h" +#include "oops/util/abor1_cpp.h" +#include "oops/util/Logger.h" + +namespace umdsst { + +// ---------------------------------------------------------------------------- + + State::State(const Geometry & geom, const eckit::Configuration & conf) + : Fields(geom, oops::Variables(conf, "state variables"), + util::DateTime(conf.getString("date"))) { + // check and read in data if it has filename + if (conf.has("filename")) + read(conf); + } + +// ---------------------------------------------------------------------------- + + State::State(const Geometry & geom, const oops::Variables & vars, + const util::DateTime & time) + : Fields(geom, vars, time) {} + +// ---------------------------------------------------------------------------- + + State::State(const Geometry & geom, const State & other) + : State(other) { + // Change state resolution, normally used for interpolation. + // For now, just copy without interpolation + } + +// ---------------------------------------------------------------------------- + + State::State(const State & other) + : Fields(other) {} + +// ---------------------------------------------------------------------------- + + State::~State() {} + +// ---------------------------------------------------------------------------- + + State & State::operator+=(const Increment & dx) { + Fields::operator+=(dx); + return *this; + } + +// ---------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/umdsst/State/State.h b/src/umdsst/State/State.h new file mode 100644 index 0000000..55c5f5b --- /dev/null +++ b/src/umdsst/State/State.h @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2019-2020 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_STATE_STATE_H_ +#define UMDSST_STATE_STATE_H_ + +#include + +#include "umdsst/Fields/Fields.h" + +#include "oops/base/Variables.h" +#include "oops/util/DateTime.h" +#include "oops/util/ObjectCounter.h" + +// forward declarations +namespace umdsst { + class Geometry; + class Increment; +} + +namespace eckit { + class Configuration; +} +namespace ufo { + class GeoVaLs; + class Locations; +} + +// ---------------------------------------------------------------------------- + +namespace umdsst { + + // State class + class State : private util::ObjectCounter, + public umdsst::Fields { + public: + static const std::string classname() {return "umdsst::State";} + + // constructors, destructors + State(const Geometry &, const eckit::Configuration &); + State(const Geometry &, const oops::Variables &, + const util::DateTime &); + State(const Geometry &, const State &); + State(const State &); + ~State(); + + // wrappers of methods that are fully implemented in Fields + State & operator+=(const Increment &); + }; +} // namespace umdsst + +#endif // UMDSST_STATE_STATE_H_ diff --git a/src/umdsst/Traits.h b/src/umdsst/Traits.h new file mode 100644 index 0000000..a73556c --- /dev/null +++ b/src/umdsst/Traits.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2019-2020 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_TRAITS_H_ +#define UMDSST_TRAITS_H_ + +#include + +#include "umdsst/Covariance/Covariance.h" +#include "umdsst/Geometry/Geometry.h" +#include "umdsst/GetValues/GetValues.h" +#include "umdsst/GetValues/LinearGetValues.h" +#include "umdsst/Increment/Increment.h" +#include "umdsst/ModelAux/ModelAuxControl.h" +#include "umdsst/ModelAux/ModelAuxCovariance.h" +#include "umdsst/ModelAux/ModelAuxIncrement.h" +#include "umdsst/State/State.h" + +namespace umdsst { + + struct Traits{ + static std::string name() {return "umdsst";} + static std::string nameCovar() {return "umdsstCovar";} + static std::string nameCovar4D() {return "umdsstCovar";} + + // Interfaces that umdsst has to implement + // --------------------------------------------------- + typedef umdsst::Covariance Covariance; + typedef umdsst::Geometry Geometry; + typedef umdsst::GetValues GetValues; + typedef umdsst::Increment Increment; + typedef umdsst::LinearGetValues LinearGetValues; + typedef umdsst::ModelAuxControl ModelAuxControl; + typedef umdsst::ModelAuxCovariance ModelAuxCovariance; + typedef umdsst::ModelAuxIncrement ModelAuxIncrement; + typedef umdsst::State State; + }; +} // namespace umdsst + +#endif // UMDSST_TRAITS_H_ diff --git a/src/umdsst/VariableChange/CMakeLists.txt b/src/umdsst/VariableChange/CMakeLists.txt new file mode 100644 index 0000000..16c434e --- /dev/null +++ b/src/umdsst/VariableChange/CMakeLists.txt @@ -0,0 +1,4 @@ +umdsst_target_sources( + Model2GeoVaLs.cc + Model2GeoVaLs.h +) \ No newline at end of file diff --git a/src/umdsst/VariableChange/Model2GeoVaLs.cc b/src/umdsst/VariableChange/Model2GeoVaLs.cc new file mode 100644 index 0000000..d193063 --- /dev/null +++ b/src/umdsst/VariableChange/Model2GeoVaLs.cc @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2021-2021 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#include "umdsst/VariableChange/Model2GeoVaLs.h" + +#include "atlas/array.h" +#include "atlas/field.h" + +#include "oops/util/abor1_cpp.h" + +namespace umdsst { + +// ----------------------------------------------------------------------------- + +static oops::VariableChangeMaker + makerVariableChangeModel2GeoVaLs_("Model2GeoVaLs"); + +static oops::VariableChangeMaker< Traits, Model2GeoVaLs> + makerVariableChangeDefault_("default"); + +// ----------------------------------------------------------------------------- + +Model2GeoVaLs::Model2GeoVaLs(const Geometry & geom, + const eckit::Configuration & conf) + : geom_(new Geometry(geom)) { +} + +// ----------------------------------------------------------------------------- + +void Model2GeoVaLs::changeVar(const State & xin, State & xout) const { + const int size = geom_->atlasFunctionSpace()->size(); + + for ( int i = 0; i < xout.variables().size(); i++ ) { + std::string name = xout.variables()[i]; + + if ( xin.variables().has(name) ) { + // variable is simply being copied from xin to xout + xout.atlasFieldSet()->field(name) = xin.atlasFieldSet()->field(name); + + } else if (name == "sea_area_fraction") { + // convert integer land mask to a floating point field + auto fd = atlas::array::make_view( + xout.atlasFieldSet()->field(name)); + auto fd_src = atlas::array::make_view( + geom_->atlasFieldSet()->field("gmask")); + for (int j=0; j < size; j++) + fd(j, 0) = static_cast(fd_src(j, 0)); + } + } +} + +// ----------------------------------------------------------------------------- + +void Model2GeoVaLs::changeVarInverse(const State &, State &) const { + util::abor1_cpp("Model2GeoVaLs::changeVarInverse not implemented"); +} + +// ----------------------------------------------------------------------------- + +} // namespace umdsst diff --git a/src/umdsst/VariableChange/Model2GeoVaLs.h b/src/umdsst/VariableChange/Model2GeoVaLs.h new file mode 100644 index 0000000..015430b --- /dev/null +++ b/src/umdsst/VariableChange/Model2GeoVaLs.h @@ -0,0 +1,37 @@ +/* + * (C) Copyright 2021-2021 UCAR, University of Maryland + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UMDSST_VARIABLECHANGE_MODEL2GEOVALS_H_ +#define UMDSST_VARIABLECHANGE_MODEL2GEOVALS_H_ + +#include +#include + +#include "umdsst/Traits.h" + +#include "oops/base/VariableChangeBase.h" + +namespace umdsst { + +class Model2GeoVaLs: public oops::VariableChangeBase { + public: + static const std::string classname() {return "umdsst::Model2GeoVaLs";} + + Model2GeoVaLs(const Geometry &, const eckit::Configuration &); + ~Model2GeoVaLs() = default; + + void changeVar(const State &, State &) const override; + void changeVarInverse(const State &, State &) const override; + + private: + std::unique_ptr geom_; + void print(std::ostream &) const override {} +}; + +} // namespace umdsst + +#endif // UMDSST_VARIABLECHANGE_MODEL2GEOVALS_H_ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 32e5d73..2b4bc1f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,86 +1,206 @@ -list( APPEND oisst_test_input - testinput/geometry.yml +list( APPEND umdsst_test_input testinput/errorcovariance.yml + testinput/geometry.yml testinput/getvalues.yml - testinput/lineargetvalues.yml - testinput/linearmodel.yml + testinput/hofx3d.yml testinput/increment.yml - testinput/model.yml + testinput/lineargetvalues.yml + testinput/linearvarchange_stddev.yml testinput/modelaux.yml testinput/state.yml + testinput/dirac.yml + testinput/staticbinit.yml + testinput/var.yml ) +list( APPEND umdsst_test_ref + testref/hofx3d.ref + testref/dirac.ref + testref/staticbinit.ref + testref/var.ref + ) -# link the input files for the tests +list( APPEND umdsst_test_data + Data/19850101_regridded_sst_1x1.nc + Data/landmask_1x1.nc + Data/obs_sst.nc + Data/rossby_radius.dat + ) + + +# create necessary directories file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testinput) -foreach(FILENAME ${oisst_test_input}) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testref) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testoutput) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Data) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Data/bump) + +# link the input files for the tests +foreach(FILENAME + ${umdsst_test_input} + ${umdsst_test_ref} + ${umdsst_test_data} + ) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME} ${CMAKE_CURRENT_BINARY_DIR}/${FILENAME} ) endforeach() +# number of PEs to use for MPI enabled tests. +set( MPI_PES 2) + + +#------------------------------------------------------------------------------- +# The following is a wrapper to simplify the generation of tests of the umdsst +# executables. +function(umdsst_exe_test) + # parse the passed arguments + set(prefix ARG) + set(novals NOCOMPARE NOTRAPFPE) + set(singlevals NAME EXE CFG CLEAN) + set(multivals TEST_DEPENDS TOL) + cmake_parse_arguments(${prefix} + "${novals}" "${singlevals}" "${multivals}" + ${ARGN}) + + # set the tolerances to defaults if none given, or if we want to override + IF(NOT ARG_TOL) + SET(ARG_TOL "1.0e-12;0") + ENDIF() + LIST(GET ARG_TOL 0 TOL_F) + LIST(GET ARG_TOL 1 TOL_I) + + # determine if floating point error trapping should be set + if( ARG_NOTRAPFPE) + set ( TRAPFPE_ENV "OOPS_TRAPFPE=0") + else() + set ( TRAPFPE_ENV "OOPS_TRAPFPE=1") + endif() + + # determine the default config file name + if ( ARG_CFG ) + set ( CONFIG_FILE testinput/${ARG_CFG} ) + else() + set ( CONFIG_FILE testinput/${ARG_NAME}.yml ) + endif() + + # find the MPI command + set(MPI_CMD "${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPI_PES}") + + # find compare.py provided by oops + find_file(COMPARE_BIN oops_compare.py HINTS ${oops_BINDIR}) + + # add the test + ecbuild_add_test( TARGET test_umdsst_${ARG_NAME} + TYPE SCRIPT + COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_wrapper.sh" + ARGS "${CMAKE_BINARY_DIR}/bin/${ARG_EXE}" + ${CONFIG_FILE} + ENVIRONMENT + ${TRAPFPE_ENV} + COMPARE_SCRIPT=${COMPARE_BIN} + COMPARE_TESTNAME=${ARG_NAME} + COMPARE_TOL_F=${TOL_F} + COMPARE_TOL_I=${TOL_I} + MPI_CMD=${MPI_CMD} + SKIP_COMPARE=${ARG_NOCOMPARE} + CLEAN_FILES=${ARG_CLEAN} + DEPENDS ${ARGE_EXE} + TEST_DEPENDS ${ARG_TEST_DEPENDS}) +endfunction() #================================================================================ # Tests of class interfaces # TODO: uncomment all of these tests as the appropriate interfaces are implemented #================================================================================ -# ecbuild_add_test( -# TARGET test_oisst_geometry -# SOURCES executables/TestGeometry.cc -# ARGS testinput/geometry.yml -# LIBS oisst ) + ecbuild_add_test( + TARGET test_umdsst_geometry + SOURCES executables/TestGeometry.cc + ARGS testinput/geometry.yml + MPI ${MPI_PES} + LIBS umdsst ) -# ecbuild_add_test( -# TARGET test_oisst_state -# SOURCES executables/TestState.cc -# ARGS testinput/state.yml -# LIBS oisst ) - -# ecbuild_add_test( -# TARGET test_oisst_increment -# SOURCES executables/TestIncrement.cc -# ARGS testinput/increment.yml -# LIBS oisst ) + ecbuild_add_test( + TARGET test_umdsst_state + SOURCES executables/TestState.cc + ARGS testinput/state.yml + MPI ${MPI_PES} + LIBS umdsst ) -# ecbuild_add_test( -# TARGET test_oisst_model -# SOURCES executables/TestModel.cc -# ARGS testinput/model.yml -# LIBS oisst ) + ecbuild_add_test( + TARGET test_umdsst_increment + SOURCES executables/TestIncrement.cc + ARGS testinput/increment.yml + MPI ${MPI_PES} + LIBS umdsst ) # ecbuild_add_test( -# TARGET test_oisst_modelauxcontrol +# TARGET test_umdsst_modelauxcontrol # SOURCES executables/TestModelAuxControl.cc # ARGS testinput/modelaux.yml -# LIBS oisst ) +# MPI ${MPI_PES} +# LIBS umdsst ) -# ecbuild_add_test( -# TARGET test_oisst_getvalues -# SOURCES executables/TestGetValues.cc -# ARGS testinput/getvalues.yml -# LIBS oisst ) + ecbuild_add_test( + TARGET test_umdsst_getvalues + SOURCES executables/TestGetValues.cc + ARGS testinput/getvalues.yml + MPI ${MPI_PES} + LIBS umdsst ) -# ecbuild_add_test( -# TARGET test_oisst_lineargetvalues -# SOURCES executables/TestLinearGetValues.cc -# ARGS testinput/lineargetvalues.yml -# LIBS oisst ) + ecbuild_add_test( + TARGET test_umdsst_lineargetvalues + SOURCES executables/TestLinearGetValues.cc + ARGS testinput/lineargetvalues.yml + MPI ${MPI_PES} + LIBS umdsst ) -# ecbuild_add_test( -# TARGET test_oisst_errorcovariance -# SOURCES executables/TestErrorCovariance.cc -# ARGS testinput/errorcovariance.yml -# LIBS oisst ) + ecbuild_add_test( + TARGET test_umdsst_linearvarchange_stddev + SOURCES executables/TestLinearVariableChange.cc + ARGS testinput/linearvarchange_stddev.yml + MPI ${MPI_PES} + LIBS umdsst ) + + ecbuild_add_test( + TARGET test_umdsst_errorcovariance + SOURCES executables/TestErrorCovariance.cc + ARGS testinput/errorcovariance.yml + MPI ${MPI_PES} + LIBS umdsst + TEST_DEPENDS test_umdsst_staticbinit) # ecbuild_add_test( -# TARGET test_oisst_modelauxcovariance +# TARGET test_umdsst_modelauxcovariance # SOURCES executables/TestModelAuxCovariance.cc # ARGS testinput/modelaux.yml -# LIBS oisst ) +# MPI ${MPI_PES} +# LIBS umdsst ) # ecbuild_add_test( -# TARGET test_oisst_modelauxincrement +# TARGET test_umdsst_modelauxincrement # SOURCES executables/TestModelAuxIncrement.cc # ARGS testinput/modelaux.yml -# LIBS oisst ) +# MPI ${MPI_PES} +# LIBS umdsst ) + + +#================================================================================ +# Test of executables +#================================================================================ + + umdsst_exe_test( NAME hofx3d + EXE umdsst_hofx3d.x ) + + umdsst_exe_test( NAME staticbinit + EXE umdsst_staticbinit.x + CLEAN Data/bump/* ) + + umdsst_exe_test( NAME dirac + EXE umdsst_dirac.x + TEST_DEPENDS test_umdsst_staticbinit ) + + umdsst_exe_test( NAME var + EXE umdsst_var.x + TEST_DEPENDS test_umdsst_staticbinit ) diff --git a/test/Data/19850101_regridded_sst_1x1.nc b/test/Data/19850101_regridded_sst_1x1.nc new file mode 100644 index 0000000..62dcacb --- /dev/null +++ b/test/Data/19850101_regridded_sst_1x1.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a22e4a263338a99166b1e6209b183caed4b6981b40442887b2a2f886eabbc534 +size 1109711 diff --git a/test/Data/20100101_regridded_sst_0.25x0.25.nc b/test/Data/20100101_regridded_sst_0.25x0.25.nc new file mode 100644 index 0000000..88ce998 --- /dev/null +++ b/test/Data/20100101_regridded_sst_0.25x0.25.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7c3ecfe347be26345c68f77ad91270de62d8bcb383c525a87f0f1d55591f4ef +size 3345540 diff --git a/test/Data/20120101_regridded_sst_0.25x0.25.nc b/test/Data/20120101_regridded_sst_0.25x0.25.nc new file mode 100644 index 0000000..2a575ae --- /dev/null +++ b/test/Data/20120101_regridded_sst_0.25x0.25.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:245a45117c0723d6a01d3218bdf86f02c6030be6d9d57b3ef2276610b5bbf575 +size 3788933 diff --git a/test/Data/landmask_0.25x0.25.nc b/test/Data/landmask_0.25x0.25.nc new file mode 100644 index 0000000..9c01502 --- /dev/null +++ b/test/Data/landmask_0.25x0.25.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38eadd752bc0735860b2fce33ac235926ad6e8f5f9781a81299c5a129ee2cf61 +size 4164413 diff --git a/test/Data/landmask_1x1.nc b/test/Data/landmask_1x1.nc new file mode 100644 index 0000000..f6d1472 --- /dev/null +++ b/test/Data/landmask_1x1.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:348b9fe486da6768d82cc95e4059cb2d4460ed0e18dfc9dcef7fcc584cbd896b +size 272041 diff --git a/test/Data/obs_sst.nc b/test/Data/obs_sst.nc new file mode 100644 index 0000000..2a7d466 --- /dev/null +++ b/test/Data/obs_sst.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42dd448285de892b5c38e721d2c055dbece53a140d4421fe965fc9dee06c0fd3 +size 25172 diff --git a/test/Data/rossby_radius.dat b/test/Data/rossby_radius.dat new file mode 100644 index 0000000..d15ee9f --- /dev/null +++ b/test/Data/rossby_radius.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2a49cdc619ec8c44186bc6a8de7bf607734868c923236e0805644c0bf5c54dd +size 1117445 diff --git a/test/executables/TestErrorCovariance.cc b/test/executables/TestErrorCovariance.cc index dfd7be4..5961ce8 100644 --- a/test/executables/TestErrorCovariance.cc +++ b/test/executables/TestErrorCovariance.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/ErrorCovariance.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::ErrorCovariance tests; + test::ErrorCovariance tests; return run.execute(tests); } diff --git a/test/executables/TestGeometry.cc b/test/executables/TestGeometry.cc index 3add7e4..5cc2419 100644 --- a/test/executables/TestGeometry.cc +++ b/test/executables/TestGeometry.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/Geometry.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::Geometry tests; + test::Geometry tests; return run.execute(tests); } diff --git a/test/executables/TestGetValues.cc b/test/executables/TestGetValues.cc index 53f5426..6eac37b 100644 --- a/test/executables/TestGetValues.cc +++ b/test/executables/TestGetValues.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/GetValues.h" #include "ufo/ObsTraits.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::GetValues tests; + test::GetValues tests; return run.execute(tests); } \ No newline at end of file diff --git a/test/executables/TestIncrement.cc b/test/executables/TestIncrement.cc index 067a2c1..f87c259 100644 --- a/test/executables/TestIncrement.cc +++ b/test/executables/TestIncrement.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/Increment.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::Increment tests; + test::Increment tests; return run.execute(tests); } diff --git a/test/executables/TestLinearGetValues.cc b/test/executables/TestLinearGetValues.cc index c4114c1..f13e409 100644 --- a/test/executables/TestLinearGetValues.cc +++ b/test/executables/TestLinearGetValues.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/LinearGetValues.h" #include "ufo/ObsTraits.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::LinearGetValues tests; + test::LinearGetValues tests; return run.execute(tests); } \ No newline at end of file diff --git a/test/executables/TestModel.cc b/test/executables/TestLinearVariableChange.cc similarity index 63% rename from test/executables/TestModel.cc rename to test/executables/TestLinearVariableChange.cc index d39841c..0e0a747 100644 --- a/test/executables/TestModel.cc +++ b/test/executables/TestLinearVariableChange.cc @@ -1,16 +1,17 @@ /* - * (C) Copyright 2019-2019 UCAR. + * (C) Copyright 2021-2021 UCAR. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" -#include "test/interface/Model.h" +#include "test/interface/LinearVariableChange.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::Model tests; + test::LinearVariableChange tests; return run.execute(tests); } + diff --git a/test/executables/TestModelAuxControl.cc b/test/executables/TestModelAuxControl.cc index 4b2eca6..5f984b6 100644 --- a/test/executables/TestModelAuxControl.cc +++ b/test/executables/TestModelAuxControl.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/ModelAuxControl.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::ModelAuxControl tests; + test::ModelAuxControl tests; return run.execute(tests); } diff --git a/test/executables/TestModelAuxCovariance.cc b/test/executables/TestModelAuxCovariance.cc index b235dbb..2ec50d2 100644 --- a/test/executables/TestModelAuxCovariance.cc +++ b/test/executables/TestModelAuxCovariance.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/ModelAuxCovariance.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::ModelAuxCovariance tests; + test::ModelAuxCovariance tests; return run.execute(tests); } diff --git a/test/executables/TestModelAuxIncrement.cc b/test/executables/TestModelAuxIncrement.cc index e43efb2..aee0019 100644 --- a/test/executables/TestModelAuxIncrement.cc +++ b/test/executables/TestModelAuxIncrement.cc @@ -5,13 +5,13 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/ModelAuxIncrement.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::ModelAuxIncrement tests; + test::ModelAuxIncrement tests; return run.execute(tests); } diff --git a/test/executables/TestState.cc b/test/executables/TestState.cc index fa75ed1..f8cc7cf 100644 --- a/test/executables/TestState.cc +++ b/test/executables/TestState.cc @@ -5,12 +5,12 @@ * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. */ -#include "oisst/Traits.h" +#include "umdsst/Traits.h" #include "oops/runs/Run.h" #include "test/interface/State.h" int main(int argc, char ** argv) { oops::Run run(argc, argv); - test::State tests; + test::State tests; return run.execute(tests); } diff --git a/test/test_wrapper.sh b/test/test_wrapper.sh new file mode 100755 index 0000000..162ac07 --- /dev/null +++ b/test/test_wrapper.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# simple script to combine into a single ctest the 1) running of executable and +# 2)comparing its answers to reference answers. + +# optionally delete existing files +if [[ ${#CLEAN_FILES} -gt 0 ]]; then + echo "" + echo "===============================================================================" + echo "Deleting files" + echo "===============================================================================" + for f in ${CLEAN_FILES}; do + echo Deleting: $f + rm -f $f + done +fi + +# run the executable +echo "" +echo "===============================================================================" +echo "Running test executable" +echo "===============================================================================" +${MPI_CMD} $1 $2 testoutput/${COMPARE_TESTNAME}.log +e=$? +if [[ "$e" -gt 0 ]]; then + echo -e "Failed to run executable. Error code: $e \n" + exit $e +fi + +# run compare, if needed +if [[ "$SKIP_COMPARE" == "FALSE" ]]; then + echo "" + echo "===============================================================================" + echo "Running compare script" + echo "===============================================================================" + + $COMPARE_SCRIPT testoutput/${COMPARE_TESTNAME}.log \ + testref/${COMPARE_TESTNAME}.ref \ + ${COMPARE_TOL_F} ${COMPARE_TOL_I} + e=$? + if [[ "$e" -gt 0 ]]; then + echo -e "Failed in the COMPARE step. Error code: $e \n" + exit $e + fi + echo -e "PASSED \n" +fi diff --git a/test/testinput/dirac.yml b/test/testinput/dirac.yml new file mode 100644 index 0000000..2f8b837 --- /dev/null +++ b/test/testinput/dirac.yml @@ -0,0 +1,50 @@ +geometry: + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + +analysis variables: &vars [sea_surface_temperature] + +background: # must have + state variables: *vars + date: 2018-04-15T00:00:00Z + filename: Data/19850101_regridded_sst_1x1.nc + +background error: + covariance model: BUMP + bump: + mask_check: 1 + network: 1 + verbosity: main + datadir: Data/bump + method: cor + load_nicas: 1 + prefix: bump_sst + mpicom: 2 + strategy: specific_univariate + variable changes: + - variable change: umdsstStdDev + input variables: *vars + output variables: *vars + fixed: 1.0 + +dirac: + date: 2010-01-01T12:00:00Z + ixdir: [20, 50, 95, 100, 150, 200, 250, 300, 350] + iydir: [10, 25, 95, 50, 75, 100, 125, 150, 175] + +initial condition: + date: 2010-01-01T12:00:00Z + filename: Data/19850101_regridded_sst_1x1.nc + state variables: [sea_surface_temperature] + +output B: + datadir: Data + filename: Data/dirac.x_output.nc + date: 2010-01-01T12:00:00Z + exp: dirac_umdsst_B + type: an diff --git a/test/testinput/errorcovariance.yml b/test/testinput/errorcovariance.yml index 80ae312..3173fad 100644 --- a/test/testinput/errorcovariance.yml +++ b/test/testinput/errorcovariance.yml @@ -1,15 +1,32 @@ geometry: - # insert other model specific things here + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + covariance test: tolerance: 1e-12 testinverse: false -analysis variables: &vars [var1, var2] +analysis variables: &vars [sea_surface_temperature] background: state variables: *vars date: 2018-04-15T00:00:00Z background error: - covariance model: oisstCovar + covariance model: umdsstCovar + bump: + mask_check: 1 + network: 1 + verbosity: main + datadir: Data/bump + method: cor + load_nicas: 1 + prefix: bump_sst + mpicom: 2 + strategy: specific_univariate diff --git a/test/testinput/geometry.yml b/test/testinput/geometry.yml index e14c921..029a888 100644 --- a/test/testinput/geometry.yml +++ b/test/testinput/geometry.yml @@ -1,2 +1,9 @@ geometry: - # insert other model specific things here \ No newline at end of file + grid: + name: S360x180 + domain: + type: global + west: -180 + + landmask: + filename: Data/landmask_1x1.nc diff --git a/test/testinput/getvalues.yml b/test/testinput/getvalues.yml index f7d3522..c4ef7c7 100644 --- a/test/testinput/getvalues.yml +++ b/test/testinput/getvalues.yml @@ -1,7 +1,13 @@ geometry: - # insert other model specific things here + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc -state variables: &state_vars [var1, var2] +state variables: &state_vars [sea_surface_temperature] locations: window begin: 2018-04-15T00:00:00Z @@ -16,11 +22,12 @@ locations: lat2: 90 lon1: 0 lon2: 360 - obs errors: [1.0, 1.0] + obs errors: [1.0] getvalues test: state generate: date: 2018-04-15T00:00:00Z + filename: Data/19850101_regridded_sst_1x1.nc state variables: *state_vars interpolation tolerance: 1e-10 diff --git a/test/testinput/hofx3d.yml b/test/testinput/hofx3d.yml new file mode 100644 index 0000000..b9a590b --- /dev/null +++ b/test/testinput/hofx3d.yml @@ -0,0 +1,31 @@ +window length: P1D +window begin: 2018-04-15T00:00:00Z + +geometry: + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + +state: + date: 2018-04-15T12:00:00Z + state variables: [sea_surface_temperature] + filename: Data/19850101_regridded_sst_1x1.nc + kelvin: true + +observations: + - obs space: + name: SST + obsdatain: {obsfile: ./Data/obs_sst.nc} + obsdataout: {obsfile: ./Data/hofx_sst.nc} + simulated variables: [sea_surface_temperature] + obs operator: + name: Identity + obs filters: + - filter: Domain Check + where: + - variable: {name: sea_area_fraction@GeoVaLs} + minvalue: 1.0 diff --git a/test/testinput/increment.yml b/test/testinput/increment.yml index c030e60..2715535 100644 --- a/test/testinput/increment.yml +++ b/test/testinput/increment.yml @@ -1,5 +1,14 @@ geometry: - # insert other model specific things here + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc -inc variables: [var1, var2] -test date: 2018-04-15T00:00:00Z +inc variables: [sea_surface_temperature] + +increment test: + date: 1985-01-01T12:00:00Z + tolerance: 1e-12 diff --git a/test/testinput/lineargetvalues.yml b/test/testinput/lineargetvalues.yml index a49506c..aa776aa 100644 --- a/test/testinput/lineargetvalues.yml +++ b/test/testinput/lineargetvalues.yml @@ -1,7 +1,13 @@ geometry: - # insert other model specific things here + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc -state variables: &state_vars [var1, var2] +state variables: &state_vars [sea_surface_temperature] locations: window begin: 2018-04-15T00:00:00Z @@ -16,7 +22,7 @@ locations: lat2: 90 lon1: 0 lon2: 360 - obs errors: [1.0, 1.0] + obs errors: [1.0] background: state variables: *state_vars diff --git a/test/testinput/linearvarchange_stddev.yml b/test/testinput/linearvarchange_stddev.yml new file mode 100644 index 0000000..39383f7 --- /dev/null +++ b/test/testinput/linearvarchange_stddev.yml @@ -0,0 +1,20 @@ +geometry: + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + +background: + state variables: &vars [sea_surface_temperature] + date: 2018-04-15T00:00:00Z + +linear variable change tests: +- variable change: umdsstStdDev + tolerance inverse: 1e-12 + test inverse: 1 + input variables: *vars + output variables: *vars + fixed: 2.0 diff --git a/test/testinput/model.yml b/test/testinput/model.yml deleted file mode 100644 index df39a1c..0000000 --- a/test/testinput/model.yml +++ /dev/null @@ -1,19 +0,0 @@ -geometry: - # insert other model specific things here - -model: - name: OISST - model variables: [var1, var2] - tstep: PT6H - # insert other model specific things here - -model test: - forecast length: P1D - final norm: 0.0 - tolerance: 1e-12 - -initial condition: - state variables: [var1, var2] - date: 2018-04-15T00:00:00Z - -model aux control: diff --git a/test/testinput/state.yml b/test/testinput/state.yml index 6cd38f4..03fe53f 100644 --- a/test/testinput/state.yml +++ b/test/testinput/state.yml @@ -1,11 +1,27 @@ geometry: - # insert other model specific things here + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + state test: - norm file: 0.0 - tolerance: 1.0e-12 - date: &date 2018-04-15T00:00:00Z + norm file: 17.618557808088323 + tolerance: 1e-6 + date: &date 1985-01-01T12:00:00Z statefile: date: *date - state variables: &state_vars [statevar1, statevar2] - # insert other model specific things here \ No newline at end of file + filename: Data/19850101_regridded_sst_1x1.nc + kelvin: true + state variables: &state_vars [sea_surface_temperature] + statefileout: + datadir: ./Data + exp: out + type: fc + date: 1985-01-01T12:00:00Z + filename: Data/out.19850101_regridded_sst.nc + kelvin: true + state variables: *state_vars diff --git a/test/testinput/staticbinit.yml b/test/testinput/staticbinit.yml new file mode 100644 index 0000000..e9e4e80 --- /dev/null +++ b/test/testinput/staticbinit.yml @@ -0,0 +1,37 @@ +geometry: + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + rossby radius file: Data/rossby_radius.dat + +analysis variables: &vars [sea_surface_temperature] # must have + +background: # must have + state variables: *vars + date: 2018-04-15T00:00:00Z + filename: Data/19850101_regridded_sst_1x1.nc + +background error: + covariance model: umdsstCovar + bump: + mask_check: 1 + network: 1 + verbosity: main + datadir: Data/bump + method: cor + new_nicas: 1 + ntry: 3 + prefix: bump_sst + resol: 6.0 + mpicom: 2 + strategy: specific_univariate + nc1max: 100000 + correlation lengths: + base value: 500.0e3 + rossby mult: 1.0 + min grid mult: 5.0 + #min value: 200.0e3 diff --git a/test/testinput/var.yml b/test/testinput/var.yml new file mode 100644 index 0000000..ce87f9b --- /dev/null +++ b/test/testinput/var.yml @@ -0,0 +1,82 @@ +cost function: + cost type: 3D-Var + window begin: 2018-04-15T00:00:00Z + window length: PT24H + analysis variables: &vars [sea_surface_temperature] + + geometry: &geometry + grid: + name: S360x180 + domain: + type: global + west: -180 + landmask: + filename: Data/landmask_1x1.nc + + background: + state variables: *vars + date: 2018-04-15T12:00:00Z + filename: Data/19850101_regridded_sst_1x1.nc + kelvin: true + + background error: + covariance model: BUMP + bump: + mask_check: 1 + network: 1 + verbosity: main + datadir: Data/bump + method: cor + load_nicas: 1 + prefix: bump_sst + mpicom: 2 + strategy: specific_univariate + variable changes: + - variable change: umdsstStdDev + input variables: *vars + output variables: *vars + fixed: 1.0 + + observations: + - obs error: + covariance model: diagonal + obs operator: + name: Identity + obs filters: + - filter: Domain Check + where: + - variable: {name: sea_area_fraction@GeoVaLs} + minvalue: 1.0 + obs space: + name: sea_surface_temperature + obsdatain: + obsfile: Data/obs_sst.nc + simulated variables: [sea_surface_temperature] + obsdataout: + obsfile: Data/var.output.obs3d.nc + + +variational: + minimizer: + algorithm: DRIPCG + + iterations: + - diagnostics: + departures: ombg + gradient norm reduction: 1.0e-10 + ninner: 10 + geometry: *geometry + test: on + online diagnostics: + write increment: true + increment: + filename: Data/var.output.increment.nc + + +final: + diagnostics: + departures: oman + + +output: + filename: Data/var.output.final.nc diff --git a/test/testref/dirac.ref b/test/testref/dirac.ref new file mode 100644 index 0000000..0be53a0 --- /dev/null +++ b/test/testref/dirac.ref @@ -0,0 +1,2 @@ +Test : Input Dirac increment: min = 0, max = 1, mean = 0.000138889 +Test : B * Increment: min = -0, max = 1, mean = 0.0237249 diff --git a/test/testref/hofx3d.ref b/test/testref/hofx3d.ref new file mode 100644 index 0000000..fe8d991 --- /dev/null +++ b/test/testref/hofx3d.ref @@ -0,0 +1,4 @@ +Test : State: min = -1.74296, max = 30.7226, mean = 13.5655 +Test : H(x): +Test : SST nobs= 200 Min=-2.5419e+38, Max=29.7967, RMS=3.39967e+37 +Test : End H(x) diff --git a/test/testref/staticbinit.ref b/test/testref/staticbinit.ref new file mode 100644 index 0000000..9b20288 --- /dev/null +++ b/test/testref/staticbinit.ref @@ -0,0 +1 @@ +Test : min = -3.9276, max = 5.00076, mean = 0.00100917 diff --git a/test/testref/var.ref b/test/testref/var.ref new file mode 100644 index 0000000..04dc0e2 --- /dev/null +++ b/test/testref/var.ref @@ -0,0 +1,9 @@ +Test : CostJb : Nonlinear Jb = 0 +Test : CostJo : Nonlinear Jo(sea_surface_temperature) = 2106.96, nobs = 188, Jo/n = 11.2072, err = 0.363015 +Test : CostFunction: Nonlinear J = 2106.96 +Test : DRIPCGMinimizer: reduction in residual norm = 0.0278441 +Test : CostFunction::addIncrement: Analysis: min = -2.16241, max = 32.1528, mean = 13.8328 +Test : umdsst::ModelAuxControl not implemented +Test : CostJb : Nonlinear Jb = 111.292 +Test : CostJo : Nonlinear Jo(sea_surface_temperature) = 28.1357, nobs = 188, Jo/n = 0.149658, err = 0.363015 +Test : CostFunction: Nonlinear J = 139.427