Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executable to rule them all #1075

Merged
merged 8 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ 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)

Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ set -x
if [[ $BUILD_JCSDA == 'YES' ]]; then
make -j ${BUILD_JOBS:-6} VERBOSE=$BUILD_VERBOSE
else
builddirs="fv3-jedi soca iodaconv land-imsproc land-jediincr gdas-utils"
builddirs="gdas iodaconv land-imsproc land-jediincr gdas-utils"
for b in $builddirs; do
cd $b
make -j ${BUILD_JOBS:-6} VERBOSE=$BUILD_VERBOSE
Expand Down
23 changes: 23 additions & 0 deletions mains/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Build the big gdas executable used for all generic JEDI applications
# --------------------------------------------------------------------
ecbuild_add_executable( TARGET gdas.x
SOURCES gdas.cc
LIBS fv3jedi soca
)

# Build the soca executables that are not OOPS-based
# --------------------------------------------------
ecbuild_add_executable( TARGET gdas_soca_gridgen.x
SOURCES ${CMAKE_SOURCE_DIR}/soca/src/mains/GridGen.cc
LIBS soca
)

ecbuild_add_executable( TARGET gdas_soca_error_covariance_toolbox.x
SOURCES ${CMAKE_SOURCE_DIR}/soca/src/mains/ErrorCovarianceToolbox.cc
LIBS soca saber
)

ecbuild_add_executable( TARGET gdas_soca_setcorscales.x
SOURCES ${CMAKE_SOURCE_DIR}/soca/src/mains/SetCorScales.cc
LIBS soca
)
122 changes: 122 additions & 0 deletions mains/gdas.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// -------------------------------------------------------------------------------------------------

#include <functional>
#include <map>

#include "fv3jedi/ObsLocalization/instantiateObsLocFactory.h"
#include "fv3jedi/Utilities/Traits.h"

#include "soca/Traits.h"

#include "oops/generic/instantiateModelFactory.h"
#include "saber/oops/instantiateCovarFactory.h"
#include "ufo/instantiateObsErrorFactory.h"
#include "ufo/instantiateObsFilterFactory.h"
#include "ufo/ObsTraits.h"

#include "oops/runs/ConvertState.h"
#include "oops/runs/HofX4D.h"
#include "oops/runs/LocalEnsembleDA.h"
#include "oops/runs/Run.h"
#include "oops/runs/Variational.h"

// -------------------------------------------------------------------------------------------------

template<typename Traits>
int runApp(int argc, char** argv, const std::string traits, const std::string appName) {
// Create the Run object
oops::Run run(argc, argv);

// Instantiate oops factories
oops::instantiateModelFactory<Traits>();

// Instantiate saber factories
saber::instantiateCovarFactory<Traits>();

// Intantiate ufo factories
ufo::instantiateObsErrorFactory();
ufo::instantiateObsFilterFactory();

// Localization for ensemble DA
if (appName == "localensembleda") {
if (traits == "fv3jedi") {
fv3jedi::instantiateObsLocFactory();
} else if (traits == "soca") {
ufo::instantiateObsLocFactory<soca::Traits>();
}
}

// Application pointer
std::unique_ptr<oops::Application> app;

// Define a map from app names to lambda functions that create unique_ptr to Applications
std::map<std::string, std::function<std::unique_ptr<oops::Application>()>> apps;

apps["convertstate"] = []() {
CoryMartin-NOAA marked this conversation as resolved.
Show resolved Hide resolved
return std::make_unique<oops::ConvertState<Traits>>();
};
apps["hofx4d"] = []() {
return std::make_unique<oops::HofX4D<Traits, ufo::ObsTraits>>();
};
apps["localensembleda"] = []() {
return std::make_unique<oops::LocalEnsembleDA<fv3jedi::Traits, ufo::ObsTraits>>();
};
apps["variational"] = []() {
return std::make_unique<oops::Variational<Traits, ufo::ObsTraits>>();
};

// Create application object and point to it
auto it = apps.find(appName);

// Run the application
return run.execute(*(it->second()));
}

// -------------------------------------------------------------------------------------------------

int main(int argc, char ** argv) {
// Check that the number of arguments is correct
// ----------------------------------------------
ASSERT_MSG(argc >= 3, "Usage: " + std::string(argv[0]) + " <traits> <application> <options>");

// Get traits from second argument passed to executable
// ----------------------------------------------------
std::string traits = argv[1];
for (char &c : traits) {c = std::tolower(c);}

// Get the application to be run
std::string app = argv[2];
for (char &c : app) {c = std::tolower(c);}

// Check that the traits are recognized
// ------------------------------------
const std::set<std::string> validTraits = {"fv3jedi", "soca"};
ASSERT_MSG(validTraits.find(traits) != validTraits.end(), "Traits not recognized: " + traits);

// Check that the application is recognized
// ----------------------------------------
const std::set<std::string> validApps = {
"convertstate",
"hofx4d",
"localensembleda",
"variational"
};
ASSERT_MSG(validApps.find(app) != validApps.end(), "Application not recognized: " + app);

// Remove traits and program from argc and argv
// --------------------------------------------
argv[2] = argv[0]; // Move executable name to third position
argv += 2; // Move pointer up two
argc -= 2; // Remove 2 from count

// Call application specific main functions
// ----------------------------------------
if (traits == "fv3jedi") {
fv3jedi::instantiateObsLocFactory();
return runApp<fv3jedi::Traits>(argc, argv, traits, app);
} else if (traits == "soca") {
return runApp<soca::Traits>(argc, argv, traits, app);
}
}

// -------------------------------------------------------------------------------------------------
10 changes: 5 additions & 5 deletions scripts/exgdas_global_marine_analysis_bmat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ function clean_yaml()
if [[ -e 'soca_gridspec.nc' ]]; then
echo "soca_gridspc.nc already exists, skip the grid generation step"
else
# Run soca_gridgen.x if the grid was not staged
# Run gdas_soca_gridgen.x if the grid was not staged
# TODO (Guillaume): Should not use all pe's for the grid generation
$APRUN_OCNANAL $JEDI_BIN/soca_gridgen.x gridgen.yaml
$APRUN_OCNANAL $JEDI_BIN/gdas_soca_gridgen.x gridgen.yaml
export err=$?; err_chk
if [ $err -gt 0 ]; then
exit $err
Expand Down Expand Up @@ -101,14 +101,14 @@ fi
# Horizontal diffusion
if [ ! -f "ocn.cor_rh.incr.0001-01-01T00:00:00Z.nc" ]; then
# Set decorrelation scales for the static B
$APRUN_OCNANAL $JEDI_BIN/soca_setcorscales.x soca_setcorscales.yaml
$APRUN_OCNANAL $JEDI_BIN/gdas_soca_setcorscales.x soca_setcorscales.yaml
export err=$?; err_chk
if [ $err -gt 0 ]; then
exit $err
fi
# Initialize the horizontal diffusion block and normalize
clean_yaml soca_parameters_diffusion_hz.yaml
$APRUN_OCNANAL $JEDI_BIN/soca_error_covariance_toolbox.x soca_parameters_diffusion_hz.yaml
$APRUN_OCNANAL $JEDI_BIN/gdas_soca_error_covariance_toolbox.x soca_parameters_diffusion_hz.yaml
export err=$?; err_chk
if [ $err -gt 0 ]; then
exit $err
Expand All @@ -125,7 +125,7 @@ python ${HOMEgfs}/sorc/gdas.cd/sorc/soca/tools/calc_scales.py soca_vtscales.yaml
clean_yaml soca_parameters_diffusion_vt.yaml

# Initialize the vertical diffusion block and normalize
$APRUN_OCNANAL $JEDI_BIN/soca_error_covariance_toolbox.x soca_parameters_diffusion_vt.yaml
$APRUN_OCNANAL $JEDI_BIN/gdas_soca_error_covariance_toolbox.x soca_parameters_diffusion_vt.yaml
export err=$?; err_chk
if [ $err -gt 0 ]; then
exit $err
Expand Down
4 changes: 2 additions & 2 deletions scripts/exgdas_global_marine_analysis_chkpt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ fi
# TODO: This should probably be in a separate j-job, that includes
# the mom6 incr postprocessing from above.

$APRUN_OCNANAL ${JEDI_BIN}/soca_convertstate.x soca_2cice_arctic.yaml
$APRUN_OCNANAL ${JEDI_BIN}/soca_convertstate.x soca_2cice_antarctic.yaml
$APRUN_OCNANAL ${JEDI_BIN}/gdas.x soca convertstate soca_2cice_arctic.yaml
$APRUN_OCNANAL ${JEDI_BIN}/gdas.x soca convertstate soca_2cice_antarctic.yaml
export err=$?; err_chk

################################################################################
Expand Down
2 changes: 1 addition & 1 deletion scripts/exgdas_global_marine_analysis_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function clean_yaml()
# run the variational application
cp var.yaml var_original.yaml
clean_yaml var.yaml
$APRUN_OCNANAL $JEDI_BIN/soca_var.x var.yaml
$APRUN_OCNANAL $JEDI_BIN/gdas.x soca variational var.yaml
export err=$?; err_chk

################################################################################
Expand Down
2 changes: 1 addition & 1 deletion test/aero/global-workflow/config.aeroanl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ export BERROR_DATE="20160630.000000"
export io_layout_x=1
export io_layout_y=1

export JEDIEXE=${HOMEgfs}/exec/fv3jedi_var.x
export JEDIEXE=${HOMEgfs}/exec/gdas.x

echo "END: config.aeroanl"
2 changes: 1 addition & 1 deletion test/atm/global-workflow/config.atmanl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ export layout_y_atmanl=@LAYOUT_Y_ATMANL@
export io_layout_x=@IO_LAYOUT_X@
export io_layout_y=@IO_LAYOUT_Y@

export JEDIEXE=${EXECgfs}/fv3jedi_var.x
export JEDIEXE=${EXECgfs}/gdas.x

echo "END: config.atmanl"
2 changes: 1 addition & 1 deletion test/atm/global-workflow/config.atmensanl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ export layout_y_atmensanl=@LAYOUT_Y_ATMENSANL@
export io_layout_x=@IO_LAYOUT_X@
export io_layout_y=@IO_LAYOUT_Y@

export JEDIEXE=${EXECgfs}/fv3jedi_letkf.x
export JEDIEXE=${EXECgfs}/gdas.x

echo "END: config.atmensanl"
2 changes: 1 addition & 1 deletion test/snow/create_bkg_ens.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ if [[ ${DAtype} == 'letkfoi_snow' ]]; then

B=30 # background error std for LETKFOI

JEDI_EXEC="fv3jedi_letkf.x"
JEDI_EXEC="gdas.x fv3jedi localensembleda"

# FOR LETKFOI, CREATE THE PSEUDO-ENSEMBLE
for ens in 001 002
Expand Down
2 changes: 1 addition & 1 deletion test/snow/letkfoi_snowda.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if [[ ${DAtype} == 'letkfoi_snow' ]]; then

B=30 # background error std for LETKFOI

JEDI_EXEC="fv3jedi_letkf.x"
JEDI_EXEC="gdas.x fv3jedi localensembleda"

# FOR LETKFOI, CREATE THE PSEUDO-ENSEMBLE
for ens in 001 002
Expand Down
2 changes: 1 addition & 1 deletion ush/soca/marine_recenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def run(self):
chdir(self.runtime_config.DATA)

exec_cmd_gridgen = Executable(self.config.APRUN_OCNANALECEN)
exec_name_gridgen = os.path.join(self.config.JEDI_BIN, 'soca_gridgen.x')
exec_name_gridgen = os.path.join(self.config.JEDI_BIN, 'gdas_soca_gridgen.x')
exec_cmd_gridgen.add_default_arg(exec_name_gridgen)
exec_cmd_gridgen.add_default_arg(self.config.gridgen_yaml)

Expand Down
Loading