diff --git a/parm/aero/jcb-base.yaml.j2 b/parm/aero/jcb-base.yaml.j2 index 5988e05d1..df7454d7f 100644 --- a/parm/aero/jcb-base.yaml.j2 +++ b/parm/aero/jcb-base.yaml.j2 @@ -34,7 +34,6 @@ analysis_variables: [mass_fraction_of_sulfate_in_air, mass_fraction_of_dust005_in_air, mass_fraction_of_sea_salt001_in_air, mass_fraction_of_sea_salt002_in_air, mass_fraction_of_sea_salt003_in_air, mass_fraction_of_sea_salt004_in_air] -iau_hours: {{ IAUFHRS }} # Model things # ------------ @@ -72,6 +71,10 @@ aero_cycle_time_fv3: "{{ current_cycle | to_fv3time }}" aero_background_error_time_iso: "{{ background_time | to_isotime }}" aero_background_error_time_fv3: "{{ background_time | to_fv3time }}" +# IAU times +aero_iau_hours: {{ IAUFHRS }} +aero_iau_times_iso: {{ iau_times_iso }} + # Background error aero_berror_data_directory: "{{ DATA }}/berror" aero_berror_diffusion_directory: "{{ DATA }}/diffusion" diff --git a/parm/atm/jcb-base.yaml.j2 b/parm/atm/jcb-base.yaml.j2 index 4a4c0448b..fcdeec240 100644 --- a/parm/atm/jcb-base.yaml.j2 +++ b/parm/atm/jcb-base.yaml.j2 @@ -26,7 +26,6 @@ final_diagnostics_departures: anlmob final_prints_frequency: PT3H analysis_variables: [ua,va,t,ps,sphum,ice_wat,liq_wat,o3mr] number_of_outer_loops: 2 -iau_hours: {{ IAUFHRS }} # Model things # ------------ @@ -50,6 +49,10 @@ atmosphere_background_ensemble_path: ./ens/mem%mem% # Default background time is for 3D applications atmosphere_background_time_iso: "{{ current_cycle | to_isotime }}" +# IAU times +atmosphere_iau_hours: {{ IAUFHRS }} +atmosphere_iau_times_iso: {{ iau_times_iso }} + # Background error atmosphere_bump_data_directory: "{{ DATA }}/berror" atmosphere_gsibec_path: "{{ DATA }}/berror" diff --git a/parm/jcb-gdas b/parm/jcb-gdas index 2274a9def..921cb9e5f 160000 --- a/parm/jcb-gdas +++ b/parm/jcb-gdas @@ -1 +1 @@ -Subproject commit 2274a9def6c224b3ca9a7e307aa24c33094b52d7 +Subproject commit 921cb9e5fc7add309efc2aa72ae992c703319574 diff --git a/parm/snow/jcb-base.yaml.j2 b/parm/snow/jcb-base.yaml.j2 index d5bf4a055..11f8318af 100644 --- a/parm/snow/jcb-base.yaml.j2 +++ b/parm/snow/jcb-base.yaml.j2 @@ -28,7 +28,9 @@ snow_background_time_fv3: "{{ bkg_time_fv3 }}" snow_increment_time_iso: "{{ bkg_time_iso }}" snow_increment_time_fv3: "{{ bkg_time_fv3 }}" -iau_hours: {{ IAUFHRS }} +# IAU times +snow_iau_hours: {{ IAUFHRS }} +snow_iau_times_iso: {{ iau_times_iso }} # Analysis standard things # ------------------------ diff --git a/utils/fv3jedi/CMakeLists.txt b/utils/fv3jedi/CMakeLists.txt index 1b7654210..856130ced 100644 --- a/utils/fv3jedi/CMakeLists.txt +++ b/utils/fv3jedi/CMakeLists.txt @@ -5,7 +5,7 @@ target_compile_features( fv3jedi_fv3inc.x PUBLIC cxx_std_17) target_link_libraries( fv3jedi_fv3inc.x PUBLIC NetCDF::NetCDF_CXX oops fv3jedi) # Ensemble increment recentering -ecbuild_add_executable( TARGET fv3jedi_ecen.x - SOURCES fv3jedi_ecen.cc fv3jedi_ecen.h) -target_compile_features( fv3jedi_ecen.x PUBLIC cxx_std_17) -target_link_libraries( fv3jedi_ecen.x PUBLIC NetCDF::NetCDF_CXX oops fv3jedi) +ecbuild_add_executable( TARGET fv3jedi_ensemble_recenter.x + SOURCES fv3jedi_ensemble_recenter.cc fv3jedi_ensemble_recenter.h) +target_compile_features( fv3jedi_ensemble_recenter.x PUBLIC cxx_std_17) +target_link_libraries( fv3jedi_ensemble_recenter.x PUBLIC NetCDF::NetCDF_CXX oops fv3jedi) diff --git a/utils/fv3jedi/fv3jedi_ecen.cc b/utils/fv3jedi/fv3jedi_ecen.cc deleted file mode 100644 index 31f0c9de8..000000000 --- a/utils/fv3jedi/fv3jedi_ecen.cc +++ /dev/null @@ -1,8 +0,0 @@ -#include "fv3jedi_ecen.h" -#include "oops/runs/Run.h" - -int main(int argc, char ** argv) { - oops::Run run(argc, argv); - gdasapp::ecen ecen; - return run.execute(ecen); -} diff --git a/utils/fv3jedi/fv3jedi_ecen.h b/utils/fv3jedi/fv3jedi_ecen.h deleted file mode 100644 index 420de50ce..000000000 --- a/utils/fv3jedi/fv3jedi_ecen.h +++ /dev/null @@ -1,121 +0,0 @@ -#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 ecen : public oops::Application { - public: - explicit ecen(const eckit::mpi::Comm & comm = oops::mpi::world()) - : Application(comm) {} - static const std::string classname() {return "gdasapp::ecen";} - - int execute(const eckit::Configuration & fullConfig) 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 incrVars(fullConfig, "increment variables"); - - // Get geometry configurations - const eckit::LocalConfiguration varIncrGeomConfig(fullConfig, \ - "variational increment geometry"); - const eckit::LocalConfiguration detBkgGeomConfig(fullConfig, \ - "deterministic background geometry"); - const eckit::LocalConfiguration ensMeanAnlGeomConfig(fullConfig, \ - "ensemble mean analysis geometry"); - const eckit::LocalConfiguration corIncrGeomConfig(fullConfig, \ - "correction increment geometry"); - - // Setup geometries - const fv3jedi::Geometry varIncrGeom(varIncrGeomConfig, this->getComm()); - const fv3jedi::Geometry detBkgGeom(detBkgGeomConfig, this->getComm()); - const fv3jedi::Geometry ensMeanAnlGeom(ensMeanAnlGeomConfig, this->getComm()); - const fv3jedi::Geometry corIncrGeom(corIncrGeomConfig, 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 varIncrConfig(additionsConfig[ihrs], \ - "variational increment"); - const eckit::LocalConfiguration detBkgConfig(additionsConfig[ihrs], \ - "deterministic background"); - const eckit::LocalConfiguration ensMeanAnlConfig(additionsConfig[ihrs], \ - "ensemble mean analysis"); - const eckit::LocalConfiguration corIncrConfig(additionsConfig[ihrs], \ - "correction increment"); - - // Initialize increment - fv3jedi::Increment dxVar(varIncrGeom, incrVars, currentCycle); - dxVar.read(varIncrConfig); - - // Initialize backgroun - fv3jedi::State xxBkgDet(detBkgGeom, incrVars, currentCycle); - xxBkgDet.read(detBkgConfig); - - // Initialize ensemble mean analysis - fv3jedi::State xxAnlEnsMean(ensMeanAnlGeom, incrVars, currentCycle); - xxAnlEnsMean.read(ensMeanAnlConfig); - - // Compute analysis - fv3jedi::State xxAnlVar(detBkgGeom, xxBkgDet); - xxAnlVar += dxVar; - - // Interpolate full resolution analysis to ensemble resolution - fv3jedi::State xxAnlVarEnsRes(corIncrGeom, xxAnlVar); - - // Compute correction increment - fv3jedi::Increment dxCor(corIncrGeom, incrVars, xxBkgDet.validTime()); - dxCor.diff(xxAnlVarEnsRes, xxAnlEnsMean); - - // Write correction increment - dxCor.write(corIncrConfig); - } - - return 0; - } - - private: - std::string appname() const { - return "gdasapp::ecen"; - } - }; -} // namespace gdasapp diff --git a/utils/fv3jedi/fv3jedi_ensemble_recenter.cc b/utils/fv3jedi/fv3jedi_ensemble_recenter.cc new file mode 100644 index 000000000..195f58da4 --- /dev/null +++ b/utils/fv3jedi/fv3jedi_ensemble_recenter.cc @@ -0,0 +1,8 @@ +#include "fv3jedi_ensemble_recenter.h" +#include "oops/runs/Run.h" + +int main(int argc, char ** argv) { + oops::Run run(argc, argv); + gdasapp::EnsembleRecenter EnsembleRecenter; + return run.execute(EnsembleRecenter); +} diff --git a/utils/fv3jedi/fv3jedi_ensemble_recenter.h b/utils/fv3jedi/fv3jedi_ensemble_recenter.h new file mode 100644 index 000000000..3aeec314d --- /dev/null +++ b/utils/fv3jedi/fv3jedi_ensemble_recenter.h @@ -0,0 +1,120 @@ +#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" +#include "oops/util/parameters/OptionalParameter.h" +#include "oops/util/parameters/Parameter.h" +#include "oops/util/parameters/Parameters.h" +#include "oops/util/parameters/RequiredParameter.h" + +class ForecastHourParameters : public oops::Parameters { + OOPS_CONCRETE_PARAMETERS(ForecastHourParameters, Parameters) + public: + oops::RequiredParameter fcstTimeStr{"forecast time", \ + this}; + oops::RequiredParameter detBkgConfig{"deterministic background", \ + this}; + oops::RequiredParameter varIncrConfig{"variational increment", \ + this}; + oops::RequiredParameter ensMeanAnlConfig{"ensemble mean analysis", \ + this}; + oops::RequiredParameter corIncrConfig{"correction increment", \ + this}; +}; + +class EnsembleRecenterParameters : public oops::Parameters { + OOPS_CONCRETE_PARAMETERS(EnsembleRecenterParameters, Parameters) + public: + oops::RequiredParameter \ + incrVars{"increment variables", this}; + oops::RequiredParameter \ + varIncrGeomConfig{"variational increment geometry", this}; + oops::RequiredParameter \ + detBkgGeomConfig{"deterministic background geometry", this}; + oops::RequiredParameter \ + ensMeanAnlGeomConfig{"ensemble mean analysis geometry", this}; + oops::RequiredParameter \ + corIncrGeomConfig{"correction increment geometry", this}; + oops::RequiredParameter> \ + fcstHourParams{"forecast hours", this}; +}; + +namespace gdasapp { + + // Main application class + class EnsembleRecenter : public oops::Application { + public: + explicit EnsembleRecenter(const eckit::mpi::Comm & comm = oops::mpi::world()) + : Application(comm) {} + static const std::string classname() {return "gdasapp::EnsembleRecenter";} + + int execute(const eckit::Configuration & fullConfig) const { + // Deserialize parameters + EnsembleRecenterParameters params; + params.deserialize(fullConfig); + + // Setup geometries + const fv3jedi::Geometry varIncrGeom(params.varIncrGeomConfig.value(), this->getComm()); + const fv3jedi::Geometry detBkgGeom(params.detBkgGeomConfig.value(), this->getComm()); + const fv3jedi::Geometry ensMeanAnlGeom(params.ensMeanAnlGeomConfig.value(), this->getComm()); + const fv3jedi::Geometry corIncrGeom(params.corIncrGeomConfig.value(), this->getComm()); + + // Loop through forecast hours ("recenterings") + const int nhours = params.fcstHourParams.value().size(); + for ( int ihour = 0; ihour < nhours; ihour++ ) { + const ForecastHourParameters fcstHourParams = params.fcstHourParams.value()[ihour]; + + // Get forecast time + const util::DateTime fcstTime(fcstHourParams.fcstTimeStr.value()); + + // Initialize background + fv3jedi::State xxBkgDet(detBkgGeom, params.incrVars.value(), fcstTime); + xxBkgDet.read(fcstHourParams.detBkgConfig.value()); + + // Initialize increment + fv3jedi::Increment dxVar(varIncrGeom, params.incrVars.value(), fcstTime); + dxVar.read(fcstHourParams.varIncrConfig.value()); + + // Initialize ensemble mean analysis + fv3jedi::State xxAnlEnsMean(ensMeanAnlGeom, params.incrVars.value(), fcstTime); + xxAnlEnsMean.read(fcstHourParams.ensMeanAnlConfig.value()); + + // Compute analysis + fv3jedi::State xxAnlVar(detBkgGeom, xxBkgDet); + xxAnlVar += dxVar; + + // Interpolate full resolution analysis to ensemble resolution + fv3jedi::State xxAnlVarEnsRes(corIncrGeom, xxAnlVar); + + // Compute correction increment + fv3jedi::Increment dxCor(corIncrGeom, params.incrVars.value(), fcstTime); + dxCor.diff(xxAnlVarEnsRes, xxAnlEnsMean); + + // Write correction increment + dxCor.write(fcstHourParams.corIncrConfig.value()); + } + + return 0; + } + + private: + std::string appname() const { + return "gdasapp::EnsembleRecenter"; + } + }; +} // namespace gdasapp