77
88namespace py = pybind11;
99
10- template <typename CoefficientPrecision>
11- class VirtualCoarseSpaceBuilderPython : public VirtualCoarseSpaceBuilder <CoefficientPrecision> {
10+ template <typename CoefficientPrecision, typename CoordinatePrecision = htool::underlying_type<CoefficientPrecision> >
11+ class VirtualGeneoCoarseSpaceBuilderPython : public VirtualCoarseSpaceBuilder <CoefficientPrecision> {
1212 py::array_t <CoefficientPrecision, py::array::f_style> m_coarse_space;
1313
14+ int m_size_wo_overlap;
15+ int m_size_with_overlap;
16+ const HMatrix<CoefficientPrecision, CoordinatePrecision> &m_local_hmatrix;
17+ int m_geneo_nu = 2 ;
18+ htool::underlying_type<CoefficientPrecision> m_geneo_threshold = -1 .;
19+
1420 public:
15- Matrix<CoefficientPrecision> build_coarse_space () {
16- compute_coarse_space ();
17- if (m_coarse_space.ndim () != 2 ) {
18- htool::Logger::get_instance ()
19- .log (LogLevel::ERROR, " Wrong dimension for coarse space matrix when building coarse space." ); // LCOV_EXCL_LINE
21+ int get_geneo_nu () { return this ->m_geneo_nu ; }
22+ htool::underlying_type<CoefficientPrecision> get_geneo_threshold () { return this ->m_geneo_threshold ; }
23+
24+ explicit VirtualGeneoCoarseSpaceBuilderPython (int size_wo_overlap, int size_with_overlap, const HMatrix<CoefficientPrecision> &Ai, int geneo_nu, htool::underlying_type<CoefficientPrecision> geneo_threshold) : m_size_wo_overlap(size_wo_overlap), m_size_with_overlap(size_with_overlap), m_local_hmatrix(Ai), m_geneo_nu(geneo_nu), m_geneo_threshold(geneo_threshold) {}
25+
26+ Matrix<CoefficientPrecision> build_coarse_space () override {
27+ std::function<py::array_t <CoefficientPrecision>(py::array_t <CoefficientPrecision>)> hmatrix_callback;
28+
29+ if (this ->m_local_hmatrix .nb_cols () == this ->m_size_with_overlap ) {
30+ hmatrix_callback = [this ](py::array_t <CoefficientPrecision> in) {
31+ std::fill (in.mutable_data () + this ->m_size_wo_overlap , in.mutable_data () + this ->m_size_with_overlap , CoefficientPrecision (0 ));
32+ py::array_t <CoefficientPrecision> out (this ->m_local_hmatrix .nb_rows ());
33+ std::fill_n (out.mutable_data (), this ->m_local_hmatrix .nb_rows (), CoefficientPrecision (0 ));
34+ add_hmatrix_vector_product (' N' , CoefficientPrecision (1 ), this ->m_local_hmatrix , in.data (), CoefficientPrecision (0 ), out.mutable_data ());
35+ std::fill (out.mutable_data () + this ->m_size_wo_overlap , out.mutable_data () + this ->m_size_with_overlap , CoefficientPrecision (0 ));
36+ return out;
37+ };
38+ } else if (this ->m_local_hmatrix .nb_cols () == this ->m_size_wo_overlap ) {
39+ hmatrix_callback = [this ](py::array_t <CoefficientPrecision> in) {
40+ py::array_t <CoefficientPrecision> out (in.size ());
41+ std::fill_n (out.mutable_data (), in.size (), CoefficientPrecision (0 ));
42+ internal_add_hmatrix_vector_product (' N' , CoefficientPrecision (1 ), this ->m_local_hmatrix , in.data (), CoefficientPrecision (0 ), out.mutable_data ());
43+ return out;
44+ };
2045 }
2146
22- Matrix<CoefficientPrecision> coarse_space (m_coarse_space.shape ()[0 ], m_coarse_space.shape ()[1 ]);
23- std::copy_n (m_coarse_space.data (), m_coarse_space.shape ()[0 ] * m_coarse_space.shape ()[1 ], coarse_space.data ());
24- return coarse_space;
47+ compute_coarse_space (hmatrix_callback);
48+ Matrix<CoefficientPrecision> coarse_space_mat (m_coarse_space.shape ()[0 ], m_coarse_space.shape ()[1 ]);
49+ 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.
50+ return coarse_space_mat;
2551 }
2652
27- // lcov does not see it because of trampoline I assume
28- virtual void compute_coarse_space () const = 0; // LCOV_EXCL_LINE
53+ virtual void compute_coarse_space (std::function<py::array_t <CoefficientPrecision>(py::array_t <CoefficientPrecision>)> Ai) = 0;
2954
3055 void set_coarse_space (py::array_t <CoefficientPrecision, py::array::f_style> coarse_space) {
3156 m_coarse_space = coarse_space;
3257 }
3358};
3459
35- template <typename CoefficientPrecision>
36- class PyVirtualCoarseSpaceBuilder : public VirtualCoarseSpaceBuilderPython <CoefficientPrecision> {
60+ template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
61+ class PyVirtualGeneoCoarseSpaceBuilder : public VirtualGeneoCoarseSpaceBuilderPython <CoefficientPrecision> {
62+
3763 public:
38- using VirtualCoarseSpaceBuilderPython<CoefficientPrecision>::VirtualCoarseSpaceBuilderPython;
64+ /* Inherit the constructors */
65+ using VirtualGeneoCoarseSpaceBuilderPython<CoefficientPrecision>::VirtualGeneoCoarseSpaceBuilderPython;
3966
4067 /* Trampoline (need one for each virtual function) */
41- virtual void compute_coarse_space () const override {
68+ void compute_coarse_space (std::function<py:: array_t <CoefficientPrecision>(py:: array_t <CoefficientPrecision>)> Ai) override {
4269 PYBIND11_OVERRIDE_PURE (
43- void , /* Return type */
44- VirtualCoarseSpaceBuilderPython<CoefficientPrecision>, /* Parent class */
45- compute_coarse_space /* Name of function in C++ (must match Python name) */
70+ void , /* Return type */
71+ VirtualGeneoCoarseSpaceBuilderPython<CoefficientPrecision>, /* Parent class */
72+ compute_coarse_space, /* Name of function in C++ (must match Python name) */
73+ Ai /* Argument(s) */
4674 );
4775 }
4876};
@@ -52,10 +80,28 @@ void declare_virtual_coarse_space_builder(py::module &m, const std::string &clas
5280 using BaseClass = VirtualCoarseSpaceBuilder<CoefficientPrecision>;
5381 py::class_<BaseClass>(m, base_class_name.c_str ());
5482
55- using Class = VirtualCoarseSpaceBuilderPython<CoefficientPrecision>;
56- py::class_<Class, BaseClass, PyVirtualCoarseSpaceBuilder<CoefficientPrecision>> py_class (m, className.c_str ());
57- py_class.def (py::init<>());
58- py_class.def (" compute_coarse_space" , &Class::compute_coarse_space);
83+ using Class = VirtualGeneoCoarseSpaceBuilderPython<CoefficientPrecision>;
84+ py::class_<Class, PyVirtualGeneoCoarseSpaceBuilder<CoefficientPrecision>, VirtualCoarseSpaceBuilder<CoefficientPrecision>> py_class (m, className.c_str ());
85+ py_class.def (py::init ([](int size_wo_overlap, int size_with_overlap, const HMatrix<CoefficientPrecision> &Ai, int geneo_nu) {
86+ return PyVirtualGeneoCoarseSpaceBuilder<CoefficientPrecision>(size_wo_overlap, size_with_overlap, Ai, geneo_nu, -1 );
87+ }),
88+ py::arg (" size_wo_overlap" ), // LCOV_EXCL_START
89+ py::arg (" size_with_overlap" ),
90+ py::arg (" Ai" ),
91+ py::kw_only (),
92+ py::arg (" geneo_nu" ));
93+ // LCOV_EXCL_STOP
94+ py_class.def (py::init ([](int size_wo_overlap, int size_with_overlap, const HMatrix<CoefficientPrecision> &Ai, double geneo_threshold) {
95+ return PyVirtualGeneoCoarseSpaceBuilder<CoefficientPrecision>(size_wo_overlap, size_with_overlap, Ai, 0 , geneo_threshold);
96+ }),
97+ py::arg (" size_wo_overlap" ), // LCOV_EXCL_START
98+ py::arg (" size_with_overlap" ),
99+ py::arg (" Ai" ),
100+ py::kw_only (),
101+ py::arg (" geneo_threshold" ));
102+ // LCOV_EXCL_STOP
59103 py_class.def (" set_coarse_space" , &Class::set_coarse_space);
104+ py_class.def_property_readonly (" geneo_nu" , &Class::get_geneo_nu);
105+ py_class.def_property_readonly (" geneo_threshold" , &Class::get_geneo_threshold);
60106}
61107#endif
0 commit comments