Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
wdeconinck committed Dec 6, 2024
1 parent 7c1f738 commit 88badf1
Show file tree
Hide file tree
Showing 13 changed files with 460 additions and 379 deletions.
5 changes: 3 additions & 2 deletions src/atlas/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,8 @@ linalg/sparse.h
linalg/sparse/Backend.h
linalg/sparse/Backend.cc
linalg/sparse/MakeEckitSparseMatrix.h
linalg/sparse/MakeSparseMatrixStorageEckit.h
linalg/sparse/MakeSparseMatrixStorageEigen.h
linalg/sparse/SparseMatrixMultiply.h
linalg/sparse/SparseMatrixMultiply.tcc
linalg/sparse/SparseMatrixMultiply_EckitLinalg.h
Expand All @@ -714,8 +716,7 @@ linalg/sparse/SparseMatrixMultiply_OpenMP.h
linalg/sparse/SparseMatrixMultiply_OpenMP.cc
linalg/sparse/SparseMatrixStorage.cc
linalg/sparse/SparseMatrixStorage.h
linalg/sparse/SparseMatrixConvertor.h
linalg/sparse/SparseMatrixAdaptor.h
linalg/sparse/SparseMatrixView.h
linalg/dense.h
linalg/dense/Backend.h
linalg/dense/Backend.cc
Expand Down
2 changes: 1 addition & 1 deletion src/atlas/interpolation/method/Method.cc
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ void Method::setup(const FunctionSpace& source, const FunctionSpace& target) {
if (not matrix_->empty()) {
eckit::linalg::SparseMatrix matrix_copy = make_eckit_sparse_matrix(*matrix_); // Makes a copy!
matrix_copy.transpose(); // transpose the copy in place
matrix_transpose_ = atlas::linalg::SparseMatrixStorage(std::move(matrix_copy)); // Move the copy into storage
matrix_transpose_ = linalg::make_sparse_matrix_storage(std::move(matrix_copy)); // Move the copy into storage
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/atlas/interpolation/method/Method.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "atlas/util/Object.h"
#include "eckit/config/Configuration.h"
#include "eckit/linalg/SparseMatrix.h"
#include "atlas/linalg/sparse/MakeSparseMatrixStorageEckit.h"

namespace atlas {
class Field;
Expand Down Expand Up @@ -122,7 +123,7 @@ class Method : public util::Object {
}

void setMatrix(eckit::linalg::SparseMatrix&& m, const std::string& uid = "") {
setMatrix( Matrix(std::move(m)), uid );
setMatrix( linalg::make_sparse_matrix_storage(std::move(m)), uid );
}

void setMatrix(std::size_t rows, std::size_t cols, const Triplets& triplets, const std::string& uid = "") {
Expand Down
4 changes: 2 additions & 2 deletions src/atlas/linalg/sparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

#include "sparse/Backend.h"
#include "sparse/MakeEckitSparseMatrix.h"
#include "sparse/SparseMatrixAdaptor.h"
#include "sparse/SparseMatrixConvertor.h"
#include "sparse/MakeSparseMatrixStorageEckit.h"
#include "sparse/SparseMatrixMultiply.h"
#include "sparse/SparseMatrixStorage.h"
#include "sparse/SparseMatrixView.h"

namespace atlas {
namespace linalg {} // namespace linalg
Expand Down
135 changes: 135 additions & 0 deletions src/atlas/linalg/sparse/MakeSparseMatrixStorageEckit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* (C) Copyright 2024- ECMWF.
*
* 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.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/

#pragma once

#include <any>
#include <memory>
#include <algorithm>
#include <type_traits>

#include "eckit/linalg/SparseMatrix.h"

#include "atlas/array.h"
#include "atlas/linalg/sparse/SparseMatrixStorage.h"

namespace atlas {
namespace linalg {

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

template<typename OutputT, typename InputT>
void host_copy_eckit (const InputT* input_data, array::Array& output) {
auto size = output.size();
OutputT* output_data = output.host_data<OutputT>();
std::copy( input_data, input_data + size, output_data );
}

inline SparseMatrixStorage make_sparse_matrix_storage(eckit::linalg::SparseMatrix&& m) {
using Index = eckit::linalg::Index;
using Value = eckit::linalg::Scalar;
std::cout << "make_sparse_matrix_storage move" << std::endl;

std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = array::Array::wrap(const_cast<Index*>(m.outer()), array::make_shape(rows+1));
auto* inner = array::Array::wrap(const_cast<Index*>(m.inner()), array::make_shape(nnz));
auto* value = array::Array::wrap(const_cast<Value*>(m.data()), array::make_shape(nnz));

// We now move the eckit::linalg::SparseMatrix into a generic storage so
// the wrapped array data does not go out of scope
auto storage = std::make_any<eckit::linalg::SparseMatrix>(std::move(m));

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<array::Array>(value),
std::unique_ptr<array::Array>(inner),
std::unique_ptr<array::Array>(outer),
std::move(storage)
);
}

template< typename value_type, typename index_type = eckit::linalg::Index>
SparseMatrixStorage make_sparse_matrix_storage(eckit::linalg::SparseMatrix&& m) {
std::cout << "make_sparse_matrix_storage move or convert" << std::endl;

if (std::is_same_v<eckit::linalg::Scalar, value_type> && std::is_same_v<eckit::linalg::Index, index_type>) {
return make_sparse_matrix_storage(std::move(m));
}
std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = array::Array::create<index_type>(rows+1);
auto* inner = array::Array::create<index_type>(nnz);
auto* value = array::Array::create<value_type>(nnz);

host_copy_eckit<index_type>(m.outer(), *outer);
host_copy_eckit<index_type>(m.inner(), *inner);
host_copy_eckit<value_type>(m.data(), *value);

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<array::Array>(value),
std::unique_ptr<array::Array>(inner),
std::unique_ptr<array::Array>(outer),
std::any()
);
}


inline SparseMatrixStorage make_sparse_matrix_storage(const eckit::linalg::SparseMatrix& m) {
using Index = eckit::linalg::Index;
using Value = eckit::linalg::Scalar;

std::cout << "make_sparse_matrix_storage copy" << std::endl;
std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = array::Array::create<Index>(rows+1);
auto* inner = array::Array::create<Index>(nnz);
auto* value = array::Array::create<Value>(nnz);

host_copy_eckit<Index>(m.outer(), *outer);
host_copy_eckit<Index>(m.inner(), *inner);
host_copy_eckit<Value>(m.data(), *value);

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<array::Array>(value),
std::unique_ptr<array::Array>(inner),
std::unique_ptr<array::Array>(outer),
std::any()
);
}

template< typename value_type, typename index_type = eckit::linalg::Index>
SparseMatrixStorage make_sparse_matrix_storage(const eckit::linalg::SparseMatrix& m) {
std::cout << "make_sparse_matrix_storage copy and convert" << std::endl;

std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = array::Array::create<index_type>(rows+1);
auto* inner = array::Array::create<index_type>(nnz);
auto* value = array::Array::create<value_type>(nnz);
host_copy_eckit<index_type>(m.outer(), *outer);
host_copy_eckit<index_type>(m.inner(), *inner);
host_copy_eckit<value_type>(m.data(), *value);

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<array::Array>(value),
std::unique_ptr<array::Array>(inner),
std::unique_ptr<array::Array>(outer),
std::any()
);
}

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

} // namespace linalg
} // namespace atlas
142 changes: 142 additions & 0 deletions src/atlas/linalg/sparse/MakeSparseMatrixStorageEigen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* (C) Copyright 2024- ECMWF.
*
* 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.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/

#pragma once

#include <any>
#include <memory>
#include <algorithm>
#include <type_traits>

#include "atlas/library/defines.h"
#if ATLAS_HAVE_EIGEN
#include <Eigen/Sparse>
#endif

#include "atlas/array.h"
#include "atlas/linalg/sparse/SparseMatrixStorage.h"

namespace atlas {
namespace linalg {

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

#if ATLAS_HAVE_EIGEN

template<typename OutputT, typename InputT>
void host_copy_eigen (const InputT* input_data, atlas::array::Array& output) {
auto size = output.size();
OutputT* output_data = output.host_data<OutputT>();
std::copy( input_data, input_data + size, output_data );
}

template <typename Value, typename Index>
SparseMatrixStorage make_sparse_matrix_storage(Eigen::SparseMatrix<Value, Eigen::RowMajor, Index>&& m) {
std::cout << "make_sparse_matrix_storage move" << std::endl;

std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = atlas::array::Array::wrap(const_cast<Index*>(m.outerIndexPtr()), atlas::array::make_shape(rows+1));
auto* inner = atlas::array::Array::wrap(const_cast<Index*>(m.innerIndexPtr()), atlas::array::make_shape(nnz));
auto* value = atlas::array::Array::wrap(const_cast<Value*>(m.valuePtr()), atlas::array::make_shape(nnz));

using EigenMatrix = Eigen::SparseMatrix<Value, Eigen::RowMajor, Index>;
auto m_ptr = std::make_shared<EigenMatrix>();
m_ptr->swap(m);
auto storage = std::make_any<std::shared_ptr<EigenMatrix>>(std::move(m_ptr));

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<atlas::array::Array>(value),
std::unique_ptr<atlas::array::Array>(inner),
std::unique_ptr<atlas::array::Array>(outer),
std::move(storage)
);
}

template< typename value_type, typename index_type = eckit::linalg::Index, typename Value, typename Index,
typename = std::enable_if_t < !std::is_same_v<value_type,Value>>>
SparseMatrixStorage make_sparse_matrix_storage(Eigen::SparseMatrix<Value, Eigen::RowMajor, Index>&& m) {
std::cout << "make_sparse_matrix_storage move or convert" << std::endl;

if (std::is_same_v<Value, value_type> && std::is_same_v<Index, index_type>) {
return make_sparse_matrix_storage(std::move(m));
}
std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = atlas::array::Array::create<index_type>(rows+1);
auto* inner = atlas::array::Array::create<index_type>(nnz);
auto* value = atlas::array::Array::create<value_type>(nnz);

host_copy_eigen<index_type>(m.outerIndexPtr(), *outer);
host_copy_eigen<index_type>(m.innerIndexPtr(), *inner);
host_copy_eigen<value_type>(m.valuePtr(), *value);

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<atlas::array::Array>(value),
std::unique_ptr<atlas::array::Array>(inner),
std::unique_ptr<atlas::array::Array>(outer),
std::any()
);
}


template <typename Value, typename Index>
SparseMatrixStorage make_sparse_matrix_storage(const Eigen::SparseMatrix<Value, Eigen::RowMajor, Index>& m) {
std::cout << "make_sparse_matrix_storage copy" << std::endl;
std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = atlas::array::Array::create<Index>(rows+1);
auto* inner = atlas::array::Array::create<Index>(nnz);
auto* value = atlas::array::Array::create<Value>(nnz);

host_copy_eigen<Index>(m.outerIndexPtr(), *outer);
host_copy_eigen<Index>(m.innerIndexPtr(), *inner);
host_copy_eigen<Value>(m.valuePtr(), *value);

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<atlas::array::Array>(value),
std::unique_ptr<atlas::array::Array>(inner),
std::unique_ptr<atlas::array::Array>(outer),
std::any()
);
}

template< typename value_type, typename index_type = eckit::linalg::Index, typename Value, typename Index,
typename = std::enable_if_t < !std::is_same_v<value_type,Value>>>
SparseMatrixStorage make_sparse_matrix_storage(const Eigen::SparseMatrix<Value, Eigen::RowMajor, Index>& m) {
std::cout << "make_sparse_matrix_storage copy and convert" << std::endl;

std::size_t rows = m.rows();
std::size_t cols = m.cols();
std::size_t nnz = m.nonZeros();
auto* outer = atlas::array::Array::create<index_type>(rows+1);
auto* inner = atlas::array::Array::create<index_type>(nnz);
auto* value = atlas::array::Array::create<value_type>(nnz);
host_copy_eigen<index_type>(m.outerIndexPtr(), *outer);
host_copy_eigen<index_type>(m.innerIndexPtr(), *inner);
host_copy_eigen<value_type>(m.valuePtr(), *value);

return SparseMatrixStorage::make( rows, cols, nnz,
std::unique_ptr<atlas::array::Array>(value),
std::unique_ptr<atlas::array::Array>(inner),
std::unique_ptr<atlas::array::Array>(outer),
std::any()
);
}

#endif

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

} // namespace linalg
} // namespace atlas
55 changes: 0 additions & 55 deletions src/atlas/linalg/sparse/SparseMatrixAdaptor.h

This file was deleted.

Loading

0 comments on commit 88badf1

Please sign in to comment.