File: ParSparseMatrix.h

package info (click to toggle)
lammps 20220106.git7586adbb6a%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 348,064 kB
  • sloc: cpp: 831,421; python: 24,896; xml: 14,949; f90: 10,845; ansic: 7,967; sh: 4,226; perl: 4,064; fortran: 2,424; makefile: 1,501; objc: 238; lisp: 163; csh: 16; awk: 14; tcl: 6
file content (150 lines) | stat: -rw-r--r-- 5,000 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#ifndef PARSPARSEMATRIX_H
#define PARSPARSEMATRIX_H

#include "mpi.h"
#include "MPI_Wrappers.h"
#include "SparseMatrix.h"
#include "DiagonalMatrix.h"
#include <algorithm>

namespace ATC_matrix {

  /**
   *  @class  ParSparseMatrix
   *  @brief  Parallelized version of SparseMatrix class.
   *
   *  ParSparseMatrix<double>::MultMv is used in LinearSolver, which is then
   *  used in NonLinearSolver, PoissonSolver, and SchrodingerSolver. These
   *  parallelized solvers are used in the following locations:
   *
   *  - LinearSolver
   *    - ExtrinsicModelDriftDiffusion.cpp (lines 511 and 522)
   *    - AtomicRegulator.cpp (line 926)
   *    - TransferLibrary.cpp (lines 72 and 260)
   *  - PoissonSolver
   *    - ExtrinsicModelDriftDiffusion.cpp (line 232)
   *  - SchrodingerSolver
   *    - ExtrinsicModelDriftDiffusion.cpp (line 251)
   *  - SliceSchrodingerSolver
   *    - ExtrinsicModelDriftDiffusion.cpp (line 246)
   */

  template <typename T>
  class ParSparseMatrix : public SparseMatrix<T>
  {
    public:
      ParSparseMatrix(MPI_Comm comm, INDEX rows = 0, INDEX cols = 0)
        : SparseMatrix<T>(rows, cols), _comm(comm){}

      ParSparseMatrix(MPI_Comm comm, const SparseMatrix<T> &c)
        : SparseMatrix<T>(c), _comm(comm){}

      ParSparseMatrix(MPI_Comm comm, INDEX* rows, INDEX* cols, T* vals,
                      INDEX size, INDEX nRows, INDEX nCols, INDEX nRowsCRS)
        : SparseMatrix<T>(rows, cols, vals, size, nRows, nCols, nRowsCRS)
         ,_comm(comm){}

      ParSparseMatrix(MPI_Comm comm)
        : SparseMatrix<T>(), _comm(comm){}

    virtual void operator=(const SparseMatrix<T> &source)
    {
      copy(source);
    }

    template<typename U>
    friend void ParMultAB(MPI_Comm comm, const SparseMatrix<U>& A,
                          const Matrix<U>& B, DenseMatrix<U>& C);

    private:
        MPI_Comm _comm;
  };

  template <>
  class ParSparseMatrix<double> : public SparseMatrix<double>
  {
  public:
    // All the same constructors as for SparseMatrix
    ParSparseMatrix(MPI_Comm comm, INDEX rows = 0, INDEX cols=0);
    ParSparseMatrix(MPI_Comm comm, const SparseMatrix<double> &c);
    ParSparseMatrix(MPI_Comm comm, INDEX* rows, INDEX* cols, double* vals, INDEX size,
        INDEX nRows, INDEX nCols, INDEX nRowsCRS);

    // Parallel sparse matrix multiplication functions
    void MultMv(const Vector<double>& v, DenseVector<double>& c) const;
    DenseVector<double> transMat(const Vector<double>& v) const;
    void MultAB(const Matrix<double>& B, DenseMatrix<double>& C) const;
    DenseMatrix<double> transMat(const DenseMatrix<double>& B) const;
    DenseMatrix<double> transMat(const SparseMatrix<double>& B) const;

    virtual void operator=(const SparseMatrix<double> &source);

    template<typename U>
    friend void ParMultAB(MPI_Comm comm, const SparseMatrix<U>& A, const Matrix<U>& B, DenseMatrix<U>& C);

  private:
    void partition(ParSparseMatrix<double>& A_local) const;
    void finalize();
    MPI_Comm _comm;
  };

  // The SparseMatrix versions of these functions will call the correct
  //   MultMv/MultAB:
  // DenseVector<double> operator*(const ParSparseMatrix<double> &A, const Vector<double> &v);
  // DenseVector<double> operator*(const Vector<double> &v, const ParSparseMatrix<double> &A);
  // DenseMatrix<double> operator*(const ParSparseMatrix<double> &A, const Matrix<double> &B);


  template<typename T>
  void ParMultAB(MPI_Comm comm, const SparseMatrix<T>& A, const Matrix<T>& B, DenseMatrix<T>& C)
  {
    SparseMatrix<T>::compress(A);

    INDEX M = A.nRows(), N = B.nCols();
    if (!C.is_size(M, N))
    {
      C.resize(M, N);
      C.zero();
    }

    // Temporarily put fields into a ParSparseMatrix for distributed multiplication
    ParSparseMatrix<T> Ap(comm);
    Ap._nRows       = A._nRows;
    Ap._nCols       = A._nCols;
    Ap._size        = A._size;
    Ap._nRowsCRS    = A._nRowsCRS;
    Ap._val         = A._val;
    Ap._ja          = A._ja;
    Ap._ia          = A._ia;
    Ap.hasTemplate_ = A.hasTemplate_;

    // MultAB calls compress(), but we hope that does nothing because we just
    // compressed A. If it did something, it might mess up other members
    // (e.g. _tri).
    Ap.MultAB(B, C);

    // We're not changing the matrix's values, so we can justify calling A const.
    SparseMatrix<T> &Avar = const_cast<SparseMatrix<T> &>(A);
    Avar._nRows       = Ap._nRows;
    Avar._nCols       = Ap._nCols;
    Avar._size        = Ap._size;
    Avar._nRowsCRS    = Ap._nRowsCRS;
    Avar._val         = Ap._val;
    Avar._ja          = Ap._ja;
    Avar._ia          = Ap._ia;
    Avar.hasTemplate_ = Ap.hasTemplate_;

    // Avoid catastrophe
    Ap._val = nullptr;
    Ap._ja  = nullptr;
    Ap._ia  = nullptr;
  }


  /*SparseMatrix<double> operator*(const ParSparseMatrix<double> &A, const SparseMatrix<double> &B);

  SparseMatrix<double> operator*(const ParSparseMatrix<double> &A, const DiagonalMatrix<double> &B);
  */
} // end namespace
#endif