Skip to content

Commit

Permalink
add coarse_space interface
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreMarchand20 committed Jan 29, 2024
1 parent cd4ee5c commit 65a5847
Show file tree
Hide file tree
Showing 23 changed files with 498 additions and 278 deletions.
3 changes: 0 additions & 3 deletions example/create_geometry.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import math

import mpi4py
import numpy as np


Expand Down
2 changes: 0 additions & 2 deletions example/define_custom_dense_blocks_generator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import mpi4py

import Htool


Expand Down
4 changes: 1 addition & 3 deletions example/define_custom_generators.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import mpi4py
import numpy as np

import Htool
import numpy as np


class CustomGenerator(Htool.VirtualGenerator):
Expand Down
4 changes: 1 addition & 3 deletions example/define_custom_local_operator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import mpi4py
import numpy as np

import Htool
import numpy as np


class CustomLocalOperator(Htool.LocalOperator):
Expand Down
3 changes: 1 addition & 2 deletions example/define_custom_low_rank_generator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import math

import numpy as np

import Htool
import numpy as np


class CustomSVD(Htool.VirtualLowRankGenerator):
Expand Down
4 changes: 1 addition & 3 deletions example/use_cluster.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import Htool
import matplotlib.pyplot as plt
import mpi4py
import numpy as np
from create_geometry import create_random_geometries

import Htool

# Random geometry
nb_rows = 500
nb_cols = 500
Expand Down
1 change: 0 additions & 1 deletion example/use_cluster_with_given_partition.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import matplotlib.pyplot as plt
import mpi4py
import numpy as np
from create_geometry import create_partitionned_geometries

import Htool
Expand Down
1 change: 0 additions & 1 deletion example/use_custom_dense_block_generator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import matplotlib.pyplot as plt
import mpi4py
import numpy as np
from create_geometry import create_partitionned_geometries
Expand Down
8 changes: 5 additions & 3 deletions example/use_custom_low_rank_approximation.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import Htool
import mpi4py
import numpy as np
from create_geometry import create_partitionned_geometries
from define_custom_generators import CustomGenerator
from define_custom_low_rank_generator import CustomSVD

import Htool

# Random geometry
nb_rows = 500
nb_cols = 500
Expand Down Expand Up @@ -52,8 +51,11 @@
-1,
mpi4py.MPI.COMM_WORLD.rank,
)
# hmatrix_builder.set_low_rank_generator(low_rank_generator)
hmatrix_builder.set_low_rank_generator(low_rank_generator)
hmatrix: Htool.HMatrix = hmatrix_builder.build(generator)
del hmatrix_builder
low_rank_generator.test()
del low_rank_generator


# Build local operator
Expand Down
3 changes: 1 addition & 2 deletions example/use_default_build.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import logging

import matplotlib.pyplot as plt
import mpi4py
import numpy as np
from create_geometry import create_partitionned_geometries
from define_custom_generators import CustomGenerator, CustomGeneratorWithPermutation
from define_custom_generators import CustomGenerator

import Htool

Expand Down
3 changes: 1 addition & 2 deletions example/use_local_build.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import logging

import matplotlib.pyplot as plt
import mpi4py
import numpy as np
from create_geometry import create_partitionned_geometries, create_random_geometries
from create_geometry import create_random_geometries
from define_custom_generators import CustomGenerator
from define_custom_local_operator import CustomLocalOperator

Expand Down
5 changes: 3 additions & 2 deletions src/htool/hmatrix/interfaces/virtual_low_rank_generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ using namespace htool;

template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
class VirtualLowRankGeneratorPython : public VirtualLowRankGenerator<CoefficientPrecision, CoordinatePrecision> {

int m_rank;
mutable std::vector<py::array_t<CoefficientPrecision, py::array::f_style>> m_mats_U; // owned by Python
mutable std::vector<py::array_t<CoefficientPrecision, py::array::f_style>> m_mats_V; // owned by Python
Expand All @@ -35,7 +34,9 @@ class VirtualLowRankGeneratorPython : public VirtualLowRankGenerator<Coefficient
// lcov does not see it because of trampoline I assume
virtual void build_low_rank_approximation(const VirtualGenerator<CoefficientPrecision> &A, int target_size, int source_size, int target_offset, int source_offset, underlying_type<CoefficientPrecision> epsilon) const = 0; // LCOV_EXCL_LINE

void set_U(py::array_t<CoefficientPrecision, py::array::f_style> U0) { m_mats_U.push_back(U0); }
void set_U(py::array_t<CoefficientPrecision, py::array::f_style> U0) {
m_mats_U.push_back(U0); // no copy here
}
void set_V(py::array_t<CoefficientPrecision, py::array::f_style> V0) { m_mats_V.push_back(V0); }
void set_rank(int rank) { m_rank = rank; }
};
Expand Down
18 changes: 17 additions & 1 deletion src/htool/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@
#include "distributed_operator/implementation/partition_from_cluster.hpp"
#include "distributed_operator/utility.hpp"

#include "solver/geneo/coarse_operator_builder.hpp"
#include "solver/geneo/coarse_space_builder.hpp"
#include "solver/interfaces/virtual_coarse_operator_builder.hpp"
#include "solver/interfaces/virtual_coarse_space_builder.hpp"
#include "solver/solver.hpp"
#include "solver/utility.hpp"

#include "matplotlib/cluster.hpp"
#include "matplotlib/hmatrix.hpp"
#include "misc/logger.hpp"
#include "misc/wrapper_mpi.hpp"
// #include "ddm_solver.hpp"
// #include "dense_blocks_generator.hpp"
// #include "hmatrix.hpp"
Expand All @@ -39,7 +44,7 @@

PYBIND11_MODULE(Htool, m) {
// Delegate logging to python logging module
Logger::get_instance().set_current_writer(std::make_shared<PythonLoggerWriter>());
htool::Logger::get_instance().set_current_writer(std::make_shared<PythonLoggerWriter>());

// import the mpi4py API
if (import_mpi4py() < 0) {
Expand Down Expand Up @@ -72,6 +77,11 @@ PYBIND11_MODULE(Htool, m) {
declare_distributed_operator_utility<double, double>(m);

declare_DDM<double>(m, "Solver");
declare_virtual_coarse_space_builder<double>(m, "VirtualCoarseSpaceBuilder", "ICoarseSpaceBuilder");
declare_virtual_coarse_operator_builder<double>(m, "", "ICoarseOperatorBuilder");
declare_geneo_coarse_operator_builder<double>(m, "GeneoCoarseOperatorBuilder");
declare_geneo_coarse_space_dense_builder<double>(m, "GeneoCoarseSpaceDenseBuilder");
declare_virtual_geneo_coarse_space_dense_builder<double>(m, "VirtualGeneoCoarseSpaceDenseBuilder");
declare_solver_utility(m);
declare_solver_utility<double, double>(m);

Expand All @@ -86,5 +96,11 @@ PYBIND11_MODULE(Htool, m) {
declare_distributed_operator_utility<std::complex<double>, double>(m, "Complex");

declare_DDM<std::complex<double>>(m, "ComplexSolver");
declare_virtual_coarse_space_builder<std::complex<double>>(m, "ComplexVirtualCoarseSpaceBuilder", "IComplexCoarseSpaceBuilder");
declare_virtual_coarse_operator_builder<std::complex<double>>(m, "", "IComplexCoarseOperatorBuilder");
declare_geneo_coarse_operator_builder<std::complex<double>>(m, "ComplexGeneoCoarseOperatorBuilder");
declare_geneo_coarse_space_dense_builder<std::complex<double>>(m, "ComplexGeneoCoarseSpaceDenseBuilder");
declare_virtual_geneo_coarse_space_dense_builder<std::complex<double>>(m, "VirtualComplexGeneoCoarseSpaceDenseBuilder");

declare_solver_utility<std::complex<double>, double>(m, "Complex");
}
18 changes: 9 additions & 9 deletions src/htool/misc/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@

#include <htool/misc/logger.hpp>
#include <pybind11/pybind11.h>

namespace py = pybind11;
// Delegates formatting and filtering to python logging module
// mapping python logging level to Htool logging level

class PythonLoggerWriter : public IObjectWriter {
class PythonLoggerWriter : public htool::IObjectWriter {

public:
void write(LogLevel logging_level, const std::string &message) override {
void write(htool::LogLevel logging_level, const std::string &message) override {
py::object logging_module = py::module::import("logging");
py::object logger = logging_module.attr("getLogger")("Htool");
switch (logging_level) {
case LogLevel::CRITICAL:
case htool::LogLevel::CRITICAL:
logger.attr("critical")(message);
break;
case LogLevel::ERROR:
case htool::LogLevel::ERROR:
logger.attr("error")(message);
break;
case LogLevel::WARNING:
case htool::LogLevel::WARNING:
logger.attr("warning")(message);
break;
case LogLevel::DEBUG:
case htool::LogLevel::DEBUG:
logger.attr("debug")(message);
break;
case LogLevel::INFO:
case htool::LogLevel::INFO:
logger.attr("info")(message);
break;
default:
break;
}
}

void set_log_level(LogLevel log_level) override {
void set_log_level(htool::LogLevel log_level) override {
}
};

Expand Down
16 changes: 16 additions & 0 deletions src/htool/solver/geneo/coarse_operator_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef HTOOL_PYTHON_GENEO_COARSE_OPERATOR_BUILDER_HPP
#define HTOOL_PYTHON_GENEO_COARSE_OPERATOR_BUILDER_HPP

#include <htool/solvers/geneo/coarse_operator_builder.hpp>
#include <pybind11/pybind11.h>
namespace py = pybind11;

template <typename CoefficientPrecision>
void declare_geneo_coarse_operator_builder(py::module &m, const std::string &className) {

using Class = GeneoCoarseOperatorBuilder<CoefficientPrecision>;
py::class_<Class, VirtualCoarseOperatorBuilder<CoefficientPrecision>> py_class(m, className.c_str());
py_class.def(py::init<const DistributedOperator<CoefficientPrecision> &>());
}

#endif
131 changes: 131 additions & 0 deletions src/htool/solver/geneo/coarse_space_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#ifndef HTOOL_PYTHON_GENEO_COARSE_SPACE_BUILDER_HPP
#define HTOOL_PYTHON_GENEO_COARSE_SPACE_BUILDER_HPP

#include <htool/solvers/geneo/coarse_space_builder.hpp>
#include <pybind11/pybind11.h>
namespace py = pybind11;

template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
class GeneoCoarseSpaceDenseBuilderPython : public GeneoCoarseSpaceDenseBuilder<CoefficientPrecision> {
py::array_t<CoefficientPrecision, py::array::f_style> m_coarse_space;

using GeneoCoarseSpaceDenseBuilder<CoefficientPrecision>::GeneoCoarseSpaceDenseBuilder;

public:
char get_symmetry() { return this->m_symmetry; }
int get_geneo_nu() { return this->m_geneo_nu; }
htool::underlying_type<CoefficientPrecision> get_geneo_threshold() { return this->m_geneo_threshold; }

GeneoCoarseSpaceDenseBuilderPython(int size_wo_overlap, Matrix<CoefficientPrecision> Ai, Matrix<CoefficientPrecision> Bi, char symmetry, char uplo, int geneo_nu, htool::underlying_type<CoefficientPrecision> geneo_threshold) : GeneoCoarseSpaceDenseBuilder<CoefficientPrecision>(size_wo_overlap, Ai, Bi, symmetry, uplo, geneo_nu, geneo_threshold) {}

Matrix<CoefficientPrecision> build_coarse_space() override {
py::array_t<CoefficientPrecision, py::array::f_style> Ai(std::array<long int, 2>{this->m_DAiD.nb_rows(), this->m_DAiD.nb_cols()}, this->m_DAiD.data(), py::capsule(this->m_DAiD.data()));
py::array_t<CoefficientPrecision, py::array::f_style> Bi(std::array<long int, 2>{this->m_Bi.nb_rows(), this->m_Bi.nb_cols()}, this->m_Bi.data(), py::capsule(this->m_Bi.data()));
compute_coarse_space(Ai, Bi);
Matrix<CoefficientPrecision> coarse_space_mat(m_coarse_space.shape()[0], m_coarse_space.shape()[1]);
std::copy_n(m_coarse_space.data(), m_coarse_space.shape()[0] * m_coarse_space.shape()[1], coarse_space_mat.data()); // HPDDM deletes the coarse space, so we have to copy.
// coarse_space_mat.assign(m_coarse_space.shape()[0], m_coarse_space.shape()[1], m_coarse_space.mutable_data(), false);
// coarse_space_mat.print(std::cout, ",");
return coarse_space_mat;
}

virtual void compute_coarse_space(py::array_t<CoefficientPrecision, py::array::f_style> Ai, py::array_t<CoefficientPrecision, py::array::f_style> Bi) = 0;

void set_coarse_space(py::array_t<CoefficientPrecision, py::array::f_style> coarse_space) {
m_coarse_space = coarse_space;
}
};

template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
class PyGeneoCoarseSpaceDenseBuilder : public GeneoCoarseSpaceDenseBuilderPython<CoefficientPrecision> {

public:
/* Inherit the constructors */
using GeneoCoarseSpaceDenseBuilderPython<CoefficientPrecision>::GeneoCoarseSpaceDenseBuilderPython;

/* Trampoline (need one for each virtual function) */
void compute_coarse_space(py::array_t<CoefficientPrecision, py::array::f_style> Ai, py::array_t<CoefficientPrecision, py::array::f_style> Bi) override {
PYBIND11_OVERRIDE_PURE(
void, /* Return type */
GeneoCoarseSpaceDenseBuilderPython<CoefficientPrecision>, /* Parent class */
compute_coarse_space, /* Name of function in C++ (must match Python name) */
Ai,
Bi /* Argument(s) */
);
}
};

template <typename CoefficientPrecision>
void declare_geneo_coarse_space_dense_builder(py::module &m, const std::string &className) {

using Class = GeneoCoarseSpaceDenseBuilder<CoefficientPrecision>;
py::class_<Class, VirtualCoarseSpaceBuilder<CoefficientPrecision>> py_class(m, className.c_str());
py_class.def(py::init([](int size_wo_overlap, py::array_t<CoefficientPrecision, py::array::f_style> Ai, py::array_t<CoefficientPrecision, py::array::f_style> Bi, char symmetry, char uplo, int geneo_nu) {
Matrix<CoefficientPrecision> Ai_mat;
Ai_mat.assign(Ai.shape()[0], Ai.shape()[1], Ai.mutable_data(), false);
Matrix<CoefficientPrecision> Bi_mat;
Bi_mat.assign(Bi.shape()[0], Bi.shape()[1], Bi.mutable_data(), false);
return Class::GeneoWithNu(size_wo_overlap, Ai_mat, Bi_mat, symmetry, uplo, geneo_nu);
}),
py::arg("size_wo_overlap"),
py::arg("Ai"),
py::arg("Bi"),
py::arg("symmetry"),
py::arg("uplo"),
py::kw_only(),
py::arg("geneo_nu"));
py_class.def(py::init([](int size_wo_overlap, py::array_t<CoefficientPrecision, py::array::f_style> Ai, py::array_t<CoefficientPrecision, py::array::f_style> Bi, char symmetry, char uplo, double geneo_threshold) {
Matrix<CoefficientPrecision> Ai_mat;
Ai_mat.assign(Ai.shape()[0], Ai.shape()[1], Ai.mutable_data(), false);
Matrix<CoefficientPrecision> Bi_mat;
Bi_mat.assign(Bi.shape()[0], Bi.shape()[1], Bi.mutable_data(), false);
return Class::GeneoWithThreshold(size_wo_overlap, Ai_mat, Bi_mat, symmetry, uplo, geneo_threshold);
}),
py::arg("size_wo_overlap"),
py::arg("Ai"),
py::arg("Bi"),
py::arg("symmetry"),
py::arg("uplo"),
py::kw_only(),
py::arg("geneo_threshold"));
}

template <typename CoefficientPrecision>
void declare_virtual_geneo_coarse_space_dense_builder(py::module &m, const std::string &className) {

using Class = GeneoCoarseSpaceDenseBuilderPython<CoefficientPrecision>;
py::class_<Class, PyGeneoCoarseSpaceDenseBuilder<CoefficientPrecision>, VirtualCoarseSpaceBuilder<CoefficientPrecision>> py_class(m, className.c_str());
py_class.def(py::init([](int size_wo_overlap, py::array_t<CoefficientPrecision, py::array::f_style> Ai, py::array_t<CoefficientPrecision, py::array::f_style> Bi, char symmetry, char uplo, int geneo_nu) {
Matrix<CoefficientPrecision> Ai_mat;
Ai_mat.assign(Ai.shape()[0], Ai.shape()[1], Ai.mutable_data(), false);
Matrix<CoefficientPrecision> Bi_mat;
Bi_mat.assign(Bi.shape()[0], Bi.shape()[1], Bi.mutable_data(), false);
return PyGeneoCoarseSpaceDenseBuilder<CoefficientPrecision>(size_wo_overlap, Ai_mat, Bi_mat, symmetry, uplo, geneo_nu, -1);
}),
py::arg("size_wo_overlap"),
py::arg("Ai"),
py::arg("Bi"),
py::arg("symmetry"),
py::arg("uplo"),
py::kw_only(),
py::arg("geneo_nu"));
py_class.def(py::init([](int size_wo_overlap, py::array_t<CoefficientPrecision, py::array::f_style> Ai, py::array_t<CoefficientPrecision, py::array::f_style> Bi, char symmetry, char uplo, double geneo_threshold) {
Matrix<CoefficientPrecision> Ai_mat;
Ai_mat.assign(Ai.shape()[0], Ai.shape()[1], Ai.mutable_data(), false);
Matrix<CoefficientPrecision> Bi_mat;
Bi_mat.assign(Bi.shape()[0], Bi.shape()[1], Bi.mutable_data(), false);
return PyGeneoCoarseSpaceDenseBuilder<CoefficientPrecision>(size_wo_overlap, Ai_mat, Bi_mat, symmetry, uplo, 0, geneo_threshold);
}),
py::arg("size_wo_overlap"),
py::arg("Ai"),
py::arg("Bi"),
py::arg("symmetry"),
py::arg("uplo"),
py::kw_only(),
py::arg("geneo_threshold"));
py_class.def("set_coarse_space", &Class::set_coarse_space);
py_class.def_property_readonly("symmetry", &Class::get_symmetry);
py_class.def_property_readonly("geneo_nu", &Class::get_geneo_nu);
py_class.def_property_readonly("geneo_threshold", &Class::get_geneo_threshold);
}
#endif
14 changes: 14 additions & 0 deletions src/htool/solver/interfaces/virtual_coarse_operator_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef HTOOL_PYTHON_VIRTUAL_COARSE_OPERATOR_BUILDER_HPP
#define HTOOL_PYTHON_VIRTUAL_COARSE_OPERATOR_BUILDER_HPP

#include <htool/solvers/interfaces/virtual_coarse_operator_builder.hpp>
#include <pybind11/pybind11.h>
namespace py = pybind11;

template <typename CoefficientPrecision>
void declare_virtual_coarse_operator_builder(py::module &m, const std::string &className, const std::string &base_class_name) {
using BaseClass = VirtualCoarseOperatorBuilder<CoefficientPrecision>;
py::class_<BaseClass>(m, base_class_name.c_str());
}

#endif
Loading

0 comments on commit 65a5847

Please sign in to comment.