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);
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++)
597 "incompatible matrix sizes.");
603 for (
int j = 0; j <
width; j++)
605 for (
int i = 0; i <
height; i++)
607 (*this)(i, j) -= m(i, j);
617 for (
int i = 0; i <
s; i++)
627 for (
int i = 0; i < hw; i++)
638 mfem_error(
"DenseMatrix::Invert(): dimension mismatch");
642 #ifdef MFEM_USE_LAPACK
643 int *ipiv =
new int[
width];
652 mfem_error(
"DenseMatrix::Invert() : Error in DGETRF");
658 work =
new double[lwork];
664 mfem_error(
"DenseMatrix::Invert() : Error in DGETRI");
670 int c, i, j, n =
Width();
674 for (c = 0; c < n; c++)
676 a = fabs((*
this)(c, c));
678 for (j = c + 1; j < n; j++)
680 b = fabs((*
this)(j, c));
689 mfem_error(
"DenseMatrix::Invert() : singular matrix");
692 for (j = 0; j < n; j++)
694 mfem::Swap<double>((*this)(c, j), (*
this)(i, j));
697 a = (*this)(c, c) = 1.0 / (*
this)(c, c);
698 for (j = 0; j < c; j++)
702 for (j++; j < n; j++)
706 for (i = 0; i < c; i++)
708 (*this)(i, c) = a * (b = -(*
this)(i, c));
709 for (j = 0; j < c; j++)
711 (*this)(i, j) += b * (*
this)(c, j);
713 for (j++; j < n; j++)
715 (*this)(i, j) += b * (*
this)(c, j);
718 for (i++; i < n; i++)
720 (*this)(i, c) = a * (b = -(*
this)(i, c));
721 for (j = 0; j < c; j++)
723 (*this)(i, j) += b * (*
this)(c, j);
725 for (j++; j < n; j++)
727 (*this)(i, j) += b * (*
this)(c, j);
732 for (c = n - 1; c >= 0; c--)
735 for (i = 0; i < n; i++)
737 mfem::Swap<double>((*this)(i, c), (*
this)(i, j));
749 mfem_error(
"DenseMatrix::SquareRootInverse() matrix not square.");
759 for (
int v = 0; v <
Height() ; v++) { (*this)(v,v) = 1.0; }
761 for (
int j = 0; j < 10; j++)
763 for (
int i = 0; i < 10; i++)
778 for (
int v = 0; v <
Height() ; v++) { tmp2(v,v) -= 1.0; }
779 if (tmp2.FNorm() < 1e-10) {
break; }
782 if (tmp2.FNorm() > 1e-10)
784 mfem_error(
"DenseMatrix::SquareRootInverse not converged");
790 for (
int j = 0; j <
Width(); j++)
793 for (
int i = 0; i <
Height(); i++)
795 v[j] += (*this)(i,j)*(*
this)(i,j);
804 const double *d = data;
805 double norm = 0.0, abs_entry;
807 for (
int i = 0; i < hw; i++)
809 abs_entry = fabs(d[i]);
810 if (norm < abs_entry)
822 double max_norm = 0.0, entry, fnorm2;
824 for (i = 0; i < hw; i++)
826 entry = fabs(data[i]);
827 if (entry > max_norm)
835 scale_factor = scaled_fnorm2 = 0.0;
840 for (i = 0; i < hw; i++)
842 entry = data[i] / max_norm;
843 fnorm2 += entry * entry;
846 scale_factor = max_norm;
847 scaled_fnorm2 = fnorm2;
852 #ifdef MFEM_USE_LAPACK
859 double *A =
new double[N*N];
870 int *ISUPPZ =
new int[2*N];
889 double *data = a.
Data();
891 for (
int i = 0; i < hw; i++)
896 dsyevr_( &JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU,
897 &ABSTOL, &M, W, Z, &LDZ, ISUPPZ, &QWORK, &LWORK,
898 &QIWORK, &LIWORK, &INFO );
903 WORK =
new double[LWORK];
904 IWORK =
new int[LIWORK];
906 dsyevr_( &JOBZ, &RANGE, &UPLO, &N, A, &LDA, &VL, &VU, &IL, &IU,
907 &ABSTOL, &M, W, Z, &LDZ, ISUPPZ, WORK, &LWORK,
908 IWORK, &LIWORK, &INFO );
912 mfem::err <<
"dsyevr_Eigensystem(...): DSYEVR error code: "
920 mfem::err <<
"dsyevr_Eigensystem(...):\n"
921 <<
" DSYEVR did not find all eigenvalues "
922 << M <<
"/" << N << endl;
927 mfem_error(
"dsyevr_Eigensystem(...): inf/nan values in W");
931 mfem_error(
"dsyevr_Eigensystem(...): inf/nan values in Z");
934 for (IL = 0; IL < N; IL++)
935 for (IU = 0; IU <= IL; IU++)
938 for (M = 0; M < N; M++)
940 VL += Z[M+IL*N] * Z[M+IU*N];
957 <<
" Z^t Z - I deviation = " << VU
958 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
959 << W[0] <<
", N = " << N << endl;
966 <<
" Z^t Z - I deviation = " << VU
967 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
968 << W[0] <<
", N = " << N << endl;
972 mfem_error(
"dsyevr_Eigensystem(...): ERROR: ...");
975 for (IL = 0; IL < N; IL++)
976 for (IU = 0; IU < N; IU++)
979 for (M = 0; M < N; M++)
981 VL += Z[IL+M*N] * W[M] * Z[IU+M*N];
983 VL = fabs(VL-data[IL+N*IU]);
992 <<
" max matrix deviation = " << VU
993 <<
"\n W[max] = " << W[N-1] <<
", W[min] = "
994 << W[0] <<
", N = " << N << endl;
998 mfem_error(
"dsyevr_Eigensystem(...): ERROR: ...");
1007 MFEM_CONTRACT_VAR(a);
1008 MFEM_CONTRACT_VAR(ev);
1009 MFEM_CONTRACT_VAR(evect);
1015 #ifdef MFEM_USE_LAPACK
1027 double *WORK = NULL;
1038 A =
new double[N*N];
1042 double *data = a.
Data();
1043 for (
int i = 0; i < hw; i++)
1048 dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, &QWORK, &LWORK, &INFO);
1050 LWORK = (int) QWORK;
1051 WORK =
new double[LWORK];
1053 dsyev_(&JOBZ, &UPLO, &N, A, &LDA, W, WORK, &LWORK, &INFO);
1057 mfem::err <<
"dsyev_Eigensystem: DSYEV error code: " << INFO << endl;
1062 if (evect == NULL) {
delete [] A; }
1064 MFEM_CONTRACT_VAR(a);
1065 MFEM_CONTRACT_VAR(ev);
1066 MFEM_CONTRACT_VAR(evect);
1070 void DenseMatrix::Eigensystem(Vector &ev, DenseMatrix *evect)
1072 #ifdef MFEM_USE_LAPACK
1080 MFEM_CONTRACT_VAR(ev);
1081 MFEM_CONTRACT_VAR(evect);
1082 mfem_error(
"DenseMatrix::Eigensystem: Compiled without LAPACK");
1090 #ifdef MFEM_USE_LAPACK
1103 double *B =
new double[N*N];
1105 double *WORK = NULL;
1116 A =
new double[N*N];
1120 double *a_data = a.
Data();
1121 double *b_data = b.
Data();
1122 for (
int i = 0; i < hw; i++)
1128 dsygv_(&ITYPE, &JOBZ, &UPLO, &N, A, &LDA, B, &LDB, W, &QWORK, &LWORK, &INFO);
1130 LWORK = (int) QWORK;
1131 WORK =
new double[LWORK];
1133 dsygv_(&ITYPE, &JOBZ, &UPLO, &N, A, &LDA, B, &LDB, W, WORK, &LWORK, &INFO);
1137 mfem::err <<
"dsygv_Eigensystem: DSYGV error code: " << INFO << endl;
1143 if (evect == NULL) {
delete [] A; }
1145 MFEM_CONTRACT_VAR(a);
1146 MFEM_CONTRACT_VAR(b);
1147 MFEM_CONTRACT_VAR(ev);
1148 MFEM_CONTRACT_VAR(evect);
1152 void DenseMatrix::Eigensystem(DenseMatrix &
b, Vector &ev,
1155 #ifdef MFEM_USE_LAPACK
1160 MFEM_CONTRACT_VAR(b);
1161 MFEM_CONTRACT_VAR(ev);
1162 MFEM_CONTRACT_VAR(evect);
1163 mfem_error(
"DenseMatrix::Eigensystem(generalized): Compiled without LAPACK");
1169 #ifdef MFEM_USE_LAPACK
1175 double *
a = copy_of_this.data;
1180 double *work = NULL;
1185 dgesvd_(&jobu, &jobvt, &m, &n, a, &m,
1186 s, u, &m, vt, &n, &qwork, &lwork, &info);
1188 lwork = (int) qwork;
1189 work =
new double[lwork];
1191 dgesvd_(&jobu, &jobvt, &m, &n, a, &m,
1192 s, u, &m, vt, &n, work, &lwork, &info);
1197 mfem::err <<
"DenseMatrix::SingularValues : info = " << info << endl;
1201 MFEM_CONTRACT_VAR(sv);
1203 mfem_error(
"DenseMatrix::SingularValues: Compiled without LAPACK");
1213 for (
int i=0; i < sv.
Size(); ++i)
1225 "The matrix must be square and sized 1, 2, or 3 to compute the"
1227 <<
" Height() = " <<
Height()
1228 <<
", Width() = " <<
Width());
1231 const double *d = data;
1257 const double *d = data;
1275 const double* rp = data + r;
1278 for (
int i = 0; i < n; i++)
1290 double *cp =
Data() + c * m;
1293 for (
int i = 0; i < m; i++)
1307 for (
int i = 0; i <
height; ++i)
1309 d(i) = (*this)(i,i);
1323 for (
int j = 0; j <
width; ++j)
1324 for (
int i = 0; i <
height; ++i)
1326 l(i) += fabs((*
this)(i,j));
1333 for (
int i = 0; i <
height; i++)
1336 for (
int j = 0; j <
width; j++)
1349 for (
int i = 0; i < N; i++)
1353 for (
int i = 0; i < n; i++)
1364 for (i = 0; i < N; i++)
1368 for (i = 0; i < n; i++)
1370 data[i*(n+1)] = diag[i];
1381 for (i = 0; i <
Height(); i++)
1382 for (j = i+1; j <
Width(); j++)
1385 (*this)(i,j) = (*
this)(j,i);
1400 for (
int i = 0; i <
Height(); i++)
1401 for (
int j = 0; j <
Width(); j++)
1403 (*this)(i,j) = A(j,i);
1412 mfem_error(
"DenseMatrix::Symmetrize() : not a square matrix!");
1420 for (
int i = 0; i <
Height(); i++)
1423 for (
int j = 0; j <
Width(); j++)
1426 (*this)(i, j) = 0.0;
1440 mfem_error(
"DenseMatrix::GradToCurl(...): dimension mismatch");
1446 for (
int i = 0; i < n; i++)
1449 double x = (*this)(i,0);
1450 double y = (*this)(i,1);
1463 for (
int i = 0; i < n; i++)
1466 double x = (*this)(i,0);
1467 double y = (*this)(i,1);
1468 double z = (*this)(i,2);
1493 MFEM_ASSERT(
Width()*
Height() == div.
Size(),
"incompatible Vector 'div'!");
1498 double *ddata = div.
GetData();
1500 for (
int i = 0; i < n; i++)
1510 for (
int j = 0; j <
Width(); j++)
1512 for (
int i = row1; i <= row2; i++)
1514 (*this)(i-row1,j) = A(i,j);
1523 for (
int j = col1; j <= col2; j++)
1525 for (
int i = 0; i <
Height(); i++)
1527 (*this)(i,j-col1) = A(i,j);
1536 for (
int j = 0; j < n; j++)
1538 for (
int i = 0; i < m; i++)
1540 (*this)(i,j) = A(Aro+i,Aco+j);
1547 double *v = A.
Data();
1549 for (
int j = 0; j < A.
Width(); j++)
1551 for (
int i = 0; i < A.
Height(); i++)
1553 (*this)(row_offset+i,col_offset+j) = *(v++);
1560 double *v = A.
Data();
1562 for (
int i = 0; i < A.
Width(); i++)
1564 for (
int j = 0; j < A.
Height(); j++)
1566 (*this)(row_offset+i,col_offset+j) = *(v++);
1572 int row_offset,
int col_offset)
1574 MFEM_VERIFY(row_offset+m <= this->
Height() && col_offset+n <= this->
Width(),
1575 "this DenseMatrix is too small to accomodate the submatrix. "
1576 <<
"row_offset = " << row_offset
1578 <<
", this->Height() = " << this->
Height()
1579 <<
", col_offset = " << col_offset
1581 <<
", this->Width() = " << this->
Width()
1583 MFEM_VERIFY(Aro+m <= A.
Height() && Aco+n <= A.
Width(),
1584 "The A DenseMatrix is too small to accomodate the submatrix. "
1587 <<
", A.Height() = " << A.
Height()
1588 <<
", Aco = " << Aco
1590 <<
", A.Width() = " << A.
Width()
1593 for (
int j = 0; j < n; j++)
1595 for (
int i = 0; i < m; i++)
1597 (*this)(row_offset+i,col_offset+j) = A(Aro+i,Aco+j);
1604 for (
int i = 0; i < n; i++)
1606 for (
int j = i+1; j < n; j++)
1608 (*this)(row_offset+i,col_offset+j) =
1609 (*
this)(row_offset+j,col_offset+i) = 0.0;
1613 for (
int i = 0; i < n; i++)
1615 (*this)(row_offset+i,col_offset+i) = c;
1622 for (
int i = 0; i < n; i++)
1624 for (
int j = i+1; j < n; j++)
1626 (*this)(row_offset+i,col_offset+j) =
1627 (*
this)(row_offset+j,col_offset+i) = 0.0;
1631 for (
int i = 0; i < n; i++)
1633 (*this)(row_offset+i,col_offset+i) = diag[i];
1641 int i, j, i_off = 0, j_off = 0;
1643 for (j = 0; j < A.
Width(); j++)
1650 for (i = 0; i < A.
Height(); i++)
1657 (*this)(i-i_off,j-j_off) = A(i,j);
1673 if (co+aw >
Width() || ro+ah > h)
1675 mfem_error(
"DenseMatrix::AddMatrix(...) 1 : dimension mismatch");
1679 p = data + ro + co * h;
1682 for (
int c = 0; c < aw; c++)
1684 for (
int r = 0; r < ah; r++)
1703 if (co+aw >
Width() || ro+ah > h)
1705 mfem_error(
"DenseMatrix::AddMatrix(...) 2 : dimension mismatch");
1709 p = data + ro + co * h;
1712 for (
int c = 0; c < aw; c++)
1714 for (
int r = 0; r < ah; r++)
1726 double *vdata = v.
GetData() + offset;
1728 for (
int i = 0; i < n; i++)
1730 vdata[i] += data[i];
1737 const double *vdata = v.
GetData() + offset;
1739 for (
int i = 0; i < n; i++)
1752 mfem_error(
"DenseMatrix::AdjustDofDirection(...): dimension mismatch");
1757 for (
int i = 0; i < n-1; i++)
1759 const int s = (dof[i] < 0) ? (-1) : (1);
1760 for (
int j = i+1; j < n; j++)
1762 const int t = (dof[j] < 0) ? (-s) : (
s);
1765 (*this)(i,j) = -(*
this)(i,j);
1766 (*this)(j,i) = -(*
this)(j,i);
1774 for (
int j = 0; j <
Width(); j++)
1776 (*this)(row, j) = value;
1782 for (
int i = 0; i <
Height(); i++)
1784 (*this)(i, col) = value;
1790 MFEM_ASSERT(row !=
nullptr,
"supplied row pointer is null");
1791 for (
int j = 0; j <
Width(); j++)
1793 (*this)(r, j) = row[j];
1805 MFEM_ASSERT(col !=
nullptr,
"supplied column pointer is null");
1806 for (
int i = 0; i <
Height(); i++)
1808 (*this)(i, c) = col[i];
1820 for (
int col = 0; col <
Width(); col++)
1822 for (
int row = 0; row <
Height(); row++)
1824 if (std::abs(
operator()(row,col)) <= eps)
1835 ios::fmtflags old_flags = out.flags();
1837 out << setiosflags(ios::scientific | ios::showpos);
1838 for (
int i = 0; i <
height; i++)
1840 out <<
"[row " << i <<
"]\n";
1841 for (
int j = 0; j <
width; j++)
1843 out << (*this)(i,j);
1844 if (j+1 == width || (j+1) % width_ == 0)
1855 out.flags(old_flags);
1861 ios::fmtflags old_flags = out.flags();
1863 out << setiosflags(ios::scientific | ios::showpos);
1864 for (
int i = 0; i <
height; i++)
1866 for (
int j = 0; j <
width; j++)
1868 out << (*this)(i,j);
1874 out.flags(old_flags);
1880 ios::fmtflags old_flags = out.flags();
1882 out << setiosflags(ios::scientific | ios::showpos);
1883 for (
int j = 0; j <
width; j++)
1885 out <<
"[col " << j <<
"]\n";
1886 for (
int i = 0; i <
height; i++)
1888 out << (*this)(i,j);
1889 if (i+1 == height || (i+1) % width_ == 0)
1900 out.flags(old_flags);
1909 for (
int i = 0; i <
width; i++)
1914 <<
", cond_F = " <<
FNorm()*copy.FNorm() << endl;
1955 MFEM_VERIFY(A.
IsSquare(),
"A must be a square matrix!");
1956 MFEM_ASSERT(A.
NumCols() > 0,
"supplied matrix, A, is empty!");
1957 MFEM_ASSERT(X !=
nullptr,
"supplied vector, X, is null!");
1965 double det = A(0,0);
1966 if (std::abs(det) <= TOL) {
return false; }
1973 double det = A.
Det();
1974 if (std::abs(det) <= TOL) {
return false; }
1976 double invdet = 1. / det;
1981 X[0] = ( A(1,1)*b0 - A(0,1)*b1) * invdet;
1982 X[1] = (-A(1,0)*b0 + A(0,0)*b1) * invdet;
1991 if (!lu.Factor(N,TOL)) {
return false; }
2004 b.
Width() == c.
Height(),
"incompatible dimensions");
2006 #ifdef MFEM_USE_LAPACK
2007 static char transa =
'N', transb =
'N';
2008 static double alpha = 1.0, beta = 0.0;
2011 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2012 c.
Data(), &k, &beta, a.
Data(), &m);
2014 const int ah = a.
Height();
2015 const int aw = a.
Width();
2016 const int bw = b.
Width();
2017 double *ad = a.
Data();
2018 const double *bd = b.
Data();
2019 const double *cd = c.
Data();
2028 b.
Width() == c.
Height(),
"incompatible dimensions");
2030 #ifdef MFEM_USE_LAPACK
2031 static char transa =
'N', transb =
'N';
2032 static double beta = 1.0;
2035 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2036 c.
Data(), &k, &beta, a.
Data(), &m);
2038 const int ah = a.
Height();
2039 const int aw = a.
Width();
2040 const int bw = b.
Width();
2041 double *ad = a.
Data();
2042 const double *bd = b.
Data();
2043 const double *cd = c.
Data();
2044 for (
int j = 0; j < aw; j++)
2046 for (
int k = 0; k < bw; k++)
2048 for (
int i = 0; i < ah; i++)
2050 ad[i+j*ah] += alpha * bd[i+k*ah] * cd[k+j*bw];
2060 b.
Width() == c.
Height(),
"incompatible dimensions");
2062 #ifdef MFEM_USE_LAPACK
2063 static char transa =
'N', transb =
'N';
2064 static double alpha = 1.0, beta = 1.0;
2067 dgemm_(&transa, &transb, &m, &n, &k, &alpha, b.
Data(), &m,
2068 c.
Data(), &k, &beta, a.
Data(), &m);
2070 const int ah = a.
Height();
2071 const int aw = a.
Width();
2072 const int bw = b.
Width();
2073 double *ad = a.
Data();
2074 const double *bd = b.
Data();
2075 const double *cd = c.
Data();
2076 for (
int j = 0; j < aw; j++)
2078 for (
int k = 0; k < bw; k++)
2080 for (
int i = 0; i < ah; i++)
2082 ad[i+j*ah] += bd[i+k*ah] * cd[k+j*bw];
2094 mfem_error(
"CalcAdjugate(...): unsupported dimensions");
2098 mfem_error(
"CalcAdjugate(...): dimension mismatch");
2104 const double *d = a.
Data();
2105 double *ad = adja.
Data();
2120 e = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
2121 g = d[3]*d[3] + d[4]*d[4] + d[5]*d[5];
2122 f = d[0]*d[3] + d[1]*d[4] + d[2]*d[5];
2124 ad[0] = d[0]*g - d[3]*
f;
2125 ad[1] = d[3]*e - d[0]*
f;
2126 ad[2] = d[1]*g - d[4]*
f;
2127 ad[3] = d[4]*e - d[1]*
f;
2128 ad[4] = d[2]*g - d[5]*
f;
2129 ad[5] = d[5]*e - d[2]*
f;
2138 else if (a.
Width() == 2)
2141 adja(0,1) = -
a(0,1);
2142 adja(1,0) = -
a(1,0);
2147 adja(0,0) =
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1);
2148 adja(0,1) =
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2);
2149 adja(0,2) =
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1);
2151 adja(1,0) =
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2);
2152 adja(1,1) =
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0);
2153 adja(1,2) =
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2);
2155 adja(2,0) =
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0);
2156 adja(2,1) =
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1);
2157 adja(2,2) =
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0);
2167 mfem_error(
"CalcAdjugateTranspose(...): dimension mismatch");
2174 else if (a.
Width() == 2)
2176 adjat(0,0) =
a(1,1);
2177 adjat(1,0) = -
a(0,1);
2178 adjat(0,1) = -
a(1,0);
2179 adjat(1,1) =
a(0,0);
2183 adjat(0,0) =
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1);
2184 adjat(1,0) =
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2);
2185 adjat(2,0) =
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1);
2187 adjat(0,1) =
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2);
2188 adjat(1,1) =
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0);
2189 adjat(2,1) =
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2);
2191 adjat(0,2) =
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0);
2192 adjat(1,2) =
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1);
2193 adjat(2,2) =
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0);
2200 MFEM_ASSERT(inva.
Height() == a.
Width(),
"incorrect dimensions");
2201 MFEM_ASSERT(inva.
Width() == a.
Height(),
"incorrect dimensions");
2207 const double *d = a.
Data();
2208 double *
id = inva.
Data();
2211 t = 1.0 / (d[0]*d[0] + d[1]*d[1]);
2219 t = 1.0 / (d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
2227 e = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
2228 g = d[3]*d[3] + d[4]*d[4] + d[5]*d[5];
2229 f = d[0]*d[3] + d[1]*d[4] + d[2]*d[5];
2230 t = 1.0 / (e*g - f*
f);
2231 e *=
t; g *=
t; f *=
t;
2233 id[0] = d[0]*g - d[3]*
f;
2234 id[1] = d[3]*e - d[0]*
f;
2235 id[2] = d[1]*g - d[4]*
f;
2236 id[3] = d[4]*e - d[1]*
f;
2237 id[4] = d[2]*g - d[5]*
f;
2238 id[5] = d[5]*e - d[2]*
f;
2246 MFEM_ASSERT(std::abs(t) > 1.0e-14 * pow(a.FNorm()/a.
Width(), a.
Width()),
2247 "singular matrix!");
2253 inva(0,0) = 1.0 / a.
Det();
2256 kernels::CalcInverse<2>(a.
Data(), inva.
Data());
2259 kernels::CalcInverse<3>(a.
Data(), inva.
Data());
2270 mfem_error(
"CalcInverseTranspose(...): dimension mismatch");
2274 double t = 1. / a.
Det() ;
2279 inva(0,0) = 1.0 /
a(0,0);
2282 inva(0,0) =
a(1,1) *
t ;
2283 inva(1,0) = -
a(0,1) *
t ;
2284 inva(0,1) = -
a(1,0) *
t ;
2285 inva(1,1) =
a(0,0) *
t ;
2288 inva(0,0) = (
a(1,1)*
a(2,2)-
a(1,2)*
a(2,1))*t;
2289 inva(1,0) = (
a(0,2)*
a(2,1)-
a(0,1)*
a(2,2))*t;
2290 inva(2,0) = (
a(0,1)*
a(1,2)-
a(0,2)*
a(1,1))*t;
2292 inva(0,1) = (
a(1,2)*
a(2,0)-
a(1,0)*
a(2,2))*t;
2293 inva(1,1) = (
a(0,0)*
a(2,2)-
a(0,2)*
a(2,0))*t;
2294 inva(2,1) = (
a(0,2)*
a(1,0)-
a(0,0)*
a(1,2))*t;
2296 inva(0,2) = (
a(1,0)*
a(2,1)-
a(1,1)*
a(2,0))*t;
2297 inva(1,2) = (
a(0,1)*
a(2,0)-
a(0,0)*
a(2,1))*t;
2298 inva(2,2) = (
a(0,0)*
a(1,1)-
a(0,1)*
a(1,0))*t;
2308 "Matrix must be 3x2 or 2x1, "
2309 <<
"and the Vector must be sized with the rows. "
2310 <<
" J.Height() = " << J.
Height()
2311 <<
", J.Width() = " << J.
Width()
2312 <<
", n.Size() = " << n.
Size()
2315 const double *d = J.
Data();
2323 n(0) = d[1]*d[5] - d[2]*d[4];
2324 n(1) = d[2]*d[3] - d[0]*d[5];
2325 n(2) = d[0]*d[4] - d[1]*d[3];
2331 const int height = a.
Height();
2332 const int width = a.
Width();
2333 for (
int i = 0; i < height; i++)
2335 for (
int j = 0; j <= i; j++)
2338 for (
int k = 0; k < width; k++)
2340 temp +=
a(i,k) *
a(j,k);
2342 aat(j,i) = aat(i,j) = temp;
2349 for (
int i = 0; i < A.
Height(); i++)
2351 for (
int j = 0; j < i; j++)
2354 for (
int k = 0; k < A.
Width(); k++)
2356 t += D(k) * A(i, k) * A(j, k);
2364 for (
int i = 0; i < A.
Height(); i++)
2367 for (
int k = 0; k < A.
Width(); k++)
2369 t += D(k) * A(i, k) * A(i, k);
2377 for (
int i = 0; i < A.
Height(); i++)
2379 for (
int j = 0; j <= i; j++)
2382 for (
int k = 0; k < A.
Width(); k++)
2384 t += D(k) * A(i, k) * A(j, k);
2386 ADAt(j, i) = ADAt(i, j) =
t;
2397 mfem_error(
"MultABt(...): dimension mismatch");
2401 #ifdef MFEM_USE_LAPACK
2402 static char transa =
'N', transb =
'T';
2403 static double alpha = 1.0, beta = 0.0;
2406 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2407 B.
Data(), &n, &beta, ABt.
Data(), &m);
2409 const int ah = A.
Height();
2410 const int bh = B.
Height();
2411 const int aw = A.
Width();
2412 const double *ad = A.
Data();
2413 const double *bd = B.
Data();
2414 double *cd = ABt.
Data();
2418 const int ah = A.
Height();
2419 const int bh = B.
Height();
2420 const int aw = A.
Width();
2421 const double *ad = A.
Data();
2422 const double *bd = B.
Data();
2423 double *cd = ABt.
Data();
2425 for (
int j = 0; j < bh; j++)
2426 for (
int i = 0; i < ah; i++)
2429 const double *ap = ad + i;
2430 const double *bp = bd + j;
2431 for (
int k = 0; k < aw; k++)
2443 for (i = 0; i < A.
Height(); i++)
2444 for (j = 0; j < B.
Height(); j++)
2447 for (k = 0; k < A.
Width(); k++)
2449 d += A(i, k) * B(j, k);
2463 mfem_error(
"MultADBt(...): dimension mismatch");
2467 const int ah = A.
Height();
2468 const int bh = B.
Height();
2469 const int aw = A.
Width();
2470 const double *ad = A.
Data();
2471 const double *bd = B.
Data();
2472 const double *dd = D.
GetData();
2473 double *cd = ADBt.
Data();
2475 for (
int i = 0,
s = ah*bh; i <
s; i++)
2479 for (
int k = 0; k < aw; k++)
2482 for (
int j = 0; j < bh; j++)
2484 const double dk_bjk = dd[k] * bd[j];
2485 for (
int i = 0; i < ah; i++)
2487 cp[i] += ad[i] * dk_bjk;
2502 mfem_error(
"AddMultABt(...): dimension mismatch");
2506 #ifdef MFEM_USE_LAPACK
2507 static char transa =
'N', transb =
'T';
2508 static double alpha = 1.0, beta = 1.0;
2511 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2512 B.
Data(), &n, &beta, ABt.
Data(), &m);
2514 const int ah = A.
Height();
2515 const int bh = B.
Height();
2516 const int aw = A.
Width();
2517 const double *ad = A.
Data();
2518 const double *bd = B.
Data();
2519 double *cd = ABt.
Data();
2521 for (
int k = 0; k < aw; k++)
2524 for (
int j = 0; j < bh; j++)
2526 const double bjk = bd[j];
2527 for (
int i = 0; i < ah; i++)
2529 cp[i] += ad[i] * bjk;
2540 for (i = 0; i < A.
Height(); i++)
2541 for (j = 0; j < B.
Height(); j++)
2544 for (k = 0; k < A.
Width(); k++)
2546 d += A(i, k) * B(j, k);
2560 mfem_error(
"AddMultADBt(...): dimension mismatch");
2564 const int ah = A.
Height();
2565 const int bh = B.
Height();
2566 const int aw = A.
Width();
2567 const double *ad = A.
Data();
2568 const double *bd = B.
Data();
2569 const double *dd = D.
GetData();
2570 double *cd = ADBt.
Data();
2572 for (
int k = 0; k < aw; k++)
2575 for (
int j = 0; j < bh; j++)
2577 const double dk_bjk = dd[k] * bd[j];
2578 for (
int i = 0; i < ah; i++)
2580 cp[i] += ad[i] * dk_bjk;
2596 mfem_error(
"AddMult_a_ABt(...): dimension mismatch");
2600 #ifdef MFEM_USE_LAPACK
2601 static char transa =
'N', transb =
'T';
2603 static double beta = 1.0;
2606 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &m,
2607 B.
Data(), &n, &beta, ABt.
Data(), &m);
2609 const int ah = A.
Height();
2610 const int bh = B.
Height();
2611 const int aw = A.
Width();
2612 const double *ad = A.
Data();
2613 const double *bd = B.
Data();
2614 double *cd = ABt.
Data();
2616 for (
int k = 0; k < aw; k++)
2619 for (
int j = 0; j < bh; j++)
2621 const double bjk = a * bd[j];
2622 for (
int i = 0; i < ah; i++)
2624 cp[i] += ad[i] * bjk;
2635 for (i = 0; i < A.
Height(); i++)
2636 for (j = 0; j < B.
Height(); j++)
2639 for (k = 0; k < A.
Width(); k++)
2641 d += A(i, k) * B(j, k);
2654 mfem_error(
"MultAtB(...): dimension mismatch");
2658 #ifdef MFEM_USE_LAPACK
2659 static char transa =
'T', transb =
'N';
2660 static double alpha = 1.0, beta = 0.0;
2663 dgemm_(&transa, &transb, &m, &n, &k, &alpha, A.
Data(), &k,
2664 B.
Data(), &k, &beta, AtB.
Data(), &m);
2666 const int ah = A.
Height();
2667 const int aw = A.
Width();
2668 const int bw = B.
Width();
2669 const double *ad = A.
Data();
2670 const double *bd = B.
Data();
2671 double *cd = AtB.
Data();
2673 for (
int j = 0; j < bw; j++)
2675 const double *ap = ad;
2676 for (
int i = 0; i < aw; i++)
2679 for (
int k = 0; k < ah; k++)
2692 for (i = 0; i < A.
Width(); i++)
2693 for (j = 0; j < B.
Width(); j++)
2696 for (k = 0; k < A.
Height(); k++)
2698 d += A(k, i) * B(k, j);
2709 for (
int i = 0; i < A.
Height(); i++)
2711 for (
int j = 0; j < i; j++)
2714 for (
int k = 0; k < A.
Width(); k++)
2716 d += A(i,k) * A(j,k);
2718 AAt(i, j) += (d *=
a);
2722 for (
int k = 0; k < A.
Width(); k++)
2724 d += A(i,k) * A(i,k);
2732 for (
int i = 0; i < A.
Height(); i++)
2734 for (
int j = 0; j <= i; j++)
2737 for (
int k = 0; k < A.
Width(); k++)
2739 d += A(i,k) * A(j,k);
2741 AAt(i, j) = AAt(j, i) = a * d;
2748 for (
int i = 0; i < v.
Size(); i++)
2750 for (
int j = 0; j <= i; j++)
2752 vvt(i,j) = vvt(j,i) = v(i) * v(j);
2762 mfem_error(
"MultVWt(...): dimension mismatch");
2766 for (
int i = 0; i < v.
Size(); i++)
2768 const double vi = v(i);
2769 for (
int j = 0; j < w.
Size(); j++)
2771 VWt(i, j) = vi * w(j);
2778 const int m = v.
Size(), n = w.
Size();
2783 mfem_error(
"AddMultVWt(...): dimension mismatch");
2787 for (
int i = 0; i < m; i++)
2789 const double vi = v(i);
2790 for (
int j = 0; j < n; j++)
2792 VWt(i, j) += vi * w(j);
2799 const int n = v.
Size();
2804 mfem_error(
"AddMultVVt(...): dimension mismatch");
2808 for (
int i = 0; i < n; i++)
2810 const double vi = v(i);
2811 for (
int j = 0; j < i; j++)
2813 const double vivj = vi * v(j);
2817 VVt(i, i) += vi * vi;
2824 const int m = v.
Size(), n = w.
Size();
2829 mfem_error(
"AddMult_a_VWt(...): dimension mismatch");
2833 for (
int j = 0; j < n; j++)
2835 const double awj = a * w(j);
2836 for (
int i = 0; i < m; i++)
2838 VWt(i, j) += v(i) * awj;
2846 "incompatible dimensions!");
2848 const int n = v.
Size();
2849 for (
int i = 0; i < n; i++)
2851 double avi = a * v(i);
2852 for (
int j = 0; j < i; j++)
2854 const double avivj = avi * v(j);
2858 VVt(i, i) += avi * v(i);
2865 #ifdef MFEM_USE_LAPACK
2872 for (
int i = 0; i < m; i++)
2877 double a = std::abs(data[piv+i*m]);
2878 for (
int j = i+1; j < m; j++)
2880 const double b = std::abs(data[j+i*m]);
2891 for (
int j = 0; j < m; j++)
2893 mfem::Swap<double>(data[i+j*m], data[piv+j*m]);
2898 if (abs(data[i + i*m]) <= TOL)
2903 const double a_ii_inv = 1.0 / data[i+i*m];
2904 for (
int j = i+1; j < m; j++)
2906 data[j+i*m] *= a_ii_inv;
2908 for (
int k = i+1; k < m; k++)
2910 const double a_ik = data[i+k*m];
2911 for (
int j = i+1; j < m; j++)
2913 data[j+k*m] -= a_ik * data[j+i*m];
2925 for (
int i=0; i<m; i++)
2929 det *= -
data[m * i + i];
2933 det *=
data[m * i + i];
2944 for (
int k = 0; k < n; k++)
2947 for (
int i = 0; i < m; i++)
2949 double x_i = x[i] * data[i+i*m];
2950 for (
int j = i+1; j < m; j++)
2952 x_i += x[j] * data[i+j*m];
2957 for (
int i = m-1; i >= 0; i--)
2960 for (
int j = 0; j < i; j++)
2962 x_i += x[j] * data[i+j*m];
2967 for (
int i = m-1; i >= 0; i--)
2969 mfem::Swap<double>(x[i], x[ipiv[i]-
ipiv_base]);
2980 for (
int k = 0; k < n; k++)
2983 for (
int i = 0; i < m; i++)
2985 mfem::Swap<double>(x[i], x[ipiv[i]-
ipiv_base]);
2988 for (
int j = 0; j < m; j++)
2990 const double x_j = x[j];
2991 for (
int i = j+1; i < m; i++)
2993 x[i] -= data[i+j*m] * x_j;
3005 for (
int k = 0; k < n; k++)
3007 for (
int j = m-1; j >= 0; j--)
3009 const double x_j = ( x[j] /= data[j+j*m] );
3010 for (
int i = 0; i < j; i++)
3012 x[i] -= data[i+j*m] * x_j;
3021 #ifdef MFEM_USE_LAPACK
3024 if (m > 0 && n > 0) {
dgetrs_(&trans, &m, &n,
data, &m,
ipiv, X, &m, &info); }
3025 MFEM_VERIFY(!info,
"LAPACK: error in DGETRS");
3036 #ifdef MFEM_USE_LAPACK
3037 char n_ch =
'N', side =
'R', u_ch =
'U', l_ch =
'L';
3041 dtrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&alpha,
data,&m,X,&n);
3042 dtrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&alpha,
data,&m,X,&n);
3048 for (
int k = 0; k < n; k++)
3050 for (
int j = 0; j < m; j++)
3052 const double x_j = ( x[j*n] /=
data[j+j*m]);
3053 for (
int i = j+1; i < m; i++)
3055 x[i*n] -=
data[j + i*m] * x_j;
3063 for (
int k = 0; k < n; k++)
3065 for (
int j = m-1; j >= 0; j--)
3067 const double x_j = x[j*n];
3068 for (
int i = 0; i < j; i++)
3070 x[i*n] -=
data[j + i*m] * x_j;
3078 for (
int k = 0; k < n; k++)
3080 for (
int i = m-1; i >= 0; --i)
3095 for (
int k = 0; k < m; k++)
3097 const double minus_x_k = -( x[k] = 1.0/data[k+k*m] );
3098 for (
int i = 0; i < k; i++)
3100 x[i] = data[i+k*m] * minus_x_k;
3102 for (
int j = k-1; j >= 0; j--)
3104 const double x_j = ( x[j] /= data[j+j*m] );
3105 for (
int i = 0; i < j; i++)
3107 x[i] -= data[i+j*m] * x_j;
3115 for (
int j = 0; j < k; j++)
3117 const double minus_L_kj = -data[k+j*m];
3118 for (
int i = 0; i <= j; i++)
3120 X[i+j*m] += X[i+k*m] * minus_L_kj;
3122 for (
int i = j+1; i < m; i++)
3124 X[i+j*m] = X[i+k*m] * minus_L_kj;
3128 for (
int k = m-2; k >= 0; k--)
3130 for (
int j = 0; j < k; j++)
3132 const double L_kj = data[k+j*m];
3133 for (
int i = 0; i < m; i++)
3135 X[i+j*m] -= X[i+k*m] * L_kj;
3140 for (
int k = m-1; k >= 0; k--)
3145 for (
int i = 0; i < m; i++)
3147 Swap<double>(X[i+k*m], X[i+piv_k*m]);
3154 const double *X1,
double *X2)
3157 for (
int k = 0; k < r; k++)
3159 for (
int j = 0; j < m; j++)
3161 const double x1_jk = X1[j+k*m];
3162 for (
int i = 0; i < n; i++)
3164 X2[i+k*n] -= A21[i+j*n] * x1_jk;
3171 int m,
int n,
double *A12,
double *A21,
double *A22)
const
3177 for (
int j = 0; j < m; j++)
3179 const double u_jj_inv = 1.0/data[j+j*m];
3180 for (
int i = 0; i < n; i++)
3182 A21[i+j*n] *= u_jj_inv;
3184 for (
int k = j+1; k < m; k++)
3186 const double u_jk = data[j+k*m];
3187 for (
int i = 0; i < n; i++)
3189 A21[i+k*n] -= A21[i+j*n] * u_jk;
3194 SubMult(m, n, n, A21, A12, A22);
3198 double *B1,
double *B2)
const
3203 SubMult(m, n, r, L21, B1, B2);
3207 const double *X2,
double *Y1)
const
3210 SubMult(n, m, r, U12, X2, Y1);
3219 MFEM_ASSERT(
height ==
width,
"not a square matrix");
3229 MFEM_ASSERT(
height ==
width,
"not a square matrix");
3237 MFEM_ASSERT(a,
"DenseMatrix is not given");
3238 const double *adata = a->data;
3240 for (
int i = 0; i <
s; i++)
3242 lu.
data[i] = adata[i];
3255 MFEM_VERIFY(mat.
height == mat.
width,
"DenseMatrix is not square!");
3271 MFEM_VERIFY(p != NULL,
"Operator is not a DenseMatrix!");
3277 for (
int row = 0; row <
height; row++)
3300 for (
int i = 0; i <
width; i++)
3322 #ifdef MFEM_USE_LAPACK
3328 &qwork, &lwork, &info);
3330 lwork = (int) qwork;
3331 work =
new double[lwork];
3337 : mat(other.mat), EVal(other.EVal), EVect(other.EVect), ev(NULL, other.n),
3340 #ifdef MFEM_USE_LAPACK
3343 lwork = other.lwork;
3345 work =
new double[lwork];
3352 if (mat.
Width() != n)
3354 mfem_error(
"DenseMatrixEigensystem::Eval(): dimension mismatch");
3358 #ifdef MFEM_USE_LAPACK
3361 work, &lwork, &info);
3365 mfem::err <<
"DenseMatrixEigensystem::Eval(): DSYEV error code: "
3370 mfem_error(
"DenseMatrixEigensystem::Eval(): Compiled without LAPACK");
3376 #ifdef MFEM_USE_LAPACK
3396 void DenseMatrixSVD::Init()
3398 #ifdef MFEM_USE_LAPACK
3407 NULL, &n, &qwork, &lwork, &info);
3409 lwork = (int) qwork;
3410 work =
new double[lwork];
3412 mfem_error(
"DenseMatrixSVD::Init(): Compiled without LAPACK");
3425 #ifdef MFEM_USE_LAPACK
3427 NULL, &n, work, &lwork, &info);
3431 mfem::err <<
"DenseMatrixSVD::Eval() : info = " << info << endl;
3435 mfem_error(
"DenseMatrixSVD::Eval(): Compiled without LAPACK");
3441 #ifdef MFEM_USE_LAPACK
3451 const int *I = elem_dof.
GetI(), *J = elem_dof.
GetJ(), *dofs;
3452 const double *d_col = tdata;
3455 const double *xp = x;
3459 for (
int i = 0; i < ne; i++)
3462 for (
int col = 0; col < n; col++)
3464 x_col = xp[dofs[col]];
3465 for (
int row = 0; row < n; row++)
3467 yp[dofs[row]] += x_col*d_col[row];
3476 for (
int i = 0; i < ne; i++)
3479 x_col = xp[dofs[0]];
3480 for (
int row = 0; row < n; row++)
3482 ye(row) = x_col*d_col[row];
3485 for (
int col = 1; col < n; col++)
3487 x_col = xp[dofs[col]];
3488 for (
int row = 0; row < n; row++)
3490 ye(row) += x_col*d_col[row];
3494 for (
int row = 0; row < n; row++)
3496 yp[dofs[row]] += ye(row);
3505 for (
int i=0; i<
s; i++)
3521 const int m = Mlu.
SizeI();
3522 const int NE = Mlu.
SizeK();
3528 pivot_flag[0] =
true;
3529 bool *d_pivot_flag = pivot_flag.ReadWrite();
3533 for (
int i = 0; i < m; i++)
3538 double a = fabs(data_all(piv,i,e));
3539 for (
int j = i+1; j < m; j++)
3541 const double b = fabs(data_all(j,i,e));
3548 ipiv_all(i,e) = piv;
3552 for (
int j = 0; j < m; j++)
3554 mfem::kernels::internal::Swap<double>(data_all(i,j,e), data_all(piv,j,e));
3559 if (abs(data_all(i,i,e)) <= TOL)
3561 d_pivot_flag[0] =
false;
3564 const double a_ii_inv = 1.0 / data_all(i,i,e);
3565 for (
int j = i+1; j < m; j++)
3567 data_all(j,i,e) *= a_ii_inv;
3570 for (
int k = i+1; k < m; k++)
3572 const double a_ik = data_all(i,k,e);
3573 for (
int j = i+1; j < m; j++)
3575 data_all(j,k,e) -= a_ik * data_all(j,i,e);
3583 MFEM_ASSERT(pivot_flag.HostRead()[0],
"Batch LU factorization failed \n");
3589 const int m = Mlu.
SizeI();
3590 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. 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 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 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
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.
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)
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.
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
DenseMatrix & operator+=(const double *m)