SparseCholeskyFactorisation.cxx
1 // Copyright (C) 2010 Marc DuruflĂ©
2 //
3 // This file is part of the linear-algebra library Seldon,
4 // http://seldon.sourceforge.net/.
5 //
6 // Seldon is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your option)
9 // any later version.
10 //
11 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
14 // more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with Seldon. If not, see http://www.gnu.org/licenses/.
18 
19 #ifndef SELDON_FILE_SPARSE_CHOLESKY_FACTORISATION_CXX
20 
21 
22 #include "SparseCholeskyFactorisation.hxx"
23 
24 namespace Seldon
25 {
26 
28 
33  template<class T, class Prop, class Allocator>
35  int print_level)
36  {
37  int n = A.GetN();
38  T t, s, fact;
39  int j_col, jrow, index_lu, jpos;
40  Vector<T> Row_Val(n);
41  IVect Index(n), Row_Ind(n);
42  Row_Val.Fill(0);
43  Row_Ind.Fill(-1);
44 
45  Index.Fill(-1);
46 
47  // conversion to unsymmetric matrix
49  Copy(A, B);
50 
51  // A is cleared
52  A.Clear();
53  A.Reallocate(n, n);
54 
55  // Main loop over rows.
56  T zero, one;
57  SetComplexZero(zero);
58  SetComplexOne(one);
59  int new_percent = 0, old_percent = 0;
60  for (int i_row = 0; i_row < n; i_row++)
61  {
62  // Progress bar if print level is high enough.
63  if (print_level > 0)
64  {
65  new_percent = int(double(i_row) / double(n-1) * 78.);
66  for (int percent = old_percent; percent < new_percent; percent++)
67  {
68  cout << "#";
69  cout.flush();
70  }
71 
72  old_percent = new_percent;
73  }
74 
75  int size_row = B.GetRowSize(i_row);
76 
77  // we are separating lower from upper part
78  int length_lower = 0, length_upper = 1;
79  Row_Ind(i_row) = i_row;
80  Row_Val(i_row) = zero;
81  Index(i_row) = i_row;
82 
83  for (int j = 0; j < size_row; j++)
84  {
85  int k = B.Index(i_row, j);
86  t = B.Value(i_row, j);
87  if (k < i_row)
88  {
89  Row_Ind(length_lower) = k;
90  Row_Val(length_lower) = t;
91  Index(k) = length_lower;
92  length_lower++;
93  }
94  else if (k == i_row)
95  Row_Val(i_row) = t;
96  else
97  {
98  jpos = i_row + length_upper;
99  Row_Ind(jpos) = k;
100  Row_Val(jpos) = t;
101  Index(k) = jpos;
102  length_upper++;
103  }
104  }
105 
106  B.ClearRow(i_row);
107 
108  j_col = 0;
109  int length = 0;
110 
111  // previous rows are eliminated
112  while (j_col < length_lower)
113  {
114  jrow = Row_Ind(j_col);
115 
116  // we search first element in lower part
117  int k = j_col;
118  for (int j = (j_col+1) ; j < length_lower; j++)
119  {
120  if (Row_Ind(j) < jrow)
121  {
122  jrow = Row_Ind(j);
123  k = j;
124  }
125  }
126 
127 
128  if (k != j_col)
129  {
130  // if k different from j_col, we are exchanging positions
131  int j = Row_Ind(j_col);
132  Row_Ind(j_col) = Row_Ind(k);
133  Row_Ind(k) = j;
134 
135  Index(jrow) = j_col;
136  Index(j) = k;
137 
138  s = Row_Val(j_col);
139  Row_Val(j_col) = Row_Val(k);
140  Row_Val(k) = s;
141  }
142 
143  // zero out element in row
144  Index(jrow) = -1;
145  fact = Row_Val(j_col) * A.Value(jrow, 0);
146 
147  // combine current row and row jrow
148  for (int k = 1; k < A.GetRowSize(jrow); k++)
149  {
150  s = fact * A.Value(jrow, k);
151  int j = A.Index(jrow, k);
152 
153  jpos = Index(j);
154  if (j >= i_row)
155  {
156  // dealing with upper part
157  if (jpos == -1)
158  {
159  // this is a fill-in element
160  int i = i_row + length_upper;
161  Row_Ind(i) = j;
162  Index(j) = i;
163  Row_Val(i) = -s;
164  length_upper++;
165  }
166  else
167  {
168  // this is not a fill-in element
169  Row_Val(jpos) -= s;
170  }
171  }
172  else
173  {
174  // dealing with lower part.
175  if (jpos == -1)
176  {
177  // this is a fill-in element
178  Row_Ind(length_lower) = j;
179  Index(j) = length_lower;
180  Row_Val(length_lower) = -s;
181  length_lower++;
182  }
183  else
184  {
185  // this is not a fill-in element
186  Row_Val(jpos) -= s;
187  }
188  }
189  }
190 
191  // store this pivot element
192  // (from left to right -- no danger of overlap
193  // with the working elements in L (pivots).
194  Row_Val(length) = fact;
195  Row_Ind(length) = jrow;
196  ++length;
197  j_col++;
198  }
199 
200  for (int k = 0; k < length_upper; k++)
201  Index(Row_Ind(i_row+k )) = -1;
202 
203  // now we can store the uppert part of row
204  size_row = length_upper;
205  A.ReallocateRow(i_row, length_upper);
206 
207  // We store inverse of square root of diagonal element of u.
208  if (Row_Val(i_row) <= 0)
209  {
210  cout << "Error during Cholesky factorization " << endl;
211  cout << "Matrix must be definite positive " << endl;
212  cout << "but diagonal element of row " << i_row
213  << "is equal to " << Row_Val(i_row) << endl;
214 
215  throw WrongArgument("GetCholesky", "Negative diagonal");
216  }
217 
218  A.Value(i_row, 0) = one / Row_Val(i_row);
219  A.Index(i_row, 0) = i_row;
220  index_lu = 1;
221 
222  // and extra-diagonal terms
223  for (int k = (i_row+1); k < (i_row+length_upper); k++)
224  {
225  A.Index(i_row, index_lu) = Row_Ind(k);
226  A.Value(i_row, index_lu) = Row_Val(k);
227  index_lu++;
228  }
229  }
230 
231  if (print_level > 0)
232  {
233  cout << endl;
234  cout << "The matrix takes " <<
235  int((A.GetDataSize() * (sizeof(T)+4)) / (1024*1024)) << " MB" << endl;
236  }
237 
238  // Diagonal of A is replaced by its square root.
239  for (int i = 0; i < n; i++)
240  {
241  A.Value(i, 0) = sqrt(A.Value(i,0));
242  // and other elements multiplied by this value
243  for (int k = 1; k < A.GetRowSize(i); k++)
244  A.Value(i, k) *= A.Value(i, 0);
245 
246  A.Value(i, 0) = one / A.Value(i, 0);
247  }
248  }
249 
250 
252 
257  template<class T0, class Prop, class Allocator0,
258  class T1, class Storage, class Allocator1>
259  void SolveCholesky(const SeldonTranspose& TransA,
262  {
263  int n = A.GetM();
264  if (n <= 0)
265  return;
266 
267  if (TransA.Trans())
268  {
269  // we solve L^T x = x
270  int j;
271  for (int i = n-1; i >= 0; i--)
272  {
273  T1 val = x(i);
274  for (int k = 1; k < A.GetRowSize(i) ; k++)
275  {
276  j = A.Index(i, k);
277  val -= A.Value(i, k)*x(j);
278  }
279 
280  x(i) = val / A.Value(i, 0);
281  }
282  }
283  else
284  {
285  // we solve L x = x
286  int j;
287  for (int i = 0; i < n; i++)
288  {
289  x(i) /= A.Value(i, 0);
290  for (int k = 1; k < A.GetRowSize(i) ; k++)
291  {
292  j = A.Index(i, k);
293  x(j) -= A.Value(i, k)*x(i);
294  }
295  }
296  }
297  }
298 
299 
301 
306  template<class T0, class Prop, class Alloc0,
307  class T1, class Storage, class Allocator1>
308  void SolveCholesky(const SeldonTranspose& TransA,
311  {
312  int n = A.GetM();
313  if (n <= 0)
314  return;
315 
316  int* ind = A.GetInd();
317  long* ptr = A.GetPtr();
318  T0* data = A.GetData();
319  T1 val;
320 
321  if (TransA.Trans())
322  {
323  // Resolution of L^T x = x.
324  for (int i = n - 1; i >= 0; i--)
325  {
326  val = X(i);
327  for (long j = ptr[i] + 1; j < ptr[i+1]; j++)
328  val -= data[j] * X(ind[j]);
329 
330  X(i) = val / data[ptr[i]];
331  }
332  }
333  else
334  {
335  // Resolution of L x = x.
336  for (int i = 0; i < n; i++)
337  {
338  X(i) /= data[ptr[i]];
339  for (long j = ptr[i] + 1; j < ptr[i+1]; j++)
340  X(ind[j]) -= data[j] * X(i);
341  }
342  }
343  }
344 
345 
347 
352  template<class T0, class Prop, class Allocator0,
353  class T1, class Storage, class Allocator1>
354  void MltCholesky(const SeldonTranspose& TransA,
357  {
358  int n = A.GetM();
359  if (n <= 0)
360  return;
361 
362  if (TransA.Trans())
363  {
364  // we overwrite x by L^T x
365  int j;
366  for (int i = 0; i < n; i++)
367  {
368  T1 val = x(i) * A.Value(i, 0);
369  for (int k = 1; k < A.GetRowSize(i) ; k++)
370  {
371  j = A.Index(i, k);
372  val += A.Value(i, k)*x(j);
373  }
374 
375  x(i) = val;
376  }
377  }
378  else
379  {
380  // we overwrite x by L x
381  int j;
382  for (int i = n-1; i >= 0; i--)
383  {
384  for (int k = 1; k < A.GetRowSize(i) ; k++)
385  {
386  j = A.Index(i, k);
387  x(j) += A.Value(i, k)*x(i);
388  }
389 
390  x(i) *= A.Value(i, 0);
391  }
392  }
393  }
394 
395 
397 
402  template<class T0, class Prop, class Allocator0,
403  class T1, class Storage, class Allocator1>
404  void MltCholesky(const SeldonTranspose& TransA,
407  {
408  int n = A.GetM();
409  if (n <= 0)
410  return;
411 
412  int* ind = A.GetInd();
413  long* ptr = A.GetPtr();
414  T0* data = A.GetData();
415  T1 val;
416 
417  if (TransA.Trans())
418  {
419  // We overwrite x by L^T x
420  for (int i = 0; i < n; i++)
421  {
422  val = x(i) * data[ptr[i]];
423  for (long k = ptr[i] + 1; k < ptr[i+1]; k++)
424  val += data[k] * x(ind[k]);
425 
426  x(i) = val;
427  }
428  }
429  else
430  {
431  // We overwrite x by L x.
432  for (int i = n-1; i >= 0; i--)
433  {
434  for (long k = ptr[i] + 1; k < ptr[i+1]; k++)
435  x(ind[k]) += data[k] * x(i);
436 
437  x(i) *= data[ptr[i]];
438  }
439  }
440  }
441 
442 
444  template<class T>
446  {
447  n = 0;
448  print_level = -1;
449  type_ordering = SparseMatrixOrdering::IDENTITY;
450 
451  type_solver = SELDON_SOLVER;
452 #ifdef SELDON_WITH_CHOLMOD
453  type_solver = CHOLMOD;
454 #endif
455 #ifdef SELDON_WITH_PASTIX
456  type_solver = PASTIX;
457 #endif
458 
459  solver = NULL;
460  InitSolver();
461  }
462 
463 
465  template<class T>
467  {
468  print_level = -1;
469  if (solver != NULL)
470  solver->HideMessages();
471  }
472 
473 
475  template<class T>
477  {
478  print_level = 1;
479  if (solver != NULL)
480  solver->ShowMessages();
481  }
482 
483 
485  template<class T>
487  {
488  print_level = 3;
489  if (solver != NULL)
490  solver->ShowMessages();
491  }
492 
493 
495  template<class T>
497  {
498  if (n > 0)
499  {
500  n = 0;
501  if (solver != NULL)
502  solver->Clear();
503 
504  mat_sym.Clear();
505  }
506  }
507 
508 
510  template<class T>
512  {
513  return n;
514  }
515 
516 
518  template<class T>
520  {
521  return n;
522  }
523 
524 
526  template<class T>
528  {
529  size_t taille = mat_sym.GetMemorySize();
530  taille += xtmp.GetMemorySize();
531  if (solver != NULL)
532  taille += solver->GetMemorySize();
533 
534  return taille;
535  }
536 
537 
539  template<class T>
541  {
542  return type_ordering;
543  }
544 
545 
547  template<class T>
549  {
550  type_ordering = SparseMatrixOrdering::USER;
551  permutation = num;
552  }
553 
554 
556  template<class T>
558  {
559  type_ordering = type;
560  }
561 
562 
564  template<class T>
566  {
567  type_solver = type;
568  InitSolver();
569  }
570 
571 
573  template<class T>
575  {
576  return type_solver;
577  }
578 
579 
580  template<class T>
582  {
583  if (solver != NULL)
584  delete solver;
585 
586  if (type_solver == CHOLMOD)
587  {
588 #ifdef SELDON_WITH_CHOLMOD
589  solver = new MatrixCholmod();
590 #else
591  cout << "Seldon compiled without Cholmod support" << endl;
592  cout << "SELDON_WITH_CHOLMOD is not defined" << endl;
593 #endif
594  }
595  else if (type_solver == PASTIX)
596  {
597 #ifdef SELDON_WITH_PASTIX
598  solver = new MatrixPastix<T>();
599 #else
600  cout << "Seldon compiled without Pastix support" << endl;
601  cout << "SELDON_WITH_PASTIX is not defined" << endl;
602 #endif
603  }
604  else
605  {
606  // Seldon solver stored in mat_sym
607  solver = NULL;
608  }
609  }
610 
611 
613  template<class T>
614  template<class Prop, class Storage, class Allocator>
617  {
618  n = A.GetM();
619  if (type_solver == CHOLMOD)
620  {
621 #ifdef SELDON_WITH_CHOLMOD
622  if (print_level >= 1)
623  cout << "Calling Cholmod to factorize the matrix" << endl;
624 
625  MatrixCholmod& mat_chol =
626  dynamic_cast<MatrixCholmod&>(*this->solver);
627 
628  mat_chol.FactorizeMatrix(A, keep_matrix);
629 #else
630  throw Error("SparseCholeskySolver::Factorize",
631  "Recompile with Cholmod or change solver type.");
632 #endif
633  }
634  else if (type_solver == PASTIX)
635  {
636 #ifdef SELDON_WITH_PASTIX
637  if (print_level >= 1)
638  cout << "Calling Pastix to factorize the matrix" << endl;
639 
640  MatrixPastix<T>& mat_pastix =
641  dynamic_cast<MatrixPastix<T>&>(*this->solver);
642 
643  GetCholesky(A, mat_pastix, keep_matrix);
644 #else
645  throw Error("SparseCholeskySolver::Factorize",
646  "Recompile with Pastix or change solver type.");
647 #endif
648  }
649  else
650  {
651  FindSparseOrdering(A, permutation, type_ordering);
652  Copy(A, mat_sym);
653  if (!keep_matrix)
654  A.Clear();
655 
656  ApplyInversePermutation(mat_sym, permutation, permutation);
657 
658  GetCholesky(mat_sym, print_level);
659  xtmp.Reallocate(n);
660  }
661  }
662 
663 
665  template<class T> template<class T1>
667  ::Solve(const SeldonTranspose& TransA, Vector<T1>& x_solution, bool assemble)
668  {
669  if (type_solver == CHOLMOD)
670  {
671 #ifdef SELDON_WITH_CHOLMOD
672  MatrixCholmod& mat_chol =
673  dynamic_cast<MatrixCholmod&>(*this->solver);
674 
675  mat_chol.Solve(TransA, x_solution);
676 #else
677  throw Error("SparseCholeskySolver::Solve",
678  "Recompile with Cholmod or change solver type.");
679 #endif
680  }
681  else if (type_solver == PASTIX)
682  {
683 #ifdef SELDON_WITH_PASTIX
684  MatrixPastix<T>& mat_pastix =
685  dynamic_cast<MatrixPastix<T>&>(*this->solver);
686 
687  SolveCholesky(TransA, mat_pastix, x_solution);
688 #else
689  throw Error("SparseCholeskySolver::Solve",
690  "Recompile with Pastix or change solver type.");
691 #endif
692  }
693  else
694  {
695  if (TransA.NoTrans())
696  {
697  for (int i = 0; i < x_solution.GetM(); i++)
698  xtmp(permutation(i)) = x_solution(i);
699 
700  SolveCholesky(TransA, mat_sym, xtmp);
701  Copy(xtmp, x_solution);
702  }
703  else
704  {
705  Copy(x_solution, xtmp);
706  SolveCholesky(TransA, mat_sym, xtmp);
707 
708  for (int i = 0; i < x_solution.GetM(); i++)
709  x_solution(i) = xtmp(permutation(i));
710  }
711  }
712  }
713 
714 
716  template<class T> template<class T1>
718  ::Mlt(const SeldonTranspose& TransA, Vector<T1>& x_solution, bool assemble)
719  {
720  if (type_solver == CHOLMOD)
721  {
722 #ifdef SELDON_WITH_CHOLMOD
723  MatrixCholmod& mat_chol =
724  dynamic_cast<MatrixCholmod&>(*this->solver);
725 
726  mat_chol.Mlt(TransA, x_solution);
727 #else
728  throw Error("SparseCholeskySolver::Mlt",
729  "Recompile with Cholmod or change solver type.");
730 #endif
731  }
732  else if (type_solver == PASTIX)
733  {
734 #ifdef SELDON_WITH_PASTIX
735  MatrixPastix<T>& mat_pastix =
736  dynamic_cast<MatrixPastix<T>&>(*this->solver);
737 
738  MltCholesky(TransA, mat_pastix, x_solution);
739 #else
740  throw Error("SparseCholeskySolver::Mlt",
741  "Recompile with Pastix or change solver type.");
742 #endif
743  }
744  else
745  {
746  if (TransA.NoTrans())
747  {
748  Copy(x_solution, xtmp);
749  MltCholesky(TransA, mat_sym, xtmp);
750 
751  for (int i = 0; i < x_solution.GetM(); i++)
752  x_solution(i) = xtmp(permutation(i));
753  }
754  else
755  {
756  for (int i = 0; i < x_solution.GetM(); i++)
757  xtmp(permutation(i)) = x_solution(i);
758 
759  MltCholesky(TransA, mat_sym, xtmp);
760  Copy(xtmp, x_solution);
761  }
762  }
763  }
764 
765 } // namespace Seldon.
766 
767 
768 #define SELDON_FILE_SPARSE_CHOLESKY_FACTORISATION_CXX
769 #endif
Seldon::MatrixPastix
Definition: Pastix.hxx:39
Seldon::SparseCholeskySolver::ShowMessages
void ShowMessages()
Displays only brief messages.
Definition: SparseCholeskyFactorisation.cxx:476
Seldon::SparseCholeskySolver::GetTypeOrdering
int GetTypeOrdering() const
Returns the type of ordering used.
Definition: SparseCholeskyFactorisation.cxx:540
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::Matrix< T, Prop, ArrayRowSymSparse, Allocator >::GetRowSize
int GetRowSize(int i) const
Returns the number of non-zero entries of a row.
Definition: Matrix_ArraySparseInline.cxx:1360
Seldon::MatrixCholmod::Solve
void Solve(const SeldonTranspose &TransA, Vector< double, VectFull, Allocator > &x)
Solves L x = b or L^T x = b.
Definition: Cholmod.cxx:147
Seldon::SparseCholeskySolver::GetM
int GetM() const
Returns the number of rows.
Definition: SparseCholeskyFactorisation.cxx:511
Seldon::SparseCholeskySolver::SetPermutation
void SetPermutation(const IVect &)
Modifies the ordering used.
Definition: SparseCholeskyFactorisation.cxx:548
Seldon::Vector< T >
Seldon::Matrix_ArraySparse::Clear
void Clear()
Clears the matrix.
Definition: Matrix_ArraySparseInline.cxx:66
Seldon::SparseCholeskySolver::Solve
void Solve(const SeldonTranspose &TransA, Vector< T1 > &x, bool assemble=true)
Solves L x = b or L^T x = b.
Definition: SparseCholeskyFactorisation.cxx:667
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Error
Definition: Errors.hxx:38
Seldon::SparseCholeskySolver::SparseCholeskySolver
SparseCholeskySolver()
Default constructor.
Definition: SparseCholeskyFactorisation.cxx:445
Seldon::VirtualMatrix::GetN
int GetN() const
Returns the number of columns.
Definition: Matrix_BaseInline.cxx:80
Seldon::FindSparseOrdering
void FindSparseOrdering(Matrix< T, Prop, Storage, Allocator > &A, Vector< Tint, VectFull, Alloc > &num, int type)
Constructs an ordering for the factorization of a sparse matrix.
Definition: Ordering.cxx:137
Seldon::Matrix_ArraySparse::Value
const T & Value(int num_row, int i) const
Returns j-th non-zero value of row/column i.
Definition: Matrix_ArraySparseInline.cxx:286
Seldon::SparseCholeskySolver
Class grouping different Cholesky solvers.
Definition: SparseCholeskyFactorisation.hxx:28
Seldon::SparseCholeskySolver::GetN
int GetN() const
Returns the number of rows.
Definition: SparseCholeskyFactorisation.cxx:519
Seldon::SparseCholeskySolver::Mlt
void Mlt(const SeldonTranspose &TransA, Vector< T1 > &x, bool assemble=true)
Computes L x or L^T.
Definition: SparseCholeskyFactorisation.cxx:718
Seldon::SparseCholeskySolver::SelectDirectSolver
void SelectDirectSolver(int)
Modifies the direct solver used.
Definition: SparseCholeskyFactorisation.cxx:565
Seldon::MatrixCholmod
Object containing Cholesky factorization.
Definition: Cholmod.hxx:32
Seldon::Matrix_ArraySparse::GetDataSize
long GetDataSize() const
Returns the number of elements stored in memory.
Definition: Matrix_ArraySparseInline.cxx:86
Seldon::Matrix_ArraySparse::Index
int Index(int num_row, int i) const
Returns column/row number of j-th non-zero value of row/column i.
Definition: Matrix_ArraySparseInline.cxx:325
Seldon::SparseCholeskySolver::Clear
void Clear()
Clears Cholesky factors.
Definition: SparseCholeskyFactorisation.cxx:496
Seldon::WrongArgument
Definition: Errors.hxx:76
Seldon::Matrix_ArraySparse::Reallocate
void Reallocate(int i, int j)
Reallocates memory to resize the matrix.
Definition: Matrix_ArraySparse.cxx:42
Seldon::MatrixCholmod::Mlt
void Mlt(const SeldonTranspose &TransA, Vector< double, VectFull, Allocator > &x)
Performs the matrix vector product y = L X or y = L^T X.
Definition: Cholmod.cxx:190
Seldon::Matrix< T, Prop, ArrayRowSymSparse, Allocator >::ReallocateRow
void ReallocateRow(int i, int j)
Reallocates row i.
Definition: Matrix_ArraySparseInline.cxx:1308
Seldon::SparseCholeskySolver::HideMessages
void HideMessages()
Displays no messages.
Definition: SparseCholeskyFactorisation.cxx:466
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::SparseCholeskySolver::Factorize
void Factorize(Matrix< T, Prop, Storage, Allocator > &A, bool keep_matrix=false)
Performs Cholesky factorization.
Definition: SparseCholeskyFactorisation.cxx:616
Seldon::Matrix< T, Prop, ArrayRowSymSparse, Allocator >
Row-major symmetric sparse-matrix class.
Definition: Matrix_ArraySparse.hxx:311
Seldon::SparseCholeskySolver::GetMemorySize
size_t GetMemorySize() const
returns memory size used by the object in bytes
Definition: SparseCholeskyFactorisation.cxx:527
Seldon::SparseCholeskySolver::SelectOrdering
void SelectOrdering(int)
Modifies the type of ordering used.
Definition: SparseCholeskyFactorisation.cxx:557
Seldon::SparseCholeskySolver::GetDirectSolver
int GetDirectSolver()
returns the type of direct solver used
Definition: SparseCholeskyFactorisation.cxx:574
Seldon::SparseCholeskySolver::ShowFullHistory
void ShowFullHistory()
Displays a lot of messages.
Definition: SparseCholeskyFactorisation.cxx:486