47 "This matrix is not square, the matrix MUST be square!",
48 OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
51 if (rhs.size()!=
nrow())
53 std::ostringstream error_message_stream;
55 <<
"The rhs vector is not the right size. It is " << rhs.size()
56 <<
", it should be " <<
nrow() << std::endl;
59 OOMPH_CURRENT_FUNCTION,
60 OOMPH_EXCEPTION_LOCATION);
77 Vector<std::complex<double> > &soln)
88 const unsigned long &j)
const 96 return std::complex<double>(0.0, 0.0);
101 const unsigned long &j)
105 return Matrixdata[
i];
110 "You can only write the diagonal components of a diagonal matrix",
111 OOMPH_CURRENT_FUNCTION,
112 OOMPH_EXCEPTION_LOCATION);
122 OOMPH_CURRENT_FUNCTION,
123 OOMPH_EXCEPTION_LOCATION);
126 Matrixdata.resize(N);
130 std::complex<double> z)
136 OOMPH_CURRENT_FUNCTION,
137 OOMPH_EXCEPTION_LOCATION);
140 Matrixdata.resize(N, z);
145 Vector<std::complex<double> > &result)
147 const unsigned N =
ncol();
151 std::ostringstream error_message_stream;
153 <<
"The x vector is not the right size. It is " << x.size()
154 <<
", it should be " << N << std::endl;
157 OOMPH_CURRENT_FUNCTION,
158 OOMPH_EXCEPTION_LOCATION);
162 for (
unsigned i=0;
i<
N;
i++)
164 result[
i] = Matrixdata[
i]*x[
i];
177 if((!Overwrite_matrix_storage) && (LU_factors!=0))
215 "This matrix is not square, the matrix MUST be square!",
216 OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
221 const double small_number=1.0e-20;
238 for(
unsigned long i=0;
i<
N;
i++)
241 for(
unsigned long j=0;j<M;j++)
243 double tmp = std::abs((*
this)(
i,j));
244 if(tmp > big) big = tmp;
249 OOMPH_CURRENT_FUNCTION,
250 OOMPH_EXCEPTION_LOCATION);
253 scaling[
i] = 1.0/big;
262 if(!Overwrite_matrix_storage)
266 LU_factors =
new std::complex<double>[N*M];
270 for(
unsigned long i=0;
i<(N*M);
i++)
272 LU_factors[
i] = Matrixdata[
i];
279 LU_factors = Matrixdata;
283 for(
unsigned long j=0;j<M;j++)
286 unsigned long imax=0;
288 for(
unsigned long i=0;
i<j;
i++)
290 std::complex<double> sum = LU_factors[M*
i+j];
291 for(
unsigned long k=0;k<
i;k++)
293 sum -= LU_factors[M*i+k]*LU_factors[M*k+j];
295 LU_factors[M*i+j] = sum;
299 double largest_entry=0.0;
300 for(
unsigned long i=j;
i<
N;
i++)
302 std::complex<double> sum = LU_factors[M*
i+j];
303 for(
unsigned long k=0;k<j;k++)
305 sum -= LU_factors[M*
i+k]*LU_factors[M*k+j];
307 LU_factors[M*
i+j] = sum;
309 double tmp = scaling[
i]*std::abs(sum);
310 if(tmp >= largest_entry)
320 for(
unsigned long k=0;k<
N;k++)
322 std::complex<double> tmp = LU_factors[M*imax+k];
323 LU_factors[M*imax+k] = LU_factors[M*j+k];
324 LU_factors[M*j+k] = tmp;
327 signature = -signature;
329 scaling[imax] = scaling[j];
334 if(LU_factors[M*j+j] == 0.0)
336 LU_factors[M*j+j] = small_number;
341 std::complex<double> tmp = 1.0/LU_factors[M*j+j];
342 for(
unsigned long i=j+1;
i<
N;
i++)
344 LU_factors[M*
i+j] *= tmp;
354 std::complex<double> determinant_mantissa(1.0,0.0);
355 std::complex<int> determinant_exponent(0,0);
356 for(
unsigned i=0;
i<
N;
i++)
359 std::complex<double> entry;
360 int iexp_real=0, iexp_imag=0;
361 entry = std::complex<double>(frexp(LU_factors[M*
i+
i].real(),&iexp_real),
362 frexp(LU_factors[M*
i+
i].imag(),&iexp_imag));
367 double temp_mantissa[4];
int temp_exp[4];
370 temp_mantissa[0] = determinant_mantissa.real()*entry.real();
371 temp_exp[0] = determinant_exponent.real() + iexp_real;
373 temp_mantissa[1] = determinant_mantissa.imag()*entry.imag();
374 temp_exp[1] = determinant_exponent.imag() + iexp_imag;
377 temp_mantissa[2] = determinant_mantissa.real()*entry.imag();
378 temp_exp[2] = determinant_exponent.real() + iexp_imag;
380 temp_mantissa[3] = determinant_mantissa.imag()*entry.real();
381 temp_exp[3] = determinant_exponent.imag() + iexp_real;
385 for(
unsigned i=0;
i<3;
i+=2)
388 if(temp_exp[
i] < temp_exp[
i+1])
391 int lower = temp_exp[
i];
394 for(
int index=lower;index<temp_exp[
i+1];++index)
396 temp_mantissa[
i] /= 2.0;
404 int lower = temp_exp[
i+1];
407 for(
int index=lower;index<temp_exp[
i];++index)
409 temp_mantissa[
i+1] /= 2.0;
417 determinant_mantissa = std::complex<double>(
418 temp_mantissa[0] - temp_mantissa[1],
419 temp_mantissa[2] + temp_mantissa[3]);
421 determinant_exponent= std::complex<int> (temp_exp[0],temp_exp[2]);
424 determinant_mantissa = std::complex<double>(
425 frexp(determinant_mantissa.real(),&iexp_real),
426 frexp(determinant_mantissa.imag(),&iexp_imag));
428 int temp_real = determinant_exponent.real() + iexp_real;
429 int temp_imag = determinant_exponent.imag() + iexp_imag;
431 determinant_exponent = std::complex<int>(temp_real,temp_imag);
437 if(std::abs(determinant_mantissa) > 0.0) {sign = 1;}
438 if(std::abs(determinant_mantissa) < 0.0) {sign = -1;}
457 "This matrix is not square, the matrix MUST be square!",
458 OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
463 std::ostringstream error_message_stream;
465 <<
"The rhs vector is not the right size. It is " << rhs.size()
466 <<
", it should be " <<
N << std::endl;
469 OOMPH_CURRENT_FUNCTION,
470 OOMPH_EXCEPTION_LOCATION);
475 "Index vector has not been allocated. Have you called ludecompse()\n",
476 OOMPH_CURRENT_FUNCTION,
477 OOMPH_EXCEPTION_LOCATION);
481 std::ostringstream error_message_stream;
483 <<
"The Index vector is not the right size. It is " << Index->size()
484 <<
", it should be " <<
N << std::endl;
487 OOMPH_CURRENT_FUNCTION,
488 OOMPH_EXCEPTION_LOCATION);
493 for(
unsigned i=0;
i<
N;
i++)
495 unsigned long ip = (*Index)[
i];
496 std::complex<double> sum = rhs[ip];
501 for(
unsigned long j=ii-1;j<
i;j++)
503 sum -= LU_factors[M*i+j]*rhs[j];
514 for (
long i=
long(N)-1;
i>=0;
i--)
516 std::complex<double> sum = rhs[
i];
517 for(
long j=
i+1;j<long(N);j++) sum -= LU_factors[M*
i+j]*rhs[j];
518 rhs[
i] = sum/LU_factors[M*
i+
i];
527 const Vector<std::complex<double> > &rhs,
535 "This matrix is not square, the matrix MUST be square!",
536 OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
541 std::ostringstream error_message_stream;
543 <<
"The rhs vector is not the right size. It is " << rhs.size()
544 <<
", it should be " <<
N << std::endl;
547 OOMPH_CURRENT_FUNCTION,
548 OOMPH_EXCEPTION_LOCATION);
553 std::ostringstream error_message_stream;
555 <<
"The x vector is not the right size. It is " << x.size()
556 <<
", it should be " <<
N << std::endl;
559 OOMPH_CURRENT_FUNCTION,
560 OOMPH_EXCEPTION_LOCATION);
570 for (
unsigned long i=0;
i<
N;
i++)
573 for (
unsigned long j=0;j<M;j++)
588 Vector<std::complex<double> > &soln)
594 std::ostringstream error_message_stream;
596 <<
"The x vector is not the right size. It is " << x.size()
597 <<
", it should be " << M << std::endl;
600 OOMPH_CURRENT_FUNCTION,
601 OOMPH_EXCEPTION_LOCATION);
612 for (
unsigned long i=0;
i<
N;
i++)
615 for (
unsigned long j=0;j<M;j++)
617 soln[
i] += Matrixdata[M*
i+j]*x[j];
629 const Vector<std::complex<double> > &x,
630 Vector<std::complex<double> > &soln)
637 std::ostringstream error_message_stream;
639 <<
"The x vector is not the right size. It is " << x.size()
640 <<
", it should be " <<
N << std::endl;
643 OOMPH_CURRENT_FUNCTION,
644 OOMPH_EXCEPTION_LOCATION);
648 if (soln.size() != M)
655 for (
unsigned long i=0;
i<M;
i++)
662 for (
unsigned long i=0;
i<
N;
i++)
664 for (
unsigned long j=0;j<M;j++)
666 soln[j] += Matrixdata[N*
i+j]*x[
i];
680 if ( this->
ncol() != matrix_in.
nrow() )
682 std::ostringstream error_message;
684 <<
"Matrix dimensions incompatable for matrix-matrix multiplication" 685 <<
"ncol() for first matrix:" << this->
ncol()
686 <<
"nrow() for second matrix: " << matrix_in.
nrow();
688 throw OomphLibError(error_message.str(), OOMPH_CURRENT_FUNCTION,
689 OOMPH_EXCEPTION_LOCATION);
694 unsigned long n_row = this->
nrow();
695 unsigned long m_col = matrix_in.
ncol();
698 result.
resize(n_row, m_col, 0.0);
703 unsigned long n_col=this->
ncol();
704 for (
unsigned long k=0; k<n_col; k++)
706 for (
unsigned long i=0;
i<n_row;
i++)
708 for (
unsigned long j=0; j<m_col; j++)
710 result(
i,j) += Matrixdata[m_col*
i+k] * matrix_in(k,j);
722 for (
unsigned long i=0;
i<
N;
i++)
724 for (
unsigned long j=0;j<M;j++)
726 Matrixdata[M*
i+j] = Matrixdata[M*
i+j]*c;
737 for (
unsigned long i=0;
i<
N;
i++)
739 for (
unsigned long j=0;j<M;j++)
741 Matrixdata[M*
i+j] = Matrixdata[M*
i+j]*c;
758 std::complex<double> *,
int *,
int *,
759 std::complex<double> *,
int *,
int *,
int *,
772 std::ostringstream error_message_stream;
773 error_message_stream <<
"Can only solve for quadratic matrices\n" 774 <<
"N, M " <<
N <<
" " << M << std::endl;
777 OOMPH_CURRENT_FUNCTION,
778 OOMPH_EXCEPTION_LOCATION);
788 if (Doc_stats_during_solve) doc=1;
792 int nnz_aux = (int)Nnz;
800 Value, Row_index, Column_start,
801 0, &n_aux, &transpose, &doc,
818 std::ostringstream error_message_stream;
819 error_message_stream <<
"Size of RHS doesn't match matrix size\n" 820 <<
"N, rhs.size() " <<
N <<
" " << rhs.size()
824 OOMPH_CURRENT_FUNCTION,
825 OOMPH_EXCEPTION_LOCATION);
829 std::ostringstream error_message_stream;
830 error_message_stream <<
"Can only solve for quadratic matrices\n" 831 <<
"N, M " <<
N <<
" " << M << std::endl;
834 OOMPH_CURRENT_FUNCTION,
835 OOMPH_EXCEPTION_LOCATION);
840 std::complex<double>* b=
new std::complex<double> [
N];
843 for (
unsigned long i=0;
i<
N;
i++) {b[
i]=rhs[
i];}
851 if (Doc_stats_during_solve) doc=1;
859 int nnz_aux = (int)Nnz;
865 Value, Row_index, Column_start,
866 b, &n_aux, &transpose, &doc,
870 for (
unsigned long i=0;i<
N;i++)
896 if (Doc_stats_during_solve) doc=1;
901 int nnz_aux = (int)Nnz;
907 Value, Row_index, Column_start,
908 0, &n_aux, &transpose, &doc,
918 const Vector<std::complex<double> >& rhs,
927 "This matrix is not square, the matrix MUST be square!",
928 OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
933 std::ostringstream error_message_stream;
935 <<
"The rhs vector is not the right size. It is " << rhs.size()
936 <<
", it should be " <<
N << std::endl;
939 OOMPH_CURRENT_FUNCTION,
940 OOMPH_EXCEPTION_LOCATION);
945 std::ostringstream error_message_stream;
947 <<
"The x vector is not the right size. It is " << x.size()
948 <<
", it should be " <<
N << std::endl;
951 OOMPH_CURRENT_FUNCTION,
952 OOMPH_EXCEPTION_LOCATION);
956 unsigned long r_n =
residual.size();
963 for (
unsigned i=0;
i<
N;
i++)
968 for (
unsigned long j=0;j<
N;j++)
970 for (
long k=Column_start[j];k<Column_start[j+1];k++)
972 unsigned long i=Row_index[k];
973 std::complex<double> a_ij=Value[k];
983 Vector<std::complex<double> > &soln)
990 std::ostringstream error_message_stream;
992 <<
"The x vector is not the right size. It is " << x.size()
993 <<
", it should be " << M << std::endl;
996 OOMPH_CURRENT_FUNCTION,
997 OOMPH_EXCEPTION_LOCATION);
1001 if (soln.size() !=
N)
1006 for (
unsigned i=0;
i<
N;
i++)
1011 for (
unsigned long j=0;j<
N;j++)
1013 for (
long k=Column_start[j];k<Column_start[j+1];k++)
1015 unsigned long i = Row_index[k];
1016 std::complex<double> a_ij = Value[k];
1017 soln[
i] += a_ij*x[j];
1029 const Vector<std::complex<double> > &x,
1030 Vector<std::complex<double> > &soln)
1037 std::ostringstream error_message_stream;
1038 error_message_stream
1039 <<
"The x vector is not the right size. It is " << x.size()
1040 <<
", it should be " <<
N << std::endl;
1043 OOMPH_CURRENT_FUNCTION,
1044 OOMPH_EXCEPTION_LOCATION);
1048 if (soln.size() != M)
1055 for (
unsigned long i=0;
i<M;
i++)
1061 for (
unsigned long i=0;
i<
N;
i++)
1064 for (
long k=Column_start[
i];k<Column_start[
i+1];k++)
1066 unsigned long j=Row_index[k];
1067 std::complex<double> a_ij=Value[k];
1089 std::ostringstream error_message_stream;
1090 error_message_stream <<
"Can only solve for quadratic matrices\n" 1091 <<
"N, M " <<
N <<
" " << M << std::endl;
1094 OOMPH_CURRENT_FUNCTION,
1095 OOMPH_EXCEPTION_LOCATION);
1105 if (Doc_stats_during_solve) doc=1;
1109 int nnz_aux=int(Nnz);
1117 Value, Column_index, Row_start,
1118 0, &n_aux, &transpose, &doc,
1135 std::ostringstream error_message_stream;
1136 error_message_stream <<
"Size of RHS doesn't match matrix size\n" 1137 <<
"N, rhs.size() " <<
N <<
" " << rhs.size()
1141 OOMPH_CURRENT_FUNCTION,
1142 OOMPH_EXCEPTION_LOCATION);
1146 std::ostringstream error_message_stream;
1147 error_message_stream <<
"Can only solve for quadratic matrices\n" 1148 <<
"N, M " <<
N <<
" " << M << std::endl;
1151 OOMPH_CURRENT_FUNCTION,
1152 OOMPH_EXCEPTION_LOCATION);
1157 std::complex<double> * b=
new std::complex<double> [
N];
1160 for (
unsigned long i=0;
i<
N;
i++) {b[
i]=rhs[
i];}
1168 if (Doc_stats_during_solve) doc=1;
1175 int nnz_aux=int(Nnz);
1181 Value, Column_index, Row_start,
1182 b, &n_aux, &transpose, &doc,
1186 for (
unsigned long i=0;i<
N;i++)
1211 if (Doc_stats_during_solve) doc=1;
1215 int nnz_aux=int(Nnz);
1221 Value, Column_index, Row_start,
1222 0, &n_aux, &transpose, &doc,
1232 const Vector<std::complex<double> > &rhs,
1240 std::ostringstream error_message_stream;
1241 error_message_stream
1242 <<
"The rhs vector is not the right size. It is " << rhs.size()
1243 <<
", it should be " <<
N << std::endl;
1246 OOMPH_CURRENT_FUNCTION,
1247 OOMPH_EXCEPTION_LOCATION);
1252 std::ostringstream error_message_stream;
1253 error_message_stream
1254 <<
"The x vector is not the right size. It is " << x.size()
1255 <<
", it should be " << M << std::endl;
1258 OOMPH_CURRENT_FUNCTION,
1259 OOMPH_EXCEPTION_LOCATION);
1268 for (
unsigned long i=0;
i<
N;
i++)
1271 for (
long k=Row_start[
i];k<Row_start[
i+1];k++)
1273 unsigned long j=Column_index[k];
1274 std::complex<double> a_ij=Value[k];
1285 const Vector<std::complex<double> > &x,
1286 Vector<std::complex<double> > &soln)
1292 std::ostringstream error_message_stream;
1293 error_message_stream
1294 <<
"The x vector is not the right size. It is " << x.size()
1295 <<
", it should be " << M << std::endl;
1298 OOMPH_CURRENT_FUNCTION,
1299 OOMPH_EXCEPTION_LOCATION);
1303 if (soln.size() !=
N)
1308 for (
unsigned long i=0;
i<
N;
i++)
1311 for (
long k=Row_start[
i];k<Row_start[
i+1];k++)
1313 unsigned long j=Column_index[k];
1314 std::complex<double> a_ij=Value[k];
1328 const Vector<std::complex<double> > &x,
1329 Vector<std::complex<double> > &soln)
1336 std::ostringstream error_message_stream;
1337 error_message_stream
1338 <<
"The x vector is not the right size. It is " << x.size()
1339 <<
", it should be " <<
N << std::endl;
1342 OOMPH_CURRENT_FUNCTION,
1343 OOMPH_EXCEPTION_LOCATION);
1347 if (soln.size() != M)
1354 for (
unsigned long i=0;
i<M;
i++)
1360 for (
unsigned long i=0;
i<
N;
i++)
1362 for (
long k=Row_start[
i];k<Row_start[
i+1];k++)
1364 unsigned long j=Column_index[k];
1365 std::complex<double> a_ij=Value[k];
void residual(const Vector< std::complex< double > > &x, const Vector< std::complex< double > > &b, Vector< std::complex< double > > &residual)
Find the residual to x of Ax=b, i.e. r=b-Ax.
void lubksub(Vector< std::complex< double > > &rhs)
LU back solve for given RHS.
void multiply_transpose(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &soln)
Multiply the transposed matrix by the vector x: soln=A^T x.
void residual(const Vector< std::complex< double > > &x, const Vector< std::complex< double > > &b, Vector< std::complex< double > > &residual)
Find the residulal to x of Ax=b, ie r=b-Ax.
int ludecompose()
LU decomposition using SuperLU.
void resize(const unsigned &N, const unsigned &M)
unsigned long ncol() const
Return the number of columns of the matrix.
void multiply_transpose(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &soln)
Multiply the transposed matrix by the vector x: soln=A^T x.
virtual std::complex< double > operator()(const unsigned long &i, const unsigned long &j) const
Round brackets to give access as a(i,j) for read only (we're not providing a general interface for co...
int ludecompose()
LU decomposition using SuperLU.
void multiply_transpose(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &soln)
Multiply the transposed matrix by the vector x: soln=A^T x.
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
int ludecompose()
Overload the LU decomposition. For this storage scheme the matrix storage will be over-writeen by its...
void clean_up_memory()
LU clean up (perhaps this should happen in the destructor)
void clean_up_memory()
LU clean up (perhaps this should happen in the destructor)
void multiply(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &soln)
Multiply the matrix by the vector x: soln=Ax.
void residual(const Vector< std::complex< double > > &x, const Vector< std::complex< double > > &rhs, Vector< std::complex< double > > &residual)
Find the residual of Ax=b, ie r=b-Ax for the "solution" x.
int superlu_complex(int *, int *, int *, int *, std::complex< double > *, int *, int *, std::complex< double > *, int *, int *, int *, void *, int *)
virtual void residual(const Vector< std::complex< double > > &x, const Vector< std::complex< double > > &b, Vector< std::complex< double > > &residual)=0
Find the residual, i.e. r=b-Ax the residual.
void multiply(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &result)
Multiply the matrix by the vector x: soln=Ax.
void lubksub(Vector< std::complex< double > > &rhs)
Overload the LU back substitution. Note that the rhs will be overwritten with the solution vector...
virtual ~DenseComplexMatrix()
Destructor, delete the storage for Index vector and LU storage (if any)
void lubksub(Vector< std::complex< double > > &rhs)
LU back solve for given RHS.
virtual void lubksub(Vector< std::complex< double > > &rhs)
LU backsubstitue a previously LU-decomposed matrix; The passed rhs will be over-written with the solu...
unsigned long nrow() const
Return the number of rows of the matrix.
void multiply(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &soln)
Multiply the matrix by the vector x: soln=Ax.
void scale(const double &c)
Scale this matrix by a double c.
virtual void solve(Vector< std::complex< double > > &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)...
virtual int ludecompose()
LU decomposition of the matrix using the appropriate linear solver. Return the sign of the determinan...
Class of matrices containing double complex, and stored as a DenseMatrix<complex<double> >...
void multiply(const Vector< std::complex< double > > &x, Vector< std::complex< double > > &soln)
Multiply the matrix by the vector x: soln=Ax.
virtual unsigned long ncol() const =0
Return the number of columns of the matrix.
void resize(const unsigned long &n)