-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement a procedure to carry out a regridding from high to low reso…
…lution (binning) (#191) * implemented a procedure to evaluate the areas of the grid cell (grid type: CS-LFR) * implemented a procedure to carry out a regridding from high to low resolution (binning) * added test for the regridding procedure (high to low resolution) * updated build procedure * update 03.05.24-01 * updated build procedure * added check to identify and ignore an empty row * updated setup procedure for the method 'binning' * update 10.05.24-01 * added flag to control the adjoint operation * added tests to battery of tests * update 10.05.24-02 * added halo exchange operation before generating Gmsh data * removed variable grid_type_ * removed unnecessary namespaces * update 07.06.24-01 * update 07.06.24-02 * update 07.06.24-03 * update 07.06.24-04 * Consistency with SphericalVector: rename 'ancillary_scheme' to 'scheme' * Fix intent of halo_exchange and adjoint in Binning method * Remove SphericalVector::adjoint_ and use base class * No casting to CubedSphereProjection necessary * Reduce dimensionality of area field * redefined the procedure to evaluate the areas of the grid cells * updated build procedure * update 14.06.24-01 --------- Co-authored-by: Willem Deconinck <willem.deconinck@ecmwf.int>
- Loading branch information
1 parent
3f0055c
commit c4d34f8
Showing
11 changed files
with
661 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
/* | ||
* (C) Crown Copyright 2024 Met Office | ||
* | ||
* 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/functionspace/NodeColumns.h" | ||
#include "atlas/functionspace/StructuredColumns.h" | ||
#include "atlas/grid.h" | ||
#include "atlas/interpolation/Interpolation.h" | ||
#include "atlas/interpolation/method/binning/Binning.h" | ||
#include "atlas/interpolation/method/MethodFactory.h" | ||
#include "atlas/mesh.h" | ||
#include "atlas/mesh/actions/GetCubedSphereNodalArea.h" | ||
#include "atlas/runtime/Trace.h" | ||
|
||
#include "eckit/config/LocalConfiguration.h" | ||
#include "eckit/linalg/SparseMatrix.h" | ||
#include "eckit/linalg/Triplet.h" | ||
#include "eckit/mpi/Comm.h" | ||
|
||
|
||
namespace atlas { | ||
namespace interpolation { | ||
namespace method { | ||
|
||
|
||
namespace { | ||
|
||
MethodBuilder<Binning> __builder("binning"); | ||
|
||
} | ||
|
||
|
||
Binning::Binning(const Config& config) : Method(config) { | ||
const auto* conf = dynamic_cast<const eckit::LocalConfiguration*>(&config); | ||
ATLAS_ASSERT(conf, "config must be derived from eckit::LocalConfiguration"); | ||
interpAncillaryScheme_ = conf->getSubConfiguration("scheme"); | ||
// enabling or disabling the adjoint operation | ||
adjoint_ = conf->getBool("adjoint", false); | ||
// enabling or disabling the halo exchange | ||
allow_halo_exchange_ = conf->getBool("halo_exchange", true); | ||
} | ||
|
||
|
||
void Binning::do_setup(const Grid& source, | ||
const Grid& target, | ||
const Cache&) { | ||
ATLAS_NOTIMPLEMENTED; | ||
} | ||
|
||
|
||
void Binning::do_setup(const FunctionSpace& source, | ||
const FunctionSpace& target) { | ||
ATLAS_TRACE("atlas::interpolation::method::Binning::do_setup()"); | ||
|
||
using Index = eckit::linalg::Index; | ||
using Triplet = eckit::linalg::Triplet; | ||
using SMatrix = eckit::linalg::SparseMatrix; | ||
|
||
source_ = source; | ||
target_ = target; | ||
|
||
if (target_.size() == 0) { | ||
return; | ||
} | ||
|
||
// note that the 'source' grid for the low-to-high regridding (interpolation) | ||
// is the 'target' grid for high-to-low regridding (binning) and | ||
// the 'target' grid for the low-to-high regridding (interpolation) is the | ||
// 'source' grid for the for high-to-low regridding (binning) | ||
const auto& fs_source_interp = target_; | ||
const auto& fs_target_interp = source_; | ||
|
||
const auto interp = Interpolation( | ||
interpAncillaryScheme_, fs_source_interp, fs_target_interp); | ||
auto smx_interp_cache = interpolation::MatrixCache(interp); | ||
|
||
auto smx_interp = smx_interp_cache.matrix(); | ||
|
||
auto smx_interp_tr = smx_interp.transpose(); | ||
|
||
const auto rows_tamx = smx_interp_tr.rows(); | ||
const auto cols_tamx = smx_interp_tr.cols(); | ||
|
||
const double* ptr_tamx_data = smx_interp_tr.data(); | ||
const Index* ptr_tamx_idxs_col = smx_interp_tr.inner(); | ||
const Index* ptr_tamx_o = smx_interp_tr.outer(); | ||
|
||
// diagonal of 'area weights matrix', W | ||
auto ds_aweights = getAreaWeights(source_); | ||
|
||
auto smx_binning_els = std::vector<Triplet>{}; | ||
size_t idx_row_next = 0; | ||
|
||
for (size_t idx_row = 0; idx_row < rows_tamx; ++idx_row) { | ||
idx_row_next = (idx_row+1); | ||
// start of the indexes associated with the row 'i' | ||
size_t lbound = ptr_tamx_o[idx_row]; | ||
// start of the indexes associated with the row 'i+1' | ||
size_t ubound = ptr_tamx_o[idx_row_next]; | ||
|
||
if (lbound == ubound) | ||
continue; | ||
|
||
double sum_row = 0; | ||
for (size_t i = lbound; i < ubound; ++i) { | ||
sum_row += (ptr_tamx_data[i] * ds_aweights.at(ptr_tamx_idxs_col[i])); | ||
} | ||
|
||
// normalization factor | ||
double nfactor = 1/sum_row; | ||
|
||
for (size_t i = lbound; i < ubound; ++i) { | ||
// evaluating the non-zero elements of the binning matrix | ||
smx_binning_els.emplace_back( | ||
idx_row, ptr_tamx_idxs_col[i], | ||
(nfactor * (ptr_tamx_data[i] * ds_aweights.at(ptr_tamx_idxs_col[i])))); | ||
} | ||
} | ||
|
||
// 'binning matrix' (sparse matrix), B = N A^T W | ||
SMatrix smx_binning{rows_tamx, cols_tamx, smx_binning_els}; | ||
setMatrix(smx_binning); | ||
} | ||
|
||
|
||
void Binning::print(std::ostream&) const { | ||
ATLAS_NOTIMPLEMENTED; | ||
} | ||
|
||
|
||
std::vector<double> Binning::getAreaWeights(const FunctionSpace& fspace) const { | ||
// diagonal of 'area weights matrix', W | ||
std::vector<double> ds_aweights; | ||
|
||
bool is_cubed_sphere {false}; | ||
if (auto csfs = functionspace::NodeColumns(fspace)) { | ||
if (CubedSphereGrid(csfs.mesh().grid())) { | ||
is_cubed_sphere = true; | ||
} | ||
} | ||
|
||
if (is_cubed_sphere) { | ||
|
||
const auto csfs = functionspace::NodeColumns(fspace); | ||
auto csmesh = csfs.mesh(); | ||
|
||
// areas of the cells (geographic coord. system) | ||
auto gcell_areas = mesh::actions::GetCubedSphereNodalArea()(csmesh); | ||
auto gcell_areas_view = array::make_view<double, 1>(gcell_areas); | ||
|
||
auto is_ghost = array::make_view<int, 1>(csfs.ghost()); | ||
|
||
double total_area {0.}; | ||
for (idx_t i = 0; i < csfs.size(); i++) { | ||
if (!is_ghost[i]) { | ||
total_area += gcell_areas_view(i); | ||
} | ||
} | ||
eckit::mpi::comm().allReduceInPlace(total_area, eckit::mpi::Operation::SUM); | ||
|
||
double aweight_temp {0.}; | ||
for (idx_t i = 0; i < csfs.size(); i++) { | ||
if (!is_ghost[i]) { | ||
aweight_temp = gcell_areas_view(i)/total_area; | ||
ds_aweights.emplace_back(aweight_temp); | ||
} | ||
} | ||
|
||
} else { | ||
|
||
// area weights (default) | ||
ds_aweights.assign(fspace.size(), 1.); | ||
|
||
} | ||
|
||
return ds_aweights; | ||
} | ||
|
||
|
||
} // namespace method | ||
} // namespace interpolation | ||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* (C) Crown Copyright 2024 Met Office | ||
* | ||
* 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. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "atlas/functionspace/FunctionSpace.h" | ||
#include "atlas/interpolation/Cache.h" | ||
#include "atlas/interpolation/method/Method.h" | ||
#include "atlas/grid/Grid.h" | ||
|
||
#include "eckit/config/Configuration.h" | ||
|
||
|
||
namespace atlas { | ||
namespace interpolation { | ||
namespace method { | ||
|
||
|
||
class Binning : public Method { | ||
public: | ||
/// @brief Binning procedure to carry out a regridding from high | ||
/// to low resolution | ||
/// | ||
/// @details This method is part of the family of the Interpolation operations; | ||
/// it relies on the evaluation of the transpose of an interpolation matrix. | ||
/// The rigridding from high to low resolution is carried out by using | ||
/// a 'binning matrix': | ||
/// binning matrix: B = N A^T W | ||
/// area weights matrix: W | ||
/// interpolation matrix: A | ||
/// normalization factor matrix: N | ||
/// | ||
/// Setup, configuration variables: | ||
/// <type>: method used to evaluate the 'B' matrix; | ||
/// value: 'binning' | ||
/// <scheme>: method used to evaluate the 'A' matrix; | ||
/// value: 'cubedsphere-bilinear', 'structured-bilinear', ... | ||
/// <halo_exchange>: flag to control the halo exchange procedure | ||
/// value: 'true', 'false' | ||
/// <adjoint>: flag to control the adjoint operation | ||
/// value: 'true', 'false' | ||
/// | ||
Binning(const Config& config); | ||
~Binning() override {} | ||
|
||
void print(std::ostream&) const override; | ||
const FunctionSpace& source() const override { return source_; } | ||
const FunctionSpace& target() const override { return target_; } | ||
|
||
private: | ||
using Method::do_setup; | ||
void do_setup(const FunctionSpace& source, | ||
const FunctionSpace& target) override; | ||
void do_setup(const Grid& source, const Grid& target, const Cache&) override; | ||
|
||
std::vector<double> getAreaWeights(const FunctionSpace& source) const; | ||
|
||
eckit::LocalConfiguration interpAncillaryScheme_{}; | ||
|
||
FunctionSpace source_{}; | ||
FunctionSpace target_{}; | ||
}; | ||
|
||
|
||
} // namespace method | ||
} // namespace interpolation | ||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.