1
// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
3
// See the LICENSE.txt file for license information. Please report all
4
// bugs and problems to <gmsh@geuz.org>.
8
#include "GmshConfig.h"
9
#include "GmshMatrix.h"
10
#include "GmshMessage.h"
12
//#if defined(_MSC_VER)
13
//#define F77NAME(x) (x)
17
#define F77NAME(x) (x##_)
20
#if defined(HAVE_BLAS)
23
void F77NAME(dgemm)(const char *transa, const char *transb, int *m, int *n, int *k,
24
double *alpha, double *a, int *lda,
25
double *b, int *ldb, double *beta,
27
void F77NAME(zgemm)(const char *transa, const char *transb, int *m, int *n, int *k,
28
std::complex<double> *alpha, std::complex<double> *a, int *lda,
29
std::complex<double> *b, int *ldb, std::complex<double> *beta,
30
std::complex<double> *c, int *ldc);
31
void F77NAME(dgemv)(const char *trans, int *m, int *n,
32
double *alpha, double *a, int *lda,
33
double *x, int *incx, double *beta,
34
double *y, int *incy);
35
void F77NAME(zgemv)(const char *trans, int *m, int *n,
36
std::complex<double> *alpha, std::complex<double> *a, int *lda,
37
std::complex<double> *x, int *incx, std::complex<double> *beta,
38
std::complex<double> *y, int *incy);
42
void gmshMatrix<double>::mult(const gmshMatrix<double> &b, gmshMatrix<double> &c)
44
int M = c.size1(), N = c.size2(), K = _c;
45
int LDA = _r, LDB = b.size1(), LDC = c.size1();
46
double alpha = 1., beta = 0.;
47
F77NAME(dgemm)("N", "N", &M, &N, &K, &alpha, _data, &LDA, b._data, &LDB,
48
&beta, c._data, &LDC);
52
void gmshMatrix<std::complex<double> >::mult(const gmshMatrix<std::complex<double> > &b,
53
gmshMatrix<std::complex<double> > &c)
55
int M = c.size1(), N = c.size2(), K = _c;
56
int LDA = _r, LDB = b.size1(), LDC = c.size1();
57
std::complex<double> alpha = 1., beta = 0.;
58
F77NAME(zgemm)("N", "N", &M, &N, &K, &alpha, _data, &LDA, b._data, &LDB,
59
&beta, c._data, &LDC);
63
void gmshMatrix<double>::gemm(gmshMatrix<double> &a, gmshMatrix<double> &b,
64
double alpha, double beta)
66
int M = size1(), N = size2(), K = a.size2();
67
int LDA = a.size1(), LDB = b.size1(), LDC = size1();
68
F77NAME(dgemm)("N", "N", &M, &N, &K, &alpha, a._data, &LDA, b._data, &LDB,
73
void gmshMatrix<std::complex<double> >::gemm(gmshMatrix<std::complex<double> > &a,
74
gmshMatrix<std::complex<double> > &b,
75
std::complex<double> alpha,
76
std::complex<double> beta)
78
int M = size1(), N = size2(), K = a.size2();
79
int LDA = a.size1(), LDB = b.size1(), LDC = size1();
80
F77NAME(zgemm)("N", "N", &M, &N, &K, &alpha, a._data, &LDA, b._data, &LDB,
85
void gmshMatrix<double>::mult(const gmshVector<double> &x, gmshVector<double> &y)
87
int M = _r, N = _c, LDA = _r, INCX = 1, INCY = 1;
88
double alpha = 1., beta = 0.;
89
F77NAME(dgemv)("N", &M, &N, &alpha, _data, &LDA, x._data, &INCX,
90
&beta, y._data, &INCY);
94
void gmshMatrix<std::complex<double> >::mult(const gmshVector<std::complex<double> > &x,
95
gmshVector<std::complex<double> > &y)
97
int M = _r, N = _c, LDA = _r, INCX = 1, INCY = 1;
98
std::complex<double> alpha = 1., beta = 0.;
99
F77NAME(zgemv)("N", &M, &N, &alpha, _data, &LDA, x._data, &INCX,
100
&beta, y._data, &INCY);
105
#if defined(HAVE_LAPACK)
108
void F77NAME(dgesv)(int *N, int *nrhs, double *A, int *lda, int *ipiv,
109
double *b, int *ldb, int *info);
110
void F77NAME(dgetrf)(int *M, int *N, double *A, int *lda, int *ipiv, int *info);
111
void F77NAME(dgetri)(int *M, double *A, int *lda, int *ipiv, double *work, int *lwork,
113
void F77NAME(dgesvd)(const char* jobu, const char *jobvt, int *M, int *N,
114
double *A, int *lda, double *S, double* U, int *ldu,
115
double *VT, int *ldvt, double *work, int *lwork, int *info);
116
void F77NAME(dgeev)(const char *jobvl, const char *jobvr,
117
int *n, double *a, int *lda,
118
double *wr, double *wi,
119
double *vl, int *ldvl,
120
double *vr, int *ldvr,
121
double *work, int *lwork,
126
bool gmshMatrix<double>::invertInPlace()
128
int N = size1(), nrhs = N, lda = N, ldb = N, info;
129
int *ipiv = new int[N];
130
double * invA = new double[N*N];
132
for (int i = 0; i < N * N; i++) invA[i] = 0.;
133
for (int i = 0; i < N; i++) invA[i * N + i] = 1.;
135
F77NAME(dgesv)(&N, &nrhs, _data, &lda, ipiv, invA, &ldb, &info);
136
memcpy(_data, invA, N * N * sizeof(double));
141
if(info == 0) return true;
143
Msg::Error("U(%d,%d)=0 in matrix inversion", info, info);
145
Msg::Error("Wrong %d-th argument in matrix inversion", -info);
151
bool gmshMatrix<double>::eig(gmshMatrix<double> &VL, gmshVector<double> &DR,
152
gmshVector<double> &DI, gmshMatrix<double> &VR,
155
int N = size1(), info;
157
double *work = new double[LWORK];
159
F77NAME(dgeev)("V", "V", &N, _data, &N, DR._data, DI._data,
160
VL._data, &N, VR._data, &N, work, &LWORK, &info);
165
Msg::Error("QR Algorithm failed to compute all the eigenvalues", info, info);
167
Msg::Error("Wrong %d-th argument in eig", -info);
172
for (int i = 0; i < size1() - 1; i++) {
174
for (int j = i + 1; j < size1(); j++)
175
if (fabs(DR(j)) < fabs(DR(minR))) minR = j;
177
tmp[0] = DR(i); tmp[1] = DI(i);
178
tmp[2] = VL(0,i); tmp[3] = VL(1,i); tmp[4] = VL(2,i);
179
tmp[5] = VR(0,i); tmp[6] = VR(1,i); tmp[7] = VR(2,i);
181
DR(i) = DR(minR); DI(i) = DI(minR);
182
VL(0,i) = VL(0,minR); VL(1,i) = VL(1,minR); VL(2,i) = VL(2,minR);
183
VR(0,i) = VR(0,minR); VR(1,i) = VR(1,minR); VR(2,i) = VR(2,minR);
185
DR(minR) = tmp[0]; DI(minR) = tmp[1];
186
VL(0,minR) = tmp[2]; VL(1,minR) = tmp[3]; VL(2,minR) = tmp[4];
187
VR(0,minR) = tmp[5]; VR(1,minR) = tmp[6]; VR(2,minR) = tmp[7];
196
bool gmshMatrix<double>::lu_solve(const gmshVector<double> &rhs, gmshVector<double> &result)
198
int N = size1(), nrhs = 1, lda = N, ldb = N, info;
199
int *ipiv = new int[N];
200
for(int i = 0; i < N; i++) result(i) = rhs(i);
201
F77NAME(dgesv)(&N, &nrhs, _data, &lda, ipiv, result._data, &ldb, &info);
203
if(info == 0) return true;
205
Msg::Error("U(%d,%d)=0 in LU decomposition", info, info);
207
Msg::Error("Wrong %d-th argument in LU decomposition", -info);
212
bool gmshMatrix<double>::invert(gmshMatrix<double> &result)
214
int M = size1(), N = size2(), lda = size1(), info;
215
int *ipiv = new int[std::min(M, N)];
217
F77NAME(dgetrf)(&M, &N, result._data, &lda, ipiv, &info);
220
double *work = new double[lwork];
221
F77NAME(dgetri)(&M, result._data, &lda, ipiv, work, &lwork, &info);
225
if(info == 0) return true;
227
Msg::Error("U(%d,%d)=0 in matrix inversion", info, info);
229
Msg::Error("Wrong %d-th argument in matrix inversion", -info);
234
double gmshMatrix<double>::determinant() const
236
gmshMatrix<double> tmp(*this);
237
int M = size1(), N = size2(), lda = size1(), info;
238
int *ipiv = new int[std::min(M, N)];
239
F77NAME(dgetrf)(&M, &N, tmp._data, &lda, ipiv, &info);
242
for(int i = 0; i < size1(); i++){
244
if(ipiv[i] != i + 1) det = -det;
250
Msg::Error("Wrong %d-th argument in matrix factorization", -info);
256
bool gmshMatrix<double>::svd(gmshMatrix<double> &V, gmshVector<double> &S)
258
gmshMatrix<double> VT(V.size2(), V.size1());
259
int M = size1(), N = size2(), LDA = size1(), LDVT = VT.size1(), info;
260
int LWORK = std::max(3 * std::min(M, N) + std::max(M, N), 5 * std::min(M, N));
261
gmshVector<double> WORK(LWORK);
262
F77NAME(dgesvd)("O", "A", &M, &N, _data, &LDA, S._data, _data, &LDA,
263
VT._data, &LDVT, WORK._data, &LWORK, &info);
265
if(info == 0) return true;
267
Msg::Error("SVD did not converge");
269
Msg::Error("Wrong %d-th argument in SVD decomposition", -info);