G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsSparseRows.hpp
1 //
2 // gsSparseRows.hpp
3 //
4 // Clemens Hofreither
5 //
6 #pragma once
7 
8 #include <vector>
9 #include <stdexcept>
10 
11 #include <gsCore/gsLinearAlgebra.h>
12 
13 namespace gismo
14 {
15 
23 template <class T>
25 {
26 public:
27  typedef gsEigen::SparseVector<T> Row;
28 
29  struct RowBlockXpr;
30 
31  gsSparseRows()
32  { }
33 
34  gsSparseRows(index_t rows, index_t cols)
35  : m_rows(rows)
36  {
37  for (index_t i = 0; i < rows; ++i)
38  m_rows[i] = new Row(cols);
39  }
40 
41  gsSparseRows(const gsSparseRows& other)
42  : m_rows(other.rows())
43  {
44  for (int i = 0; i < rows(); ++i)
45  m_rows[i] = new Row( *other.m_rows[i] );
46  }
47 
48  gsSparseRows(const RowBlockXpr& rowxpr)
49  : m_rows(rowxpr.num)
50  {
51  for (index_t i = 0; i < rowxpr.num; ++i)
52  m_rows[i] = new Row( *rowxpr.mat.m_rows[rowxpr.start + i] );
53  }
54 
55  ~gsSparseRows()
56  {
57  clear();
58  }
59 
60  gsSparseRows& operator= (const gsSparseRows other)
61  {
62  this->swap( other );
63  return *this;
64  }
65 
66  gsSparseRows& operator= (const RowBlockXpr& rowxpr)
67  {
68  gsSparseRows temp(rowxpr);
69  this->swap( temp );
70  return *this;
71  }
72 
73  index_t rows() const { return m_rows.size(); }
74  index_t cols() const { return (m_rows.size() > 0) ? m_rows[0]->size() : 0; }
75 
76  Row& row(index_t i) { return *m_rows[i]; }
77  const Row& row(index_t i) const { return *m_rows[i]; }
78 
79  void clear()
80  {
81  for (int i = 0; i < rows(); ++i)
82  delete m_rows[i];
83  m_rows.clear();
84  }
85 
86  void swap(gsSparseRows& other)
87  {
88  m_rows.swap( other.m_rows );
89  }
90 
91  void setIdentity(index_t n)
92  {
93  assert( n >= 0 );
94 
95  resize(n, n);
96 
97  for (index_t i = 0; i < n; ++i)
98  m_rows[i]->insert(i) = (T)(1.0);
99  }
100 
101  void resize(index_t rows, index_t cols)
102  {
103  assert( rows >= 0 && cols >= 0 );
104 
105  clear();
106  m_rows.resize(rows);
107  for (index_t i = 0; i < rows; ++i)
108  m_rows[i] = new Row(cols);
109  }
110 
111  void conservativeResize(index_t newRows, index_t newCols)
112  {
113  if (rows() > 0 && cols() != newCols)
114  throw std::runtime_error("cannot resize columns -- not implemented");
115 
116  const index_t oldRows = rows();
117  resizeRows(newRows);
118 
119  // allocate newly added rows, if any
120  for (index_t i = oldRows; i < newRows; ++i)
121  m_rows[i] = new Row(newCols);
122  }
123 
124  void duplicateRow(index_t k)
125  {
126  assert ( 0 <= k && k < rows() );
127 
128  // add one new row
129  resizeRows( rows() + 1 );
130 
131  // shift rows [k+1,...) down to [k+2,...)
132  for (index_t i = rows() - 1; i > k + 1; --i)
133  m_rows[i] = m_rows[i-1];
134 
135  // allocate new row
136  m_rows[k+1] = new Row( row(k) );
137  }
138 
139  // row expressions
140 
141  RowBlockXpr topRows(index_t num) { return RowBlockXpr(*this, 0, num); }
142  const RowBlockXpr topRows(index_t num) const { return RowBlockXpr(*this, 0, num); }
143 
144  RowBlockXpr bottomRows(index_t num) { return RowBlockXpr(*this, rows() - num, num); }
145  const RowBlockXpr bottomRows(index_t num) const { return RowBlockXpr(*this, rows() - num, num); }
146 
147  RowBlockXpr middleRows(index_t start, index_t num) { return RowBlockXpr(*this, start, num); }
148  const RowBlockXpr middleRows(index_t start, index_t num) const { return RowBlockXpr(*this, start, num); }
149 
150  index_t nonZeros() const
151  {
152  index_t nnz = 0;
153  for (index_t i = 0; i < rows(); ++i)
154  nnz += m_rows[i]->nonZeros();
155  return nnz;
156  }
157 
158  template <class Derived>
159  void toSparseMatrix(gsEigen::SparseMatrixBase<Derived>& m) const
160  {
161  m.derived().resize( rows(), cols() );
162  m.derived().reserve( nonZeros() );
163  for (index_t i = 0; i < rows(); ++i)
164  {
165  for (typename Row::InnerIterator it(*m_rows[i]); it; ++it)
166  m.derived().insert(i, it.index()) = it.value();
167  }
168  m.derived().makeCompressed();
169  }
170 
171  struct RowBlockXpr
172  {
173  RowBlockXpr(const gsSparseRows& _mat, index_t _start, index_t _num)
174  : mat(const_cast<gsSparseRows&>(_mat)), start(_start), num(_num)
175  {
176  // HACK: We cast away the constness of the matrix, otherwise we would need two versions of
177  // this expression class.
178  // It's still safe because the row block methods in gsSparseRows above return the proper constness.
179  assert( 0 <= num && 0 <= start );
180  assert( start < mat.rows() );
181  assert( start + num <= mat.rows() );
182  }
183 
184  gsSparseRows & mat;
185  index_t start, num;
186 
187  RowBlockXpr& operator= (const RowBlockXpr& other)
188  {
189  assert(num == other.num);
190  for (index_t i = 0; i < num; ++i)
191  mat.row(start + i) = other.mat.row(other.start + i);
192  return *this;
193  }
194 
195  RowBlockXpr& operator= (const gsSparseRows& other)
196  {
197  assert(num == other.rows());
198  for (index_t i = 0; i < num; ++i)
199  mat.row(start + i) = other.row(i);
200  return *this;
201  }
202  };
203 
204 private:
205  std::vector< Row* > m_rows;
206 
208  void resizeRows(index_t newRows)
209  {
210  // delete rows which will be removed from the array
211  // (does nothing if newRows >= rows())
212  for (index_t i = newRows; i < rows(); ++i)
213  delete m_rows[i];
214 
215  m_rows.resize(newRows);
216  }
217 
218 };
219 
220 } // namespace gismo
#define index_t
Definition: gsConfig.h:32
This is the main header file that collects wrappers of Eigen for linear algebra.
A specialized sparse matrix class which stores each row as a separate sparse vector.
Definition: gsSparseRows.hpp:24
void resizeRows(index_t newRows)
Change the number of rows without allocating newly added rows.
Definition: gsSparseRows.hpp:208