16 #include "kernels.hpp"
20 #include "kernels.hpp"
21 #include "../general/forall.hpp"
22 #include "../general/table.hpp"
23 #include "../general/globals.hpp"
30 #if defined(_MSC_VER) && (_MSC_VER < 1800)
32 #define copysign _copysign
36 #ifdef MFEM_USE_LAPACK
38 dgemm_(
char *,
char *,
int *,
int *,
int *,
double *,
double *,
39 int *,
double *,
int *,
double *,
double *,
int *);
41 dgetrf_(
int *,
int *,
double *,
int *,
int *,
int *);
43 dgetrs_(
char *,
int *,
int *,
double *,
int *,
int *,
double *,
int *,
int *);
45 dgetri_(
int *N,
double *A,
int *LDA,
int *IPIV,
double *WORK,
46 int *LWORK,
int *INFO);
48 dsyevr_(
char *JOBZ,
char *RANGE,
char *UPLO,
int *N,
double *A,
int *LDA,
49 double *VL,
double *VU,
int *IL,
int *IU,
double *ABSTOL,
int *M,
50 double *W,
double *Z,
int *LDZ,
int *ISUPPZ,
double *WORK,
int *LWORK,
51 int *IWORK,
int *LIWORK,
int *INFO);
53 dsyev_(
char *JOBZ,
char *UPLO,
int *N,
double *A,
int *LDA,
double *W,
54 double *WORK,
int *LWORK,
int *INFO);
56 dsygv_ (
int *ITYPE,
char *JOBZ,
char *UPLO,
int * N,
double *A,
int *LDA,
57 double *B,
int *LDB,
double *W,
double *WORK,
int *LWORK,
int *INFO);
59 dgesvd_(
char *JOBU,
char *JOBVT,
int *M,
int *N,
double *A,
int *LDA,
60 double *S,
double *U,
int *LDU,
double *VT,
int *LDVT,
double *WORK,
61 int *LWORK,
int *INFO);
63 dtrsm_(
char *side,
char *uplo,
char *transa,
char *diag,
int *m,
int *n,
64 double *
alpha,
double *
a,
int *lda,
double *
b,
int *ldb);
66 dggev_(
char *jobvl,
char *jobvr,
int *n,
double *
a,
int *lda,
double *B,
67 int *ldb,
double *alphar,
double *alphai,
double *beta,
double *vl,
68 int * ldvl,
double * vr,
int * ldvr,
double * work,
int * lwork,
int* info);
84 MFEM_ASSERT(m.data,
"invalid source matrix");
86 std::memcpy(data, m.data,
sizeof(
double)*hw);
92 MFEM_ASSERT(s >= 0,
"invalid DenseMatrix size: " << s);
102 MFEM_ASSERT(m >= 0 && n >= 0,
103 "invalid DenseMatrix size: " << m <<
" x " << n);
104 const int capacity = m*n;
113 :
Matrix(mat.width, mat.height)
115 MFEM_CONTRACT_VAR(ch);
121 for (
int i = 0; i <
height; i++)
123 for (
int j = 0; j <
width; j++)
125 (*this)(i,j) = mat(j,i);
133 MFEM_ASSERT(h >= 0 && w >= 0,
134 "invalid DenseMatrix size: " << h <<
" x " << w);
168 "incompatible dimensions");
170 Mult((
const double *)x, (
double *)y);
176 "incompatible dimensions");
180 for (
int i = 0; i < hw; i++)
182 a += data[i] * m.data[i];
190 double *d_col =
Data();
191 for (
int col = 0; col <
width; col++)
194 for (
int row = 0; row <
height; row++)
196 y_col += x[row]*d_col[row];
206 "incompatible dimensions");
214 "incompatible dimensions");
216 const double *xp = x, *d_col = data;
218 for (
int col = 0; col <
width; col++)
220 double x_col = xp[col];
221 for (
int row = 0; row <
height; row++)
223 yp[row] += x_col*d_col[row];
232 "incompatible dimensions");
234 const double *d_col = data;
235 for (
int col = 0; col <
width; col++)
238 for (
int row = 0; row <
height; row++)
240 y_col += x[row]*d_col[row];
250 "incompatible dimensions");
252 const double *xp = x, *d_col = data;
254 for (
int col = 0; col <
width; col++)
256 const double x_col = a*xp[col];
257 for (
int row = 0; row <
height; row++)
259 yp[row] += x_col*d_col[row];
269 "incompatible dimensions");
271 const double *d_col = data;
272 for (
int col = 0; col <
width; col++)
275 for (
int row = 0; row <
height; row++)
277 y_col += x[row]*d_col[row];
288 for (
int i = 0; i <
height; i++)
291 for (
int j = 0; j <
width; j++)
293 Axi += (*this)(i,j) * x[j];
304 double * it_data = data;
305 for (
int j = 0; j <
width; ++j)
307 for (
int i = 0; i <
height; ++i)
309 *(it_data++) *=
s(i);
317 double * it_data = data;
318 for (
int j = 0; j <
width; ++j)
320 for (
int i = 0; i <
height; ++i)
322 *(it_data++) /=
s(i);
331 double * it_data = data;
332 for (
int j = 0; j <
width; ++j)
335 for (
int i = 0; i <
height; ++i)
345 double * it_data = data;
346 for (
int j = 0; j <
width; ++j)
348 const double sj = 1./
s(j);
349 for (
int i = 0; i <
height; ++i)
361 mfem_error(
"DenseMatrix::SymmetricScaling: dimension mismatch");
364 double * ss =
new double[
width];
367 for (
double * end_s = it_s +
width; it_s != end_s; ++it_s)
369 *(it_ss++) =
sqrt(*it_s);
372 double * it_data = data;
373 for (
int j = 0; j <
width; ++j)
375 for (
int i = 0; i <
height; ++i)
377 *(it_data++) *= ss[i]*ss[j];
389 mfem_error(
"DenseMatrix::InvSymmetricScaling: dimension mismatch");
392 double * ss =
new double[
width];
395 for (
double * end_s = it_s +
width; it_s != end_s; ++it_s)
397 *(it_ss++) = 1./
sqrt(*it_s);
400 double * it_data = data;
401 for (
int j = 0; j <
width; ++j)
403 for (
int i = 0; i <
height; ++i)
405 *(it_data++) *= ss[i]*ss[j];
417 mfem_error(
"DenseMatrix::Trace() : not a square matrix!");
423 for (
int i = 0; i <
width; i++)
439 "The matrix must be square and "
440 <<
"sized larger than zero to compute the determinant."
441 <<
" Height() = " <<
Height()
442 <<
", Width() = " <<
Width());
450 return data[0] * data[3] - data[1] * data[2];
454 const double *d = data;
456 d[0] * (d[4] * d[8] - d[5] * d[7]) +
457 d[3] * (d[2] * d[7] - d[1] * d[8]) +
458 d[6] * (d[1] * d[5] - d[2] * d[4]);
462 const double *d = data;
464 d[ 0] * (d[ 5] * (d[10] * d[15] - d[11] * d[14]) -
465 d[ 9] * (d[ 6] * d[15] - d[ 7] * d[14]) +
466 d[13] * (d[ 6] * d[11] - d[ 7] * d[10])
468 d[ 4] * (d[ 1] * (d[10] * d[15] - d[11] * d[14]) -
469 d[ 9] * (d[ 2] * d[15] - d[ 3] * d[14]) +
470 d[13] * (d[ 2] * d[11] - d[ 3] * d[10])
472 d[ 8] * (d[ 1] * (d[ 6] * d[15] - d[ 7] * d[14]) -
473 d[ 5] * (d[ 2] * d[15] - d[ 3] * d[14]) +
474 d[13] * (d[ 2] * d[ 7] - d[ 3] * d[ 6])
476 d[12] * (d[ 1] * (d[ 6] * d[11] - d[ 7] * d[10]) -
477 d[ 5] * (d[ 2] * d[11] - d[ 3] * d[10]) +
478 d[ 9] * (d[ 2] * d[ 7] - d[ 3] * d[ 6])
487 return lu_factors.
Det();
502 return sqrt(data[0] * data[0] + data[1] * data[1]);
506 return sqrt(data[0] * data[0] + data[1] * data[1] + data[2] * data[2]);
510 const double *d = data;
511 double E = d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
512 double G = d[3] * d[3] + d[4] * d[4] + d[5] * d[5];
513 double F = d[0] * d[3] + d[1] * d[4] + d[2] * d[5];
514 return sqrt(E * G - F * F);
516 mfem_error(
"DenseMatrix::Weight(): mismatched or unsupported dimensions");
523 for (
int i = 0; i <
s; i++)
525 data[i] = alpha*A[i];
531 for (
int j = 0; j <
Width(); j++)
533 for (
int i = 0; i <
Height(); i++)
535 (*this)(i,j) += c * A(i,j);
543 for (
int i = 0; i <
s; i++)
553 for (
int i = 0; i <
s; i++)
565 for (
int i = 0; i < hw; i++)
582 "incompatible matrix sizes.");
588 for (
int j = 0; j <
width; j++)
590 for (
int i = 0; i <
height; i++)
592 (*this)(i, j) -= m(i, j);
602 for (
int i = 0; i <
s; i++)
612 for (
int i = 0; i < hw; i++)
623 mfem_error(
"DenseMatrix::Invert(): dimension mismatch");
627 #ifdef MFEM_USE_LAPACK
628 int *ipiv =
new int[
width];
637 mfem_error(
"DenseMatrix::Invert() : Error in DGETRF");
643 work =
new double[lwork];
649 mfem_error(
"DenseMatrix::Invert() : Error in DGETRI");
655 int c, i, j, n =
Width();
659 for (c = 0; c < n; c++)
661 a = fabs((*
this)(c, c));
663 for (j = c + 1; j < n; j++)
665 b = fabs((*
this)(j, c));
674 mfem_error(
"DenseMatrix::Invert() : singular matrix");
677 for (j = 0; j < n; j++)
679 mfem::Swap<double>((*this)(c, j), (*
this)(i, j));
682 a = (*this)(c, c) = 1.0 / (*
this)(c, c);
683 for (j = 0; j < c; j++)
687 for (j++; j < n; j++)
691 for (i = 0; i < c; i++)
693 (*this)(i, c) = a * (b = -(*
this)(i, c));
694 for (j = 0; j < c; j++)
696 (*this)(i, j) += b * (*
this)(c, j);
698 for (j++; j < n; j++)
700 (*this)(i, j) += b * (*
this)(c, j);
703 for (i++; i < n; i++)
705 (*this)(i, c) = a * (b = -(*
this)(i, c));
706 for (j = 0; j < c; j++)
708 (*this)(i, j) += b * (*
this)(c, j);
710 for (j++; j < n; j++)
712 (*this)(i, j) += b * (*
this)(c, j);
717 for (c = n - 1; c >= 0; c--)
720 for (i = 0; i < n; i++)
722 mfem::Swap<double>((*this)(i, c), (*
this)(i, j));
734 mfem_error(
"DenseMatrix::SquareRootInverse() matrix not square.");
744 for (
int v = 0; v <
Height() ; v++) { (*this)(v,v) = 1.0; }
746 for (
int j = 0; j < 10; j++)
748 for (
int i = 0; i < 10; i++)
763 for (
int v = 0; v <
Height() ; v++) { tmp2(v,v) -= 1.0; }
764 if (tmp2.FNorm() < 1e-10) {
break; }
767 if (tmp2.FNorm() > 1e-10)
769 mfem_error(
"DenseMatrix::SquareRootInverse not converged");
775 for (
int j = 0; j <
Width(); j++)
778 for (
int i = 0; i <
Height(); i++)
780 v[j] += (*this)(i,j)*(*
this)(i,j);
789 const double *d = data;
790 double norm = 0.0, abs_entry;
792 for (
int i = 0; i < hw; i++)
794 abs_entry = fabs(d[i]);
795 if (norm < abs_entry)
807 double max_norm = 0.0, entry, fnorm2;
809 for (i = 0; i < hw; i++)
811 entry = fabs(data[i]);
812 if (entry > max_norm)
820 scale_factor = scaled_fnorm2 = 0.0;
825 for (i = 0; i < hw; i++)
827 entry = data[i] / max_norm;
828 fnorm2 += entry * entry;
831 scale_factor = max_norm;
832 scaled_fnorm2 = fnorm2;
837 #ifdef MFEM_USE_LAPACK
844 double *A =
new double[N*N];
855 int *ISUPPZ =
new int[2*N];
874 double *data = a.
Data();
876 for (
int i = 0; i < hw; i++)
881 dsyevr_( &JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU,
882 &ABSTOL, &M, W, Z, &LDZ, ISUPPZ, &QWORK, &LWORK,
883 &QIWORK, &LIWORK, &INFO );
888 WORK =
new double[LWORK];
889 IWORK =
new int[LIWORK];
891 dsyevr_( &JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU,
892 &ABSTOL, &M, W, Z, &LDZ, ISUPPZ, WORK, &LWORK,
893 IWORK, &LIWORK, &INFO );
897 mfem::err <<
"dsyevr_Eigensystem(...): DSYEVR error code: "
905 mfem::err <<
"dsyevr_Eigensystem(...):\n"
906 <<
" DSYEVR did not find all eigenvalues "
907 << M <<
"/" << N << endl;
912 mfem_error(
"dsyevr_Eigensystem(...): inf/nan values in W");
916 mfem_error(
"dsyevr_Eigensystem(...): inf/nan values in Z");
919 for (IL = 0; IL < N; IL++)
920 for (IU = 0; IU <= IL; IU++)
923 for (M = 0; M < N; M++)
925 VL += Z[M+IL*N] * Z[M+IU*N];
942 <<
" Z^t Z - I deviation = " << VU
943 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
944 << W[0] <<
", N = " << N << endl;
951 <<
" Z^t Z - I deviation = " << VU
952 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
953 << W[0] <<
", N = " << N << endl;
957 mfem_error(
"dsyevr_Eigensystem(...): ERROR: ...");
960 for (IL = 0; IL < N; IL++)
961 for (IU = 0; IU < N; IU++)
964 for (M = 0; M < N; M++)
966 VL += Z[IL+M*N] * W[M] * Z[IU+M*N];
968 VL = fabs(VL-data[IL+N*IU]);
977 <<
" max matrix deviation = " << VU
978 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
979 << W[0] <<
", N = " << N << endl;
983 mfem_error(
"dsyevr_Eigensystem(...): ERROR: ...");
992 MFEM_CONTRACT_VAR(a);
993 MFEM_CONTRACT_VAR(ev);
994 MFEM_CONTRACT_VAR(evect);
1000 #ifdef MFEM_USE_LAPACK
1012 double *WORK = NULL;
1023 A =
new double[N*N];
1027 double *data = a.
Data();
1028 for (
int i = 0; i < hw; i++)
1033 dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, &QWORK, &LWORK, &INFO);
1035 LWORK = (int) QWORK;
1036 WORK =
new double[LWORK];
1038 dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, WORK, &LWORK, &INFO);
1042 mfem::err <<
"dsyev_Eigensystem: DSYEV error code: " << INFO << endl;
1047 if (evect == NULL) {
delete [] A; }
1049 MFEM_CONTRACT_VAR(a);
1050 MFEM_CONTRACT_VAR(ev);
1051 MFEM_CONTRACT_VAR(evect);
1055 void DenseMatrix::Eigensystem(Vector &ev, DenseMatrix *evect)
1057 #ifdef MFEM_USE_LAPACK
1065 MFEM_CONTRACT_VAR(ev);
1066 MFEM_CONTRACT_VAR(evect);
1067 mfem_error(
"DenseMatrix::Eigensystem: Compiled without LAPACK");
1075 #ifdef MFEM_USE_LAPACK
1088 double *B =
new double[N*N];
1090 double *WORK = NULL;
1101 A =
new double[N*N];
1105 double *a_data = a.
Data();
1106 double *b_data = b.
Data();
1107 for (
int i = 0; i < hw; i++)
1113 dsygv_(&ITYPE, &JOBZ, &UPLO, &N, A, &LDA, B, &LDB, W, &QWORK, &LWORK, &INFO);
1115 LWORK = (int) QWORK;
1116 WORK =
new double[LWORK];
1118 dsygv_(&ITYPE, &JOBZ, &UPLO, &N, A, &LDA, B, &LDB, W, WORK, &LWORK, &INFO);
1122 mfem::err <<
"dsygv_Eigensystem: DSYGV error code: " << INFO << endl;
1128 if (evect == NULL) {
delete [] A; }
1130 MFEM_CONTRACT_VAR(a);
1131 MFEM_CONTRACT_VAR(b);
1132 MFEM_CONTRACT_VAR(ev);
1133 MFEM_CONTRACT_VAR(evect);
1137 void DenseMatrix::Eigensystem(DenseMatrix &
b, Vector &ev,
1140 #ifdef MFEM_USE_LAPACK
1145 MFEM_CONTRACT_VAR(b);
1146 MFEM_CONTRACT_VAR(ev);
1147 MFEM_CONTRACT_VAR(evect);
1148 mfem_error(
"DenseMatrix::Eigensystem(generalized): Compiled without LAPACK");
1154 #ifdef MFEM_USE_LAPACK
1160 double *
a = copy_of_this.data;
1165 double *work = NULL;
1170 dgesvd_(&jobu, &jobvt, &m, &n, a, &m,
1171 s, u, &m, vt, &n, &qwork, &lwork, &info);
1173 lwork = (int) qwork;
1174 work =
new double[lwork];
1176 dgesvd_(&jobu, &jobvt, &m, &n, a, &m,
1177 s, u, &m, vt, &n, work, &lwork, &info);
1182 mfem::err <<
"DenseMatrix::SingularValues : info = " << info << endl;
1186 MFEM_CONTRACT_VAR(sv);
1188 mfem_error(
"DenseMatrix::SingularValues: Compiled without LAPACK");
1198 for (
int i=0; i < sv.
Size(); ++i)
1210 "The matrix must be square and sized 1, 2, or 3 to compute the"
1212 <<
" Height() = " <<
Height()
1213 <<
", Width() = " <<
Width());
1216 const double *d = data;
1242 const double *d = data;
1260 const double* rp = data + r;
1263 for (
int i = 0; i < n; i++)
1275 double *cp =
Data() + c * m;
1278 for (
int i = 0; i < m; i++)
1292 for (
int i = 0; i <
height; ++i)
1294 d(i) = (*this)(i,i);
1308 for (
int j = 0; j <
width; ++j)
1309 for (
int i = 0; i <
height; ++i)
1311 l(i) += fabs((*
this)(i,j));
1318 for (
int i = 0; i <
height; i++)
1321 for (
int j = 0; j <
width; j++)
1334 for (
int i = 0; i < N; i++)
1338 for (
int i = 0; i < n; i++)
1349 for (i = 0; i < N; i++)
1353 for (i = 0; i < n; i++)
1355 data[i*(n+1)] = diag[i];
1366 for (i = 0; i <
Height(); i++)
1367 for (j = i+1; j <
Width(); j++)
1370 (*this)(i,j) = (*
this)(j,i);
1385 for (
int i = 0; i <
Height(); i++)
1386 for (
int j = 0; j <
Width(); j++)
1388 (*this)(i,j) = A(j,i);
1397 mfem_error(
"DenseMatrix::Symmetrize() : not a square matrix!");
1405 for (
int i = 0; i <
Height(); i++)
1408 for (
int j = 0; j <
Width(); j++)
1411 (*this)(i, j) = 0.0;
1425 mfem_error(
"DenseMatrix::GradToCurl(...): dimension mismatch");
1431 for (
int i = 0; i < n; i++)
1434 double x = (*this)(i,0);
1435 double y = (*this)(i,1);
1448 for (
int i = 0; i < n; i++)
1451 double x = (*this)(i,0);
1452 double y = (*this)(i,1);
1453 double z = (*this)(i,2);
1478 MFEM_ASSERT(
Width()*
Height() == div.
Size(),
"incompatible Vector 'div'!");
1483 double *ddata = div.
GetData();
1485 for (
int i = 0; i < n; i++)
1495 for (
int j = 0; j <
Width(); j++)
1497 for (
int i = row1; i <= row2; i++)
1499 (*this)(i-row1,j) = A(i,j);
1508 for (
int j = col1; j <= col2; j++)
1510 for (
int i = 0; i <
Height(); i++)
1512 (*this)(i,j-col1) = A(i,j);
1521 for (
int j = 0; j < n; j++)
1523 for (
int i = 0; i < m; i++)
1525 (*this)(i,j) = A(Aro+i,Aco+j);
1532 double *v = A.
Data();
1534 for (
int j = 0; j < A.
Width(); j++)
1536 for (
int i = 0; i < A.
Height(); i++)
1538 (*this)(row_offset+i,col_offset+j) = *(v++);
1545 double *v = A.
Data();
1547 for (
int i = 0; i < A.
Width(); i++)
1549 for (
int j = 0; j < A.
Height(); j++)
1551 (*this)(row_offset+i,col_offset+j) = *(v++);
1557 int row_offset,
int col_offset)
1559 MFEM_VERIFY(row_offset+m <= this->
Height() && col_offset+n <= this->
Width(),
1560 "this DenseMatrix is too small to accomodate the submatrix. "
1561 <<
"row_offset = " << row_offset
1563 <<
", this->Height() = " << this->
Height()
1564 <<
", col_offset = " << col_offset
1566 <<
", this->Width() = " << this->
Width()
1568 MFEM_VERIFY(Aro+m <= A.
Height() && Aco+n <= A.
Width(),
1569 "The A DenseMatrix is too small to accomodate the submatrix. "
1572 <<
", A.Height() = " << A.
Height()
1573 <<
", Aco = " << Aco
1575 <<
", A.Width() = " << A.
Width()
1578 for (
int j = 0; j < n; j++)
1580 for (
int i = 0; i < m; i++)
1582 (*this)(row_offset+i,col_offset+j) = A(Aro+i,Aco+j);
1589 for (
int i = 0; i < n; i++)
1591 for (
int j = i+1; j < n; j++)
1593 (*this)(row_offset+i,col_offset+j) =
1594 (*
this)(row_offset+j,col_offset+i) = 0.0;
1598 for (
int i = 0; i < n; i++)
1600 (*this)(row_offset+i,col_offset+i) = c;
1607 for (
int i = 0; i < n; i++)
1609 for (
int j = i+1; j < n; j++)
1611 (*this)(row_offset+i,col_offset+j) =
1612 (*
this)(row_offset+j,col_offset+i) = 0.0;
1616 for (
int i = 0; i < n; i++)
1618 (*this)(row_offset+i,col_offset+i) = diag[i];
1626 int i, j, i_off = 0, j_off = 0;
1628 for (j = 0; j < A.
Width(); j++)
1635 for (i = 0; i < A.
Height(); i++)
1642 (*this)(i-i_off,j-j_off) = A(i,j);
1658 if (co+aw >
Width() || ro+ah > h)
1660 mfem_error(
"DenseMatrix::AddMatrix(...) 1 : dimension mismatch");
1664 p = data + ro + co * h;
1667 for (
int c = 0; c < aw; c++)
1669 for (
int r = 0; r < ah; r++)
1688 if (co+aw >
Width() || ro+ah > h)
1690 mfem_error(
"DenseMatrix::AddMatrix(...) 2 : dimension mismatch");
1694 p = data + ro + co * h;
1697 for (
int c = 0; c < aw; c++)
1699 for (
int r = 0; r < ah; r++)
1711 double *vdata = v.
GetData() + offset;
1713 for (
int i = 0; i < n; i++)
1715 vdata[i] += data[i];
1722 const double *vdata = v.
GetData() + offset;
1724 for (
int i = 0; i < n; i++)
1737 mfem_error(
"DenseMatrix::AdjustDofDirection(...): dimension mismatch");
1742 for (
int i = 0; i < n-1; i++)
1744 const int s = (dof[i] < 0) ? (-1) : (1);
1745 for (
int j = i+1; j < n; j++)
1747 const int t = (dof[j] < 0) ? (-s) : (
s);
1750 (*this)(i,j) = -(*
this)(i,j);
1751 (*this)(j,i) = -(*
this)(j,i);
1759 for (
int j = 0; j <
Width(); j++)
1761 (*this)(row, j) = value;
1767 for (
int i = 0; i <
Height(); i++)
1769 (*this)(i, col) = value;
1775 MFEM_ASSERT(row !=
nullptr,
"supplied row pointer is null");
1776 for (
int j = 0; j <
Width(); j++)
1778 (*this)(r, j) = row[j];
1790 MFEM_ASSERT(col !=
nullptr,
"supplied column pointer is null");
1791 for (
int i = 0; i <
Height(); i++)
1793 (*this)(i, c) = col[i];
1805 for (
int col = 0; col <
Width(); col++)
1807 for (
int row = 0; row <
Height(); row++)
1809 if (std::abs(
operator()(row,col)) <= eps)
1820 ios::fmtflags old_flags = os.flags();
1822 os << setiosflags(ios::scientific | ios::showpos);
1823 for (
int i = 0; i <
height; i++)
1825 os <<
"[row " << i <<
"]\n";
1826 for (
int j = 0; j <
width; j++)
1829 if (j+1 == width || (j+1) % width_ == 0)
1840 os.flags(old_flags);
1846 ios::fmtflags old_flags = os.flags();
1848 os << setiosflags(ios::scientific | ios::showpos);
1849 for (
int i = 0; i <
height; i++)
1851 for (
int j = 0; j <
width; j++)
1859 os.flags(old_flags);
1865 ios::fmtflags old_flags = os.flags();
1867 os << setiosflags(ios::scientific | ios::showpos);
1868 for (
int j = 0; j <
width; j++)
1870 os <<
"[col " << j <<
"]\n";
1871 for (
int i = 0; i <
height; i++)
1874 if (i+1 == height || (i+1) % width_ == 0)
1885 os.flags(old_flags);
1894 for (
int i = 0; i <
width; i++)
1899 <<
", cond_F = " <<
FNorm()*copy.FNorm() << endl;
1940 MFEM_VERIFY(A.
IsSquare(),
"A must be a square matrix!");
1941 MFEM_ASSERT(A.
NumCols() > 0,
"supplied matrix, A, is empty!");
1942 MFEM_ASSERT(X !=
nullptr,
"supplied vector, X, is null!");
1950 double det = A(0,0);
1951 if (std::abs(det) <= TOL) {
return false; }
1958 double det = A.
Det();
1959 if (std::abs(det) <= TOL) {
return false; }
1961 double invdet = 1. / det;
1966 X[0] = ( A(1,1)*b0 - A(0,1)*b1) * invdet;
1967 X[1] = (-A(1,0)*b0 + A(0,0)*b1) * invdet;
1976 if (!lu.Factor(N,TOL)) {
return false; }
1989 b.
Width() == c.
Height(),
"incompatible dimensions");
1991 #ifdef MFEM_USE_LAPACK
1992 static char transa =
'N', transb =
'N';
1993 static double alpha = 1.0, beta = 0.0;
1996 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
1997 c.
Data(), &k, &beta, a.
Data(), &m);
1999 const int ah = a.
Height();
2000 const int aw = a.
Width();
2001 const int bw = b.
Width();
2002 double *ad = a.
Data();
2003 const double *bd = b.
Data();
2004 const double *cd = c.
Data();
2013 b.
Width() == c.
Height(),
"incompatible dimensions");
2015 #ifdef MFEM_USE_LAPACK
2016 static char transa =
'N', transb =
'N';
2017 static double beta = 1.0;
2020 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2021 c.
Data(), &k, &beta, a.
Data(), &m);
2023 const int ah = a.
Height();
2024 const int aw = a.
Width();
2025 const int bw = b.
Width();
2026 double *ad = a.
Data();
2027 const double *bd = b.
Data();
2028 const double *cd = c.
Data();
2029 for (
int j = 0; j < aw; j++)
2031 for (
int k = 0; k < bw; k++)
2033 for (
int i = 0; i < ah; i++)
2035 ad[i+j*ah] += alpha * bd[i+k*ah] * cd[k+j*bw];
2045 b.
Width() == c.
Height(),
"incompatible dimensions");
2047 #ifdef MFEM_USE_LAPACK
2048 static char transa =
'N', transb =
'N';
2049 static double alpha = 1.0, beta = 1.0;
2052 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2053 c.
Data(), &k, &beta, a.
Data(), &m);
2055 const int ah = a.
Height();
2056 const int aw = a.
Width();
2057 const int bw = b.
Width();
2058 double *ad = a.
Data();
2059 const double *bd = b.
Data();
2060 const double *cd = c.
Data();
2061 for (
int j = 0; j < aw; j++)
2063 for (
int k = 0; k < bw; k++)
2065 for (
int i = 0; i < ah; i++)
2067 ad[i+j*ah] += bd[i+k*ah] * cd[k+j*bw];
2079 mfem_error(
"CalcAdjugate(...): unsupported dimensions");
2083 mfem_error(
"CalcAdjugate(...): dimension mismatch");
2089 const double *d = a.
Data();
2090 double *ad = adja.
Data();
2105 e = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
2106 g = d[3]*d[3] + d[4]*d[4] + d[5]*d[5];
2107 f = d[0]*d[3] + d[1]*d[4] + d[2]*d[5];
2109 ad[0] = d[0]*g - d[3]*
f;
2110 ad[1] = d[3]*e - d[0]*
f;
2111 ad[2] = d[1]*g - d[4]*
f;
2112 ad[3] = d[4]*e - d[1]*
f;
2113 ad[4] = d[2]*g - d[5]*
f;
2114 ad[5] = d[5]*e - d[2]*
f;
2123 else if (a.
Width() == 2)
2126 adja(0,1) = -
a(0,1);
2127 adja(1,0) = -
a(1,0);
2132 adja(0,0) =
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1);
2133 adja(0,1) =
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2);
2134 adja(0,2) =
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1);
2136 adja(1,0) =
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2);
2137 adja(1,1) =
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0);
2138 adja(1,2) =
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2);
2140 adja(2,0) =
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0);
2141 adja(2,1) =
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1);
2142 adja(2,2) =
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0);
2152 mfem_error(
"CalcAdjugateTranspose(...): dimension mismatch");
2159 else if (a.
Width() == 2)
2161 adjat(0,0) =
a(1,1);
2162 adjat(1,0) = -
a(0,1);
2163 adjat(0,1) = -
a(1,0);
2164 adjat(1,1) =
a(0,0);
2168 adjat(0,0) =
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1);
2169 adjat(1,0) =
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2);
2170 adjat(2,0) =
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1);
2172 adjat(0,1) =
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2);
2173 adjat(1,1) =
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0);
2174 adjat(2,1) =
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2);
2176 adjat(0,2) =
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0);
2177 adjat(1,2) =
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1);
2178 adjat(2,2) =
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0);
2185 MFEM_ASSERT(inva.
Height() == a.
Width(),
"incorrect dimensions");
2186 MFEM_ASSERT(inva.
Width() == a.
Height(),
"incorrect dimensions");
2192 const double *d = a.
Data();
2193 double *
id = inva.
Data();
2196 t = 1.0 / (d[0]*d[0] + d[1]*d[1]);
2204 t = 1.0 / (d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
2212 e = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
2213 g = d[3]*d[3] + d[4]*d[4] + d[5]*d[5];
2214 f = d[0]*d[3] + d[1]*d[4] + d[2]*d[5];
2215 t = 1.0 / (e*g - f*
f);
2216 e *=
t; g *=
t; f *=
t;
2218 id[0] = d[0]*g - d[3]*
f;
2219 id[1] = d[3]*e - d[0]*
f;
2220 id[2] = d[1]*g - d[4]*
f;
2221 id[3] = d[4]*e - d[1]*
f;
2222 id[4] = d[2]*g - d[5]*
f;
2223 id[5] = d[5]*e - d[2]*
f;
2231 MFEM_ASSERT(std::abs(t) > 1.0e-14 *
pow(a.FNorm()/a.
Width(), a.
Width()),
2232 "singular matrix!");
2238 inva(0,0) = 1.0 / a.
Det();
2241 kernels::CalcInverse<2>(a.
Data(), inva.
Data());
2244 kernels::CalcInverse<3>(a.
Data(), inva.
Data());
2255 mfem_error(
"CalcInverseTranspose(...): dimension mismatch");
2259 double t = 1. / a.
Det() ;
2264 inva(0,0) = 1.0 /
a(0,0);
2267 inva(0,0) =
a(1,1) *
t ;
2268 inva(1,0) = -
a(0,1) *
t ;
2269 inva(0,1) = -
a(1,0) *
t ;
2270 inva(1,1) =
a(0,0) *
t ;
2273 inva(0,0) = (
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1))*t;
2274 inva(1,0) = (
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2))*t;
2275 inva(2,0) = (
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1))*t;
2277 inva(0,1) = (
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2))*t;
2278 inva(1,1) = (
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0))*t;
2279 inva(2,1) = (
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2))*t;
2281 inva(0,2) = (
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0))*t;
2282 inva(1,2) = (
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1))*t;
2283 inva(2,2) = (
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0))*t;
2293 "Matrix must be 3x2 or 2x1, "
2294 <<
"and the Vector must be sized with the rows. "
2295 <<
" J.Height() = " << J.
Height()
2296 <<
", J.Width() = " << J.
Width()
2297 <<
", n.Size() = " << n.
Size()
2300 const double *d = J.
Data();
2308 n(0) = d[1]*d[5] - d[2]*d[4];
2309 n(1) = d[2]*d[3] - d[0]*d[5];
2310 n(2) = d[0]*d[4] - d[1]*d[3];
2316 const int height = a.
Height();
2317 const int width = a.
Width();
2318 for (
int i = 0; i < height; i++)
2320 for (
int j = 0; j <= i; j++)
2323 for (
int k = 0; k < width; k++)
2325 temp +=
a(i,k) *
a(j,k);
2327 aat(j,i) = aat(i,j) = temp;
2334 for (
int i = 0; i < A.
Height(); i++)
2336 for (
int j = 0; j < i; j++)
2339 for (
int k = 0; k < A.
Width(); k++)
2341 t += D(k) * A(i, k) * A(j, k);
2349 for (
int i = 0; i < A.
Height(); i++)
2352 for (
int k = 0; k < A.
Width(); k++)
2354 t += D(k) * A(i, k) * A(i, k);
2362 for (
int i = 0; i < A.
Height(); i++)
2364 for (
int j = 0; j <= i; j++)
2367 for (
int k = 0; k < A.
Width(); k++)
2369 t += D(k) * A(i, k) * A(j, k);
2371 ADAt(j, i) = ADAt(i, j) =
t;
2382 mfem_error(
"MultABt(...): dimension mismatch");
2386 #ifdef MFEM_USE_LAPACK
2387 static char transa =
'N', transb =
'T';
2388 static double alpha = 1.0, beta = 0.0;
2391 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2392 B.
Data(), &n, &beta, ABt.
Data(), &m);
2394 const int ah = A.
Height();
2395 const int bh = B.
Height();
2396 const int aw = A.
Width();
2397 const double *ad = A.
Data();
2398 const double *bd = B.
Data();
2399 double *cd = ABt.
Data();
2403 const int ah = A.
Height();
2404 const int bh = B.
Height();
2405 const int aw = A.
Width();
2406 const double *ad = A.
Data();
2407 const double *bd = B.
Data();
2408 double *cd = ABt.
Data();
2410 for (
int j = 0; j < bh; j++)
2411 for (
int i = 0; i < ah; i++)
2414 const double *ap = ad + i;
2415 const double *bp = bd + j;
2416 for (
int k = 0; k < aw; k++)
2428 for (i = 0; i < A.
Height(); i++)
2429 for (j = 0; j < B.
Height(); j++)
2432 for (k = 0; k < A.
Width(); k++)
2434 d += A(i, k) * B(j, k);
2448 mfem_error(
"MultADBt(...): dimension mismatch");
2452 const int ah = A.
Height();
2453 const int bh = B.
Height();
2454 const int aw = A.
Width();
2455 const double *ad = A.
Data();
2456 const double *bd = B.
Data();
2457 const double *dd = D.
GetData();
2458 double *cd = ADBt.
Data();
2460 for (
int i = 0,
s = ah*bh; i <
s; i++)
2464 for (
int k = 0; k < aw; k++)
2467 for (
int j = 0; j < bh; j++)
2469 const double dk_bjk = dd[k] * bd[j];
2470 for (
int i = 0; i < ah; i++)
2472 cp[i] += ad[i] * dk_bjk;
2487 mfem_error(
"AddMultABt(...): dimension mismatch");
2491 #ifdef MFEM_USE_LAPACK
2492 static char transa =
'N', transb =
'T';
2493 static double alpha = 1.0, beta = 1.0;
2496 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2497 B.
Data(), &n, &beta, ABt.
Data(), &m);
2499 const int ah = A.
Height();
2500 const int bh = B.
Height();
2501 const int aw = A.
Width();
2502 const double *ad = A.
Data();
2503 const double *bd = B.
Data();
2504 double *cd = ABt.
Data();
2506 for (
int k = 0; k < aw; k++)
2509 for (
int j = 0; j < bh; j++)
2511 const double bjk = bd[j];
2512 for (
int i = 0; i < ah; i++)
2514 cp[i] += ad[i] * bjk;
2525 for (i = 0; i < A.
Height(); i++)
2526 for (j = 0; j < B.
Height(); j++)
2529 for (k = 0; k < A.
Width(); k++)
2531 d += A(i, k) * B(j, k);
2545 mfem_error(
"AddMultADBt(...): dimension mismatch");
2549 const int ah = A.
Height();
2550 const int bh = B.
Height();
2551 const int aw = A.
Width();
2552 const double *ad = A.
Data();
2553 const double *bd = B.
Data();
2554 const double *dd = D.
GetData();
2555 double *cd = ADBt.
Data();
2557 for (
int k = 0; k < aw; k++)
2560 for (
int j = 0; j < bh; j++)
2562 const double dk_bjk = dd[k] * bd[j];
2563 for (
int i = 0; i < ah; i++)
2565 cp[i] += ad[i] * dk_bjk;
2581 mfem_error(
"AddMult_a_ABt(...): dimension mismatch");
2585 #ifdef MFEM_USE_LAPACK
2586 static char transa =
'N', transb =
'T';
2588 static double beta = 1.0;
2591 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2592 B.
Data(), &n, &beta, ABt.
Data(), &m);
2594 const int ah = A.
Height();
2595 const int bh = B.
Height();
2596 const int aw = A.
Width();
2597 const double *ad = A.
Data();
2598 const double *bd = B.
Data();
2599 double *cd = ABt.
Data();
2601 for (
int k = 0; k < aw; k++)
2604 for (
int j = 0; j < bh; j++)
2606 const double bjk = a * bd[j];
2607 for (
int i = 0; i < ah; i++)
2609 cp[i] += ad[i] * bjk;
2620 for (i = 0; i < A.
Height(); i++)
2621 for (j = 0; j < B.
Height(); j++)
2624 for (k = 0; k < A.
Width(); k++)
2626 d += A(i, k) * B(j, k);
2639 mfem_error(
"MultAtB(...): dimension mismatch");
2643 #ifdef MFEM_USE_LAPACK
2644 static char transa =
'T', transb =
'N';
2645 static double alpha = 1.0, beta = 0.0;
2648 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &k,
2649 B.
Data(), &k, &beta, AtB.
Data(), &m);
2651 const int ah = A.
Height();
2652 const int aw = A.
Width();
2653 const int bw = B.
Width();
2654 const double *ad = A.
Data();
2655 const double *bd = B.
Data();
2656 double *cd = AtB.
Data();
2658 for (
int j = 0; j < bw; j++)
2660 const double *ap = ad;
2661 for (
int i = 0; i < aw; i++)
2664 for (
int k = 0; k < ah; k++)
2677 for (i = 0; i < A.
Width(); i++)
2678 for (j = 0; j < B.
Width(); j++)
2681 for (k = 0; k < A.
Height(); k++)
2683 d += A(k, i) * B(k, j);
2694 for (
int i = 0; i < A.
Height(); i++)
2696 for (
int j = 0; j < i; j++)
2699 for (
int k = 0; k < A.
Width(); k++)
2701 d += A(i,k) * A(j,k);
2703 AAt(i, j) += (d *=
a);
2707 for (
int k = 0; k < A.
Width(); k++)
2709 d += A(i,k) * A(i,k);
2717 for (
int i = 0; i < A.
Height(); i++)
2719 for (
int j = 0; j <= i; j++)
2722 for (
int k = 0; k < A.
Width(); k++)
2724 d += A(i,k) * A(j,k);
2726 AAt(i, j) = AAt(j, i) = a * d;
2733 for (
int i = 0; i < v.
Size(); i++)
2735 for (
int j = 0; j <= i; j++)
2737 vvt(i,j) = vvt(j,i) = v(i) * v(j);
2747 mfem_error(
"MultVWt(...): dimension mismatch");
2751 for (
int i = 0; i < v.
Size(); i++)
2753 const double vi = v(i);
2754 for (
int j = 0; j < w.
Size(); j++)
2756 VWt(i, j) = vi * w(j);
2763 const int m = v.
Size(), n = w.
Size();
2768 mfem_error(
"AddMultVWt(...): dimension mismatch");
2772 for (
int i = 0; i < m; i++)
2774 const double vi = v(i);
2775 for (
int j = 0; j < n; j++)
2777 VWt(i, j) += vi * w(j);
2784 const int n = v.
Size();
2789 mfem_error(
"AddMultVVt(...): dimension mismatch");
2793 for (
int i = 0; i < n; i++)
2795 const double vi = v(i);
2796 for (
int j = 0; j < i; j++)
2798 const double vivj = vi * v(j);
2802 VVt(i, i) += vi * vi;
2809 const int m = v.
Size(), n = w.
Size();
2814 mfem_error(
"AddMult_a_VWt(...): dimension mismatch");
2818 for (
int j = 0; j < n; j++)
2820 const double awj = a * w(j);
2821 for (
int i = 0; i < m; i++)
2823 VWt(i, j) += v(i) * awj;
2831 "incompatible dimensions!");
2833 const int n = v.
Size();
2834 for (
int i = 0; i < n; i++)
2836 double avi = a * v(i);
2837 for (
int j = 0; j < i; j++)
2839 const double avivj = avi * v(j);
2843 VVt(i, i) += avi * v(i);
2850 #ifdef MFEM_USE_LAPACK
2856 double *data_ptr = this->
data;
2857 for (
int i = 0; i < m; i++)
2862 double a = std::abs(data_ptr[piv+i*m]);
2863 for (
int j = i+1; j < m; j++)
2865 const double b = std::abs(data_ptr[j+i*m]);
2876 for (
int j = 0; j < m; j++)
2878 mfem::Swap<double>(data_ptr[i+j*m], data_ptr[piv+j*m]);
2883 if (abs(data_ptr[i + i*m]) <= TOL)
2888 const double a_ii_inv = 1.0 / data_ptr[i+i*m];
2889 for (
int j = i+1; j < m; j++)
2891 data_ptr[j+i*m] *= a_ii_inv;
2893 for (
int k = i+1; k < m; k++)
2895 const double a_ik = data_ptr[i+k*m];
2896 for (
int j = i+1; j < m; j++)
2898 data_ptr[j+k*m] -= a_ik * data_ptr[j+i*m];
2910 for (
int i=0; i<m; i++)
2914 det *= -
data[m * i + i];
2918 det *=
data[m * i + i];
2927 for (
int k = 0; k < n; k++)
2930 for (
int i = 0; i < m; i++)
2932 double x_i = x[i] *
data[i+i*m];
2933 for (
int j = i+1; j < m; j++)
2935 x_i += x[j] * data[i+j*m];
2940 for (
int i = m-1; i >= 0; i--)
2943 for (
int j = 0; j < i; j++)
2945 x_i += x[j] *
data[i+j*m];
2950 for (
int i = m-1; i >= 0; i--)
2961 for (
int k = 0; k < n; k++)
2964 for (
int i = 0; i < m; i++)
2969 for (
int j = 0; j < m; j++)
2971 const double x_j = x[j];
2972 for (
int i = j+1; i < m; i++)
2974 x[i] -=
data[i+j*m] * x_j;
2985 for (
int k = 0; k < n; k++)
2987 for (
int j = m-1; j >= 0; j--)
2989 const double x_j = ( x[j] /=
data[j+j*m] );
2990 for (
int i = 0; i < j; i++)
2992 x[i] -=
data[i+j*m] * x_j;
3001 #ifdef MFEM_USE_LAPACK
3004 if (m > 0 && n > 0) {
dgetrs_(&trans, &m, &n,
data, &m,
ipiv, X, &m, &info); }
3005 MFEM_VERIFY(!info,
"LAPACK: error in DGETRS");
3016 #ifdef MFEM_USE_LAPACK
3017 char n_ch =
'N', side =
'R', u_ch =
'U', l_ch =
'L';
3021 dtrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&alpha,
data,&m,X,&n);
3022 dtrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&alpha,
data,&m,X,&n);
3028 for (
int k = 0; k < n; k++)
3030 for (
int j = 0; j < m; j++)
3032 const double x_j = ( x[j*n] /=
data[j+j*m]);
3033 for (
int i = j+1; i < m; i++)
3035 x[i*n] -=
data[j + i*m] * x_j;
3043 for (
int k = 0; k < n; k++)
3045 for (
int j = m-1; j >= 0; j--)
3047 const double x_j = x[j*n];
3048 for (
int i = 0; i < j; i++)
3050 x[i*n] -=
data[j + i*m] * x_j;
3058 for (
int k = 0; k < n; k++)
3060 for (
int i = m-1; i >= 0; --i)
3073 for (
int k = 0; k < m; k++)
3075 const double minus_x_k = -( x[k] = 1.0/
data[k+k*m] );
3076 for (
int i = 0; i < k; i++)
3078 x[i] =
data[i+k*m] * minus_x_k;
3080 for (
int j = k-1; j >= 0; j--)
3082 const double x_j = ( x[j] /=
data[j+j*m] );
3083 for (
int i = 0; i < j; i++)
3085 x[i] -=
data[i+j*m] * x_j;
3093 for (
int j = 0; j < k; j++)
3095 const double minus_L_kj = -
data[k+j*m];
3096 for (
int i = 0; i <= j; i++)
3098 X[i+j*m] += X[i+k*m] * minus_L_kj;
3100 for (
int i = j+1; i < m; i++)
3102 X[i+j*m] = X[i+k*m] * minus_L_kj;
3106 for (
int k = m-2; k >= 0; k--)
3108 for (
int j = 0; j < k; j++)
3110 const double L_kj =
data[k+j*m];
3111 for (
int i = 0; i < m; i++)
3113 X[i+j*m] -= X[i+k*m] * L_kj;
3118 for (
int k = m-1; k >= 0; k--)
3123 for (
int i = 0; i < m; i++)
3125 Swap<double>(X[i+k*m], X[i+piv_k*m]);
3132 const double *X1,
double *X2)
3135 for (
int k = 0; k < r; k++)
3137 for (
int j = 0; j < m; j++)
3139 const double x1_jk = X1[j+k*m];
3140 for (
int i = 0; i < n; i++)
3142 X2[i+k*n] -= A21[i+j*n] * x1_jk;
3149 int m,
int n,
double *A12,
double *A21,
double *A22)
const
3154 for (
int j = 0; j < m; j++)
3156 const double u_jj_inv = 1.0/
data[j+j*m];
3157 for (
int i = 0; i < n; i++)
3159 A21[i+j*n] *= u_jj_inv;
3161 for (
int k = j+1; k < m; k++)
3163 const double u_jk =
data[j+k*m];
3164 for (
int i = 0; i < n; i++)
3166 A21[i+k*n] -= A21[i+j*n] * u_jk;
3171 SubMult(m, n, n, A21, A12, A22);
3175 double *B1,
double *B2)
const
3180 SubMult(m, n, r, L21, B1, B2);
3184 const double *X2,
double *Y1)
const
3187 SubMult(n, m, r, U12, X2, Y1);
3196 MFEM_ASSERT(
height ==
width,
"not a square matrix");
3206 MFEM_ASSERT(
height ==
width,
"not a square matrix");
3214 MFEM_ASSERT(a,
"DenseMatrix is not given");
3215 const double *adata = a->data;
3217 for (
int i = 0; i <
s; i++)
3219 lu.
data[i] = adata[i];
3232 MFEM_VERIFY(mat.
height == mat.
width,
"DenseMatrix is not square!");
3248 MFEM_VERIFY(p != NULL,
"Operator is not a DenseMatrix!");
3254 for (
int row = 0; row <
height; row++)
3277 for (
int i = 0; i <
width; i++)
3290 #ifdef MFEM_USE_LAPACK
3305 &qwork, &lwork, &info);
3307 lwork = (int) qwork;
3308 work =
new double[lwork];
3313 : mat(other.mat), EVal(other.EVal), EVect(other.EVect), ev(NULL, other.n),
3318 lwork = other.lwork;
3320 work =
new double[lwork];
3326 if (mat.
Width() != n)
3328 mfem_error(
"DenseMatrixEigensystem::Eval(): dimension mismatch");
3334 work, &lwork, &info);
3338 mfem::err <<
"DenseMatrixEigensystem::Eval(): DSYEV error code: "
3352 bool left_eigen_vectors,
3353 bool right_eigen_vectors)
3356 MFEM_VERIFY(A.
Height() == A.
Width(),
"A has to be a square matrix");
3357 MFEM_VERIFY(B.
Height() == B.
Width(),
"B has to be a square matrix");
3359 MFEM_VERIFY(B.
Height() == n,
"A and B dimension mismatch");
3365 if (left_eigen_vectors)
3370 if (right_eigen_vectors)
3379 alphar =
new double[n];
3380 alphai =
new double[n];
3381 beta =
new double[n];
3383 int nl = max(1,Vl.
Height());
3384 int nr = max(1,Vr.
Height());
3386 dggev_(&jobvl,&jobvr,&n,A_copy.
Data(),&n,B_copy.
Data(),&n,alphar,
3387 alphai, beta, Vl.
Data(), &nl, Vr.
Data(), &nr,
3388 &qwork, &lwork, &info);
3390 lwork = (int) qwork;
3391 work =
new double[lwork];
3397 int nl = max(1,Vl.
Height());
3398 int nr = max(1,Vr.
Height());
3402 dggev_(&jobvl,&jobvr,&n,A_copy.Data(),&n,B_copy.
Data(),&n,alphar,
3403 alphai, beta, Vl.
Data(), &nl, Vr.
Data(), &nr,
3404 work, &lwork, &info);
3408 mfem::err <<
"DenseMatrixGeneralizedEigensystem::Eval(): DGGEV error code: "
3414 for (
int i = 0; i<n; i++)
3418 evalues_r(i) = alphar[i]/beta[i];
3419 evalues_i(i) = alphai[i]/beta[i];
3438 bool left_singular_vectors,
3439 bool right_singular_vectors)
3443 jobu = (left_singular_vectors)?
'S' :
'N';
3444 jobvt = (right_singular_vectors)?
'S' :
'N';
3449 bool left_singular_vectors,
3450 bool right_singular_vectors)
3454 jobu = (left_singular_vectors)?
'S' :
'N';
3455 jobvt = (right_singular_vectors)?
'S' :
'N';
3459 void DenseMatrixSVD::Init()
3465 NULL, &n, &qwork, &lwork, &info);
3467 lwork = (int) qwork;
3468 work =
new double[lwork];
3479 double * datau =
nullptr;
3480 double * datavt =
nullptr;
3493 datavt, &n, work, &lwork, &info);
3497 mfem::err <<
"DenseMatrixSVD::Eval() : info = " << info << endl;
3507 #endif // if MFEM_USE_LAPACK
3514 const int *I = elem_dof.
GetI(), *J = elem_dof.
GetJ(), *dofs;
3515 const double *d_col = tdata;
3518 const double *xp = x;
3522 for (
int i = 0; i < ne; i++)
3525 for (
int col = 0; col < n; col++)
3527 x_col = xp[dofs[col]];
3528 for (
int row = 0; row < n; row++)
3530 yp[dofs[row]] += x_col*d_col[row];
3539 for (
int i = 0; i < ne; i++)
3542 x_col = xp[dofs[0]];
3543 for (
int row = 0; row < n; row++)
3545 ye(row) = x_col*d_col[row];
3548 for (
int col = 1; col < n; col++)
3550 x_col = xp[dofs[col]];
3551 for (
int row = 0; row < n; row++)
3553 ye(row) += x_col*d_col[row];
3557 for (
int row = 0; row < n; row++)
3559 yp[dofs[row]] += ye(row);
3568 for (
int i=0; i<
s; i++)
3584 const int m = Mlu.
SizeI();
3585 const int NE = Mlu.
SizeK();
3591 pivot_flag[0] =
true;
3592 bool *d_pivot_flag = pivot_flag.ReadWrite();
3596 for (
int i = 0; i < m; i++)
3601 double a = fabs(data_all(piv,i,e));
3602 for (
int j = i+1; j < m; j++)
3604 const double b = fabs(data_all(j,i,e));
3611 ipiv_all(i,e) = piv;
3615 for (
int j = 0; j < m; j++)
3617 mfem::kernels::internal::Swap<double>(data_all(i,j,e), data_all(piv,j,e));
3622 if (abs(data_all(i,i,e)) <= TOL)
3624 d_pivot_flag[0] =
false;
3627 const double a_ii_inv = 1.0 / data_all(i,i,e);
3628 for (
int j = i+1; j < m; j++)
3630 data_all(j,i,e) *= a_ii_inv;
3633 for (
int k = i+1; k < m; k++)
3635 const double a_ik = data_all(i,k,e);
3636 for (
int j = i+1; j < m; j++)
3638 data_all(j,k,e) -= a_ik * data_all(j,i,e);
3646 MFEM_ASSERT(pivot_flag.HostRead()[0],
"Batch LU factorization failed \n");
3652 const int m = Mlu.
SizeI();
3653 const int NE = Mlu.
SizeK();
void Symmetrize()
(*this) = 1/2 ((*this) + (*this)^t)
void dsyevr_Eigensystem(DenseMatrix &a, Vector &ev, DenseMatrix *evect)
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
int Size() const
Return the logical size of the array.
DenseMatrix & operator-=(const DenseMatrix &m)
void SymmetricScaling(const Vector &s)
SymmetricScaling this = diag(sqrt(s)) * this * diag(sqrt(s))
void SquareRootInverse()
Replaces the current matrix with its square root inverse.
int CheckFinite(const double *v, const int n)
void trans(const Vector &u, Vector &x)
void BatchLUFactor(DenseTensor &Mlu, Array< int > &P, const double TOL)
Compute the LU factorization of a batch of matrices.
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
DenseMatrix & operator*=(double c)
void GetDiag(Vector &d) const
Returns the diagonal of the matrix.
void SetCol(int c, const double *col)
DenseTensor & operator=(double c)
Sets the tensor elements equal to constant c.
void MultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
void SetRow(int r, const double *row)
void InvRightScaling(const Vector &s)
InvRightScaling: this = this * diag(1./s);.
MFEM_HOST_DEVICE void MultABt(const int Aheight, const int Awidth, const int Bheight, const TA *Adata, const TB *Bdata, TC *ABtdata)
Multiply a matrix of size Aheight x Awidth and data Adata with the transpose of a matrix of size Bhei...
void SingularValues(Vector &sv) const
void dsyev_Eigensystem(DenseMatrix &a, Vector &ev, DenseMatrix *evect)
void SetSize(int s)
Resize the vector to size s.
void Delete()
Delete the owned pointers and reset the Memory object.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void BlockFactor(int m, int n, double *A12, double *A21, double *A22) const
MFEM_HOST_DEVICE void Add(const int height, const int width, const TALPHA alpha, const TA *Adata, const TB *Bdata, TC *Cdata)
Compute C = A + alpha*B, where the matrices A, B and C are of size height x width with data Adata...
void BlockBackSolve(int m, int n, int r, const double *U12, const double *X2, double *Y1) const
double InnerProduct(const double *x, const double *y) const
Compute y^t A x.
void CalcAdjugate(const DenseMatrix &a, DenseMatrix &adja)
DenseMatrixSVD(DenseMatrix &M, bool left_singular_vectors=false, bool right_singlular_vectors=false)
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
void dgetri_(int *N, double *A, int *LDA, int *IPIV, double *WORK, int *LWORK, int *INFO)
void AddMult(const Table &elem_dof, const Vector &x, Vector &y) const
void TestInversion()
Invert and print the numerical conditioning of the inversion.
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
void CopyRows(const DenseMatrix &A, int row1, int row2)
Copy rows row1 through row2 from A to *this.
void Swap(DenseTensor &t)
void Eval(DenseMatrix &M)
Abstract data type for matrix inverse.
void AddMult_a_ABt(double a, const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += a * A * B^t.
void GetInverseMatrix(DenseMatrix &Ainv) const
Compute and return the inverse matrix in Ainv.
void Factor()
Factor the current DenseMatrix, *a.
MFEM_HOST_DEVICE double CalcSingularvalue< 3 >(const double *data, const int i)
Return the i'th singular value of the matrix of size 3 with given data.
void GetInverseMatrix(int m, double *X) const
Assuming L.U = P.A factored data of size (m x m), compute X <- A^{-1}.
bool IsSquare() const
Returns whether the matrix is a square matrix.
double * GetData() const
Returns the matrix data array.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void CalcOrtho(const DenseMatrix &J, Vector &n)
DenseMatrix & operator=(double c)
Sets the matrix elements equal to constant c.
void Set(double alpha, const double *A)
Set the matrix to alpha * A, assuming that A has the same dimensions as the matrix and uses column-ma...
int Capacity() const
Return the size of the allocated memory.
void Mult_a_AAt(double a, const DenseMatrix &A, DenseMatrix &AAt)
AAt = a * A * A^t.
void dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb)
void dgesvd_(char *JOBU, char *JOBVT, int *M, int *N, double *A, int *LDA, double *S, double *U, int *LDU, double *VT, int *LDVT, double *WORK, int *LWORK, int *INFO)
void dsygv_Eigensystem(DenseMatrix &a, DenseMatrix &b, Vector &ev, DenseMatrix *evect)
static void SubMult(int m, int n, int r, const double *A21, const double *X1, double *X2)
virtual void Print(std::ostream &out=mfem::out, int width_=4) const
Prints matrix to stream out.
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void dggev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *B, int *ldb, double *alphar, double *alphai, double *beta, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info)
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
double & operator()(int i, int j)
Returns reference to a_{ij}.
void USolve(int m, int n, double *X) const
double FNorm() const
Compute the Frobenius norm of the matrix.
MFEM_HOST_DEVICE void CalcEigenvalues< 2 >(const double *data, double *lambda, double *vec)
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
void CalcAdjugateTranspose(const DenseMatrix &a, DenseMatrix &adjat)
Calculate the transposed adjugate of a matrix (for NxN matrices, N=1,2,3)
friend class DenseMatrixInverse
void RightSolve(int m, int n, double *X) const
double f(const Vector &xvec)
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.
double operator*(const DenseMatrix &m) const
Matrix inner product: tr(A^t B)
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
void Add(const double c, const DenseMatrix &A)
Adds the matrix A multiplied by the number c to the matrix.
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void AddMult_a_VWt(const double a, const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += a * v w^t.
void InvSymmetricScaling(const Vector &s)
InvSymmetricScaling this = diag(sqrt(1./s)) * this * diag(sqrt(1./s))
void GetRow(int r, Vector &row) const
void BlockForwSolve(int m, int n, int r, const double *L21, double *B1, double *B2) const
Abstract data type matrix.
void Norm2(double *v) const
Take the 2-norm of the columns of A and store in v.
void MultADBt(const DenseMatrix &A, const Vector &D, const DenseMatrix &B, DenseMatrix &ADBt)
ADBt = A D B^t, where D is diagonal.
void Invert()
Replaces the current matrix with its inverse.
bool LinearSolve(DenseMatrix &A, double *X, double TOL)
Solves the dense linear system, A * X = B for X
virtual ~DenseMatrixInverse()
Destroys dense inverse matrix.
void LSolve(int m, int n, double *X) const
DenseMatrixGeneralizedEigensystem(DenseMatrix &a, DenseMatrix &b, bool left_eigen_vectors=false, bool right_eigen_vectors=false)
void LeftScaling(const Vector &s)
LeftScaling this = diag(s) * this.
double Det() const
Compute the determinant of the original DenseMatrix using the LU factors.
void AddMultVVt(const Vector &v, DenseMatrix &VVt)
VVt += v v^t.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
void CopyMNDiag(double c, int n, int row_offset, int col_offset)
Copy c on the diagonal of size n to *this at row_offset, col_offset.
void dgetrf_(int *, int *, double *, int *, int *, int *)
~DenseMatrixEigensystem()
void AddMult_a_VVt(const double a, const Vector &v, DenseMatrix &VVt)
VVt += a * v v^t.
void Neg()
(*this) = -(*this)
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
MFEM_HOST_DEVICE void LUSolve(const double *data, const int m, const int *ipiv, double *x)
Assuming L.U = P.A for a factored matrix (m x m),.
void Solve(int m, int n, double *X) const
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(GetMemory(), TotalSize(), on_dev).
void Getl1Diag(Vector &l) const
Returns the l1 norm of the rows of the matrix v_i = sum_j |a_ij|.
void AddToVector(int offset, Vector &v) const
Add the matrix 'data' to the Vector 'v' at the given 'offset'.
void GetColumn(int c, Vector &col) const
void AddMult(const Vector &x, Vector &y) const
y += A.x
void dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *)
void Threshold(double eps)
Replace small entries, abs(a_ij) <= eps, with zero.
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
FDualNumber< tbase > pow(const FDualNumber< tbase > &a, const FDualNumber< tbase > &b)
pow([dual number],[dual number])
void TestInversion()
Print the numerical conditioning of the inversion: ||A^{-1} A - I||.
MFEM_HOST_DEVICE void Mult(const int height, const int width, const TA *data, const TX *x, TY *y)
Matrix vector multiplication: y = A x, where the matrix A is of size height x width with given data...
double MaxMaxNorm() const
Compute the norm ||A|| = max_{ij} |A_{ij}|.
double * Data() const
Returns the matrix data array.
void Swap(Array< T > &, Array< T > &)
double p(const Vector &x, double t)
void Transpose()
(*this) = (*this)^t
void MultVVt(const Vector &v, DenseMatrix &vvt)
Make a matrix from a vector V.Vt.
double Trace() const
Trace of a square matrix.
void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += A * B^t.
void dgetrs_(char *, int *, int *, double *, int *, int *, double *, int *, int *)
void BatchLUSolve(const DenseTensor &Mlu, const Array< int > &P, Vector &X)
Solve batch linear systems.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void MultAAt(const DenseMatrix &a, DenseMatrix &aat)
Calculate the matrix A.At.
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
void Swap(DenseMatrix &other)
void AddMatrix(DenseMatrix &A, int ro, int co)
Perform (ro+i,co+j)+=A(i,j) for 0<=i<A.Height, 0<=j<A.Width.
void Mult(const double *x, double *y) const
Matrix vector multiplication with the inverse of dense matrix.
void CalcInverseTranspose(const DenseMatrix &a, DenseMatrix &inva)
Calculate the inverse transpose of a matrix (for NxN matrices, N=1,2,3)
A class to initialize the size of a Tensor.
void SetDataAndSize(double *d, int s)
Set the Vector data and size.
MFEM_HOST_DEVICE double CalcSingularvalue< 2 >(const double *data, const int i)
Return the i'th singular value of the matrix of size 2 with given data.
void dsygv_(int *ITYPE, char *JOBZ, char *UPLO, int *N, double *A, int *LDA, double *B, int *LDB, double *W, double *WORK, int *LWORK, int *INFO)
void MultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt)
ADAt = A D A^t, where D is diagonal.
int height
Dimension of the output / number of rows in the matrix.
virtual void PrintT(std::ostream &out=mfem::out, int width_=4) const
Prints the transpose matrix to stream out.
void CopyCols(const DenseMatrix &A, int col1, int col2)
Copy columns col1 through col2 from A to *this.
virtual MatrixInverse * Inverse() const
Returns a pointer to the inverse matrix.
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
void AddMultADBt(const DenseMatrix &A, const Vector &D, const DenseMatrix &B, DenseMatrix &ADBt)
ADBt = A D B^t, where D is diagonal.
virtual ~DenseMatrix()
Destroys dense matrix.
void CopyMNt(const DenseMatrix &A, int row_offset, int col_offset)
Copy matrix A^t to the location in *this at row_offset, col_offset.
void AddMultTranspose(const Vector &x, Vector &y) const
y += A^t x
void CopyExceptMN(const DenseMatrix &A, int m, int n)
Copy All rows and columns except m and n from A.
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
void Diag(double c, int n)
Creates n x n diagonal matrix with diagonal elements c.
void Mult(int m, int n, double *X) const
MFEM_HOST_DEVICE void CalcEigenvalues< 3 >(const double *data, double *lambda, double *vec)
FDualNumber< tbase > sqrt(const FDualNumber< tbase > &f)
sqrt([dual number])
bool Factor(int m, double TOL=0.0)
Compute the LU factorization of the current matrix.
static const int ipiv_base
void GradToCurl(DenseMatrix &curl)
DenseMatrixInverse()
Default constructor.
double CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
void GetRowSums(Vector &l) const
Compute the row sums of the DenseMatrix.
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
void CalcEigenvalues(double *lambda, double *vec) const
DenseMatrixEigensystem(DenseMatrix &m)
void dsyevr_(char *JOBZ, char *RANGE, char *UPLO, int *N, double *A, int *LDA, double *VL, double *VU, int *IL, int *IU, double *ABSTOL, int *M, double *W, double *Z, int *LDZ, int *ISUPPZ, double *WORK, int *LWORK, int *IWORK, int *LIWORK, int *INFO)
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
int Rank(double tol) const
void AddMult_a(double a, const Vector &x, Vector &y) const
y += a * A.x
void RightScaling(const Vector &s)
RightScaling: this = this * diag(s);.
void MultAtB(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &AtB)
Multiply the transpose of a matrix A with a matrix B: At*B.
void Mult(const double *x, double *y) const
Matrix vector multiplication.
void AddMultTranspose_a(double a, const Vector &x, Vector &y) const
y += a * A^t x
void AddMultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt)
ADAt += A D A^t, where D is diagonal.
void GetFromVector(int offset, const Vector &v)
Get the matrix 'data' from the Vector 'v' at the given 'offset'.
void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco)
Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this.
~DenseMatrixGeneralizedEigensystem()
double u(const Vector &xvec)
void InvLeftScaling(const Vector &s)
InvLeftScaling this = diag(1./s) * this.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void AddMult_a(double alpha, const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += alpha * B * C.
Rank 3 tensor (array of matrices)
virtual double & Elem(int i, int j)
Returns reference to a_{ij}.
void AdjustDofDirection(Array< int > &dofs)
MFEM_HOST_DEVICE void Symmetrize(const int size, T *data)
Symmetrize a square matrix with given size and data: A -> (A+A^T)/2.
virtual double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
void GradToDiv(Vector &div)
void AddMult_a_AAt(double a, const DenseMatrix &A, DenseMatrix &AAt)
AAt += a * A * A^t.
int width
Dimension of the input / number of columns in the matrix.
void dsyev_(char *JOBZ, char *UPLO, int *N, double *A, int *LDA, double *W, double *WORK, int *LWORK, int *INFO)
virtual void PrintMatlab(std::ostream &out=mfem::out) const
Prints operator in Matlab format.
DenseMatrix & operator+=(const double *m)