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

implement a procedure to carry out a regridding from high to low resolution (binning) #191

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
236ed1f
implemented a procedure to evaluate the areas of the grid cell (grid …
mo-lormi May 3, 2024
83beabe
implemented a procedure to carry out a regridding from high to low re…
mo-lormi May 3, 2024
08a2f06
added test for the regridding procedure (high to low resolution)
mo-lormi May 3, 2024
7f3705a
updated build procedure
mo-lormi May 3, 2024
87312a5
update 03.05.24-01
mo-lormi May 3, 2024
3f1fdfd
updated build procedure
mo-lormi May 9, 2024
475e9f0
added check to identify and ignore an empty row
mo-lormi May 9, 2024
dbf3bea
updated setup procedure for the method 'binning'
mo-lormi May 9, 2024
41c8e4c
update 10.05.24-01
mo-lormi May 10, 2024
15f92a4
added flag to control the adjoint operation
mo-lormi May 10, 2024
0f97c05
added tests to battery of tests
mo-lormi May 10, 2024
a05b292
update 10.05.24-02
mo-lormi May 10, 2024
2494b51
merged branch develop into feature/interpolation_binning_01
mo-lormi Jun 7, 2024
2d63679
added halo exchange operation before generating Gmsh data
mo-lormi Jun 7, 2024
25e9b59
removed variable grid_type_
mo-lormi Jun 7, 2024
1631e61
removed unnecessary namespaces
mo-lormi Jun 7, 2024
c9cbaeb
update 07.06.24-01
mo-lormi Jun 7, 2024
4b8e336
update 07.06.24-02
mo-lormi Jun 7, 2024
fb36305
update 07.06.24-03
mo-lormi Jun 7, 2024
c0b8577
update 07.06.24-04
mo-lormi Jun 7, 2024
d766d88
Consistency with SphericalVector: rename 'ancillary_scheme' to 'scheme'
wdeconinck Jun 10, 2024
b09c2a5
Fix intent of halo_exchange and adjoint in Binning method
wdeconinck Jun 10, 2024
d31023e
Remove SphericalVector::adjoint_ and use base class
wdeconinck Jun 10, 2024
9f8aab0
No casting to CubedSphereProjection necessary
wdeconinck Jun 11, 2024
175d12f
Reduce dimensionality of area field
wdeconinck Jun 11, 2024
2df6ac7
redefined the procedure to evaluate the areas of the grid cells
mo-lormi Jun 13, 2024
1e45e6f
updated build procedure
mo-lormi Jun 13, 2024
7aa4ec8
update 14.06.24-01
mo-lormi Jun 14, 2024
9390bdc
Merge branch 'develop' into feature/interpolation_binning_01
wdeconinck Jun 17, 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
8 changes: 6 additions & 2 deletions src/atlas/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,6 @@ mesh/detail/AccumulateFacets.cc
util/Unique.h
util/Unique.cc

mesh/actions/ExtendNodesGlobal.h
mesh/actions/ExtendNodesGlobal.cc
mesh/actions/BuildDualMesh.h
mesh/actions/BuildCellCentres.cc
mesh/actions/BuildCellCentres.h
Expand All @@ -401,6 +399,10 @@ mesh/actions/BuildStatistics.cc
mesh/actions/BuildStatistics.h
mesh/actions/BuildXYZField.cc
mesh/actions/BuildXYZField.h
mesh/actions/ExtendNodesGlobal.h
mesh/actions/ExtendNodesGlobal.cc
mesh/actions/GetCubedSphereNodalArea.cc
mesh/actions/GetCubedSphereNodalArea.h
mesh/actions/WriteLoadBalanceReport.cc
mesh/actions/BuildTorusXYZField.h
mesh/actions/BuildTorusXYZField.cc
Expand Down Expand Up @@ -618,6 +620,8 @@ interpolation/method/PointIndex3.cc
interpolation/method/PointIndex3.h
interpolation/method/PointIndex2.cc
interpolation/method/PointIndex2.h
interpolation/method/binning/Binning.cc
interpolation/method/binning/Binning.h
interpolation/method/cubedsphere/CubedSphereBilinear.cc
interpolation/method/cubedsphere/CubedSphereBilinear.h
interpolation/method/knn/GridBox.cc
Expand Down
4 changes: 2 additions & 2 deletions src/atlas/grid/detail/grid/CubedSphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class CubedSphere : public Grid {
virtual std::string name() const override;
virtual std::string type() const override;

// Return number of faces on cube
// Return N_, where (N_ * N_) is the number of cells on a tile
inline idx_t N() const { return N_; }

// Access to the tile class
Expand Down Expand Up @@ -436,7 +436,7 @@ class CubedSphere : public Grid {
void xyt2xy(const double xyt[], double xy[]) const;

protected:
// Number of faces on tile
// (N_ * N_) = number of cells on a tile
idx_t N_;

// Number of tiles
Expand Down
2 changes: 1 addition & 1 deletion src/atlas/interpolation/method/Method.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ class Method : public util::Object {
interpolation::MatrixCache matrix_cache_;
NonLinear nonLinear_;
std::string linalg_backend_;
bool adjoint_{false};
Matrix matrix_transpose_;

protected:
bool adjoint_{false};
bool allow_halo_exchange_{true};
std::vector<idx_t> missing_;
};
Expand Down
2 changes: 2 additions & 0 deletions src/atlas/interpolation/method/MethodFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "MethodFactory.h"

// for static linking
#include "binning/Binning.h"
#include "cubedsphere/CubedSphereBilinear.h"
#include "knn/GridBoxAverage.h"
#include "knn/GridBoxMaximum.h"
Expand Down Expand Up @@ -49,6 +50,7 @@ void force_link() {
MethodBuilder<method::GridBoxMaximum>();
MethodBuilder<method::CubedSphereBilinear>();
MethodBuilder<method::SphericalVector>();
MethodBuilder<method::Binning>();
}
} link;
}
Expand Down
186 changes: 186 additions & 0 deletions src/atlas/interpolation/method/binning/Binning.cc
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
74 changes: 74 additions & 0 deletions src/atlas/interpolation/method/binning/Binning.h
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
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ class SphericalVector : public Method {
void do_setup(const Grid& source, const Grid& target, const Cache&) override;

eckit::LocalConfiguration interpolationScheme_{};
bool adjoint_{};

FunctionSpace source_{};
FunctionSpace target_{};
Expand Down
Loading
Loading