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

Add 3DVar and error covariance toolbox (dirac test) main programs. #106

Merged
merged 24 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0a98ddb
Add 3DVar and error covariance toolbox (dirac test) main programs.
frld Jul 26, 2024
c252483
Add initial version of 3dvar and dirac ctest.
frld Jul 26, 2024
95f4279
Add saber to citest.
frld Jul 26, 2024
ed041af
Another attempt to fix CI test. Add state tofieldset test.
frld Jul 26, 2024
fd34d29
Fixes to yaml files. Dirac test working. 3DVar needs adjoint
frld Jul 29, 2024
fa7c893
Add interpolator increment apply and adjoint methods and add incremen…
frld Jul 30, 2024
a197c85
Merge branch 'develop' into feature/add_simple_dirac_3dvar
frld Aug 22, 2024
0f760ef
Initial attempt to implement an increment interpolator unit test.
frld Sep 13, 2024
da0ee33
Merge branch 'develop' into feature/add_simple_dirac_3dvar
frld Sep 13, 2024
7eab74e
Fixes to new interpolator unit tests.
frld Sep 13, 2024
a999325
interpolator adjoint deal with missing values.
frld Sep 13, 2024
df0992a
Add some additional code to respect fillvalues.
frld Sep 20, 2024
52ea581
Update ci container (#117)
twsearle Sep 24, 2024
f4e160f
Fix coding norms.
frld Sep 24, 2024
a7c038c
Merge branch 'develop' into feature/add_simple_dirac_3dvar
frld Sep 24, 2024
c8d3372
Tidying up.
frld Sep 24, 2024
cc01553
Merge branch 'develop' into feature/add_simple_dirac_3dvar
frld Sep 26, 2024
dade994
Fix a merge error.
frld Sep 26, 2024
d873f0a
Apply suggestions from code review
frld Oct 2, 2024
bbcb396
Update copyrights.
frld Oct 2, 2024
465dfab
Merge branch 'feature/add_simple_dirac_3dvar' of https://github.com/M…
frld Oct 2, 2024
6614b47
Add reference data for 3dvar and dirac application tests. Turn off
frld Oct 2, 2024
5591c76
Update 3dvar 3dvar 3dvar minimizer to DRPCG as recommended.
frld Oct 2, 2024
5d57b35
Rename ice to sic to match other tests etc.
frld Oct 9, 2024
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
17 changes: 16 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ on:
branches: [develop]
pull_request:
branches: [develop]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: twsearle/orca-jedi/ci-almalinux9:v1.3.0
IMAGE_NAME: twsearle/orca-jedi/ci-almalinux9:v1.4.0
jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -32,6 +33,20 @@ jobs:
repository: JCSDA-internal/oops
token: ${{ secrets.GHCR_PAT }}

- name: checkout vader
uses: actions/checkout@v3
with:
path: ci/vader
repository: JCSDA-internal/vader
token: ${{ secrets.GHCR_PAT }}

- name: checkout saber
uses: actions/checkout@v3
with:
path: ci/saber
repository: JCSDA-internal/saber
token: ${{ secrets.GHCR_PAT }}

- name: checkout ioda
uses: actions/checkout@v3
with:
Expand Down
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ ecbuild_debug( " atlas_orca_FEATURES: [${atlas_orca_FEATURES}]" )
find_package( oops REQUIRED )
ecbuild_debug( " oops_FEATURES : [${oops_FEATURES}]" )

find_package( saber REQUIRED)
ecbuild_debug( " saber_FEATURES : [${saber_FEATURES}]" )

find_package( ufo REQUIRED)
ecbuild_debug( " ufo_FEATURES : [${ufo_FEATURES}]" )

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.0
1.4.0
2 changes: 2 additions & 0 deletions ci/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ if(NOT DEFINED jedicmake_DIR)
endif()

add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/oops" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/vader" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/saber" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/ioda" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/ufo" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/orca-jedi")
Expand Down
8 changes: 8 additions & 0 deletions ci/hpccm_recipe_almalinux9.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def gitlab_url(repo, vn):
odc_vn = USERARG.get('odc_vn', '1.5.2')
openmpi_vn = USERARG.get('openmpi_vn', '4.1.5')
pycodestyle_vn = USERARG.get('pycodestyle_vn', '2.10')
qhull_vn = USERARG.get('qhull_vn', '8.0.2') # no qhull-devel rpm
udunits_vn = USERARG.get('udunits_vn', '2.2.28')
yaxt_vn = USERARG.get('yaxt_vn', '528-0.10.0') # URL has a number and a version

Expand Down Expand Up @@ -203,6 +204,13 @@ def gitlab_url(repo, vn):
cmake_opts=['-DCMAKE_BUILD_TYPE=Release', '-DJSON_BuildTests=OFF'],
)

Stage0 += generic_cmake(
prefix='/usr/local',
url=github_url('qhull/qhull', f'v{qhull_vn}'),
directory=f'qhull-{qhull_vn}',
cmake_opts=['-DCMAKE_BUILD_TYPE=Release'],
)

Stage0 += generic_cmake(
prefix='/usr/local',
url=github_url('NOAA-EMC/NCEPLIBS-bufr', f'v{nceplibs_bufr_vn}'),
Expand Down
21 changes: 21 additions & 0 deletions src/mains/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ if( ${nemo-feedback_FOUND} )
LIBS orcamodel nemo_feedback
DEFINITIONS NEMO_FEEDBACK_EXISTS
)

ecbuild_add_executable( TARGET orcamodel_3DVar.x
SOURCES orcamodel3DVar.cc
LIBS orcamodel nemo_feedback
DEFINITIONS NEMO_FEEDBACK_EXISTS
)
else()
message(" compiling without feedback file support")
ecbuild_add_executable( TARGET orcamodel_hofx.x
Expand All @@ -22,6 +28,21 @@ else()
SOURCES orcamodelHofX3D.cc
LIBS orcamodel
)

ecbuild_add_executable( TARGET orcamodel_3DVar.x
SOURCES orcamodel3DVar.cc
LIBS orcamodel
)
endif()

ecbuild_add_executable( TARGET orcamodel_ErrorCovarianceToolbox.x
SOURCES orcamodelErrorCovarianceToolbox.cc
LIBS orcamodel
)

oops_output_json_schema( "orcamodel_hofx.x" )
oops_output_json_schema( "orcamodel_hofx3D.x" )
# The applications below throw an error generating json schema.
# This appears to be a generic issue see also oops/qg/mains/CMakeLists.txt
#oops_output_json_schema( "orcamodel_3DVar.x" )
#oops_output_json_schema( "orcamodel_ErrorCovarianceToolbox.x" )
frld marked this conversation as resolved.
Show resolved Hide resolved
36 changes: 36 additions & 0 deletions src/mains/orcamodel3DVar.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* (C) British Crown Copyright 2024 MetOffice
*
* 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 "atlas/library/Library.h"
#include "oops/generic/instantiateModelFactory.h"

#include "oops/runs/Run.h"
#include "oops/runs/Variational.h"
#include "saber/oops/instantiateCovarFactory.h"

#include "ufo/ObsTraits.h"
#include "ufo/instantiateObsFilterFactory.h"
#if defined(NEMO_FEEDBACK_EXISTS)
#include "nemo-feedback/instantiateObsFilterFactory.h"
#endif

#include "orca-jedi/utilities/OrcaModelTraits.h"

int main(int argc, char ** argv) {
oops::Run run(argc, argv);
oops::instantiateModelFactory<orcamodel::OrcaModelTraits>();
atlas::Library::instance().initialise();
saber::instantiateCovarFactory<orcamodel::OrcaModelTraits>();
ufo::instantiateObsFilterFactory();
#if defined(NEMO_FEEDBACK_EXISTS)
nemo_feedback::instantiateObsFilterFactory<ufo::ObsTraits>();
#endif
oops::Variational<orcamodel::OrcaModelTraits , ufo::ObsTraits> var;
int i = run.execute(var);
atlas::Library::instance().finalise();
return i;
}
25 changes: 25 additions & 0 deletions src/mains/orcamodelErrorCovarianceToolbox.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* (C) British Crown Copyright 2024 MetOffice
*
* 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 "atlas/library/Library.h"

#include "saber/oops/ErrorCovarianceToolbox.h"
#include "saber/oops/instantiateCovarFactory.h"

#include "oops/runs/Run.h"
#include "orca-jedi/utilities/OrcaModelTraits.h"

int main(int argc, char ** argv) {
oops::Run run(argc, argv);
atlas::Library::instance().initialise();
saber::instantiateCovarFactory<orcamodel::OrcaModelTraits>();

saber::ErrorCovarianceToolbox<orcamodel::OrcaModelTraits> var;
int i = run.execute(var);
atlas::Library::instance().finalise();
return i;
}
7 changes: 6 additions & 1 deletion src/orca-jedi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,20 @@ utilities/Types.h
utilities/Types.cc
utilities/IOUtils.h
utilities/IOUtils.cc
utilities/ModelData.h
utilities/ModelData.cc
variablechanges/VariableChangeParameters.h
variablechanges/VariableChange.h
variablechanges/LinearVariableChange.h
variablechanges/LinearVariableChange.cc
variablechanges/LinearVariableChangeParameters.h
)



ecbuild_add_library( TARGET orcamodel
SOURCES ${oops_orcamodel_src_files}
PUBLIC_LIBS oops ufo atlas atlas-orca eckit netcdf
PUBLIC_LIBS oops saber ufo atlas atlas-orca eckit netcdf
INSTALL_HEADERS LISTED
LINKER_LANGUAGE ${OOPS_LINKER_LANGUAGE}
)
Expand Down
25 changes: 20 additions & 5 deletions src/orca-jedi/increment/Increment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Increment & Increment::operator*=(const double & zz) {
return *this;
}

/// \brief Create increment from the different of two state objects.
/// \brief Create increment from the difference of two state objects.
/// \param x1 State object.
/// \param x2 State object subtracted.
void Increment::diff(const State & x1, const State & x2) {
Expand All @@ -222,6 +222,12 @@ void Increment::diff(const State & x1, const State & x2) {
atlas::Field field2 = x2.getField(i);
atlas::Field fieldi = incrementFields_[i];

atlas::field::MissingValue mv1(field1);
bool has_mv1 = static_cast<bool>(mv1);
atlas::field::MissingValue mv2(field2);
bool has_mv2 = static_cast<bool>(mv2);
bool has_mv = has_mv1 || has_mv2;

std::string fieldName1 = field1.name();
std::string fieldName2 = field2.name();
std::string fieldNamei = fieldi.name();
Expand All @@ -234,8 +240,15 @@ void Increment::diff(const State & x1, const State & x2) {
auto field_viewi = atlas::array::make_view<double, 2>(fieldi);
for (atlas::idx_t j = 0; j < field_viewi.shape(0); ++j) {
for (atlas::idx_t k = 0; k < field_viewi.shape(1); ++k) {
if (!ghost(j)) { field_viewi(j, k) = field_view1(j, k) - field_view2(j, k);
} else { field_viewi(j, k) = 0; }
if (!ghost(j)) {
if (!has_mv1 || (has_mv1 && !mv1(field_view1(j, k)))) {
if (!has_mv2 || (has_mv2 && !mv2(field_view2(j, k)))) {
field_viewi(j, k) = field_view1(j, k) - field_view2(j, k);
}
}
} else {
field_viewi(j, k) = 0;
}
}
}
}
Expand Down Expand Up @@ -532,7 +545,7 @@ void Increment::read(const eckit::Configuration & conf) {
throw eckit::NotImplemented(err_message, Here());
}

/// \brief write out increments fields to a file using params specified filename.
/// \brief Write out increments fields to a file using params specified filename.
void Increment::write(const OrcaIncrementParameters & params) const {
oops::Log::debug() << "orcamodel::increment::write" << std::endl;

Expand All @@ -545,10 +558,12 @@ void Increment::write(const OrcaIncrementParameters & params) const {
oops::Log::debug() << "Increment::write to filename "
<< nemo_field_path << std::endl;

incrementFields_.haloExchange();

writeFieldsToFile(nemo_field_path, *geom_, time_, incrementFields_);
}

/// \brief write out increments fields to a file using config specified filename.
/// \brief Write out increments fields to a file using config specified filename.
void Increment::write(const eckit::Configuration & config) const {
write(oops::validateAndDeserialize<OrcaIncrementParameters>(config));
}
Expand Down
123 changes: 123 additions & 0 deletions src/orca-jedi/interpolator/Interpolator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "orca-jedi/geometry/Geometry.h"
#include "orca-jedi/state/State.h"
#include "orca-jedi/increment/Increment.h"

#include "orca-jedi/interpolator/Interpolator.h"

Expand Down Expand Up @@ -177,6 +178,128 @@ template void Interpolator::executeInterpolation<float>(
const std::vector<bool> & mask,
std::vector<double>::iterator& iter) const;

/// \brief Interpolate from model space to observation space
/// \param vars Oops variables
/// \param inc Increment object (input)
/// \param mask Mask vector in observation space
/// \param result Result (output) vector in observation space
void Interpolator::apply(const oops::Variables& vars, const Increment& inc,
const std::vector<bool> & mask,
std::vector<double>& result) const {
// input is inc output is result
const size_t nvars = vars.size();

for (size_t j=0; j < nvars; ++j) {
if (!inc.variables().has(vars[j])) {
std::stringstream err_stream;
err_stream << "orcamodel::Interpolator::apply varname \" "
<< "\" " << vars[j]
<< " not found in the model increment." << std::endl;
err_stream << " add the variable to the increment variables and "
<< "add a mapping from the geometry to that variable."
<< std::endl;
throw eckit::BadParameter(err_stream.str(), Here());
}
}

const std::vector<size_t> varSizes =
inc.geometry()->variableSizes(vars);
size_t nvals = 0;
for (size_t jvar=0; jvar < nvars; ++jvar) nvals += nlocs_ * varSizes[jvar];
result.resize(nvals);

std::size_t out_idx = 0;
for (size_t jvar=0; jvar < nvars; ++jvar) {
auto gv_varname = vars[jvar].name();
atlas::Field tgt_field = atlasObsFuncSpace_.createField<double>(
atlas::option::name(gv_varname) |
atlas::option::levels(varSizes[jvar]));
interpolator_.execute(inc.incrementFields()[gv_varname], tgt_field);
auto field_view = atlas::array::make_view<double, 2>(tgt_field);
atlas::field::MissingValue mv(inc.incrementFields()[gv_varname]);
bool has_mv = static_cast<bool>(mv);
for (std::size_t klev=0; klev < varSizes[jvar]; ++klev) {
for (std::size_t iloc=0; iloc < nlocs_; iloc++) {
if (has_mv && mv(field_view(iloc, klev))) {
result[out_idx] = util::missingValue<double>();
} else {
result[out_idx] = field_view(iloc, klev);
}
++out_idx;
}
}
}
frld marked this conversation as resolved.
Show resolved Hide resolved
}

/// \brief Interpolate from observation space to model space
/// \param vars Oops variables
/// \param inc Increment object (output)
/// \param mask Mask (observation space) vector
/// \param resultin Values (observation space) vector (input)
void Interpolator::applyAD(const oops::Variables& vars, Increment& inc,
const std::vector<bool> & mask,
const std::vector<double> & resultin) const
{
// input is resultin output is inc

oops::Log::trace() << "orcamodel::Interpolator::applyAD start "
<< std::endl;

const size_t nvars = vars.size();

for (size_t j=0; j < nvars; ++j) {
if (!inc.variables().has(vars[j])) {
std::stringstream err_stream;
err_stream << "orcamodel::Interpolator::apply varname \" "
<< "\" " << vars[j]
<< " not found in the model increment." << std::endl;
err_stream << " add the variable to the increment variables and "
<< "add a mapping from the geometry to that variable."
<< std::endl;
throw eckit::BadParameter(err_stream.str(), Here());
}
}

const std::vector<size_t> varSizes =
inc.geometry()->variableSizes(vars);
size_t nvals = 0;

for (size_t jvar=0; jvar < nvars; ++jvar) nvals += nlocs_ * varSizes[jvar];

std::size_t out_idx = 0;
for (size_t jvar=0; jvar < nvars; ++jvar) {
auto gv_varname = vars[jvar].name();
auto tgt_field = atlasObsFuncSpace_.createField<double>(
atlas::option::name(gv_varname) |
atlas::option::levels(varSizes[jvar]));

// Copying observation array vector to an atlas observation field (tgt_field)
auto field_view = atlas::array::make_view<double, 2>(tgt_field);
atlas::field::MissingValue mv(inc.incrementFields()[gv_varname]);
bool has_mv = static_cast<bool>(mv);

for (std::size_t klev=0; klev < varSizes[jvar]; ++klev) {
for (std::size_t iloc=0; iloc < nlocs_; iloc++) {
if (has_mv && mv(field_view(iloc, klev))) {
field_view(iloc, klev) = util::missingValue<double>();
} else {
field_view(iloc, klev) = resultin[out_idx];
}
++out_idx;
}
}

// halo exchange update ghost points
std::shared_ptr<const Geometry> geom = inc.geometry();
geom->functionSpace().haloExchange(inc.incrementFields()[gv_varname]);

interpolator_.execute_adjoint(inc.incrementFields()[gv_varname], tgt_field);
frld marked this conversation as resolved.
Show resolved Hide resolved
} // jvar

oops::Log::trace() << "orcamodel::Interpolator::applyAD done "
<< std::endl;
}

void Interpolator::print(std::ostream & os) const {
os << "orcamodel::Interpolator: " << std::endl;
os << " Obs function space " << atlasObsFuncSpace_ << std::endl;
Expand Down
Loading
Loading