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);
83 MFEM_ASSERT(m.data,
"invalid source matrix");
85 std::memcpy(data, m.data,
sizeof(
double)*hw);
95 MFEM_ASSERT(s >= 0,
"invalid DenseMatrix size: " << s);
109 MFEM_ASSERT(m >= 0 && n >= 0,
110 "invalid DenseMatrix size: " << m <<
" x " << n);
111 const int capacity = m*n;
124 :
Matrix(mat.width, mat.height)
126 MFEM_CONTRACT_VAR(ch);
132 for (
int i = 0; i <
height; i++)
134 for (
int j = 0; j <
width; j++)
136 (*this)(i,j) = mat(j,i);
148 MFEM_ASSERT(h >= 0 && w >= 0,
149 "invalid DenseMatrix size: " << h <<
" x " << w);
183 "incompatible dimensions");
185 Mult((
const double *)x, (
double *)y);
191 "incompatible dimensions");
195 for (
int i = 0; i < hw; i++)
197 a += data[i] * m.data[i];
205 double *d_col =
Data();
206 for (
int col = 0; col <
width; col++)
209 for (
int row = 0; row <
height; row++)
211 y_col += x[row]*d_col[row];
221 "incompatible dimensions");
229 "incompatible dimensions");
231 const double *xp = x, *d_col = data;
233 for (
int col = 0; col <
width; col++)
235 double x_col = xp[col];
236 for (
int row = 0; row <
height; row++)
238 yp[row] += x_col*d_col[row];
247 "incompatible dimensions");
249 const double *d_col = data;
250 for (
int col = 0; col <
width; col++)
253 for (
int row = 0; row <
height; row++)
255 y_col += x[row]*d_col[row];
265 "incompatible dimensions");
267 const double *xp = x, *d_col = data;
269 for (
int col = 0; col <
width; col++)
271 const double x_col = a*xp[col];
272 for (
int row = 0; row <
height; row++)
274 yp[row] += x_col*d_col[row];
284 "incompatible dimensions");
286 const double *d_col = data;
287 for (
int col = 0; col <
width; col++)
290 for (
int row = 0; row <
height; row++)
292 y_col += x[row]*d_col[row];
303 for (
int i = 0; i <
height; i++)
306 for (
int j = 0; j <
width; j++)
308 Axi += (*this)(i,j) * x[j];
319 double * it_data = data;
320 for (
int j = 0; j <
width; ++j)
322 for (
int i = 0; i <
height; ++i)
324 *(it_data++) *= s(i);
332 double * it_data = data;
333 for (
int j = 0; j <
width; ++j)
335 for (
int i = 0; i <
height; ++i)
337 *(it_data++) /= s(i);
346 double * it_data = data;
347 for (
int j = 0; j <
width; ++j)
350 for (
int i = 0; i <
height; ++i)
360 double * it_data = data;
361 for (
int j = 0; j <
width; ++j)
363 const double sj = 1./s(j);
364 for (
int i = 0; i <
height; ++i)
376 mfem_error(
"DenseMatrix::SymmetricScaling: dimension mismatch");
379 double * ss =
new double[
width];
382 for (
double * end_s = it_s +
width; it_s != end_s; ++it_s)
384 *(it_ss++) = sqrt(*it_s);
387 double * it_data = data;
388 for (
int j = 0; j <
width; ++j)
390 for (
int i = 0; i <
height; ++i)
392 *(it_data++) *= ss[i]*ss[j];
404 mfem_error(
"DenseMatrix::InvSymmetricScaling: dimension mismatch");
407 double * ss =
new double[
width];
410 for (
double * end_s = it_s +
width; it_s != end_s; ++it_s)
412 *(it_ss++) = 1./sqrt(*it_s);
415 double * it_data = data;
416 for (
int j = 0; j <
width; ++j)
418 for (
int i = 0; i <
height; ++i)
420 *(it_data++) *= ss[i]*ss[j];
432 mfem_error(
"DenseMatrix::Trace() : not a square matrix!");
438 for (
int i = 0; i <
width; i++)
454 "The matrix must be square and "
455 <<
"sized larger than zero to compute the determinant."
456 <<
" Height() = " <<
Height()
457 <<
", Width() = " <<
Width());
465 return data[0] * data[3] - data[1] * data[2];
469 const double *d = data;
471 d[0] * (d[4] * d[8] - d[5] * d[7]) +
472 d[3] * (d[2] * d[7] - d[1] * d[8]) +
473 d[6] * (d[1] * d[5] - d[2] * d[4]);
477 const double *d = data;
479 d[ 0] * (d[ 5] * (d[10] * d[15] - d[11] * d[14]) -
480 d[ 9] * (d[ 6] * d[15] - d[ 7] * d[14]) +
481 d[13] * (d[ 6] * d[11] - d[ 7] * d[10])
483 d[ 4] * (d[ 1] * (d[10] * d[15] - d[11] * d[14]) -
484 d[ 9] * (d[ 2] * d[15] - d[ 3] * d[14]) +
485 d[13] * (d[ 2] * d[11] - d[ 3] * d[10])
487 d[ 8] * (d[ 1] * (d[ 6] * d[15] - d[ 7] * d[14]) -
488 d[ 5] * (d[ 2] * d[15] - d[ 3] * d[14]) +
489 d[13] * (d[ 2] * d[ 7] - d[ 3] * d[ 6])
491 d[12] * (d[ 1] * (d[ 6] * d[11] - d[ 7] * d[10]) -
492 d[ 5] * (d[ 2] * d[11] - d[ 3] * d[10]) +
493 d[ 9] * (d[ 2] * d[ 7] - d[ 3] * d[ 6])
502 return lu_factors.
Det();
517 return sqrt(data[0] * data[0] + data[1] * data[1]);
521 return sqrt(data[0] * data[0] + data[1] * data[1] + data[2] * data[2]);
525 const double *d = data;
526 double E = d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
527 double G = d[3] * d[3] + d[4] * d[4] + d[5] * d[5];
528 double F = d[0] * d[3] + d[1] * d[4] + d[2] * d[5];
529 return sqrt(E * G - F * F);
531 mfem_error(
"DenseMatrix::Weight(): mismatched or unsupported dimensions");
538 for (
int i = 0; i < s; i++)
540 data[i] = alpha*A[i];
546 for (
int j = 0; j <
Width(); j++)
548 for (
int i = 0; i <
Height(); i++)
550 (*this)(i,j) += c * A(i,j);
558 for (
int i = 0; i < s; i++)
568 for (
int i = 0; i < s; i++)
580 for (
int i = 0; i < hw; i++)
591 for (
int i = 0; i < hw; i++)
601 "incompatible matrix sizes.");
607 for (
int j = 0; j <
width; j++)
609 for (
int i = 0; i <
height; i++)
611 (*this)(i, j) -= m(i, j);
621 for (
int i = 0; i < s; i++)
631 for (
int i = 0; i < hw; i++)
642 mfem_error(
"DenseMatrix::Invert(): dimension mismatch");
646 #ifdef MFEM_USE_LAPACK
647 int *ipiv =
new int[
width];
656 mfem_error(
"DenseMatrix::Invert() : Error in DGETRF");
662 work =
new double[lwork];
668 mfem_error(
"DenseMatrix::Invert() : Error in DGETRI");
674 int c, i, j, n =
Width();
678 for (c = 0; c < n; c++)
680 a = fabs((*
this)(c, c));
682 for (j = c + 1; j < n; j++)
684 b = fabs((*
this)(j, c));
693 mfem_error(
"DenseMatrix::Invert() : singular matrix");
696 for (j = 0; j < n; j++)
698 Swap<double>((*this)(c, j), (*
this)(i, j));
701 a = (*this)(c, c) = 1.0 / (*
this)(c, c);
702 for (j = 0; j < c; j++)
706 for (j++; j < n; j++)
710 for (i = 0; i < c; i++)
712 (*this)(i, c) = a * (b = -(*
this)(i, c));
713 for (j = 0; j < c; j++)
715 (*this)(i, j) += b * (*
this)(c, j);
717 for (j++; j < n; j++)
719 (*this)(i, j) += b * (*
this)(c, j);
722 for (i++; i < n; i++)
724 (*this)(i, c) = a * (b = -(*
this)(i, c));
725 for (j = 0; j < c; j++)
727 (*this)(i, j) += b * (*
this)(c, j);
729 for (j++; j < n; j++)
731 (*this)(i, j) += b * (*
this)(c, j);
736 for (c = n - 1; c >= 0; c--)
739 for (i = 0; i < n; i++)
741 Swap<double>((*this)(i, c), (*
this)(i, j));
753 mfem_error(
"DenseMatrix::SquareRootInverse() matrix not square.");
763 for (
int v = 0; v <
Height() ; v++) { (*this)(v,v) = 1.0; }
765 for (
int j = 0; j < 10; j++)
767 for (
int i = 0; i < 10; i++)
782 for (
int v = 0; v <
Height() ; v++) { tmp2(v,v) -= 1.0; }
783 if (tmp2.FNorm() < 1e-10) {
break; }
786 if (tmp2.FNorm() > 1e-10)
788 mfem_error(
"DenseMatrix::SquareRootInverse not converged");
794 for (
int j = 0; j <
Width(); j++)
797 for (
int i = 0; i <
Height(); i++)
799 v[j] += (*this)(i,j)*(*
this)(i,j);
808 const double *d = data;
809 double norm = 0.0, abs_entry;
811 for (
int i = 0; i < hw; i++)
813 abs_entry = fabs(d[i]);
814 if (norm < abs_entry)
826 double max_norm = 0.0, entry, fnorm2;
828 for (i = 0; i < hw; i++)
830 entry = fabs(data[i]);
831 if (entry > max_norm)
839 scale_factor = scaled_fnorm2 = 0.0;
844 for (i = 0; i < hw; i++)
846 entry = data[i] / max_norm;
847 fnorm2 += entry * entry;
850 scale_factor = max_norm;
851 scaled_fnorm2 = fnorm2;
856 #ifdef MFEM_USE_LAPACK
863 double *A =
new double[N*N];
874 int *ISUPPZ =
new int[2*N];
893 double *data = a.
Data();
895 for (
int i = 0; i < hw; i++)
900 dsyevr_( &JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU,
901 &ABSTOL, &M, W, Z, &LDZ, ISUPPZ, &QWORK, &LWORK,
902 &QIWORK, &LIWORK, &INFO );
907 WORK =
new double[LWORK];
908 IWORK =
new int[LIWORK];
910 dsyevr_( &JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU,
911 &ABSTOL, &M, W, Z, &LDZ, ISUPPZ, WORK, &LWORK,
912 IWORK, &LIWORK, &INFO );
916 mfem::err <<
"dsyevr_Eigensystem(...): DSYEVR error code: "
924 mfem::err <<
"dsyevr_Eigensystem(...):\n"
925 <<
" DSYEVR did not find all eigenvalues "
926 << M <<
"/" << N << endl;
931 mfem_error(
"dsyevr_Eigensystem(...): inf/nan values in W");
935 mfem_error(
"dsyevr_Eigensystem(...): inf/nan values in Z");
938 for (IL = 0; IL < N; IL++)
939 for (IU = 0; IU <= IL; IU++)
942 for (M = 0; M < N; M++)
944 VL += Z[M+IL*N] * Z[M+IU*N];
961 <<
" Z^t Z - I deviation = " << VU
962 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
963 << W[0] <<
", N = " << N << endl;
970 <<
" Z^t Z - I deviation = " << VU
971 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
972 << W[0] <<
", N = " << N << endl;
976 mfem_error(
"dsyevr_Eigensystem(...): ERROR: ...");
979 for (IL = 0; IL < N; IL++)
980 for (IU = 0; IU < N; IU++)
983 for (M = 0; M < N; M++)
985 VL += Z[IL+M*N] * W[M] * Z[IU+M*N];
987 VL = fabs(VL-data[IL+N*IU]);
996 <<
" max matrix deviation = " << VU
997 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
998 << W[0] <<
", N = " << N << endl;
1002 mfem_error(
"dsyevr_Eigensystem(...): ERROR: ...");
1011 MFEM_CONTRACT_VAR(a);
1012 MFEM_CONTRACT_VAR(ev);
1013 MFEM_CONTRACT_VAR(evect);
1019 #ifdef MFEM_USE_LAPACK
1031 double *WORK = NULL;
1042 A =
new double[N*N];
1046 double *data = a.
Data();
1047 for (
int i = 0; i < hw; i++)
1052 dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, &QWORK, &LWORK, &INFO);
1054 LWORK = (int) QWORK;
1055 WORK =
new double[LWORK];
1057 dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, WORK, &LWORK, &INFO);
1061 mfem::err <<
"dsyev_Eigensystem: DSYEV error code: " << INFO << endl;
1066 if (evect == NULL) {
delete [] A; }
1068 MFEM_CONTRACT_VAR(a);
1069 MFEM_CONTRACT_VAR(ev);
1070 MFEM_CONTRACT_VAR(evect);
1074 void DenseMatrix::Eigensystem(Vector &ev, DenseMatrix *evect)
1076 #ifdef MFEM_USE_LAPACK
1084 MFEM_CONTRACT_VAR(ev);
1085 MFEM_CONTRACT_VAR(evect);
1086 mfem_error(
"DenseMatrix::Eigensystem: Compiled without LAPACK");
1094 #ifdef MFEM_USE_LAPACK
1107 double *B =
new double[N*N];
1109 double *WORK = NULL;
1120 A =
new double[N*N];
1124 double *a_data = a.
Data();
1125 double *b_data = b.
Data();
1126 for (
int i = 0; i < hw; i++)
1132 dsygv_(&ITYPE, &JOBZ, &UPLO, &N, A, &LDA, B, &LDB, W, &QWORK, &LWORK, &INFO);
1134 LWORK = (int) QWORK;
1135 WORK =
new double[LWORK];
1137 dsygv_(&ITYPE, &JOBZ, &UPLO, &N, A, &LDA, B, &LDB, W, WORK, &LWORK, &INFO);
1141 mfem::err <<
"dsygv_Eigensystem: DSYGV error code: " << INFO << endl;
1147 if (evect == NULL) {
delete [] A; }
1149 MFEM_CONTRACT_VAR(a);
1150 MFEM_CONTRACT_VAR(b);
1151 MFEM_CONTRACT_VAR(ev);
1152 MFEM_CONTRACT_VAR(evect);
1156 void DenseMatrix::Eigensystem(DenseMatrix &
b, Vector &ev,
1159 #ifdef MFEM_USE_LAPACK
1164 MFEM_CONTRACT_VAR(b);
1165 MFEM_CONTRACT_VAR(ev);
1166 MFEM_CONTRACT_VAR(evect);
1167 mfem_error(
"DenseMatrix::Eigensystem(generalized): Compiled without LAPACK");
1173 #ifdef MFEM_USE_LAPACK
1179 double *
a = copy_of_this.data;
1184 double *work = NULL;
1189 dgesvd_(&jobu, &jobvt, &m, &n, a, &m,
1190 s, u, &m, vt, &n, &qwork, &lwork, &info);
1192 lwork = (int) qwork;
1193 work =
new double[lwork];
1195 dgesvd_(&jobu, &jobvt, &m, &n, a, &m,
1196 s, u, &m, vt, &n, work, &lwork, &info);
1201 mfem::err <<
"DenseMatrix::SingularValues : info = " << info << endl;
1205 MFEM_CONTRACT_VAR(sv);
1207 mfem_error(
"DenseMatrix::SingularValues: Compiled without LAPACK");
1217 for (
int i=0; i < sv.
Size(); ++i)
1229 "The matrix must be square and sized 1, 2, or 3 to compute the"
1231 <<
" Height() = " <<
Height()
1232 <<
", Width() = " <<
Width());
1235 const double *d = data;
1261 const double *d = data;
1279 const double* rp = data + r;
1282 for (
int i = 0; i < n; i++)
1294 double *cp =
Data() + c * m;
1297 for (
int i = 0; i < m; i++)
1311 for (
int i = 0; i <
height; ++i)
1313 d(i) = (*this)(i,i);
1327 for (
int j = 0; j <
width; ++j)
1328 for (
int i = 0; i <
height; ++i)
1330 l(i) += fabs((*
this)(i,j));
1337 for (
int i = 0; i <
height; i++)
1340 for (
int j = 0; j <
width; j++)
1353 for (
int i = 0; i < N; i++)
1357 for (
int i = 0; i < n; i++)
1368 for (i = 0; i < N; i++)
1372 for (i = 0; i < n; i++)
1374 data[i*(n+1)] = diag[i];
1385 for (i = 0; i <
Height(); i++)
1386 for (j = i+1; j <
Width(); j++)
1389 (*this)(i,j) = (*
this)(j,i);
1404 for (
int i = 0; i <
Height(); i++)
1405 for (
int j = 0; j <
Width(); j++)
1407 (*this)(i,j) = A(j,i);
1416 mfem_error(
"DenseMatrix::Symmetrize() : not a square matrix!");
1424 for (
int i = 0; i <
Height(); i++)
1427 for (
int j = 0; j <
Width(); j++)
1430 (*this)(i, j) = 0.0;
1444 mfem_error(
"DenseMatrix::GradToCurl(...): dimension mismatch");
1450 for (
int i = 0; i < n; i++)
1453 double x = (*this)(i,0);
1454 double y = (*this)(i,1);
1467 for (
int i = 0; i < n; i++)
1470 double x = (*this)(i,0);
1471 double y = (*this)(i,1);
1472 double z = (*this)(i,2);
1497 MFEM_ASSERT(
Width()*
Height() == div.
Size(),
"incompatible Vector 'div'!");
1502 double *ddata = div.
GetData();
1504 for (
int i = 0; i < n; i++)
1514 for (
int j = 0; j <
Width(); j++)
1516 for (
int i = row1; i <= row2; i++)
1518 (*this)(i-row1,j) = A(i,j);
1527 for (
int j = col1; j <= col2; j++)
1529 for (
int i = 0; i <
Height(); i++)
1531 (*this)(i,j-col1) = A(i,j);
1540 for (
int j = 0; j < n; j++)
1542 for (
int i = 0; i < m; i++)
1544 (*this)(i,j) = A(Aro+i,Aco+j);
1551 double *v = A.
Data();
1553 for (
int j = 0; j < A.
Width(); j++)
1555 for (
int i = 0; i < A.
Height(); i++)
1557 (*this)(row_offset+i,col_offset+j) = *(v++);
1564 double *v = A.
Data();
1566 for (
int i = 0; i < A.
Width(); i++)
1568 for (
int j = 0; j < A.
Height(); j++)
1570 (*this)(row_offset+i,col_offset+j) = *(v++);
1576 int row_offset,
int col_offset)
1578 MFEM_VERIFY(row_offset+m <= this->
Height() && col_offset+n <= this->
Width(),
1579 "this DenseMatrix is too small to accomodate the submatrix. "
1580 <<
"row_offset = " << row_offset
1582 <<
", this->Height() = " << this->
Height()
1583 <<
", col_offset = " << col_offset
1585 <<
", this->Width() = " << this->
Width()
1587 MFEM_VERIFY(Aro+m <= A.
Height() && Aco+n <= A.
Width(),
1588 "The A DenseMatrix is too small to accomodate the submatrix. "
1591 <<
", A.Height() = " << A.
Height()
1592 <<
", Aco = " << Aco
1594 <<
", A.Width() = " << A.
Width()
1597 for (
int j = 0; j < n; j++)
1599 for (
int i = 0; i < m; i++)
1601 (*this)(row_offset+i,col_offset+j) = A(Aro+i,Aco+j);
1608 for (
int i = 0; i < n; i++)
1610 for (
int j = i+1; j < n; j++)
1612 (*this)(row_offset+i,col_offset+j) =
1613 (*
this)(row_offset+j,col_offset+i) = 0.0;
1617 for (
int i = 0; i < n; i++)
1619 (*this)(row_offset+i,col_offset+i) = c;
1626 for (
int i = 0; i < n; i++)
1628 for (
int j = i+1; j < n; j++)
1630 (*this)(row_offset+i,col_offset+j) =
1631 (*
this)(row_offset+j,col_offset+i) = 0.0;
1635 for (
int i = 0; i < n; i++)
1637 (*this)(row_offset+i,col_offset+i) = diag[i];
1645 int i, j, i_off = 0, j_off = 0;
1647 for (j = 0; j < A.
Width(); j++)
1654 for (i = 0; i < A.
Height(); i++)
1661 (*this)(i-i_off,j-j_off) = A(i,j);
1677 if (co+aw >
Width() || ro+ah > h)
1679 mfem_error(
"DenseMatrix::AddMatrix(...) 1 : dimension mismatch");
1683 p = data + ro + co * h;
1686 for (
int c = 0; c < aw; c++)
1688 for (
int r = 0; r < ah; r++)
1707 if (co+aw >
Width() || ro+ah > h)
1709 mfem_error(
"DenseMatrix::AddMatrix(...) 2 : dimension mismatch");
1713 p = data + ro + co * h;
1716 for (
int c = 0; c < aw; c++)
1718 for (
int r = 0; r < ah; r++)
1730 double *vdata = v.
GetData() + offset;
1732 for (
int i = 0; i < n; i++)
1734 vdata[i] += data[i];
1741 const double *vdata = v.
GetData() + offset;
1743 for (
int i = 0; i < n; i++)
1756 mfem_error(
"DenseMatrix::AdjustDofDirection(...): dimension mismatch");
1761 for (
int i = 0; i < n-1; i++)
1763 const int s = (dof[i] < 0) ? (-1) : (1);
1764 for (
int j = i+1; j < n; j++)
1766 const int t = (dof[j] < 0) ? (-s) : (s);
1769 (*this)(i,j) = -(*
this)(i,j);
1770 (*this)(j,i) = -(*
this)(j,i);
1778 for (
int j = 0; j <
Width(); j++)
1780 (*this)(row, j) = value;
1786 for (
int i = 0; i <
Height(); i++)
1788 (*this)(i, col) = value;
1794 MFEM_ASSERT(row !=
nullptr,
"supplied row pointer is null");
1795 for (
int j = 0; j <
Width(); j++)
1797 (*this)(r, j) = row[j];
1809 MFEM_ASSERT(col !=
nullptr,
"supplied column pointer is null");
1810 for (
int i = 0; i <
Height(); i++)
1812 (*this)(i, c) = col[i];
1824 for (
int col = 0; col <
Width(); col++)
1826 for (
int row = 0; row <
Height(); row++)
1828 if (std::abs(
operator()(row,col)) <= eps)
1839 ios::fmtflags old_flags = out.flags();
1841 out << setiosflags(ios::scientific | ios::showpos);
1842 for (
int i = 0; i <
height; i++)
1844 out <<
"[row " << i <<
"]\n";
1845 for (
int j = 0; j <
width; j++)
1847 out << (*this)(i,j);
1848 if (j+1 == width || (j+1) % width_ == 0)
1859 out.flags(old_flags);
1865 ios::fmtflags old_flags = out.flags();
1867 out << setiosflags(ios::scientific | ios::showpos);
1868 for (
int i = 0; i <
height; i++)
1870 for (
int j = 0; j <
width; j++)
1872 out << (*this)(i,j);
1878 out.flags(old_flags);
1884 ios::fmtflags old_flags = out.flags();
1886 out << setiosflags(ios::scientific | ios::showpos);
1887 for (
int j = 0; j <
width; j++)
1889 out <<
"[col " << j <<
"]\n";
1890 for (
int i = 0; i <
height; i++)
1892 out << (*this)(i,j);
1893 if (i+1 == height || (i+1) % width_ == 0)
1904 out.flags(old_flags);
1913 for (
int i = 0; i <
width; i++)
1918 <<
", cond_F = " <<
FNorm()*copy.FNorm() << endl;
1939 for (
int i = 0; i < m; i++)
1941 C_data[i] = alpha*A[i] + beta*B[i];
1957 MFEM_VERIFY(A.
IsSquare(),
"A must be a square matrix!");
1958 MFEM_ASSERT(A.
NumCols() > 0,
"supplied matrix, A, is empty!");
1959 MFEM_ASSERT(X !=
nullptr,
"supplied vector, X, is null!");
1967 double det = A(0,0);
1968 if (std::abs(det) <= TOL) {
return false; }
1975 double det = A.
Det();
1976 if (std::abs(det) <= TOL) {
return false; }
1978 double invdet = 1. / det;
1983 X[0] = ( A(1,1)*b0 - A(0,1)*b1) * invdet;
1984 X[1] = (-A(1,0)*b0 + A(0,0)*b1) * invdet;
1993 if (!lu.Factor(N,TOL)) {
return false; }
2006 b.
Width() == c.
Height(),
"incompatible dimensions");
2008 #ifdef MFEM_USE_LAPACK
2009 static char transa =
'N', transb =
'N';
2010 static double alpha = 1.0, beta = 0.0;
2013 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2014 c.
Data(), &k, &beta, a.
Data(), &m);
2016 const int ah = a.
Height();
2017 const int aw = a.
Width();
2018 const int bw = b.
Width();
2019 double *ad = a.
Data();
2020 const double *bd = b.
Data();
2021 const double *cd = c.
Data();
2030 b.
Width() == c.
Height(),
"incompatible dimensions");
2032 #ifdef MFEM_USE_LAPACK
2033 static char transa =
'N', transb =
'N';
2034 static double beta = 1.0;
2037 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2038 c.
Data(), &k, &beta, a.
Data(), &m);
2040 const int ah = a.
Height();
2041 const int aw = a.
Width();
2042 const int bw = b.
Width();
2043 double *ad = a.
Data();
2044 const double *bd = b.
Data();
2045 const double *cd = c.
Data();
2046 for (
int j = 0; j < aw; j++)
2048 for (
int k = 0; k < bw; k++)
2050 for (
int i = 0; i < ah; i++)
2052 ad[i+j*ah] += alpha * bd[i+k*ah] * cd[k+j*bw];
2062 b.
Width() == c.
Height(),
"incompatible dimensions");
2064 #ifdef MFEM_USE_LAPACK
2065 static char transa =
'N', transb =
'N';
2066 static double alpha = 1.0, beta = 1.0;
2069 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2070 c.
Data(), &k, &beta, a.
Data(), &m);
2072 const int ah = a.
Height();
2073 const int aw = a.
Width();
2074 const int bw = b.
Width();
2075 double *ad = a.
Data();
2076 const double *bd = b.
Data();
2077 const double *cd = c.
Data();
2078 for (
int j = 0; j < aw; j++)
2080 for (
int k = 0; k < bw; k++)
2082 for (
int i = 0; i < ah; i++)
2084 ad[i+j*ah] += bd[i+k*ah] * cd[k+j*bw];
2096 mfem_error(
"CalcAdjugate(...): unsupported dimensions");
2100 mfem_error(
"CalcAdjugate(...): dimension mismatch");
2106 const double *d = a.
Data();
2107 double *ad = adja.
Data();
2122 e = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
2123 g = d[3]*d[3] + d[4]*d[4] + d[5]*d[5];
2124 f = d[0]*d[3] + d[1]*d[4] + d[2]*d[5];
2126 ad[0] = d[0]*g - d[3]*
f;
2127 ad[1] = d[3]*e - d[0]*
f;
2128 ad[2] = d[1]*g - d[4]*
f;
2129 ad[3] = d[4]*e - d[1]*
f;
2130 ad[4] = d[2]*g - d[5]*
f;
2131 ad[5] = d[5]*e - d[2]*
f;
2140 else if (a.
Width() == 2)
2143 adja(0,1) = -
a(0,1);
2144 adja(1,0) = -
a(1,0);
2149 adja(0,0) =
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1);
2150 adja(0,1) =
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2);
2151 adja(0,2) =
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1);
2153 adja(1,0) =
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2);
2154 adja(1,1) =
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0);
2155 adja(1,2) =
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2);
2157 adja(2,0) =
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0);
2158 adja(2,1) =
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1);
2159 adja(2,2) =
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0);
2169 mfem_error(
"CalcAdjugateTranspose(...): dimension mismatch");
2176 else if (a.
Width() == 2)
2178 adjat(0,0) =
a(1,1);
2179 adjat(1,0) = -
a(0,1);
2180 adjat(0,1) = -
a(1,0);
2181 adjat(1,1) =
a(0,0);
2185 adjat(0,0) =
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1);
2186 adjat(1,0) =
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2);
2187 adjat(2,0) =
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1);
2189 adjat(0,1) =
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2);
2190 adjat(1,1) =
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0);
2191 adjat(2,1) =
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2);
2193 adjat(0,2) =
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0);
2194 adjat(1,2) =
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1);
2195 adjat(2,2) =
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0);
2202 MFEM_ASSERT(inva.
Height() == a.
Width(),
"incorrect dimensions");
2203 MFEM_ASSERT(inva.
Width() == a.
Height(),
"incorrect dimensions");
2209 const double *d = a.
Data();
2210 double *
id = inva.
Data();
2213 t = 1.0 / (d[0]*d[0] + d[1]*d[1]);
2221 t = 1.0 / (d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
2229 e = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
2230 g = d[3]*d[3] + d[4]*d[4] + d[5]*d[5];
2231 f = d[0]*d[3] + d[1]*d[4] + d[2]*d[5];
2232 t = 1.0 / (e*g - f*
f);
2233 e *= t; g *= t; f *= t;
2235 id[0] = d[0]*g - d[3]*
f;
2236 id[1] = d[3]*e - d[0]*
f;
2237 id[2] = d[1]*g - d[4]*
f;
2238 id[3] = d[4]*e - d[1]*
f;
2239 id[4] = d[2]*g - d[5]*
f;
2240 id[5] = d[5]*e - d[2]*
f;
2248 MFEM_ASSERT(std::abs(t) > 1.0e-14 * pow(a.FNorm()/a.
Width(), a.
Width()),
2249 "singular matrix!");
2255 inva(0,0) = 1.0 / a.
Det();
2258 kernels::CalcInverse<2>(a.
Data(), inva.
Data());
2261 kernels::CalcInverse<3>(a.
Data(), inva.
Data());
2272 mfem_error(
"CalcInverseTranspose(...): dimension mismatch");
2276 double t = 1. / a.
Det() ;
2281 inva(0,0) = 1.0 /
a(0,0);
2284 inva(0,0) =
a(1,1) * t ;
2285 inva(1,0) = -
a(0,1) * t ;
2286 inva(0,1) = -
a(1,0) * t ;
2287 inva(1,1) =
a(0,0) * t ;
2290 inva(0,0) = (
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1))*t;
2291 inva(1,0) = (
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2))*t;
2292 inva(2,0) = (
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1))*t;
2294 inva(0,1) = (
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2))*t;
2295 inva(1,1) = (
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0))*t;
2296 inva(2,1) = (
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2))*t;
2298 inva(0,2) = (
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0))*t;
2299 inva(1,2) = (
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1))*t;
2300 inva(2,2) = (
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0))*t;
2310 "Matrix must be 3x2 or 2x1, "
2311 <<
"and the Vector must be sized with the rows. "
2312 <<
" J.Height() = " << J.
Height()
2313 <<
", J.Width() = " << J.
Width()
2314 <<
", n.Size() = " << n.
Size()
2317 const double *d = J.
Data();
2325 n(0) = d[1]*d[5] - d[2]*d[4];
2326 n(1) = d[2]*d[3] - d[0]*d[5];
2327 n(2) = d[0]*d[4] - d[1]*d[3];
2333 const int height = a.
Height();
2334 const int width = a.
Width();
2335 for (
int i = 0; i < height; i++)
2337 for (
int j = 0; j <= i; j++)
2340 for (
int k = 0; k < width; k++)
2342 temp +=
a(i,k) *
a(j,k);
2344 aat(j,i) = aat(i,j) = temp;
2351 for (
int i = 0; i < A.
Height(); i++)
2353 for (
int j = 0; j < i; j++)
2356 for (
int k = 0; k < A.
Width(); k++)
2358 t += D(k) * A(i, k) * A(j, k);
2366 for (
int i = 0; i < A.
Height(); i++)
2369 for (
int k = 0; k < A.
Width(); k++)
2371 t += D(k) * A(i, k) * A(i, k);
2379 for (
int i = 0; i < A.
Height(); i++)
2381 for (
int j = 0; j <= i; j++)
2384 for (
int k = 0; k < A.
Width(); k++)
2386 t += D(k) * A(i, k) * A(j, k);
2388 ADAt(j, i) = ADAt(i, j) = t;
2399 mfem_error(
"MultABt(...): dimension mismatch");
2403 #ifdef MFEM_USE_LAPACK
2404 static char transa =
'N', transb =
'T';
2405 static double alpha = 1.0, beta = 0.0;
2408 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2409 B.
Data(), &n, &beta, ABt.
Data(), &m);
2411 const int ah = A.
Height();
2412 const int bh = B.
Height();
2413 const int aw = A.
Width();
2414 const double *ad = A.
Data();
2415 const double *bd = B.
Data();
2416 double *cd = ABt.
Data();
2420 const int ah = A.
Height();
2421 const int bh = B.
Height();
2422 const int aw = A.
Width();
2423 const double *ad = A.
Data();
2424 const double *bd = B.
Data();
2425 double *cd = ABt.
Data();
2427 for (
int j = 0; j < bh; j++)
2428 for (
int i = 0; i < ah; i++)
2431 const double *ap = ad + i;
2432 const double *bp = bd + j;
2433 for (
int k = 0; k < aw; k++)
2445 for (i = 0; i < A.
Height(); i++)
2446 for (j = 0; j < B.
Height(); j++)
2449 for (k = 0; k < A.
Width(); k++)
2451 d += A(i, k) * B(j, k);
2465 mfem_error(
"MultADBt(...): dimension mismatch");
2469 const int ah = A.
Height();
2470 const int bh = B.
Height();
2471 const int aw = A.
Width();
2472 const double *ad = A.
Data();
2473 const double *bd = B.
Data();
2474 const double *dd = D.
GetData();
2475 double *cd = ADBt.
Data();
2477 for (
int i = 0, s = ah*bh; i < s; i++)
2481 for (
int k = 0; k < aw; k++)
2484 for (
int j = 0; j < bh; j++)
2486 const double dk_bjk = dd[k] * bd[j];
2487 for (
int i = 0; i < ah; i++)
2489 cp[i] += ad[i] * dk_bjk;
2504 mfem_error(
"AddMultABt(...): dimension mismatch");
2508 #ifdef MFEM_USE_LAPACK
2509 static char transa =
'N', transb =
'T';
2510 static double alpha = 1.0, beta = 1.0;
2513 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2514 B.
Data(), &n, &beta, ABt.
Data(), &m);
2516 const int ah = A.
Height();
2517 const int bh = B.
Height();
2518 const int aw = A.
Width();
2519 const double *ad = A.
Data();
2520 const double *bd = B.
Data();
2521 double *cd = ABt.
Data();
2523 for (
int k = 0; k < aw; k++)
2526 for (
int j = 0; j < bh; j++)
2528 const double bjk = bd[j];
2529 for (
int i = 0; i < ah; i++)
2531 cp[i] += ad[i] * bjk;
2542 for (i = 0; i < A.
Height(); i++)
2543 for (j = 0; j < B.
Height(); j++)
2546 for (k = 0; k < A.
Width(); k++)
2548 d += A(i, k) * B(j, k);
2562 mfem_error(
"AddMultADBt(...): dimension mismatch");
2566 const int ah = A.
Height();
2567 const int bh = B.
Height();
2568 const int aw = A.
Width();
2569 const double *ad = A.
Data();
2570 const double *bd = B.
Data();
2571 const double *dd = D.
GetData();
2572 double *cd = ADBt.
Data();
2574 for (
int k = 0; k < aw; k++)
2577 for (
int j = 0; j < bh; j++)
2579 const double dk_bjk = dd[k] * bd[j];
2580 for (
int i = 0; i < ah; i++)
2582 cp[i] += ad[i] * dk_bjk;
2598 mfem_error(
"AddMult_a_ABt(...): dimension mismatch");
2602 #ifdef MFEM_USE_LAPACK
2603 static char transa =
'N', transb =
'T';
2605 static double beta = 1.0;
2608 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2609 B.
Data(), &n, &beta, ABt.
Data(), &m);
2611 const int ah = A.
Height();
2612 const int bh = B.
Height();
2613 const int aw = A.
Width();
2614 const double *ad = A.
Data();
2615 const double *bd = B.
Data();
2616 double *cd = ABt.
Data();
2618 for (
int k = 0; k < aw; k++)
2621 for (
int j = 0; j < bh; j++)
2623 const double bjk = a * bd[j];
2624 for (
int i = 0; i < ah; i++)
2626 cp[i] += ad[i] * bjk;
2637 for (i = 0; i < A.
Height(); i++)
2638 for (j = 0; j < B.
Height(); j++)
2641 for (k = 0; k < A.
Width(); k++)
2643 d += A(i, k) * B(j, k);
2656 mfem_error(
"MultAtB(...): dimension mismatch");
2660 #ifdef MFEM_USE_LAPACK
2661 static char transa =
'T', transb =
'N';
2662 static double alpha = 1.0, beta = 0.0;
2665 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &k,
2666 B.
Data(), &k, &beta, AtB.
Data(), &m);
2668 const int ah = A.
Height();
2669 const int aw = A.
Width();
2670 const int bw = B.
Width();
2671 const double *ad = A.
Data();
2672 const double *bd = B.
Data();
2673 double *cd = AtB.
Data();
2675 for (
int j = 0; j < bw; j++)
2677 const double *ap = ad;
2678 for (
int i = 0; i < aw; i++)
2681 for (
int k = 0; k < ah; k++)
2694 for (i = 0; i < A.
Width(); i++)
2695 for (j = 0; j < B.
Width(); j++)
2698 for (k = 0; k < A.
Height(); k++)
2700 d += A(k, i) * B(k, j);
2711 for (
int i = 0; i < A.
Height(); i++)
2713 for (
int j = 0; j < i; j++)
2716 for (
int k = 0; k < A.
Width(); k++)
2718 d += A(i,k) * A(j,k);
2720 AAt(i, j) += (d *=
a);
2724 for (
int k = 0; k < A.
Width(); k++)
2726 d += A(i,k) * A(i,k);
2734 for (
int i = 0; i < A.
Height(); i++)
2736 for (
int j = 0; j <= i; j++)
2739 for (
int k = 0; k < A.
Width(); k++)
2741 d += A(i,k) * A(j,k);
2743 AAt(i, j) = AAt(j, i) = a * d;
2750 for (
int i = 0; i < v.
Size(); i++)
2752 for (
int j = 0; j <= i; j++)
2754 vvt(i,j) = vvt(j,i) = v(i) * v(j);
2764 mfem_error(
"MultVWt(...): dimension mismatch");
2768 for (
int i = 0; i < v.
Size(); i++)
2770 const double vi = v(i);
2771 for (
int j = 0; j < w.
Size(); j++)
2773 VWt(i, j) = vi * w(j);
2780 const int m = v.
Size(), n = w.
Size();
2785 mfem_error(
"AddMultVWt(...): dimension mismatch");
2789 for (
int i = 0; i < m; i++)
2791 const double vi = v(i);
2792 for (
int j = 0; j < n; j++)
2794 VWt(i, j) += vi * w(j);
2801 const int n = v.
Size();
2806 mfem_error(
"AddMultVVt(...): dimension mismatch");
2810 for (
int i = 0; i < n; i++)
2812 const double vi = v(i);
2813 for (
int j = 0; j < i; j++)
2815 const double vivj = vi * v(j);
2819 VVt(i, i) += vi * vi;
2826 const int m = v.
Size(), n = w.
Size();
2831 mfem_error(
"AddMult_a_VWt(...): dimension mismatch");
2835 for (
int j = 0; j < n; j++)
2837 const double awj = a * w(j);
2838 for (
int i = 0; i < m; i++)
2840 VWt(i, j) += v(i) * awj;
2848 "incompatible dimensions!");
2850 const int n = v.
Size();
2851 for (
int i = 0; i < n; i++)
2853 double avi = a * v(i);
2854 for (
int j = 0; j < i; j++)
2856 const double avivj = avi * v(j);
2860 VVt(i, i) += avi * v(i);
2867 #ifdef MFEM_USE_LAPACK
2874 for (
int i = 0; i < m; i++)
2879 double a = std::abs(data[piv+i*m]);
2880 for (
int j = i+1; j < m; j++)
2882 const double b = std::abs(data[j+i*m]);
2893 for (
int j = 0; j < m; j++)
2895 Swap<double>(data[i+j*m], data[piv+j*m]);
2900 if (abs(data[i + i*m]) <= TOL)
2905 const double a_ii_inv = 1.0 / data[i+i*m];
2906 for (
int j = i+1; j < m; j++)
2908 data[j+i*m] *= a_ii_inv;
2910 for (
int k = i+1; k < m; k++)
2912 const double a_ik = data[i+k*m];
2913 for (
int j = i+1; j < m; j++)
2915 data[j+k*m] -= a_ik * data[j+i*m];
2927 for (
int i=0; i<m; i++)
2931 det *= -
data[m * i + i];
2935 det *=
data[m * i + i];
2946 for (
int k = 0; k < n; k++)
2949 for (
int i = 0; i < m; i++)
2951 double x_i = x[i] * data[i+i*m];
2952 for (
int j = i+1; j < m; j++)
2954 x_i += x[j] * data[i+j*m];
2959 for (
int i = m-1; i >= 0; i--)
2962 for (
int j = 0; j < i; j++)
2964 x_i += x[j] * data[i+j*m];
2969 for (
int i = m-1; i >= 0; i--)
2971 Swap<double>(x[i], x[ipiv[i]-
ipiv_base]);
2982 for (
int k = 0; k < n; k++)
2985 for (
int i = 0; i < m; i++)
2987 Swap<double>(x[i], x[ipiv[i]-
ipiv_base]);
2990 for (
int j = 0; j < m; j++)
2992 const double x_j = x[j];
2993 for (
int i = j+1; i < m; i++)
2995 x[i] -= data[i+j*m] * x_j;
3007 for (
int k = 0; k < n; k++)
3009 for (
int j = m-1; j >= 0; j--)
3011 const double x_j = ( x[j] /= data[j+j*m] );
3012 for (
int i = 0; i < j; i++)
3014 x[i] -= data[i+j*m] * x_j;
3023 #ifdef MFEM_USE_LAPACK
3026 if (m > 0 && n > 0) {
dgetrs_(&trans, &m, &n,
data, &m,
ipiv, X, &m, &info); }
3027 MFEM_VERIFY(!info,
"LAPACK: error in DGETRS");
3038 #ifdef MFEM_USE_LAPACK
3039 char n_ch =
'N', side =
'R', u_ch =
'U', l_ch =
'L';
3043 dtrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&alpha,
data,&m,X,&n);
3044 dtrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&alpha,
data,&m,X,&n);
3050 for (
int k = 0; k < n; k++)
3052 for (
int j = 0; j < m; j++)
3054 const double x_j = ( x[j*n] /=
data[j+j*m]);
3055 for (
int i = j+1; i < m; i++)
3057 x[i*n] -=
data[j + i*m] * x_j;
3065 for (
int k = 0; k < n; k++)
3067 for (
int j = m-1; j >= 0; j--)
3069 const double x_j = x[j*n];
3070 for (
int i = 0; i < j; i++)
3072 x[i*n] -=
data[j + i*m] * x_j;
3080 for (
int k = 0; k < n; k++)
3082 for (
int i = m-1; i >= 0; --i)
3097 for (
int k = 0; k < m; k++)
3099 const double minus_x_k = -( x[k] = 1.0/data[k+k*m] );
3100 for (
int i = 0; i < k; i++)
3102 x[i] = data[i+k*m] * minus_x_k;
3104 for (
int j = k-1; j >= 0; j--)
3106 const double x_j = ( x[j] /= data[j+j*m] );
3107 for (
int i = 0; i < j; i++)
3109 x[i] -= data[i+j*m] * x_j;
3117 for (
int j = 0; j < k; j++)
3119 const double minus_L_kj = -data[k+j*m];
3120 for (
int i = 0; i <= j; i++)
3122 X[i+j*m] += X[i+k*m] * minus_L_kj;
3124 for (
int i = j+1; i < m; i++)
3126 X[i+j*m] = X[i+k*m] * minus_L_kj;
3130 for (
int k = m-2; k >= 0; k--)
3132 for (
int j = 0; j < k; j++)
3134 const double L_kj = data[k+j*m];
3135 for (
int i = 0; i < m; i++)
3137 X[i+j*m] -= X[i+k*m] * L_kj;
3142 for (
int k = m-1; k >= 0; k--)
3147 for (
int i = 0; i < m; i++)
3149 Swap<double>(X[i+k*m], X[i+piv_k*m]);
3156 const double *X1,
double *X2)
3159 for (
int k = 0; k < r; k++)
3161 for (
int j = 0; j < m; j++)
3163 const double x1_jk = X1[j+k*m];
3164 for (
int i = 0; i < n; i++)
3166 X2[i+k*n] -= A21[i+j*n] * x1_jk;
3173 int m,
int n,
double *A12,
double *A21,
double *A22)
const
3179 for (
int j = 0; j < m; j++)
3181 const double u_jj_inv = 1.0/data[j+j*m];
3182 for (
int i = 0; i < n; i++)
3184 A21[i+j*n] *= u_jj_inv;
3186 for (
int k = j+1; k < m; k++)
3188 const double u_jk = data[j+k*m];
3189 for (
int i = 0; i < n; i++)
3191 A21[i+k*n] -= A21[i+j*n] * u_jk;
3196 SubMult(m, n, n, A21, A12, A22);
3200 double *B1,
double *B2)
const
3205 SubMult(m, n, r, L21, B1, B2);
3209 const double *X2,
double *Y1)
const
3212 SubMult(n, m, r, U12, X2, Y1);
3221 MFEM_ASSERT(
height ==
width,
"not a square matrix");
3231 MFEM_ASSERT(
height ==
width,
"not a square matrix");
3239 MFEM_ASSERT(a,
"DenseMatrix is not given");
3240 const double *adata = a->data;
3242 for (
int i = 0; i < s; i++)
3244 lu.
data[i] = adata[i];
3257 MFEM_VERIFY(mat.
height == mat.
width,
"DenseMatrix is not square!");
3273 MFEM_VERIFY(p != NULL,
"Operator is not a DenseMatrix!");
3279 for (
int row = 0; row <
height; row++)
3302 for (
int i = 0; i <
width; i++)
3324 #ifdef MFEM_USE_LAPACK
3330 &qwork, &lwork, &info);
3332 lwork = (int) qwork;
3333 work =
new double[lwork];
3339 : mat(other.mat), EVal(other.EVal), EVect(other.EVect), ev(NULL, other.n),
3342 #ifdef MFEM_USE_LAPACK
3345 lwork = other.lwork;
3347 work =
new double[lwork];
3354 if (mat.
Width() != n)
3356 mfem_error(
"DenseMatrixEigensystem::Eval(): dimension mismatch");
3360 #ifdef MFEM_USE_LAPACK
3363 work, &lwork, &info);
3367 mfem::err <<
"DenseMatrixEigensystem::Eval(): DSYEV error code: "
3372 mfem_error(
"DenseMatrixEigensystem::Eval(): Compiled without LAPACK");
3378 #ifdef MFEM_USE_LAPACK
3398 void DenseMatrixSVD::Init()
3400 #ifdef MFEM_USE_LAPACK
3409 NULL, &n, &qwork, &lwork, &info);
3411 lwork = (int) qwork;
3412 work =
new double[lwork];
3414 mfem_error(
"DenseMatrixSVD::Init(): Compiled without LAPACK");
3427 #ifdef MFEM_USE_LAPACK
3429 NULL, &n, work, &lwork, &info);
3433 mfem::err <<
"DenseMatrixSVD::Eval() : info = " << info << endl;
3437 mfem_error(
"DenseMatrixSVD::Eval(): Compiled without LAPACK");
3443 #ifdef MFEM_USE_LAPACK
3453 const int *I = elem_dof.
GetI(), *J = elem_dof.
GetJ(), *dofs;
3454 const double *d_col = tdata;
3457 const double *xp = x;
3461 for (
int i = 0; i < ne; i++)
3464 for (
int col = 0; col < n; col++)
3466 x_col = xp[dofs[col]];
3467 for (
int row = 0; row < n; row++)
3469 yp[dofs[row]] += x_col*d_col[row];
3478 for (
int i = 0; i < ne; i++)
3481 x_col = xp[dofs[0]];
3482 for (
int row = 0; row < n; row++)
3484 ye(row) = x_col*d_col[row];
3487 for (
int col = 1; col < n; col++)
3489 x_col = xp[dofs[col]];
3490 for (
int row = 0; row < n; row++)
3492 ye(row) += x_col*d_col[row];
3496 for (
int row = 0; row < n; row++)
3498 yp[dofs[row]] += ye(row);
3507 for (
int i=0; i<s; i++)
3516 const int m = Mlu.
SizeI();
3517 const int NE = Mlu.
SizeK();
3523 pivot_flag[0] =
true;
3524 bool *d_pivot_flag = pivot_flag.ReadWrite();
3528 for (
int i = 0; i < m; i++)
3533 double a = fabs(data_all(piv,i,e));
3534 for (
int j = i+1; j < m; j++)
3536 const double b = fabs(data_all(j,i,e));
3543 ipiv_all(i,e) = piv;
3547 for (
int j = 0; j < m; j++)
3549 mfem::kernels::internal::Swap<double>(data_all(i,j,e), data_all(piv,j,e));
3554 if (abs(data_all(i,i,e)) <= TOL)
3556 d_pivot_flag[0] =
false;
3559 const double a_ii_inv = 1.0 / data_all(i,i,e);
3560 for (
int j = i+1; j < m; j++)
3562 data_all(j,i,e) *= a_ii_inv;
3565 for (
int k = i+1; k < m; k++)
3567 const double a_ik = data_all(i,k,e);
3568 for (
int j = i+1; j < m; j++)
3570 data_all(j,k,e) -= a_ik * data_all(j,i,e);
3578 MFEM_ASSERT(pivot_flag.HostRead()[0],
"Batch LU factorization failed \n");
3584 const int m = Mlu.
SizeI();
3585 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)
double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
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. The Memory is not reset by this method, i.e. it will, generally, not be Empty() after this call.
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)
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 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 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 * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
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
DenseMatrixSVD(DenseMatrix &M)
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
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 Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
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)
void TestInversion()
Print the numerical conditioning of the inversion: ||A^{-1} A - I||.
double MaxMaxNorm() const
Compute the norm ||A|| = max_{ij} |A_{ij}|.
double * Data() const
Returns the matrix data array.
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 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.
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)
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.
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
MFEM_HOST_DEVICE void Mult(const int height, const int width, 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...
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.
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.
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
DenseMatrix & operator+=(const double *m)
double f(const Vector &p)