G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsFiberMatrix.h
Go to the documentation of this file.
1
15#pragma once
16
18
19namespace gismo
20{
21
29template <class T, bool IsRowMajor = true>
31{
32public:
33 typedef gsEigen::SparseVector<T> Fiber;
34
35 class InnerIterator : Fiber::InnerIterator
36 {
37 typedef typename Fiber::InnerIterator Base;
38 InnerIterator(gsFiberMatrix fm, index_t j) : Base() { }
39 };
40
41 struct RowBlockXpr;
42
44 { }
45
47 : m_fibers(rows)
48 {
49 for (index_t i = 0; i < rows; ++i)
50 m_fibers[i] = new Fiber(cols);
51 }
52
53 gsFiberMatrix(const gsFiberMatrix& other)
54 : m_fibers(other.rows())
55 {
56 for (int i = 0; i < rows(); ++i)
57 m_fibers[i] = new Fiber( *other.m_fibers[i] );
58 }
59
60 gsFiberMatrix(const RowBlockXpr& rowxpr)
61 : m_fibers(rowxpr.num)
62 {
63 for (index_t i = 0; i < rowxpr.num; ++i)
64 m_fibers[i] = new Fiber( *rowxpr.mat.m_fibers[rowxpr.start + i] );
65 }
66
68 {
69 clear();
70 }
71
72 gsFiberMatrix& operator= (gsFiberMatrix other)
73 {
74 this->swap( other );
75 return *this;
76 }
77
78 gsFiberMatrix& operator= (const RowBlockXpr& rowxpr)
79 {
80 gsFiberMatrix temp(rowxpr);
81 this->swap( temp );
82 return *this;
83 }
84
85 inline index_t fibers() const { return m_fibers.size(); }
86
89 inline index_t outerSize() const
90 { return m_fibers.size(); }
91
94 inline index_t innerSize() const
95 // { return ( m_fibers.empty() ? 0 : m_fibers.front()->size() ); }
96 { return ( m_fibers.size()>0 ? m_fibers.front()->size() : 0 ); }
97
99 inline index_t rows() const { return IsRowMajor ? outerSize() : innerSize(); }
100
102 inline index_t cols() const { return IsRowMajor ? innerSize() : outerSize(); }
103
104 Fiber& fiber(index_t i) { return *m_fibers[i]; }
105 const Fiber& fiber(index_t i) const { return *m_fibers[i]; }
106
107 Fiber& row(index_t i)
108 {
109 GISMO_ASSERT( i>=0 && i<rows(), "Invalid element: "<<i<<">=0 && "<<i<<"<rows()"<<"="<<rows());
110 GISMO_ENSURE(IsRowMajor, "Cannot access row in col-major fiber matrix");
111 return *m_fibers[i];
112 }
113
114 const Fiber& row(index_t i) const
115 {
116 GISMO_ASSERT( i>=0 && i<rows(), "Invalid element: "<<i<<">=0 && "<<i<<"<rows()"<<"="<<rows());
117 GISMO_ENSURE(IsRowMajor, "Cannot access row in col-major fiber matrix");
118 return *m_fibers[i];
119 }
120
121 Fiber& col(index_t i)
122 {
123 GISMO_ASSERT(i>=0 && i<cols(), "Invalid element: "<<i<<">=0 && "<<i<<"<cols()"<<"="<<cols());
124 GISMO_ENSURE(!IsRowMajor, "Cannot access col in col-major fiber matrix");
125 return *m_fibers[i];
126 }
127
128 const Fiber& col(index_t i) const
129 {
130 GISMO_ASSERT(i>=0 && i<cols(), "Invalid element: "<<i<<">=0 && "<<i<<"<cols()"<<"="<<cols());
131 GISMO_ENSURE(!IsRowMajor, "Cannot access col in row-major fiber matrix");
132 return *m_fibers[i];
133 }
134
135 T & coef(index_t i, index_t j)
136 {
137 GISMO_ASSERT( i>=0 && i<rows() && j>=0 && i<cols(), "Invalid element: "<<i<<">=0 && "<<i<<"<rows()"<<"="<<rows()<<" && "<<j<<">=0 && "<<i<<"<cols()"<<"="<<cols() );
138 if (!IsRowMajor) std::swap(i,j);
139 return m_fibers[i]->coeff(j);
140 }
141
142 T & coeffRef(index_t i, index_t j)
143 {
144 GISMO_ASSERT( i>=0 && i<rows() && j>=0 && i<cols(), "Invalid element: "<<i<<">=0 && "<<i<<"<rows()"<<"="<<rows()<<" && "<<j<<">=0 && "<<i<<"<cols()"<<"="<<cols() );
145 if (!IsRowMajor) std::swap(i,j);
146 return m_fibers[i]->coeffRef(j);
147 }
148
149 void insertExplicitZero(index_t i, index_t j)
150 {
151 GISMO_ASSERT( i>=0 && i<rows() && j>=0 && i<cols(), "Invalid element: "<<i<<">=0 && "<<i<<"<rows()"<<"="<<rows()<<" && "<<j<<">=0 && "<<i<<"<cols()"<<"="<<cols() );
152 if (!IsRowMajor) std::swap(i,j);
153 m_fibers[i]->data().atWithInsertion(j);
154 }
155
156 bool isExplicitZero(index_t i, index_t j) const
157 {
158 GISMO_ASSERT( i>=0 && i<rows() && j>=0 && i<cols(), "Invalid element: "<<i<<">=0 && "<<i<<"<rows()"<<"="<<rows()<<" && "<<j<<">=0 && "<<i<<"<cols()"<<"="<<cols() );
159 if (!IsRowMajor) std::swap(i,j);
160 auto & vdata = m_fibers[i]->data();
161 const index_t jj = vdata.searchLowerIndex(j);
162 return ((jj==vdata.size()) || (vdata.index(jj)!=j));
163 }
164
165 void clear()
166 {
167 for (int i = 0; i < fibers(); ++i)
168 delete m_fibers[i];
169 m_fibers.clear();
170 }
171
172 //void prune()
173
174 void swap(gsFiberMatrix& other)
175 {
176 m_fibers.swap( other.m_fibers );
177 }
178
179 void setIdentity(index_t n)
180 {
181 GISMO_ASSERT( n >= 0, "n must be positive." );
182
183 resize(n, n);
184
185 for (index_t i = 0; i < n; ++i)
186 m_fibers[i]->insert(i) = (T)(1.0);
187 }
188
189 void assignZero()
190 {
191 for (auto & fb : m_fibers)
192 std::fill(fb->valuePtr(), fb->valuePtr() + fb->nonZeros(), (T)0.);
193 }
194
195 void resize(index_t rows, index_t cols)
196 {
197 GISMO_ASSERT( rows >= 0 && cols >= 0, "Invalid row/col in resize.");
198 if (!IsRowMajor) std::swap(rows,cols);
199
200 clear();
201 m_fibers.resize(rows);
202 for (index_t i = 0; i < rows; ++i)
203 m_fibers[i] = new Fiber(cols);
204 }
205
206 void reservePerColumn(index_t nz)
207 {
208 for (index_t i = 0; i < fibers(); ++i)
209 m_fibers[i]->reserve(nz);
210 }
211
212 void conservativeResize(index_t newRows, index_t newCols)
213 {
214 if (!IsRowMajor) std::swap(newRows,newCols);
215
216 const index_t oldRows = fibers();
217
218 // delete any fibers which will be removed, if any
219 for (index_t i = newRows; i < oldRows; ++i)
220 delete m_fibers[i];
221
222 m_fibers.resize(newRows);
223
224 // allocate newly added fibers, if any
225 for (index_t i = oldRows; i < newRows; ++i)
226 m_fibers[i] = new Fiber(newCols);
227
228 const index_t m = std::min(oldRows, newRows);
229 for (index_t i = 0; i < m; ++i)
230 m_fibers[i]->conservativeResize(newCols);
231 }
232
233 void duplicateRow(index_t k) //..
234 {
235 GISMO_ASSERT(IsRowMajor && 0 <= k && k < fibers(), "k out of bounds.");
236
237 //todo, something like: m_fibers.insert(m_fibers.begin()+k, new Fiber( fiber(k) );
238
239 // add one new fiber
240 m_fibers.resize(m_fibers.size()+1);
241
242 // shift rows [k+1,...) down to [k+2,...)
243 for (index_t i = fibers() - 1; i > k + 1; --i)
244 m_fibers[i] = m_fibers[i-1];
245
246 // allocate new row
247 m_fibers[k+1] = new Fiber( row(k) );
248 }
249
250 // row expressions //..
251
252 RowBlockXpr topRows(index_t num) { return RowBlockXpr(*this, 0, num); }
253 const RowBlockXpr topRows(index_t num) const { return RowBlockXpr(*this, 0, num); }
254
255 RowBlockXpr bottomRows(index_t num) { return RowBlockXpr(*this, fibers() - num, num); }
256 const RowBlockXpr bottomRows(index_t num) const { return RowBlockXpr(*this, fibers() - num, num); }
257
258 RowBlockXpr middleRows(index_t start, index_t num) { return RowBlockXpr(*this, start, num); }
259 const RowBlockXpr middleRows(index_t start, index_t num) const { return RowBlockXpr(*this, start, num); }
260
261 index_t nonZeros() const
262 {
263 index_t nnz = 0;
264 for (index_t i = 0; i < fibers(); ++i)
265 nnz += m_fibers[i]->nonZeros();
266 return nnz;
267 }
268
269 template <class Derived>
270 void toSparseMatrix(gsEigen::SparseMatrixBase<Derived>& m) const
271 {
272 m.derived().resize( rows(), cols() );
273 m.derived().reserve( nonZeros() );
274 for (index_t i = 0; i < fibers(); ++i)
275 {
276 for (typename Fiber::InnerIterator it(*m_fibers[i]); it; ++it)
277 m.derived().insert(IsRowMajor?i:it.index(), IsRowMajor?it.index():i) = it.value();
278 }
279 m.derived().makeCompressed();
280 }
281
282 struct RowBlockXpr
283 {
284 RowBlockXpr(const gsFiberMatrix& _mat, index_t _start, index_t _num)
285 : mat(const_cast<gsFiberMatrix&>(_mat)), start(_start), num(_num)
286 {
287 // HACK: We cast away the constness of the matrix, otherwise we would need two versions of
288 // this expression class.
289 // It's still safe because the row block methods in gsFiberMatrix above return the proper constness.
290 GISMO_ASSERT( 0 <= num && 0 <= start , "Invalid block.");
291 GISMO_ASSERT( start < mat.rows() , "Invalid block.");
292 GISMO_ASSERT( start + num <= mat.rows(), "Invalid block.");
293 }
294
295 gsFiberMatrix & mat;
296 index_t start, num;
297
298 RowBlockXpr& operator= (const RowBlockXpr& other)
299 {
300 GISMO_ASSERT(num == other.num, "Wrong size in assignment.");
301 for (index_t i = 0; i < num; ++i)
302 mat.row(start + i) = other.mat.row(other.start + i);
303 return *this;
304 }
305
306 RowBlockXpr& operator= (const gsFiberMatrix & other)
307 {
308 GISMO_ASSERT(num == other.rows(), "Wrong size in assignment.");
309 for (index_t i = 0; i < num; ++i)
310 mat.row(start + i) = other.row(i);
311 return *this;
312 }
313 };
314
315private:
316 std::vector< Fiber* > m_fibers;
317
319 void resizeFibers(index_t newRows)
320 {
321 // delete fibers which will be removed from the array
322 // (does nothing if newRows >= fibers())
323 for (index_t i = newRows; i < fibers(); ++i)
324 delete m_fibers[i];
325
326 m_fibers.resize(newRows);
327 }
328
329};
330
331} // namespace gismo
A specialized sparse matrix class which stores each row as a separate sparse vector.
Definition gsFiberMatrix.h:31
index_t rows() const
Definition gsFiberMatrix.h:99
index_t outerSize() const
Definition gsFiberMatrix.h:89
void resizeFibers(index_t newRows)
Change the number of fibers without allocating newly added rows.
Definition gsFiberMatrix.h:319
index_t cols() const
Definition gsFiberMatrix.h:102
index_t innerSize() const
Definition gsFiberMatrix.h:94
#define index_t
Definition gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
This is the main header file that collects wrappers of Eigen for linear algebra.
The G+Smo namespace, containing all definitions for the library.