1 /*
2 XLiFE++ is an extended library of finite elements written in C++
3 Copyright (C) 2014 Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 /*!
18 \file RowCsStorage.cpp
19 \authors D. Martin, E. Lunéville, NGUYEN Manh Ha, N. Kielbasiewicz
20 \since 21 jun 2011
21 \date 21 feb 2013
22
23 \brief Implementation of xlifepp::RowCsStorage class and functionnalities
24 */
25
26 #include "RowCsStorage.hpp"
27 #include <functional>
28
29 namespace xlifepp
30 {
31
32 /*--------------------------------------------------------------------------------
33 Constructors, Destructor
34 --------------------------------------------------------------------------------*/
35 //! default constructor
RowCsStorage(number_t nr,number_t nc,string_t id)36 RowCsStorage::RowCsStorage(number_t nr, number_t nc, string_t id)
37 : CsStorage(nr, nc, _row, id)
38 {
39 trace_p->push("RowCsStorage constructor");
40 std::vector<std::vector<number_t> > cols(nr);
41 buildCsStorage(cols, colIndex_, rowPointer_); //construct colIndex_ and rowPointer_
42 trace_p->pop();
43 }
44
45 /*! constructor by a pair of numbering vectors rowNumbers and colNumbers (same size)
46 rowNumbers[k] is the row numbers of submatrix k
47 colNumbers[k] is the col numbers of submatrix k
48 indices start from 1 !!!!
49 this constructor is well adapted to FE matrix where submatrix is linked to an element
50 */
RowCsStorage(number_t nr,number_t nc,const std::vector<std::vector<number_t>> & rowNumbers,const std::vector<std::vector<number_t>> & colNumbers,string_t id)51 RowCsStorage::RowCsStorage(number_t nr, number_t nc, const std::vector<std::vector<number_t> >& rowNumbers, const std::vector<std::vector<number_t> >& colNumbers, string_t id)
52 : CsStorage(nr, nc, _row, id)
53 {
54 trace_p->push("RowCsStorage constructor");
55 // build list of col index for each rows
56 std::vector<std::set<number_t> > colset(nbRows_); //temporary vector of col index
57 std::vector<std::vector<number_t> >::const_iterator itrs, itcs = colNumbers.begin();
58 std::vector<number_t>::const_iterator itr, itc;
59 for(itrs = rowNumbers.begin(); itrs != rowNumbers.end(); itrs++, itcs++)
60 {
61 for(itr = itrs->begin(); itr != itrs->end(); itr++)
62 for(itc = itcs->begin(); itc != itcs->end(); itc++)
63 { colset[*itr - 1].insert(*itc); }
64 }
65 // convert set to vector
66 std::vector<std::vector<number_t> > cols(nbRows_); //temporary vector of col index
67 std::vector<std::set<number_t> >::iterator itset;
68 std::vector<std::vector<number_t> >::iterator itcols = cols.begin();
69 for(itset = colset.begin(); itset != colset.end(); itset++, itcols++)
70 { *itcols = std::vector<number_t>(itset->begin(), itset->end()); }
71 // construct colIndex_ and rowPointer_
72 buildCsStorage(cols, colIndex_, rowPointer_);
73 trace_p->pop();
74 }
75
76 //! create a new scalar RowCs storage from current RowCs storage and submatrix sizes
toScalar(dimen_t nbr,dimen_t nbc)77 RowCsStorage* RowCsStorage::toScalar(dimen_t nbr, dimen_t nbc)
78 {
79 RowCsStorage* cs = new RowCsStorage(nbr*nbRows_, nbc*nbCols_, stringId+"_scalar");
80 cs->colIndex_.resize(nbr*nbc*colIndex_.size());
81 toScalarCs(rowPointer_, colIndex_, nbc, nbr, cs->rowPointer_, cs->colIndex_);
82 return cs;
83 }
84
85 //! check if two storages have the same structures
sameStorage(const MatrixStorage & sto) const86 bool RowCsStorage::sameStorage(const MatrixStorage& sto) const
87 {
88 if(!(sto.storageType()==storageType_ &&
89 sto.accessType()==accessType_ &&
90 sto.nbOfRows()==nbRows_ &&
91 sto.nbOfColumns()==nbCols_&&
92 sto.size()==size()))
93 return false;
94 const RowCsStorage& csto=static_cast<const RowCsStorage&>(sto);
95 if(rowPointer_!=csto.rowPointer_) return false;
96 if(colIndex_!=csto.colIndex_) return false;
97 return true;
98 }
99
100 /*!--------------------------------------------------------------------------------
101 add submatrix indices given by its row and column indices (>= 1)
102 --------------------------------------------------------------------------------*/
addSubMatrixIndices(const std::vector<number_t> & rows,const std::vector<number_t> & cols)103 void RowCsStorage::addSubMatrixIndices(const std::vector<number_t>& rows,const std::vector<number_t>& cols)
104 {
105 addCsSubMatrixIndices(rowPointer_,colIndex_,rows,cols, false,true);
106 }
107
108 /*!--------------------------------------------------------------------------------
109 add in storage indexes (i,j) given by rows (i) and columns (j) (i,j >= 1)
110 rows and cols are of same size
111 --------------------------------------------------------------------------------*/
addIndices(const std::vector<number_t> & rows,const std::vector<number_t> & cols)112 void RowCsStorage::addIndices(const std::vector<number_t>& rows, const std::vector<number_t>& cols)
113 {
114 if(rows.size()==0) return; //nothing to do
115
116 std::vector<number_t>::const_iterator itr = rows.begin(),itc=cols.end();
117 std::map<number_t, std::set<number_t> > rowsmap;
118 std::map<number_t, std::set<number_t> >::iterator itm;;
119 //collect col indexes by row
120 for(; itr!=rows.end(); itr++, itc++)
121 {
122 itm=rowsmap.find(*itr);
123 if(itm==rowsmap.end()) rowsmap[*itr]=std::set<number_t>();
124 rowsmap[*itr].insert(*itc);
125 }
126 //modify current rowpointer and colindex (expansive operation)
127 for(itm=rowsmap.begin(); itm!=rowsmap.end(); itm++)
128 if(itm->second.size()>0) addRow(itm->first,itm->second,_all); //insert col at row r in storage
129 }
130
131 /*!--------------------------------------------------------------------------------
132 insert in storage indexes (r,c1), (r,c2), .... c1,c2, ... given by cols (r,c>=1)
133 expansive operation !
134 MatrixPart not managed !
135 --------------------------------------------------------------------------------*/
addRow(number_t r,const std::set<number_t> & cols,MatrixPart)136 void RowCsStorage::addRow(number_t r, const std::set<number_t>& cols, MatrixPart)
137 {
138 if(cols.size()==0) return;
139 number_t rb=rowPointer_[r-1], re=rowPointer_[r];
140 std::set<number_t> allcols(colIndex_.begin()+rb, colIndex_.begin()+re);
141 std::set<number_t>::iterator its=cols.begin();
142 for(; its!=cols.end(); its++) allcols.insert(*its -1); //add current cols (-1 shift)
143 number_t nc=allcols.size()- (re - rb);
144 if(nc==0) return; //nothing to do , no new cols
145
146 std::vector<number_t>::iterator itc=colIndex_.begin()+re;
147 colIndex_.insert(itc, nc, 0); //insert nc element initialized to 0
148 its=allcols.begin();
149 itc=colIndex_.begin()+rb;
150 for(; its!=allcols.end(); its++,itc++) *itc=*its; //copy new columns set
151 std::vector<number_t>::iterator itr=rowPointer_.begin()+r;
152 for(; itr!=rowPointer_.end(); itr++) *itr+=nc; //shift rowPointer
153 }
154
155 /*!--------------------------------------------------------------------------------
156 access operator to position of (i,j)>0 coefficients (return 0 if outside)
157 This DIRECT access to (i,j) pointer SHOULD NOT be used in matrix computation
158 --------------------------------------------------------------------------------*/
pos(number_t i,number_t j,SymType s) const159 number_t RowCsStorage::pos(number_t i, number_t j, SymType s) const
160 {
161 if(i == 0 || i > nbRows_ || j == 0 || j > nbCols_) { return 0; }
162 for(number_t k = rowPointer_[i - 1]; k < rowPointer_[i]; k++) // find in list of col index of row i
163 {
164 if(colIndex_[k] == j - 1) { return k + 1; } // add 1 because values begin at address 1
165 }
166 return 0;
167 }
168
169 /*!--------------------------------------------------------------------------------
170 access to submatrix adresses, useful for assembling matrices
171 rows and cols are vector of index (>0) of row and column, no index ordering is assumed !!
172 return the vector of adresses (relative number >0 in storage) in a row storage (as Matrix)
173 if a row or a col index is out of storage
174 an error is raised if errorOn is true (default)
175 position is set to 0 else
176 if sy!=_noSymmetry only positions of lower part are requested (not used here)
177 remark : since the vector storage indexCol_ is ordered for each line, if the indices of columns
178 of the submatrix were also, one could write a faster algorithm
179 --------------------------------------------------------------------------------*/
positions(const std::vector<number_t> & rows,const std::vector<number_t> & cols,std::vector<number_t> & adrs,bool errorOn,SymType sy) const180 void RowCsStorage::positions(const std::vector<number_t>& rows, const std::vector<number_t>& cols, std::vector<number_t>& adrs, bool errorOn, SymType sy) const
181 {
182 number_t nba = rows.size() * cols.size();
183 if(adrs.size() != nba) { adrs.resize(nba); }
184 std::vector<number_t>::iterator itp = adrs.begin();
185 std::vector<number_t>::const_iterator itr, itc, itb, ite;
186 for(itr = rows.begin(); itr != rows.end(); itr++) // loop on row index
187 {
188 number_t i = *itr, rb = rowPointer_[i - 1], re = rowPointer_[i];
189 for(itc = cols.begin(); itc != cols.end(); itc++, itp++) // loop on col index
190 {
191 itb = colIndex_.begin() + rb;
192 ite = colIndex_.begin() + re;
193 *itp = 0;
194 number_t k=0;
195 while(itb != ite && *itp == 0) // find in list of col index of row i
196 {
197
198 if(*itb == (*itc - 1)) { *itp = rb + k + 1; }
199 itb++; k++;
200 }
201 if(*itp == 0 && errorOn) { error("storage_outofstorage","RowCs", *itr, *itc); }
202 }
203 }
204 }
205
206 //! get (col indices, adress) of row r in set [c1,c2] ## SymType not used ##
getRow(SymType s,number_t r,number_t c1,number_t c2) const207 std::vector<std::pair<number_t, number_t> > RowCsStorage::getRow(SymType s,number_t r, number_t c1, number_t c2) const
208 {
209 number_t nbc=c2;
210 if(nbc==0) nbc=nbCols_;
211 number_t rb=rowPointer_[r-1], re=rowPointer_[r];
212 number_t l=re-rb;
213 std::vector<std::pair<number_t, number_t> > cols(l);
214 std::vector<std::pair<number_t, number_t> >::iterator itcol=cols.begin();
215 l=0;
216 for(number_t k = rb; k < re; k++) // find in list of col index of row i
217 {
218 number_t c=colIndex_[k]+1;
219 if(c >= c1 && c<=nbc)
220 {
221 *itcol = std::make_pair(c,k+1); // add 1 because values begin at address 1
222 l++; itcol++;
223 }
224 }
225 cols.resize(l);
226 return cols;
227 }
228
229 //! get (row indices, adress) of col c in set [r1,r2] ## SymType not used ##
getCol(SymType s,number_t c,number_t r1,number_t r2) const230 std::vector<std::pair<number_t, number_t> > RowCsStorage::getCol(SymType s, number_t c, number_t r1, number_t r2) const
231 {
232 number_t nbr=r2;
233 if(nbr==0) nbr=nbRows_;
234 std::vector<std::pair<number_t, number_t> > rows(nbr-r1+1);
235 std::vector<std::pair<number_t, number_t> >::iterator itrow=rows.begin();
236 number_t l=0;
237 for(number_t i=r1; i<=nbr; i++)
238 {
239 number_t a=pos(i,c);
240 if(a!=0)
241 {
242 *itrow=std::make_pair(i,a);
243 l++; itrow++;
244 }
245 }
246 rows.resize(l);
247 return rows;
248 }
249
250 //! get col indices of row r in set [c1,c2], specific CsRow algorithm (no getRows, use generic algorithm)
getCols(number_t r,number_t c1,number_t c2) const251 std::set<number_t> RowCsStorage::getCols(number_t r, number_t c1, number_t c2) const
252 {
253 std::set<number_t> colset;
254 number_t nbc=c2;
255 if(nbc==0) nbc=nbCols_;
256 if(nbc<c1) return colset;
257 number_t rb=rowPointer_[r-1], re=rowPointer_[r];
258 for(number_t k = rb; k < re; k++) // find in list of col index of row i
259 {
260 number_t c=colIndex_[k]+1;
261 if(c >= c1 && c<=nbc) colset.insert(c);
262 }
263 return colset;
264 }
265
266 //! get col indices of row r in set [c1,c2], specific CsRow algorithm (no getRows, use generic algorithm)
267 // no allocation, no check (faster)
getColsV(std::vector<number_t> & colsv,number_t & nbcols,number_t r,number_t c1,number_t c2) const268 void RowCsStorage::getColsV(std::vector<number_t>& colsv, number_t& nbcols, number_t r, number_t c1, number_t c2) const
269 {
270 nbcols=0;
271 number_t nbc=c2;
272 if(nbc==0) nbc=nbCols_;
273 if(nbc<c1) return;
274 std::vector<number_t>::iterator itv=colsv.begin();
275 number_t rb=rowPointer_[r-1], re=rowPointer_[r];
276 for(number_t k = rb; k < re; k++) // find in list of col index of row i
277 {
278 number_t c=colIndex_[k]+1;
279 if(c >= c1 && c<=nbc) {*itv=c; itv++; nbcols++;}
280 }
281 }
282
283
284
285 //! print storage pointers
print(std::ostream & os) const286 void RowCsStorage::print(std::ostream& os) const
287 {
288 printHeader(os);
289 os<<"row pointer = "<<rowPointer_<<eol;
290 os<<"column index = "<<colIndex_<<eol;
291 }
292
293 /*!--------------------------------------------------------------------------------
294 print RowCs Storage matrix to output stream (sym is not used here)
295 --------------------------------------------------------------------------------*/
296 // print real scalar matrix
printEntries(std::ostream & os,const std::vector<real_t> & m,number_t vb,const SymType sym) const297 void RowCsStorage::printEntries(std::ostream& os, const std::vector<real_t>& m, number_t vb, const SymType sym) const
298 {
299 std::vector<real_t>::const_iterator itm = m.begin() + 1;
300 printEntriesAll(_scalar, itm, colIndex_, rowPointer_, entriesPerRow, entryWidth, entryPrec, "row", vb, os);
301 }
302
303 //! print complex scalar matrix
printEntries(std::ostream & os,const std::vector<complex_t> & m,number_t vb,SymType sym) const304 void RowCsStorage::printEntries(std::ostream& os, const std::vector<complex_t>& m, number_t vb, SymType sym) const
305 {
306 std::vector<complex_t>::const_iterator itm = m.begin() + 1;
307 printEntriesAll(_scalar, itm, colIndex_, rowPointer_, entriesPerRow / 2, 2 * entryWidth + 1, entryPrec, "row", vb, os);
308 }
309
310 //! large matrix of vectors are not available for the moment, use Matrix n x 1 or 1 x n
printEntries(std::ostream & os,const std::vector<Vector<real_t>> & m,number_t vb,SymType sym) const311 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Vector<real_t> >& m, number_t vb, SymType sym) const
312 {error("storage_novector", "RowCsStorage::printEntries");}
313
printEntries(std::ostream & os,const std::vector<Vector<complex_t>> & m,number_t vb,SymType sym) const314 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Vector<complex_t> >& m, number_t vb, SymType sym) const
315 {error("storage_novector", "RowCsStorage::printEntries");}
316
317 //! print matrix of real matrices
printEntries(std::ostream & os,const std::vector<Matrix<real_t>> & m,number_t vb,SymType sym) const318 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Matrix<real_t> >& m, number_t vb, SymType sym) const
319 {
320 std::vector< Matrix<real_t> >::const_iterator itm = m.begin() + 1;
321 printEntriesAll(_matrix, itm, colIndex_, rowPointer_, entriesPerRow, entryWidth, entryPrec, "row", vb, os);
322 }
323
324 //! print matrix of complex matrices
printEntries(std::ostream & os,const std::vector<Matrix<complex_t>> & m,number_t vb,SymType sym) const325 void RowCsStorage::printEntries(std::ostream& os, const std::vector< Matrix<complex_t> >& m, number_t vb, SymType sym) const
326 {
327 std::vector< Matrix<complex_t> >::const_iterator itm = m.begin() + 1;
328 printEntriesAll(_matrix, itm, colIndex_, rowPointer_, entriesPerRow / 2, 2 * entryWidth + 1, entryPrec, "row", vb, os);
329 }
330
331 /*!
332 --------------------------------------------------------------------------------
333 print matrix to ostream in coordinate form : i j M_ij
334 according to type of values of matrix (overload the generic method in MatrixStorage)
335 sym is not used
336 --------------------------------------------------------------------------------
337 */
printCooMatrix(std::ostream & os,const std::vector<real_t> & m,SymType sym) const338 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector<real_t>& m, SymType sym) const
339 {
340 std::vector<real_t>::const_iterator itm = m.begin() + 1;
341 printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
342 }
343
printCooMatrix(std::ostream & os,const std::vector<complex_t> & m,SymType sym) const344 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector<complex_t>& m, SymType sym) const
345 {
346 std::vector<complex_t>::const_iterator itm = m.begin() + 1;
347 printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
348 }
349
printCooMatrix(std::ostream & os,const std::vector<Matrix<real_t>> & m,SymType sym) const350 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector< Matrix<real_t> >& m, SymType sym) const
351 {
352 std::vector< Matrix<real_t> >::const_iterator itm = m.begin() + 1;
353 printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
354 }
355
printCooMatrix(std::ostream & os,const std::vector<Matrix<complex_t>> & m,SymType sym) const356 void RowCsStorage::printCooMatrix(std::ostream& os, const std::vector< Matrix<complex_t> >& m, SymType sym) const
357 {
358 std::vector< Matrix<complex_t> >::const_iterator itm = m.begin() + 1;
359 printCooTriangularPart(os, itm, colIndex_, rowPointer_, true);
360 }
361
362 /*!--------------------------------------------------------------------------------
363 template Matrix x Vector & Vector x Matrix multiplications and specializations
364 result vector has to be sized before
365 --------------------------------------------------------------------------------*/
366 template<typename M, typename V, typename R>
multMatrixVector(const std::vector<M> & m,V * vp,R * rp) const367 void RowCsStorage::multMatrixVector(const std::vector<M>& m, V* vp, R* rp) const
368 {
369 trace_p->push("RowCsStorage::multMatrixVector (pointer form)");
370 typename std::vector<M>::const_iterator itm = m.begin() + 1;
371 rowMatrixVector(colIndex_, rowPointer_, itm, vp, rp);
372 trace_p->pop();
373 }
374
375 template<typename M, typename V, typename R>
multMatrixVector(const std::vector<M> & m,const std::vector<V> & v,std::vector<R> & r) const376 void RowCsStorage::multMatrixVector(const std::vector<M>& m, const std::vector<V>& v, std::vector<R>& r) const
377 {
378 trace_p->push("RowCsStorage::multMatrixVector");
379 typename std::vector<M>::const_iterator itm = m.begin() + 1;
380 typename std::vector<V>::const_iterator itvb = v.begin();
381 typename std::vector<R>::iterator itrb = r.begin();
382 rowMatrixVector(colIndex_, rowPointer_, itm, itvb, itrb);
383 trace_p->pop();
384 }
385
386 template<typename M, typename V, typename R>
multVectorMatrix(const std::vector<M> & m,V * vp,R * rp) const387 void RowCsStorage::multVectorMatrix(const std::vector<M>& m, V* vp, R* rp) const
388 {
389 trace_p->push("RowCsStorage::multVectorMatrix (pointer form)");
390 typename std::vector<M>::const_iterator itm = m.begin() + 1;
391 rowMatrixVector(colIndex_, rowPointer_, itm, vp, rp);
392 trace_p->pop();
393 }
394
395 template<typename M, typename V, typename R>
multVectorMatrix(const std::vector<M> & m,const std::vector<V> & v,std::vector<R> & r) const396 void RowCsStorage::multVectorMatrix(const std::vector<M>& m, const std::vector<V>& v, std::vector<R>& r) const
397 {
398 trace_p->push("RowCsStorage::multVectorMatrix");
399 typename std::vector<M>::const_iterator itm = m.begin() + 1;
400 typename std::vector<V>::const_iterator itvb = v.begin();
401 typename std::vector<R>::iterator itrb = r.begin();
402 rowVectorMatrix(colIndex_, rowPointer_, itm, itvb, itrb);
403 trace_p->pop();
404 }
405
406 /*!
407 Add two matrices
408 \param m1 vector values_ of first matrix
409 \param m2 vector values_ of second matrix
410 \param r vector values_ of result matrix
411 */
412 template<typename M1, typename M2, typename R>
addMatrixMatrix(const std::vector<M1> & m1,const std::vector<M2> & m2,std::vector<R> & r) const413 void RowCsStorage::addMatrixMatrix(const std::vector<M1>& m1, const std::vector<M2>& m2, std::vector<R>& r) const
414 {
415 trace_p->push("RowCsStorage::addMatrixMatrix");
416 typename std::vector<M1>::const_iterator itm1 = m1.begin() + 1;
417 typename std::vector<M2>::const_iterator itm2 = m2.begin() + 1;
418 typename std::vector<R>::iterator itrb = r.begin() + 1, itre = r.end();
419 sumMatrixMatrix(itm1, itm2, itrb, itre);
420 trace_p->pop();
421 }
422
423 /*!
424 Extract and convert matrix storage to UMFPack format (Matlab sparse matrix)
425 \param m1 vector values_ current matrix
426 \param colPtUmf vector column Pointer of UMFPack format
427 \param rowIdxUmf vector row Index of UMFPack format
428 \param resultUmf vector values of UMFPack format
429 */
430 template<typename M1, typename Idx>
toUmfPack(const std::vector<M1> & m1,std::vector<Idx> & colPtUmf,std::vector<Idx> & rowIdxUmf,std::vector<M1> & resultUmf) const431 void RowCsStorage::toUmfPack(const std::vector<M1>& m1, std::vector<Idx>& colPtUmf, std::vector<Idx>& rowIdxUmf, std::vector<M1>& resultUmf) const
432 {
433 // Reserve memory for resultUmf and set its size to m1.size()-1 (we don't count for 0 in the first position)s
434 resultUmf.reserve(m1.size()-1);
435 resultUmf.clear();
436
437 // Reserve memory for rowIdxUmf and set its size to 0
438 rowIdxUmf.reserve(m1.size()-1);
439 rowIdxUmf.clear();
440
441 // Resize column pointer to nbCol+1
442 colPtUmf.clear();
443 colPtUmf.resize(nbCols_+1);
444
445 // Because colPointer always begins with 0, so need to to count from the second position
446 typename std::vector<Idx>::iterator itColPtUmf = colPtUmf.begin()+1;
447 colPtUmf[0] = Idx(0);
448
449 std::vector<number_t>::const_iterator itbColIdx = colIndex_.begin(), itColIdx = itbColIdx;
450 std::vector<number_t>::const_iterator iteColIdx = colIndex_.end();
451 std::vector<number_t>::const_iterator itRowPt = rowPointer_.begin();
452
453 typename std::vector<M1>::const_iterator itm = m1.begin()+1;
454 typename std::vector<M1>::const_iterator itval;
455
456 for(number_t colIdx = 0; colIdx < nbCols_; ++colIdx,++itColPtUmf)
457 {
458 itColIdx = itbColIdx;
459 Idx nzCol = Idx(0); // Number of non-zero in each "working" column
460 while(itColIdx != iteColIdx)
461 {
462 itColIdx = std::find(itColIdx,iteColIdx, colIdx);
463 if(itColIdx != iteColIdx)
464 {
465 itRowPt = std::find_if(rowPointer_.begin(), rowPointer_.end(),std::bind2nd(std::greater_equal<number_t>(), itColIdx - itbColIdx+1));
466
467 // Update values
468 itval = (itColIdx-itbColIdx) + itm;
469 resultUmf.push_back(*itval);
470
471 // Update colPtUmf with number of non-zero value
472 ++nzCol;
473
474 // Update rowIdxUmf
475 rowIdxUmf.push_back(itRowPt-rowPointer_.begin()-1);
476
477 // Increase iterator to make a search in new range
478 ++itColIdx;
479 }
480 }
481 // Update colPtUmf with number of non-zero value
482 *itColPtUmf += *(itColPtUmf-1) + nzCol;
483
484
485 }
486 }
487 /*!
488 incomplete factorization of matrix M stored as matrix F = L U where
489 - L is a lower triangular matrix with unit diagonal and is stored as
490 the strict lower triangular part of F
491 - U is a upper triangular matrix with diagonal stored as diagonal part of F
492 and strict upper triangular part stored as the strict upper triangular part of F :
493
494 */
495 template<typename M>
ilu(std::vector<M> & m,std::vector<M> & f) const496 void RowCsStorage::ilu(std::vector<M>& m, std::vector<M>& f) const
497 {
498
499 trace_p->push("RowCsStorage::ilu");
500 typename std::vector<M>::iterator f_ib=f.begin()+1;
501 std::vector<std::pair<number_t, number_t> > Cj;
502 std::vector<M> Diag(nbRows_);
503 number_t k;
504 Diag[0]=*f_ib;
505 number_t c,l;
506
507 for (number_t j=0; j < nbRows_; j++) // boucle sur les colonnes
508 {
509 Cj=getCol(_noSymmetry,j+1,1,nbRows_);
510 for (number_t p=1; p < Cj.size(); p++)
511 {//Cj[p].first-1 ligne du peme coef non nul col j
512 l=Cj[p].first-1;
513 c = rowPointer_[l];
514 k = 0;
515 while ( (Cj[k].first-1 < l) && (colIndex_[c] < j) )
516 {
517 if (colIndex_[c] == Cj[k].first-1)
518 {
519 *(f_ib+Cj[p].second-1) -=*(f_ib+Cj[k].second-1) * (*(f_ib+c));
520 c++;k++;
521 }
522 else if (colIndex_[c] < Cj[k].first-1) c++;
523 else /*if (colIndex_[c] > Cj[k].first-1) */ k++;
524 }
525 if (Cj[p].first-1 == j)
526 {
527 Diag[j]=*(f_ib+Cj[p].second-1);
528 if(std::abs(Diag[j]) < theZeroThreshold) {error("small_pivot") ; }
529 }
530 else if (Cj[p].first-1 > j) *(f_ib+Cj[p].second-1)/=Diag[j];
531 }
532 }
533 trace_p->pop();
534 }
535
536 } // end of namespace xlifepp
537
538