7
7
8
8
namespace py = pybind11;
9
9
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> {
12
12
py::array_t <CoefficientPrecision, py::array::f_style> m_coarse_space;
13
13
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
+
14
20
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
+ };
20
45
}
21
46
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;
25
51
}
26
52
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;
29
54
30
55
void set_coarse_space (py::array_t <CoefficientPrecision, py::array::f_style> coarse_space) {
31
56
m_coarse_space = coarse_space;
32
57
}
33
58
};
34
59
35
- template <typename CoefficientPrecision>
36
- class PyVirtualCoarseSpaceBuilder : public VirtualCoarseSpaceBuilderPython <CoefficientPrecision> {
60
+ template <typename CoefficientPrecision, typename CoordinatePrecision = CoefficientPrecision>
61
+ class PyVirtualGeneoCoarseSpaceBuilder : public VirtualGeneoCoarseSpaceBuilderPython <CoefficientPrecision> {
62
+
37
63
public:
38
- using VirtualCoarseSpaceBuilderPython<CoefficientPrecision>::VirtualCoarseSpaceBuilderPython;
64
+ /* Inherit the constructors */
65
+ using VirtualGeneoCoarseSpaceBuilderPython<CoefficientPrecision>::VirtualGeneoCoarseSpaceBuilderPython;
39
66
40
67
/* 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 {
42
69
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) */
46
74
);
47
75
}
48
76
};
@@ -52,10 +80,28 @@ void declare_virtual_coarse_space_builder(py::module &m, const std::string &clas
52
80
using BaseClass = VirtualCoarseSpaceBuilder<CoefficientPrecision>;
53
81
py::class_<BaseClass>(m, base_class_name.c_str ());
54
82
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
59
103
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);
60
106
}
61
107
#endif
0 commit comments