Redesign_mapping_1d - t-sakashita/rokko GitHub Wiki

mapping_1dの設計のやり直し

local_offset_の廃止

  void eigenvector(int k, distributed_vector<double>& vec) const {
    vec.initialize(dimension_, offset_local_, offset_local_ + num_local_rows_);
    eigenvector(k, vec.get_storage());
  }

rokko::distributed_vectorでは、rokko::skel::mapping_1dを継承するか、メンバとするか?

以下のみが未定義のdistributed_mfree_defaultを用いることを推奨する。

  virtual void multiply(const double *const x, double *const y) const = 0;

純粋仮想関数のmultiplyが呼び出されてしまう?

  py::class_<rokko::heisenberg_mfree, rokko::distributed_mfree>(m, "mfree")
    .def(py::init<int, const std::vector<std::pair<int, int>>&>())
    .def_property_readonly("dim", &rokko::distributed_mfree_default::get_dim)
    .def_property_readonly("num_local_rows", &rokko::distributed_mfree_default::get_num_local_rows)

heisenberg_mfreeクラスのmultiply関数は、Python側に晒されてはいない。 よって、C++内部の問題である。

以下は不要 pyrokko_distributed_mfree.cpp

  /*wrap_parameters diagonalize(distributed_mfree_default& mat, wrap_parameters const& params) {
    return parallel_sparse_ev::diagonalize(mat, parameters(params));
    }*/

pyrokko.cpp

    //.def("diagonalize", py::overload_cast<distributed_mfree_default&, wrap_parameters const&>(&wrap_parallel_sparse_ev::diagonalize),
    //     py::arg("mat"), py::arg("params") = wrap_parameters())

以下のtrampoline classも不要

class wrap_distributed_mfree_default : public distributed_mfree_default {
  using distributed_mfree_default::distributed_mfree_default;
};

CRSとmfreeとで共通化することの是非

同じ基底クラスを継承することで共通化する。 すると、diagonalize関数にmapping_1dを誤って与えたときに、mfreeと解釈されてしまう。

以下を共通化できないか?

  • rokko/distributed_mfree_c.cpp
  • rokko/distributed_mfree_f.cpp

Pythonバインディングにおいても、op.dim, op.num_local_rowsを渡さなくて良いようにした。

mat = distributed_mfree(op.multiply, op.dim, op.num_local_rows)

PythonでC++で書いたクラスを継承した。 dimやnum_local_rowsを親クラスのプロパティとして読み出せるようにできた。

C/Fortranバインディングにおいて、commを渡すか?

    call rokko_distributed_mfree_construct(mat, multiply, dim)

Cではオーバーロードやデフォルト引数が使用できないので、MPI_COMM_WORLDを渡すことにする。

コミュニケータは、vars->commにより渡される。 だが、varsはvoid*であり、distributed_mfree_cの初期化関数では型がわかないためキャストできないので、commを取り出せない。

引数として、dimとcommを含むmapping_1dを渡すことにするか?

  • CやFortranでは、mapping_1dの継承ができない。
  • mapping_1dをユーザプログラムの中でも使う。

Fortran/Cラッパーは、共通化しない方が良い。 それぞれの言語仕様に対して自然(かつ効率的?)になるように、引数の型としたいため。

Cラッパーでは、値渡し

int rokko_distributed_mfree_num_local_rows(struct rokko_distributed_mfree matrix) {

Fortranラッパーでは、ポインタ渡し

int rokko_distributed_mfree_f_num_local_rows(struct rokko_distributed_mfree* matrix) {

distributed_crs_matrixにおいて、AnasaziとSLEPcとで持つmapping_1d

--- a/rokko/distributed_crs_matrix.hpp
+++ b/rokko/distributed_crs_matrix.hpp
@@ -43,6 +43,7 @@ public:
 template<typename CRS>
 class ps_crs_wrapper : public ps_crs_base {
   using crs_type = CRS;
+  using map_type = typename CRS::map_type;
 public:
   ps_crs_wrapper() : crs_impl_() {}
   virtual ~ps_crs_wrapper() = default;
--- a/rokko/slepc/distributed_crs_matrix.hpp
+++ b/rokko/slepc/distributed_crs_matrix.hpp
@@ -26,6 +26,8 @@ namespace slepc {
 
 class distributed_crs_matrix : public rokko::detail::ps_crs_base {
 public:
+  using map_type = rokko::slepc::mapping_1d;
+
   distributed_crs_matrix() = default;
   ~distributed_crs_matrix() = default;
 
@@ -166,7 +168,7 @@ public:
     }
   }
 
-  const rokko::slepc::mapping_1d* get_map() const { return map_; }
+  const map_type* get_map() const { return map_; }

上記のように、AnasaziとSLEPcのそれぞれの型をmapping_1dを返すようにしても、rokko::distributed_crs_matrixでのget_mapの戻り値は基底型であるため、AnasaziとSLEPc向けに継承したメンバは失われてしまう。

  const ps_mapping_1d_base* get_map() const { return crs_impl_.get_map(); }
⚠️ **GitHub.com Fallback** ⚠️