aboutsummaryrefslogtreecommitdiff
path: root/src/elliptic/Jacobian.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/elliptic/Jacobian.cc')
-rw-r--r--src/elliptic/Jacobian.cc114
1 files changed, 92 insertions, 22 deletions
diff --git a/src/elliptic/Jacobian.cc b/src/elliptic/Jacobian.cc
index 603abac..8762434 100644
--- a/src/elliptic/Jacobian.cc
+++ b/src/elliptic/Jacobian.cc
@@ -6,7 +6,7 @@
//
// dense_Jacobian::dense_Jacobian
// dense_Jacobian::~dense_Jacobian
-// dense_Jacobian::zero
+// dense_Jacobian::zero_matrix
// dense_Jacobian::zero_row
// dense_Jacobian::solve_linear_system
//
@@ -47,7 +47,7 @@ using jtutil::error_exit;
#include "Jacobian.hh"
//#include "lapack.h"
//**************************************
-/* lapack.h -- C/C++ prototypes for (some) LAPACK routines */
+/* lapack.h -- C/C++ prototypes for (some) BLAS+LAPACK+wrapper routines */
/* $Id$ */
/*
@@ -60,6 +60,17 @@ using jtutil::error_exit;
extern "C" {
#endif
+/*
+ * ***** BLAS *****
+ */
+integer CCTK_FCALL
+ CCTK_FNAME(isamax)(const integer* N, const float SX[], const integer* incx);
+integer CCTK_FCALL
+ CCTK_FNAME(idamax)(const integer* N, const double DX[], const integer* incx);
+
+/*
+ * ***** LAPACK *****
+ */
void CCTK_FCALL
CCTK_FNAME(sgesv)(const integer* N, const integer* NRHS,
float A[], const int* LDA,
@@ -71,6 +82,25 @@ void CCTK_FCALL
integer IPIV[],
double B[], const integer* LDB, integer* info);
+/*
+ * ***** wrappers (for passing character-string args) *****
+ */
+/* norm_int = 0 for infinity-norm, 1 for 1-norm */
+void CCTK_FCALL
+ CCTK_FNAME(sgecon_wrapper)(const integer* norm_int,
+ const integer* N,
+ float A[], const integer* LDA,
+ const float* anorm, float* rcond,
+ float WORK[], integer IWORK[],
+ integer* info);
+void CCTK_FCALL
+ CCTK_FNAME(dgecon_wrapper)(const integer* norm_int,
+ const integer* N,
+ double A[], const integer* LDA,
+ const double* anorm, double* rcond,
+ double WORK[], integer IWORK[],
+ integer* info);
+
#ifdef __cplusplus
}; /* extern "C" */
#endif
@@ -98,7 +128,9 @@ Jacobian::Jacobian(patch_system& ps)
dense_Jacobian::dense_Jacobian(patch_system& ps)
: Jacobian(ps),
matrix_(0,NN()-1, 0,NN()-1),
- pivot_(new integer[NN()])
+ pivot_(new integer[NN()]),
+ iwork_(new integer[NN()]),
+ rwork_(new fp[4*NN()]) // no comma
{ }
//******************************************************************************
@@ -108,6 +140,8 @@ dense_Jacobian::dense_Jacobian(patch_system& ps)
//
dense_Jacobian::~dense_Jacobian()
{
+delete[] iwork_;
+delete[] rwork_;
delete[] pivot_;
}
@@ -116,7 +150,7 @@ delete[] pivot_;
//
// This function zeros a dense_Jacobian object.
//
-void dense_Jacobian::zero()
+void dense_Jacobian::zero_matrix()
{
for (int JJ = 0 ; JJ < NN() ; ++JJ)
{
@@ -144,43 +178,79 @@ void dense_Jacobian::zero_row(int II)
//
// This function solves the linear system J.x = rhs, with rhs and x
-// being nominal-grid gridfns. The computation is done using the LAPACK
-// [sd]gesv() subroutines; which modify the Jacobian matrix J in-place
-// for the LU decomposition.
+// being nominal-grid gridfns, using LU decomposition. It returns the
+// estimated infinity-norm condition number of the linear system, or
+// 0.0 if the matrix is numerically singular
//
-void dense_Jacobian::solve_linear_system(int rhs_gfn, int x_gfn)
+fp dense_Jacobian::solve_linear_system(int rhs_gfn, int x_gfn)
{
const fp *rhs = my_patch_system().gridfn_data(rhs_gfn);
fp *x = my_patch_system().gridfn_data(x_gfn);
+fp *A = matrix_.data_array();
+const integer zero = 0;
+const integer one = 1;
+const integer NRHS = 1;
+const integer N = NN();
+const integer N2 = NN() * NN();
+integer info;
+
+// compute the infinity-norm of the matrix A
+// ... posn = 1-origin index of A[] element with max absolute value
+#if defined(FP_IS_FLOAT)
+ const integer posn = CCTK_FNAME(isamax)(&N2, A, &one);
+#elif defined(FP_IS_DOUBLE)
+ const integer posn = CCTK_FNAME(idamax)(&N2, A, &one);
+#else
+ #error "don't know fp datatype!"
+#endif
+const fp A_infnorm = A[posn-1];
+
+// LU decompose and solve the linear system
//
-// [sd]gesv() use an "in out" design, where the same argument is used for
-// both rhs and x ==> first copy rhs to x so we can pass that to [sd]gesv()
+// ... [sd]gesv() use an "in out" design, where the same argument
+// is used for both rhs and x ==> we must first copy rhs to x
//
for (int II = 0 ; II < NN() ; ++II)
{
x[II] = rhs[II];
}
-
-integer N = NN();
-integer NRHS = 1;
-integer info;
-
-#ifdef FP_IS_FLOAT
- CCTK_FNAME(sgesv)(&N, &NRHS, matrix_.data_array(), &N, pivot_, x, &N, &info);
-#endif
-#ifdef FP_IS_DOUBLE
- CCTK_FNAME(dgesv)(&N, &NRHS, matrix_.data_array(), &N, pivot_, x, &N, &info);
+#if defined(FP_IS_FLOAT)
+ CCTK_FNAME(sgesv)(&N, &NRHS, A, &N, pivot_, x, &N, &info);
+#elif defined(FP_IS_DOUBLE)
+ CCTK_FNAME(dgesv)(&N, &NRHS, A, &N, pivot_, x, &N, &info);
+#else
+ #error "don't know fp datatype!"
#endif
-if (info != 0)
+if (info < 0)
then error_exit(ERROR_EXIT,
"\n"
"***** dense_Jacobian::solve_linear_system(rhs_gfn=%d, x_gfn=%d):\n"
-" error return info=%d from [sd]gesv() LAPACK routine!\n"
+" error return (bad argument) info=%d from [sd]gesv() LAPACK routine!\n"
,
rhs_gfn, x_gfn,
int(info)); /*NOTREACHED*/
+
+if (info > 0)
+ then return 0.0; // *** ERROR RETURN ***
+ // *** (singular matrix)
+
+// estimate infinity-norm condition number
+fp rcond;
+#if defined(FP_IS_FLOAT)
+ CCTK_FNAME(sgecon_wrapper)(&zero, &N, A, &N, &A_infnorm, &rcond,
+ rwork_, iwork_, &info);
+#elif defined(FP_IS_DOUBLE)
+ CCTK_FNAME(dgecon_wrapper)(&zero, &N, A, &N, &A_infnorm, &rcond,
+ rwork_, iwork_, &info);
+#else
+ #error "don't know fp datatype!"
+#endif
+if (rcond == 0.0)
+ then return 0.0; // *** ERROR RETURN ***
+ // *** (singular matrix)
+return 1.0/rcond;
}
//******************************************************************************