JDFTx  1.2.0
matrix.h
1 /*-------------------------------------------------------------------
2 Copyright 2011 Ravishankar Sundararaman
3 
4 This file is part of JDFTx.
5 
6 JDFTx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 JDFTx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with JDFTx. If not, see <http://www.gnu.org/licenses/>.
18 -------------------------------------------------------------------*/
19 
20 #ifndef JDFTX_ELECTRONIC_MATRIX_H
21 #define JDFTX_ELECTRONIC_MATRIX_H
22 
23 #include <electronic/common.h>
24 #include <core/ManagedMemory.h>
25 #include <core/matrix3.h>
26 #include <core/scaled.h>
27 #include <core/GridInfo.h>
28 #include <gsl/gsl_cblas.h>
29 
31 class diagMatrix : public std::vector<double>
32 {
33 public:
34  diagMatrix(int N=0, double d=0.) : std::vector<double>(N,d) {}
35  int nRows() const { return size(); }
36  int nCols() const { return size(); }
37  bool isScalar(double absTol=1e-14, double relTol=1e-14) const;
38 
39  diagMatrix& operator*=(double s) { for(double& d: *this) d*=s; return *this; }
40 
41  //Splicing operations:
42  diagMatrix operator()(int iStart, int iStop) const;
43  diagMatrix operator()(int iStart, int iStep, int iStop) const;
44  void set(int iStart, int iStop, const diagMatrix& m);
45  void set(int iStart, int iStep, int iStop, const diagMatrix& m);
46 
47  void scan(FILE* fp);
48  void print(FILE* fp, const char* fmt="%lg\t") const;
49 
50  //Inter-process communication:
51  void send(int dest, int tag=0) const; //send to another process
52  void recv(int src, int tag=0); //receive from another process
53  void bcast(int root=0); //synchronize across processes (using value on specified root process)
54  void allReduce(MPIUtil::ReduceOp op, bool safeMode=false); //apply all-to-all reduction (see MPIUtil::allReduce)
55 };
56 
58 class matrix : public ManagedMemory
59 {
60  int nr;
61  int nc;
62 
63 public:
64  int nRows() const { return nr; }
65  int nCols() const { return nc; }
66  int index(int i, int j) const { return nr*j+i; }
67  explicit operator bool() const { return nr*nc; }
68 
69  void init(int nrows,int ncols, bool onGpu=false);
70  void reshape(int nrows, int ncols);
71  matrix(int nrows=0, int ncols=0, bool onGpu=false);
72  matrix(const matrix& m1);
73  matrix(matrix&& m1);
74  matrix(const diagMatrix&);
75  matrix(const std::vector<complex>&);
76  explicit matrix(const matrix3<>&);
77 
78  matrix& operator=(const matrix& m1);
79  matrix& operator=(matrix&& m1);
80 
82  complex operator()(int i, int j) const;
83 
85  matrix operator()(int iStart, int iStop, int jStart, int jStop) const { return (*this)(iStart,1,iStop, jStart,1,jStop); }
86 
88  matrix operator()(int iStart, int iStep, int iStop, int jStart, int jStep, int jStop) const;
89 
91  void set(int i, int j, complex m);
92 
94  void set(int iStart, int iStop, int jStart, int jStop, const matrix& m) { set(iStart,1,iStop, jStart,1,jStop, m); }
95 
97  void set(int iStart, int iStep, int iStop, int jStart, int jStep, int jStop, const matrix& m);
98 
99  void scan(FILE* fp, const char* fmt="%lg%+lgi");
100  void scan_real(FILE* fp);
101  void print(FILE* fp, const char* fmt="%lg%+lgi\t") const;
102  void print_real(FILE* fp, const char* fmt="%lg\t") const;
103 
104  void diagonalize(matrix& evecs, diagMatrix& eigs) const;
105  void diagonalize(matrix& levecs, std::vector<complex>& eigs, matrix& revecs) const;
106  void svd(matrix& U, diagMatrix& S, matrix& Vdag) const;
107 
108  //---------octave-like slicing operators on scalar fields converted to Nx*Ny*Nz x 1 matrices --------------
109  complex getElement(vector3< int > index, GridInfo& gInfo);
110  matrix getLine(vector3<int> line, vector3<int> point, GridInfo& gInfo);
111  matrix getPlane(vector3<int> normal, vector3<int> point, GridInfo& gInfo);
112 };
113 
116 { const matrix& mat;
117  double scale;
118  CBLAS_TRANSPOSE op;
119 
120  int nRows() const { return op==CblasNoTrans ? mat.nRows() : mat.nCols(); }
121  int nCols() const { return op==CblasNoTrans ? mat.nCols() : mat.nRows(); }
122  complex conjOp(complex a) const { return (op==CblasConjTrans) ? a.conj() : a; }
123  int index(int i, int j) const { return op==CblasNoTrans ? mat.index(i,j) : mat.index(j,i); }
124 
126  matrixScaledTransOp(const matrix& mat, double scale=1.0, CBLAS_TRANSPOSE op=CblasNoTrans)
127  : mat(mat), scale(scale), op(op) {}
128 
130  matrixScaledTransOp(const scaled<matrix>& smat, CBLAS_TRANSPOSE op=CblasNoTrans)
131  : mat(smat.data), scale(smat.scale), op(op) {}
132 
133  operator matrix() const;
134 
135  //Scaling:
136  matrixScaledTransOp& operator*=(double s) { scale *= s; return *this; }
137  matrixScaledTransOp operator*(double s) const { return matrixScaledTransOp(mat,scale*s,op); }
138  friend matrixScaledTransOp operator*(double s, const matrixScaledTransOp& A) { return A * s; }
139 };
140 matrix conj(const scaled<matrix>& A);
141 matrixScaledTransOp dagger(const scaled<matrix>& A);
142 matrixScaledTransOp transpose(const scaled<matrix>& A);
143 matrix dagger_symmetrize(const scaled<matrix>& A);
144 matrix transpose_symmetrize(const scaled<matrix>& A);
145 
146 
147 //------------ Arithmetic ------------------
148 
149 inline matrix& operator*=(matrix& m, double s) { scale(s, m); return m; }
150 inline scaled<matrix> operator*(double s, const matrix &m) { return scaled<matrix>(m, s); }
151 inline scaled<matrix> operator*(const matrix &m, double s) { return scaled<matrix>(m, s); }
152 inline scaled<matrix> operator-(const matrix &m) { return scaled<matrix>(m, -1); }
153 inline matrix& operator*=(matrix& m, complex s) { scale(s, m); return m; }
154 inline matrix operator*(complex s, const matrix &m) { matrix sm(m); sm *= s; return sm; }
155 inline matrix operator*(const matrix &m, complex s) { matrix sm(m); sm *= s; return sm; }
156 inline diagMatrix operator*(double s, const diagMatrix &m) { diagMatrix ret(m); return ret*=s; }
157 inline diagMatrix operator*(const diagMatrix &m, double s) { diagMatrix ret(m); return ret*=s; }
158 inline diagMatrix operator-(const diagMatrix &m) { return m * (-1); }
159 
161 matrix operator*(const matrix&, const diagMatrix&);
162 matrix operator*(const diagMatrix&, const matrix&);
163 diagMatrix operator*(const diagMatrix&, const diagMatrix&);
164 
165 inline matrix& operator+=(matrix &m1, const matrix &m2) { if(m1) axpy(1.0, m2, m1); else m1 = m2; return m1; }
166 inline matrix& operator-=(matrix &m1, const matrix &m2) { if(m1) axpy(-1.0, m2, m1); else m1 = -m2; return m1; }
167 inline matrix operator+(const matrix &m1, const matrix &m2) { matrix tm(m1); tm += m2; return tm; }
168 inline matrix operator-(const matrix &m1, const matrix &m2) { matrix tm(m1); tm -= m2; return tm; }
169 void axpy(double alpha, const diagMatrix& x, matrix& y);
170 inline matrix& operator+=(matrix& m, const diagMatrix& d) { if(m) axpy(1., d, m); else m = d; return m; }
171 inline matrix& operator-=(matrix& m, const diagMatrix& d) { if(m) axpy(-1., d, m); else m=-d; return m; }
172 inline matrix operator+(const matrix& m, const diagMatrix& d) { matrix ret(m); ret+=d; return ret; }
173 inline matrix operator+(const diagMatrix& d, const matrix& m) { matrix ret(m); ret+=d; return ret; }
174 inline matrix operator-(const matrix& m, const diagMatrix& d) { matrix ret(m); ret-=d; return ret; }
175 inline matrix operator-(const diagMatrix& d, const matrix& m) { matrix ret(-m); ret+=d; return ret; }
176 void axpy(double alpha, const diagMatrix& x, diagMatrix& y);
177 inline diagMatrix& operator+=(diagMatrix& d1, const diagMatrix& d2) { axpy(1., d2, d1); return d1; }
178 inline diagMatrix& operator-=(diagMatrix& d1, const diagMatrix& d2) { axpy(-1., d2, d1); return d1; }
179 inline diagMatrix operator+(const diagMatrix& d1, const diagMatrix& d2) { diagMatrix ret(d1); return ret+=d2; }
180 inline diagMatrix operator-(const diagMatrix& d1, const diagMatrix& d2) { diagMatrix ret(d1); return ret-=d2; }
181 
182 //Functions required for using the Minimizable template on matrices:
183 diagMatrix clone(const diagMatrix& x);
184 matrix clone(const matrix& x);
185 double dot(const diagMatrix& x, const diagMatrix& y);
186 double dot(const matrix& x, const matrix& y);
187 void randomize(diagMatrix& x);
188 void randomize(matrix& x);
189 
190 
191 //------- Nonlinear matrix functions and their gradients ---------
192 
194 matrix inv(const matrix& A);
195 diagMatrix inv(const diagMatrix& A);
196 matrix invApply(const matrix& A, const matrix& b); //return inv(A) * b (A must be hermitian, positive-definite)
197 
199 matrix LU(const matrix& A);
200 
203 complex det(const matrix& A);
204 
206 double det(const diagMatrix& A);
207 
209 matrix pow(const matrix& A, double exponent, matrix* Aevecs=0, diagMatrix* Aeigs=0);
210 
212 matrix invsqrt(const matrix& A, matrix* Aevecs=0, diagMatrix* Aeigs=0);
213 
215 matrix cis(const matrix& A, matrix* Aevecs=0, diagMatrix* Aeigs=0);
216 
219 matrix cisInv(const matrix& A, matrix* Bevecs=0, diagMatrix* Beigs=0);
220 
222 matrix sqrt_grad(const matrix& grad_sqrtA, const matrix& Aevecs, const diagMatrix& Aeigs);
223 
225 matrix cis_grad(const matrix& grad_cisA, const matrix& Aevecs, const diagMatrix& Aeigs);
226 
227 
228 //------------ Misc matrix functions --------------
229 complex trace(const matrix &m);
230 double trace(const diagMatrix& m);
231 double nrm2(const diagMatrix& m);
232 diagMatrix diag(const matrix &m);
233 diagMatrix eye(int N);
234 matrix zeroes(int nRows, int nCols);
235 
238 {
239  const matrix& mBlock;
240  int nBlocks;
241  const std::vector<complex>* phaseArr;
242 public:
243  tiledBlockMatrix(const matrix& mBlock, int nBlocks, const std::vector<complex>* phaseArr=0);
244 
245  matrix operator*(const matrix&) const;
246 };
247 
248 #endif // JDFTX_ELECTRONIC_MATRIX_H
ScalarField pow(const ScalarField &, double alpha)
Elementwise power (preserve input)
CBLAS_TRANSPOSE op
pending operation (none, transpose or dagger)
Definition: matrix.h:118
Definition: scaled.h:25
Tptr operator*(const Tptr &in, double scaleFac)
Scalar multiply (preserve input)
Definition: Operators.h:116
void randomize(TptrCollection &x)
Initialize to normal random numbers:
Definition: ScalarFieldArray.h:154
Simulation grid descriptor.
Definition: GridInfo.h:45
Tptr conj(Tptr &&in)
Generic elementwise conjugate for complex data:
Definition: Operators.h:122
void scan(FILE *fp)
set submatrix to m at arbitrary increments
complex dot(const Tptr &X, const Tptr &Y)
Definition: Operators.h:196
double scale
pending scale factor
Definition: matrix.h:117
General complex matrix.
Definition: matrix.h:58
Template to avoid (delay) scaling operations on linear objects.
int index(int i, int j) const
Index into data()
Definition: matrix.h:66
Base class for managed-memory objects (that could potentially live on GPUs as well) ...
Definition: ManagedMemory.h:26
Real diagonal matrix.
Definition: matrix.h:31
Tptr & operator-=(Tptr &in, const Tptr &other)
Decrement.
Definition: Operators.h:170
int index(int i, int j) const
Index into data() with possible transpose.
Definition: matrix.h:123
const matrix & mat
matrix
Definition: matrix.h:116
Tptr clone(const Tptr &X)
Clone (NOTE: operator= is by reference for the ScalarField classes)
Definition: Operators.h:111
matrixScaledTransOp(const scaled< matrix > &smat, CBLAS_TRANSPOSE op=CblasNoTrans)
Create from a scaled matrix, with an optional op.
Definition: matrix.h:130
matrix operator()(int iStart, int iStop, int jStart, int jStop) const
get submatrix of elements (iStart <= i < iStop, jStart <= j < jStop)
Definition: matrix.h:85
matrixScaledTransOp(const matrix &mat, double scale=1.0, CBLAS_TRANSPOSE op=CblasNoTrans)
Create from a matrix with an optional scale and op:
Definition: matrix.h:126
bool isScalar(double absTol=1e-14, double relTol=1e-14) const
Check if all entries are identical within threshold.
Tptr operator+(const Tptr &in1, const Tptr &in2)
Add (preserve inputs)
Definition: Operators.h:171
ScalarField inv(const ScalarField &)
Elementwise reciprocal (preserve input)
Geometry of the simulation grid.
Matrix with a pending scale and transpose operation.
Definition: matrix.h:115
void print(FILE *fp, const char *fmt="%lg\t") const
print (ascii) to stream
Complex number (need to define our own because we need operators for gpu code as well) ...
Definition: scalar.h:49
void axpy(double alpha, const Tptr &X, Tptr &Y)
Generic axpy for complex data types (Note: null pointers are treated as zero)
Definition: Operators.h:158
complex conjOp(complex a) const
return conjugate if op requires it
Definition: matrix.h:122
A block matrix formed by repeating (tiling) a dense matrix along the diagonal.
Definition: matrix.h:237
Tptr & operator+=(Tptr &in, const Tptr &other)
Increment.
Definition: Operators.h:169
Tptr operator-(const Tptr &in1, const Tptr &in2)
Subtract (preserve inputs)
Definition: Operators.h:175
double nrm2(const Tptr &X)
Definition: Operators.h:199