From 0a9400f04186c97acdc20d555fb109eaa1b0310c Mon Sep 17 00:00:00 2001 From: DavidNew-NOAA Date: Thu, 12 Dec 2024 14:38:21 +0000 Subject: [PATCH] Initial commit --- parm/atm/jcb-base.yaml.j2 | 16 ++-- utils/fv3jedi/CMakeLists.txt | 57 +++++++++++++-- utils/fv3jedi/fv3jedi_recenter.cc | 8 ++ utils/fv3jedi/fv3jedi_recenter.h | 118 ++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 12 deletions(-) create mode 100644 utils/fv3jedi/fv3jedi_recenter.cc create mode 100644 utils/fv3jedi/fv3jedi_recenter.h diff --git a/parm/atm/jcb-base.yaml.j2 b/parm/atm/jcb-base.yaml.j2 index d7e1e5907..de51af4c2 100644 --- a/parm/atm/jcb-base.yaml.j2 +++ b/parm/atm/jcb-base.yaml.j2 @@ -9,12 +9,12 @@ app_path_observation_chronicle: "{{PARMgfs}}/gdas/jcb-gdas/observation_chronicle # Places where we deviate from the generic file name of a yaml # ------------------------------------------------------------ -#final_increment_file: final_increment_gaussian -final_increment_file: atmosphere_final_increment_cubed_sphere -output_ensemble_increments_file: atmosphere_output_ensemble_increments_cubed_sphere +final_increment_file: atmosphere_final_increment_fms_nonrestart +output_ensemble_increments_file: atmosphere_output_ensemble_increments_fms_nonrestart model_file: atmosphere_model_pseudo initial_condition_file: atmosphere_background # Initial conditions for 4D apps is background background_error_file: "{{BERROR_YAML}}" +posterior_output_file: atmosphere_posterior_output_cubed_sphere # Assimilation standard things (not prepended with model choice) # ---------------------------- @@ -24,11 +24,15 @@ bound_to_include: begin minimizer: DRPCG final_diagnostics_departures: anlmob final_prints_frequency: PT3H +analysis_variables: &anvars [ua,va,t,ps,sphum,ice_wat,liq_wat,o3mr] number_of_outer_loops: 2 -analysis_variables: [ua,va,t,ps,sphum,ice_wat,liq_wat,o3mr] # Model things # ------------ + +# Analysis variables +atmosphere_analysis_variables: *anvars + # Geometry atmosphere_layout_x: {{ layout_x | default(1, true) }} atmosphere_layout_y: {{ layout_y | default(1, true) }} @@ -62,8 +66,6 @@ atmosphere_forecast_timestep: "{{ BKG_TSTEP }}" # Write final increment on Guassian grid in variational atmosphere_final_increment_prefix: "./anl/atminc." -atmosphere_variational_history_prefix: "{{GPREFIX}}" - # Observation things # ------------------ observations: all_observations @@ -125,7 +127,7 @@ inflation_mult: 1.0 # Driver driver_update_obs_config_with_geometry_info: true -driver_save_posterior_mean: false +driver_save_posterior_mean: true driver_save_posterior_ensemble: false driver_save_prior_mean: false driver_save_posterior_mean_increment: false diff --git a/utils/fv3jedi/CMakeLists.txt b/utils/fv3jedi/CMakeLists.txt index 474b4478d..ef34501af 100644 --- a/utils/fv3jedi/CMakeLists.txt +++ b/utils/fv3jedi/CMakeLists.txt @@ -1,5 +1,52 @@ -# Increment post processing -ecbuild_add_executable( TARGET fv3jedi_fv3inc.x - SOURCES fv3jedi_fv3inc.cc fv3jedi_fv3inc.h) -target_compile_features( fv3jedi_fv3inc.x PUBLIC cxx_std_17) -target_link_libraries( fv3jedi_fv3inc.x PUBLIC NetCDF::NetCDF_CXX oops fv3jedi) +# ------------------------------------------------------------------------- # +# Application for the GDAS system # +# ------------------------------------------------------------------------- # + +# Check for minimim cmake requirement +cmake_minimum_required( VERSION 3.20 FATAL_ERROR ) + +find_package(ecbuild 3.5 REQUIRED HINTS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild) + +project(GDASApp VERSION 1.0.0 LANGUAGES C CXX Fortran ) +# include_directories(${CMAKE_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +include(GNUInstallDirs) +enable_testing() + +# Build type. +if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$") + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE + "Release" + CACHE STRING "Choose the type of build." FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif() + +# Find dependencies. +find_package(Python3 REQUIRED COMPONENTS Interpreter) + +# Include ecbuild_bundle macro +include( ecbuild_bundle ) + +# Enable MPI +set( ENABLE_MPI ON CACHE BOOL "Compile with MPI" ) + +# Handle user options. +option(BUILD_GDASBUNDLE "Build GDAS Bundle" ON) +option(CLONE_JCSDADATA "Clone JCSDA test data repositories" OFF) +option(WORKFLOW_TESTS "Include global-workflow dependent tests" OFF) + +# Build GDAS-managed JEDI executables +if( BUILD_GDASBUNDLE ) + find_package( fv3jedi REQUIRED ) + find_package( soca REQUIRED ) + add_subdirectory( mains ) +endif() + +# Install utility scripts. +add_subdirectory(ush) + +# Include testing. +add_subdirectory(test) diff --git a/utils/fv3jedi/fv3jedi_recenter.cc b/utils/fv3jedi/fv3jedi_recenter.cc new file mode 100644 index 000000000..58a8c8430 --- /dev/null +++ b/utils/fv3jedi/fv3jedi_recenter.cc @@ -0,0 +1,8 @@ +#include "fv3jedi_recenter.h" +#include "oops/runs/Run.h" + +int main(int argc, char ** argv) { + oops::Run run(argc, argv); + gdasapp::recenter recenter; + return run.execute(recenter); +} diff --git a/utils/fv3jedi/fv3jedi_recenter.h b/utils/fv3jedi/fv3jedi_recenter.h new file mode 100644 index 000000000..a4ef9cb24 --- /dev/null +++ b/utils/fv3jedi/fv3jedi_recenter.h @@ -0,0 +1,118 @@ +#pragma once + +#include +#include +#include +#include + +#include "eckit/config/LocalConfiguration.h" + +#include "fv3jedi/Geometry/Geometry.h" +#include "fv3jedi/Increment/Increment.h" +#include "fv3jedi/State/State.h" + +#include "oops/mpi/mpi.h" +#include "oops/runs/Application.h" +#include "oops/util/ConfigFunctions.h" +#include "oops/util/DateTime.h" +#include "oops/util/Duration.h" +#include "oops/util/Logger.h" + +namespace gdasapp { + + // Main application class + class recenter : public oops::Application { + public: + explicit recenter(const eckit::mpi::Comm & comm = oops::mpi::world()) + : Application(comm) {} + static const std::string classname() {return "gdasapp::recenter";} + + int execute(const eckit::Configuration & fullConfig, bool validate) const { + // Get analysis parameters + std::vector fcstHours; + std::string windowBeginStr; + fullConfig.get("forecast hours", fcstHours); + fullConfig.get("window begin", windowBeginStr); + const util::DateTime windowBegin(windowBeginStr); + const oops::Variables stateVars(fullConfig, "state variables"); + const oops::Variables incrVars(fullConfig, "increment variables"); + + // Get geometry configurations + const eckit::LocalConfiguration bkgGeomConfig(fullConfig, "background geometry"); + const eckit::LocalConfiguration incrGeomConfig(fullConfig, "increment geometry"); + const eckit::LocalConfiguration anlEnsMeanGeomConfig(fullConfig, \ + "ensemble mean analysis geometry"); + const eckit::LocalConfiguration incrCorGeomConfig(fullConfig, \ + "correction increment geometry"); + + // Setup geometries + const fv3jedi::Geometry incrGeom(incrGeomConfig, this->getComm()); + const fv3jedi::Geometry bkgGeom(bkgGeomConfig, this->getComm()); + const fv3jedi::Geometry anlEnsMeanGeom(anlEnsMeanGeomConfig, this->getComm()); + const fv3jedi::Geometry incrCorGeom(incrCorGeomConfig, this->getComm()); + + // Get additions configuration + int nhrs = fcstHours.size(); + std::vector additionsConfig; + eckit::LocalConfiguration additionsFromTemplateConfig(fullConfig, \ + "additions from template"); + eckit::LocalConfiguration templateConfig(additionsFromTemplateConfig, "template"); + std::string pattern; + additionsFromTemplateConfig.get("pattern", pattern); + + for ( int ihrs = 0; ihrs < nhrs; ihrs++ ) { + eckit::LocalConfiguration thisAdditionsConfig(templateConfig); + util::seekAndReplace(thisAdditionsConfig, pattern, fcstHours[ihrs]); + additionsConfig.push_back(thisAdditionsConfig); + } + + // Loops through forecast hours + for ( int ihrs = 0; ihrs < nhrs; ihrs++ ) { + // Get DateTime for forecast hour + const util::Duration fcstHour(3600*std::stoi(fcstHours[ihrs]) - 3*3600); + util::DateTime currentCycle = windowBegin + fcstHour; + + // Get elements of individual additions configurations + const eckit::LocalConfiguration bkgConfig(additionsConfig[ihrs], "background"); + const eckit::LocalConfiguration incrConfig(additionsConfig[ihrs], "increment"); + const eckit::LocalConfiguration anlEnsMeanConfig(additionsConfig[ihrs], \ + "ensemble mean analysis"); + const eckit::LocalConfiguration incrCorConfig(additionsConfig[ihrs], \ + "correction increment"); + + // Read background + fv3jedi::State xxBkg(bkgGeom, stateVars, currentCycle); + xxBkg.read(bkgConfig); + + // Read increment + fv3jedi::Increment dx(incrGeom, incrVars, currentCycle); + dx.read(incrConfig); + + // Read ensemble mean analysis + fv3jedi::State xxAnlEnsMean(anlEnsMeanGeom, incrVars, currentCycle); + xxAnlEnsMean.read(anlEnsMeanConfig); + + // Compute deterministic analysis + fv3jedi::State xxAnlDet(bkgGeom, xxBkg); + xxAnlDet += dx; + + // Interpolate full resolution analysis to ensemble resolution and then change variables + fv3jedi::State xxAnlDetEnsRes(incrCorGeom, fv3jedi::State(incrVars, xxAnlDet)); + + // Compute correction increment + fv3jedi::Increment dxCor(incrCorGeom, incrVars, xxBkg.validTime()); + dxCor.diff(xxAnlEnsMean, xxAnlDetEnsRes); + + // Write correction increment + dxCor.write(incrCorConfig); + } + + return 0; + } + + private: + std::string appname() const { + return "gdasapp::recenter"; + } + }; +} // namespace gdasapp