18cgetrf_(
int *,
int *, std::complex<float> *,
int *,
int *,
int *);
20cgetrs_(
char *,
int *,
int *, std::complex<float> *,
int *,
int *,
21 std::complex<float> *,
int *,
int *);
23cgetri_(
int *, std::complex<float> *,
int *,
int *,
24 std::complex<float> *,
int *,
int *);
26ctrsm_(
char *,
char *,
char *,
char *,
int *,
int *, std::complex<float> *,
27 std::complex<float> *,
int *, std::complex<float> *,
int *);
29cpotrf_(
char *,
int *, std::complex<float> *,
int *,
int *);
32ctrtrs_(
char *,
char*,
char *,
int *,
int *, std::complex<float> *,
int *,
33 std::complex<float> *,
int *,
int *);
35cpotri_(
char *,
int *, std::complex<float> *,
int*,
int *);
38cpotrs_(
char *,
int *,
int *, std::complex<float> *,
int *,
39 std::complex<float> *,
int *,
int *);
40#elif defined MFEM_USE_DOUBLE
42zgetrf_(
int *,
int *, std::complex<double> *,
int *,
int *,
int *);
44zgetrs_(
char *,
int *,
int *, std::complex<double> *,
int *,
int *,
45 std::complex<double> *,
int *,
int *);
47zgetri_(
int *, std::complex<double> *,
int *,
int *,
48 std::complex<double> *,
int *,
int *);
50ztrsm_(
char *,
char *,
char *,
char *,
int *,
int *, std::complex<double> *,
51 std::complex<double> *,
int *, std::complex<double> *,
int *);
53zpotrf_(
char *,
int *, std::complex<double> *,
int *,
int *);
56ztrtrs_(
char *,
char*,
char *,
int *,
int *, std::complex<double> *,
int *,
57 std::complex<double> *,
int *,
int *);
59zpotri_(
char *,
int *, std::complex<double> *,
int*,
int *);
62zpotrs_(
char *,
int *,
int *, std::complex<double> *,
int *,
63 std::complex<double> *,
int *,
int *);
72 MFEM_ASSERT(
Op_Real_,
"ComplexDenseMatrix has no real part!");
78 MFEM_ASSERT(
Op_Imag_,
"ComplexDenseMatrix has no imaginary part!");
84 MFEM_ASSERT(
Op_Real_,
"ComplexDenseMatrix has no real part!");
85 return dynamic_cast<const DenseMatrix &
>(*Op_Real_);
90 MFEM_ASSERT(
Op_Imag_,
"ComplexDenseMatrix has no imaginary part!");
91 return dynamic_cast<const DenseMatrix &
>(*Op_Imag_);
100 real_t * data_r =
nullptr;
101 real_t * data_i =
nullptr;
108 for (
int j = 0; j<w; j++)
110 for (
int i = 0; i<h; i++)
112 data[i+j*
height] = data_r[i+j*h];
113 data[i+h+(j+h)*
height] = factor*data_r[i+j*h];
120 for (
int j = 0; j<w; j++)
122 for (
int i = 0; i<h; i++)
124 data[i+h+j*
height] = factor*data_i[i+j*h];
125 data[i+(j+h)*
height] = -data_i[i+j*h];
134 MFEM_VERIFY(
height ==
width,
"Matrix has to be square");
139 std::complex<real_t> * data =
new std::complex<real_t>[h*w];
146 for (
int i = 0; i < h*w; i++)
148 data[i] = std::complex<real_t> (data_r[i], data_i[i]);
154 for (
int i = 0; i < h*w; i++)
156 data[i] = std::complex<real_t> (data_r[i], 0.);
162 for (
int i = 0; i < h*w; i++)
164 data[i] = std::complex<real_t> (0., data_i[i]);
169 MFEM_ABORT(
"ComplexDenseMatrix has neither only a real nor an imag part");
172#ifdef MFEM_USE_LAPACK
173 int *ipiv =
new int[w];
175 std::complex<real_t> qwork, *work;
178#ifdef MFEM_USE_SINGLE
179 cgetrf_(&w, &w, data, &w, ipiv, &info);
180#elif defined MFEM_USE_DOUBLE
181 zgetrf_(&w, &w, data, &w, ipiv, &info);
183 MFEM_ABORT(
"Floating point type undefined");
187 mfem_error(
"DenseMatrix::Invert() : Error in ZGETRF");
190#ifdef MFEM_USE_SINGLE
191 cgetri_(&w, data, &w, ipiv, &qwork, &lwork, &info);
192#elif defined MFEM_USE_DOUBLE
193 zgetri_(&w, data, &w, ipiv, &qwork, &lwork, &info);
195 MFEM_ABORT(
"Floating point type undefined");
197 lwork = (int) qwork.real();
198 work =
new std::complex<real_t>[lwork];
200#ifdef MFEM_USE_SINGLE
201 cgetri_(&w, data, &w, ipiv, work, &lwork, &info);
202#elif defined MFEM_USE_DOUBLE
203 zgetri_(&w, data, &w, ipiv, work, &lwork, &info);
205 MFEM_ABORT(
"Floating point type undefined");
209 mfem_error(
"DenseMatrix::Invert() : Error in ZGETRI");
220 std::complex<real_t> ac,bc;
222 for (c = 0; c < n; c++)
224 a = std::abs(data[c+c*h]);
226 for (j = c + 1; j < n; j++)
228 b = std::abs(data[j+c*h]);
237 mfem_error(
"DenseMatrix::Invert() : singular matrix");
240 for (j = 0; j < n; j++)
246 ac = data[c+c*h] = fone / data[c+c*h];
247 for (j = 0; j < c; j++)
251 for (j++; j < n; j++)
255 for (i = 0; i < c; i++)
257 data[i+c*h] = ac * (bc = -data[i+c*h]);
258 for (j = 0; j < c; j++)
260 data[i+j*h] += bc * data[c+j*h];
262 for (j++; j < n; j++)
264 data[i+j*h] += bc * data[c+j*h];
267 for (i++; i < n; i++)
269 data[i+c*h] = ac * (bc = -data[i+c*h]);
270 for (j = 0; j < c; j++)
272 data[i+j*h] += bc * data[c+j*h];
274 for (j++; j < n; j++)
276 data[i+j*h] += bc * data[c+j*h];
281 for (c = n - 1; c >= 0; c--)
284 for (i = 0; i < n; i++)
298 for (
int k = 0; k < h*w; k++)
300 datac_r[k] = data[k].real();
301 datac_i[k] = data[k].imag();
317 MFEM_VERIFY(A.
Width() == B.
Height(),
"Incompatible matrix dimensions");
333 MFEM_VERIFY(C_r || C_i,
"Both real and imag parts are null");
380 MFEM_VERIFY(A.
Height() == B.
Height(),
"Incompatible matrix dimensions");
396 MFEM_VERIFY(C_r || C_i,
"Both real and imag parts are null");
441 std::complex<real_t> * x =
new std::complex<real_t>[m];
444 for (
int i = 0; i<m; i++)
446 x[i] = std::complex<real_t>(x_r[i], x_i[i]);
451 for (
int i = 0; i<m; i++)
453 x[i] = std::complex<real_t>(x_r[i], 0.);
458 for (
int i = 0; i<m; i++)
460 x[i] = std::complex<real_t>(0., x_i[i]);
465 MFEM_ABORT(
"ComplexFactors::RealToComplex:both real and imag part are null");
474 for (
int i = 0; i<m; i++)
476 x_r[i] = x[i].real();
477 x_i[i] = x[i].imag();
484 if (
data) {
return; }
485 MFEM_VERIFY(
data_r ||
data_i,
"ComplexFactors data not set");
493#ifdef MFEM_USE_LAPACK
495 MFEM_VERIFY(
data,
"Matrix data not set");
496#ifdef MFEM_USE_SINGLE
498#elif defined MFEM_USE_DOUBLE
504 std::complex<real_t> *data_ptr = this->
data;
505 for (
int i = 0; i < m; i++)
510 real_t a = std::abs(data_ptr[piv+i*m]);
511 for (
int j = i+1; j < m; j++)
513 const real_t b = std::abs(data_ptr[j+i*m]);
524 for (
int j = 0; j < m; j++)
531 if (abs(data_ptr[i + i*m]) <= TOL)
537 const std::complex<real_t> a_ii_inv = fone / data_ptr[i+i*m];
538 for (
int j = i+1; j < m; j++)
540 data_ptr[j+i*m] *= a_ii_inv;
542 for (
int k = i+1; k < m; k++)
544 const std::complex<real_t> a_ik = data_ptr[i+k*m];
545 for (
int j = i+1; j < m; j++)
547 data_ptr[j+k*m] -= a_ik * data_ptr[j+i*m];
558 std::complex<real_t> det(1.0,0.);
559 for (
int i=0; i<m; i++)
563 det *= -
data[m * i + i];
567 det *=
data[m * i + i];
576 for (
int k = 0; k < n; k++)
579 for (
int i = 0; i < m; i++)
581 std::complex<real_t> x_i = x[i] *
data[i+i*m];
582 for (
int j = i+1; j < m; j++)
584 x_i += x[j] *
data[i+j*m];
589 for (
int i = m-1; i >= 0; i--)
591 std::complex<real_t> x_i = x[i];
592 for (
int j = 0; j < i; j++)
594 x_i += x[j] *
data[i+j*m];
599 for (
int i = m-1; i >= 0; i--)
612 std::complex<real_t> *x = X;
613 for (
int k = 0; k < n; k++)
616 for (
int i = 0; i < m; i++)
621 for (
int j = 0; j < m; j++)
623 const std::complex<real_t> x_j = x[j];
624 for (
int i = j+1; i < m; i++)
626 x[i] -=
data[i+j*m] * x_j;
638 std::complex<real_t> *x = X;
640 for (
int k = 0; k < n; k++)
642 for (
int j = m-1; j >= 0; j--)
644 const std::complex<real_t> x_j = ( x[j] /=
data[j+j*m] );
645 for (
int i = 0; i < j; i++)
647 x[i] -=
data[i+j*m] * x_j;
658#ifdef MFEM_USE_LAPACK
662#ifdef MFEM_USE_SINGLE
664#elif defined MFEM_USE_DOUBLE
667 MFEM_ABORT(
"Floating point type undefined");
669 MFEM_VERIFY(!info,
"LAPACK: error in ZGETRS");
682 std::complex<real_t> * x = X;
683#ifdef MFEM_USE_LAPACK
684 char n_ch =
'N', side =
'R', u_ch =
'U', l_ch =
'L';
687 std::complex<real_t>
alpha(1.0,0.0);
688#ifdef MFEM_USE_SINGLE
689 ctrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&
alpha,
data,&m,X,&n);
690 ctrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&
alpha,
data,&m,X,&n);
691#elif defined MFEM_USE_DOUBLE
692 ztrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&
alpha,
data,&m,X,&n);
693 ztrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&
alpha,
data,&m,X,&n);
695 MFEM_ABORT(
"Floating point type undefined");
701 for (
int k = 0; k < n; k++)
703 for (
int j = 0; j < m; j++)
705 const std::complex<real_t> x_j = ( x[j*n] /=
data[j+j*m]);
706 for (
int i = j+1; i < m; i++)
708 x[i*n] -=
data[j + i*m] * x_j;
716 for (
int k = 0; k < n; k++)
718 for (
int j = m-1; j >= 0; j--)
720 const std::complex<real_t> x_j = x[j*n];
721 for (
int i = 0; i < j; i++)
723 x[i*n] -=
data[j + i*m] * x_j;
731 for (
int k = 0; k < n; k++)
733 for (
int i = m-1; i >= 0; --i)
748 std::complex<real_t> * x = X;
750 for (
int k = 0; k < m; k++)
752 const std::complex<real_t> minus_x_k = -( x[k] = fone/
data[k+k*m] );
753 for (
int i = 0; i < k; i++)
755 x[i] =
data[i+k*m] * minus_x_k;
757 for (
int j = k-1; j >= 0; j--)
759 const std::complex<real_t> x_j = ( x[j] /=
data[j+j*m] );
760 for (
int i = 0; i < j; i++)
762 x[i] -=
data[i+j*m] * x_j;
770 for (
int j = 0; j < k; j++)
772 const std::complex<real_t> minus_L_kj = -
data[k+j*m];
773 for (
int i = 0; i <= j; i++)
775 X[i+j*m] += X[i+k*m] * minus_L_kj;
777 for (
int i = j+1; i < m; i++)
779 X[i+j*m] = X[i+k*m] * minus_L_kj;
783 for (
int k = m-2; k >= 0; k--)
785 for (
int j = 0; j < k; j++)
787 const std::complex<real_t> L_kj =
data[k+j*m];
788 for (
int i = 0; i < m; i++)
790 X[i+j*m] -= X[i+k*m] * L_kj;
795 for (
int k = m-1; k >= 0; k--)
800 for (
int i = 0; i < m; i++)
814#ifdef MFEM_USE_LAPACK
817 MFEM_VERIFY(
data,
"Matrix data not set");
818#ifdef MFEM_USE_SINGLE
820#elif defined MFEM_USE_DOUBLE
823 MFEM_ABORT(
"Floating point type undefined");
829 for (
int j = 0; j<m; j++)
831 std::complex<real_t>
a(0.,0.);
832 for (
int k = 0; k<j; k++)
837 MFEM_VERIFY((
data[j+j*m] -
a).real() > 0.,
838 "CholeskyFactors::Factor: The matrix is not SPD");
840 data[j+j*m] = std::sqrt((
data[j+j*m] -
a).real());
842 if (
data[j + j*m].real() <= TOL) {
return false; }
844 for (
int i = j+1; i<m; i++)
846 a = std::complex<real_t>(0.,0.);
847 for (
int k = 0; k<j; k++)
860 std::complex<real_t> det(1.0,0.0);
861 for (
int i=0; i<m; i++)
863 det *=
data[i + i*m];
873 std::complex<real_t> *x = X;
874 for (
int k = 0; k < n; k++)
876 for (
int j = m-1; j >= 0; j--)
878 std::complex<real_t> x_j = x[j] *
data[j+j*m];
879 for (
int i = 0; i < j; i++)
881 x_j += x[i] *
data[j+i*m];
895 std::complex<real_t> *x = X;
896 for (
int k = 0; k < n; k++)
898 for (
int i = 0; i < m; i++)
900 std::complex<real_t> x_i = x[i] *
data[i+i*m];
901 for (
int j = i+1; j < m; j++)
903 x_i += x[j] * std::conj(
data[j+i*m]);
917 std::complex<real_t> *x = X;
918#ifdef MFEM_USE_LAPACK
924#ifdef MFEM_USE_SINGLE
926#elif defined MFEM_USE_DOUBLE
929 MFEM_ABORT(
"Floating point type undefined");
931 MFEM_VERIFY(!info,
"ComplexCholeskyFactors:LSolve:: info");
933 for (
int k = 0; k < n; k++)
936 for (
int j = 0; j < m; j++)
938 const std::complex<real_t> x_j = (x[j] /=
data[j+j*m]);
939 for (
int i = j+1; i < m; i++)
941 x[i] -=
data[i+j*m] * x_j;
955 std::complex<real_t> *x = X;
956#ifdef MFEM_USE_LAPACK
963#ifdef MFEM_USE_SINGLE
965#elif defined MFEM_USE_DOUBLE
968 MFEM_ABORT(
"Floating point type undefined");
970 MFEM_VERIFY(!info,
"ComplexCholeskyFactors:USolve:: info");
973 for (
int k = 0; k < n; k++)
975 for (
int j = m-1; j >= 0; j--)
977 const std::complex<real_t> x_j = ( x[j] /=
data[j+j*m] );
978 for (
int i = 0; i < j; i++)
980 x[i] -= std::conj(
data[j+i*m]) * x_j;
993#ifdef MFEM_USE_LAPACK
997#ifdef MFEM_USE_SINGLE
999#elif defined MFEM_USE_DOUBLE
1002 MFEM_ABORT(
"Floating point type undefined");
1004 MFEM_VERIFY(!info,
"ComplexCholeskyFactors:Solve:: info");
1018 std::complex<real_t> *x = X;
1019#ifdef MFEM_USE_LAPACK
1026 std::complex<real_t>
alpha(1.0,0.0);
1029#ifdef MFEM_USE_SINGLE
1030 ctrsm_(&side,&uplo,&transt,&diag,&n,&m,&
alpha,
data,&m,x,&n);
1031 ctrsm_(&side,&uplo,&
trans,&diag,&n,&m,&
alpha,
data,&m,x,&n);
1032#elif defined MFEM_USE_DOUBLE
1033 ztrsm_(&side,&uplo,&transt,&diag,&n,&m,&
alpha,
data,&m,x,&n);
1034 ztrsm_(&side,&uplo,&
trans,&diag,&n,&m,&
alpha,
data,&m,x,&n);
1036 MFEM_ABORT(
"Floating point type undefined");
1041 for (
int k = 0; k < n; k++)
1043 for (
int j = 0; j < m; j++)
1045 const std::complex<real_t> x_j = ( x[j*n] /=
data[j+j*m]);
1046 for (
int i = j+1; i < m; i++)
1048 x[i*n] -= std::conj(
data[i + j*m]) * x_j;
1055 for (
int k = 0; k < n; k++)
1057 for (
int j = m-1; j >= 0; j--)
1059 const std::complex<real_t> x_j = (x[j*n] /=
data[j+j*m]);
1060 for (
int i = 0; i < j; i++)
1062 x[i*n] -=
data[j + i*m] * x_j;
1076 std::complex<real_t> * X =
new std::complex<real_t>[m*m];
1077#ifdef MFEM_USE_LAPACK
1079 for (
int i = 0; i<m; i++)
1081 for (
int j = i; j<m; j++)
1083 X[j+i*m] =
data[j+i*m];
1088#ifdef MFEM_USE_SINGLE
1089 cpotri_(&uplo, &m, X, &m, &info);
1090#elif defined MFEM_USE_DOUBLE
1091 zpotri_(&uplo, &m, X, &m, &info);
1093 MFEM_ABORT(
"Floating point type undefined");
1095 MFEM_VERIFY(!info,
"ComplexCholeskyFactors:GetInverseMatrix:: info");
1097 for (
int i = 0; i<m; i++)
1099 for (
int j = i+1; j<m; j++)
1101 X[i+j*m] = std::conj(X[j+i*m]);
1107 for (
int k = 0; k<m; k++)
1109 X[k+k*m] = fone/
data[k+k*m];
1110 for (
int i = k+1; i < m; i++)
1112 std::complex<real_t>
s(0.,0.);
1113 for (
int j=k; j<i; j++)
1115 s -=
data[i+j*m] * X[j+k*m]/
data[i+i*m];
1120 for (
int i = 0; i < m; i++)
1122 for (
int j = i; j < m; j++)
1124 std::complex<real_t>
s(0.,0.);
1125 for (
int k=j; k<m; k++)
1127 s += X[k+i*m] * std::conj(X[k+j*m]);
1130 X[i+j*m] = std::conj(
s);
void UMult(int m, int n, real_t *X_r, real_t *X_i) const
void LSolve(int m, int n, real_t *X_r, real_t *X_i) const
virtual void GetInverseMatrix(int m, real_t *X_r, real_t *X_i) const
Assuming L.L^H = A factored data of size (m x m), compute X <- A^{-1}.
virtual void Solve(int m, int n, real_t *X_r, real_t *X_i) const
void USolve(int m, int n, real_t *X_r, real_t *X_i) const
virtual std::complex< real_t > Det(int m) const
void RightSolve(int m, int n, real_t *X_r, real_t *X_i) const
virtual bool Factor(int m, real_t TOL=0.0)
Compute the Cholesky factorization of the current matrix.
void LMult(int m, int n, real_t *X_r, real_t *X_i) const
Specialization of the ComplexOperator built from a pair of Dense Matrices. The purpose of this specia...
ComplexDenseMatrix(DenseMatrix *A_Real, DenseMatrix *A_Imag, bool ownReal, bool ownImag, Convention convention=HERMITIAN)
DenseMatrix * GetSystemMatrix() const
ComplexDenseMatrix * ComputeInverse()
virtual DenseMatrix & real()
Real or imaginary part accessor methods.
virtual DenseMatrix & imag()
std::complex< real_t > * data
void ComplexToReal(int m, const std::complex< real_t > *x, real_t *x_r, real_t *x_i) const
void SetComplexData(int m)
std::complex< real_t > * RealToComplex(int m, const real_t *x_r, const real_t *x_i) const
virtual void GetInverseMatrix(int m, real_t *X_r, real_t *X_i) const
Assuming L.U = P.A factored data of size (m x m), compute X <- A^{-1}.
void LSolve(int m, int n, real_t *X_r, real_t *X_i) const
void USolve(int m, int n, real_t *X_r, real_t *X_i) const
void RightSolve(int m, int n, real_t *X_r, real_t *X_i) const
virtual bool Factor(int m, real_t TOL=0.0)
Compute the LU factorization of the current matrix.
static const int ipiv_base
virtual void Solve(int m, int n, real_t *X_r, real_t *X_i) const
virtual std::complex< real_t > Det(int m) const
void Mult(int m, int n, real_t *X_r, real_t *X_i) const
bool hasRealPart() const
Check for existence of real or imaginary part of the operator.
@ HERMITIAN
Native convention for Hermitian operators.
Data type dense matrix using column-major storage.
real_t * Data() const
Returns the matrix data array.
int width
Dimension of the input / number of columns in the matrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int height
Dimension of the output / number of rows in the matrix.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void zgetrf_(int *, int *, std::complex< double > *, int *, int *, int *)
void ctrtrs_(char *, char *, char *, int *, int *, std::complex< float > *, int *, std::complex< float > *, int *, int *)
void cgetrf_(int *, int *, std::complex< float > *, int *, int *, int *)
void ztrsm_(char *, char *, char *, char *, int *, int *, std::complex< double > *, std::complex< double > *, int *, std::complex< double > *, int *)
void cpotrf_(char *, int *, std::complex< float > *, int *, int *)
void zpotri_(char *, int *, std::complex< double > *, int *, int *)
void zgetri_(int *, std::complex< double > *, int *, int *, std::complex< double > *, int *, int *)
void ztrtrs_(char *, char *, char *, int *, int *, std::complex< double > *, int *, std::complex< double > *, int *, int *)
void zpotrf_(char *, int *, std::complex< double > *, int *, int *)
void cpotri_(char *, int *, std::complex< float > *, int *, int *)
void cgetrs_(char *, int *, int *, std::complex< float > *, int *, int *, std::complex< float > *, int *, int *)
void ctrsm_(char *, char *, char *, char *, int *, int *, std::complex< float > *, std::complex< float > *, int *, std::complex< float > *, int *)
void cpotrs_(char *, int *, int *, std::complex< float > *, int *, std::complex< float > *, int *, int *)
void cgetri_(int *, std::complex< float > *, int *, int *, std::complex< float > *, int *, int *)
void zgetrs_(char *, int *, int *, std::complex< double > *, int *, int *, std::complex< double > *, int *, int *)
void zpotrs_(char *, int *, int *, std::complex< double > *, int *, std::complex< double > *, int *, int *)
void trans(const Vector &u, Vector &x)
void Swap(Array< T > &, Array< T > &)
void mfem_error(const char *msg)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void AddMult_a(real_t alpha, const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += alpha * B * C.
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.