From 5eae401eca188348e6c6d87be8843f77d21e95df Mon Sep 17 00:00:00 2001
From: Jonathan Lambrechts <jonathan.lambrechts@uclouvain.be>
Date: Tue, 19 Oct 2010 17:55:00 +0000
Subject: [PATCH] Solver : linearSystemCSR : support for preallocation using
 sparsityPattern

---
 Solver/linearSystemCSR.cpp | 47 ++++++++++++++++++++++++++++++++++++++
 Solver/linearSystemCSR.h   | 16 ++++++++++++-
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/Solver/linearSystemCSR.cpp b/Solver/linearSystemCSR.cpp
index 898910ba6a..20ab399b1e 100644
--- a/Solver/linearSystemCSR.cpp
+++ b/Solver/linearSystemCSR.cpp
@@ -46,6 +46,12 @@ static void CSRList_Realloc(CSRList_T *liste, int n)
   }
 }
 
+static void CSRList_Resize(CSRList_T *liste, int n)
+{
+  CSRList_Realloc(liste, n);
+  liste->n = n;
+}
+
 static CSRList_T *CSRList_Create(int n, int incr, int size)
 {
   CSRList_T *liste;
@@ -87,6 +93,46 @@ int CSRList_Nbr(CSRList_T *liste)
   return(liste->n);
 }
 
+template<>
+void linearSystemCSR<double>::preAllocateEntries ()
+{
+  if (_entriesPreAllocated) return;
+  if (_sparsity.getNbRows() == 0) return;
+  INDEX_TYPE nnz = 0;
+  int nbRows = _b->size();
+  for (int i = 0; i < nbRows; i++){
+    int nInRow;
+    _sparsity.getRow (i, nInRow);
+    nnz += nInRow;
+  }
+  CSRList_Resize (_a, nnz);
+  CSRList_Resize (_ai, nnz);
+  CSRList_Resize (_ptr, nnz);
+  INDEX_TYPE *jptr = (INDEX_TYPE*) _jptr->array;
+  INDEX_TYPE *ai = (INDEX_TYPE*) _ai->array;
+  INDEX_TYPE *ptr = (INDEX_TYPE*) _ptr->array;
+  double *a = ( double * ) _a->array;
+  jptr[0] = 0;
+  nnz = 0;
+  for (int i = 0; i < nbRows; i++){
+    int nInRow;
+    const int *row = _sparsity.getRow (i, nInRow);
+    for (int j = 0; j < nInRow; j++) {
+      ai[nnz] = row[j];
+      a[nnz] = 0.;
+      ptr[nnz] = nnz+1;
+      nnz ++;
+    }
+    if (nInRow != 0)
+      ptr[nnz-1] = 0;
+    jptr[i+1] = nnz;
+    something[i] = (nInRow == 0 ? 0 : 1);
+  }
+  _entriesPreAllocated = true;
+  sorted = true;
+  _sparsity.clear();
+}
+
 template<>
 void linearSystemCSR<double>::allocate(int nbRows)
 {
@@ -297,6 +343,7 @@ template<>
   void linearSystemCSRGmm<double>::registerBindings(binding *b)
   {
     classBinding *cb = b->addClass< linearSystemCSRGmm<double> >("linearSystemCSRGmmdouble");
+    cb->setParentClass<linearSystem<double> >();
     cb->setDescription("Sparse matrix representation.");
     methodBinding *cm;
     cm = cb->setConstructor<linearSystemCSRGmm<double> >();
diff --git a/Solver/linearSystemCSR.h b/Solver/linearSystemCSR.h
index 6387315df9..661afc0b6c 100644
--- a/Solver/linearSystemCSR.h
+++ b/Solver/linearSystemCSR.h
@@ -10,6 +10,7 @@
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "linearSystem.h"
+#include "sparsityPattern.h"
 
 class binding;
 
@@ -29,10 +30,12 @@ int  CSRList_Nbr(CSRList_T *liste);
 template <class scalar>
 class linearSystemCSR : public linearSystem<scalar> {
  protected:
+  bool _entriesPreAllocated;
   bool sorted;
   char *something;
   CSRList_T *_a, *_ai, *_ptr, *_jptr;
   std::vector<scalar> *_b, *_x;
+  sparsityPattern _sparsity; // only used for pre-allocation, does not store the sparsity once allocated
  public:
   linearSystemCSR()
     : sorted(false), _a(0), _b(0), _x(0) {}
@@ -46,8 +49,14 @@ class linearSystemCSR : public linearSystem<scalar> {
   {
     allocate(0);
   }
+  virtual void insertInSparsityPattern (int i, int j) {
+    _sparsity.insertEntry (i,j);
+  }
+  virtual void preAllocateEntries ();
   virtual void addToMatrix(int il, int ic, const scalar &val) 
   {
+    if (!_entriesPreAllocated)
+      preAllocateEntries();
     INDEX_TYPE  *jptr  = (INDEX_TYPE*) _jptr->array;
     INDEX_TYPE  *ptr   = (INDEX_TYPE*) _ptr->array;
     INDEX_TYPE  *ai    = (INDEX_TYPE*) _ai->array;
@@ -180,8 +189,13 @@ class linearSystemCSRTaucs : public linearSystemCSR<scalar> {
   virtual ~linearSystemCSRTaucs(){}
   virtual void addToMatrix(int il, int ic, const double &val)
   {
-    if (il <= ic)
+    if (il <= ic) {
       linearSystemCSR<scalar>::addToMatrix(il, ic, val);
+    }
+  }
+  virtual void insertInSparsityPattern(int il, int ic) {
+    if (il <= ic)
+      linearSystemCSR<scalar>::insertInSparsityPattern(il,ic);
   }
   virtual int systemSolve()
 #if !defined(HAVE_TAUCS)
-- 
GitLab