14 template <
typename _Type>
18 m_minPivot(1.e-12), m_detSign(0), m_monitorDet(false) {
22 if((m_version !=
"lapack") && (m_version !=
"native")) {
24 problem =
"The DenseLinearSystem has been instantiated with an unrecognised\n";
25 problem +=
"request for a solver type. Options are 'native' or 'lapack'. \n";
30 template <
typename _Type>
32 if(
"lapack" == m_version) {
39 template <
typename _Type>
42 problem =
"The solve method for a DenseLinearSystem has not been implemented\n";
43 problem +=
"for the element type used here. \n";
49 void DenseLinearSystem<double>::solve_lapack() {
51 std::string problem =
"The DenseLinearSystem::solve_lapack method has been called\n";
52 problem +=
"but the compiler option -DLAPACK was not provided when\n";
53 problem +=
"the library was built and so LAPACK support is not available.";
54 throw ExceptionExternal(problem);
57 std::size_t N = m_pA -> nrows();
58 FortranData Af(*m_pA);
60 std::vector<int> pivots(N, 0);
64 LAPACK_DGESV(N, 1, Af.base(), N, &pivots[ 0 ], &(m_pB ->
operator[](0)), N, info);
66 std::string problem(
" The LAPACK::LU method has detected a failure \n");
67 throw ExceptionExternal(problem, info);
71 m_detSign = signature(pivots);
73 for(std::size_t i = 0; i < N; ++i) {
74 if(Af[ i * N + i ] < 0.0) {
85 void DenseLinearSystem<D_complex>::solve_lapack() {
87 std::string problem =
"The DenseLinearSystem::solve_lapack method has been called\n";
88 problem +=
"but the compiler option -DLAPACK was not provided when\n";
89 problem +=
"the library was built and so LAPACK support is not available.";
90 throw ExceptionExternal(problem);
93 std::size_t N = m_pA -> nrows();
94 FortranData Af(*m_pA);
96 std::vector<int> pivots(N, 0);
101 LAPACK_ZGESV(N, 1, Af.base(), N, &pivots[ 0 ], &
reinterpret_cast<double(&)[2]
>(m_pB ->
operator[](0))[0], N, info);
103 std::string problem(
" The LAPACK::LU method has detected a failure \n");
104 throw ExceptionExternal(problem, info);
111 template <
typename _Type>
112 void DenseLinearSystem<_Type>::solve_native() {
116 row_iter first_row(m_pA -> begin());
118 row_iter last_row(m_pA -> end());
120 elt_iter first_rhs(m_pB -> begin());
122 elt_iter last_rhs(m_pB -> end());
124 elt_iter current_rhs_elt(first_rhs);
126 for(row_iter current_row = first_row;
127 current_row != last_row;
128 ++current_row, ++current_rhs_elt) {
130 const std::size_t l = distance(first_row, current_row);
132 row_iter max_row = m_pA -> max_in_col(l, current_row, last_row);
134 if(current_row != max_row) {
143 elt_iter max_row_elt = max_row -> begin() + l;
144 for(elt_iter current_row_elt = current_row -> begin() + l;
145 current_row_elt != current_row -> end();
146 ++current_row_elt, ++max_row_elt) {
147 std::swap(*current_row_elt, *max_row_elt);
151 std::swap<_Type>(*current_rhs_elt, *(first_rhs + distance(first_row, max_row)));
154 const _Type diag_entry = *(current_row -> begin() + l);
156 if(std::abs(diag_entry) < m_minPivot) {
157 std::string problem(
"A pivot in NDMatrix.GJE is under the minimum tolerance => singular matrix. \n");
158 throw ExceptionRuntime(problem);
163 elt_iter elim_rhs(m_pB -> begin() + l + 1);
165 for(row_iter elim_row = current_row + 1;
166 elim_row != last_row;
167 ++elim_row, ++elim_rhs) {
169 const _Type mult = *(elim_row -> begin() + l) / diag_entry;
172 for(elt_iter col = elim_row -> begin() + l; col != elim_row -> end(); ++col) {
173 const unsigned col_offset(distance(elim_row -> begin(), col));
174 *col -= *(current_row -> begin() + col_offset) * mult;
177 *elim_rhs -= *current_rhs_elt * mult;
183 for(row_iter row = first_row; row != last_row; ++row) {
184 const unsigned l = distance(first_row, row);
185 if(lt(*(row -> begin() + l))) {
193 template <
typename _Type>
194 bool DenseLinearSystem<_Type>::lt(_Type value)
const {
196 problem =
"You've turned on monitoring of the sign of the determinant for a \n";
197 problem +=
"DenseLinearSystem whose elements are not of type <double>.\n";
198 throw ExceptionRuntime(problem);
202 template <
typename _Type>
203 int DenseLinearSystem<_Type>::signature(
const std::vector<int> &pivots)
const {
205 for(std::size_t i = 0; i < pivots.size(); ++i) {
206 if(pivots[ i ] - 1 !=
int(i)) {
213 template <
typename _Type>
214 void DenseLinearSystem<_Type >::backsub()
const {
216 row_riter rend_row(m_pA -> rend());
218 elt_riter rbegin_rhs(m_pB -> rbegin());
220 elt_riter current_rhs_elt(rbegin_rhs);
221 row_riter current_row(m_pA -> rbegin());
224 current_row != rend_row;
225 ++current_row, ++current_rhs_elt) {
227 elt_riter a_elt(current_row -> rbegin());
228 elt_riter b_elt(rbegin_rhs);
231 b_elt != current_rhs_elt;
233 sum += *a_elt * *b_elt;
236 *current_rhs_elt = (*current_rhs_elt - sum) / *a_elt;
240 template <
typename _Type>
245 template <
typename _Type>
Specification of the linear system class.
The collection of CppNoddy exceptions.
Some interface definitions for calling external fortran routines in LAPACK.
A linear system class for vector right-hand sides.
DenseLinearSystem(DenseMatrix< _Type > *m_pA, DenseVector< _Type > *m_pB, std::string which="native")
Constructor for a dense linear system object.
void set_monitor_det(bool flag)
Store the sign of the determinant of the LHS matrix every time a solve is requested on a real system.
int get_det_sign() const
Get the sign of the determinant of the LHS matrix from the linear system just computed.
void solve()
Solve the sparse system.
A matrix class that constructs a DENSE matrix as a row major std::vector of DenseVectors.
An DenseVector class – a dense vector object.
An exception to indicate that an error has been detected in an external (LAPACK) routine.
A generic runtime exception.
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...