csparse.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2009, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 //
36 // Interface to CSparse
37 //
38 
39 #include <stdio.h>
41 
42 using namespace Eigen;
43 
44 #include <iostream>
45 #include <iomanip>
46 #include <fstream>
47 #include <sys/time.h>
48 #include <algorithm>
49 
50 using namespace std;
51 
52 
53 //
54 // Efficient interface to the CSparse sparse solver
55 //
56 // Basic idea is to store 6x6 blocks in a sparse structure,
57 // and when we're done forming the A matrix, transfer to
58 // a CSparse compressed structure. The latter only has
59 // to be initialized once at the start of the nonlinear iterations.
60 //
61 
62 //
63 // CSparse holds its sparse NxN arrays in compressed column format:
64 //
65 // col_ptr has N+1 entries, one for each column, and a final NNZ entry.
66 // each entry is the index in row_ptr of where the column starts.
67 // row_ind has NNZ entries, each one a row index for an element.
68 // vals has NNZ entries corresponding to the row_ptr entries
69 //
70 
71 namespace sba
72 {
73 
74  CSparse::CSparse()
75  {
76  A = NULL;
77 #ifdef SBA_CHOLMOD
78  chA = NULL;
79  chInited = false;
80 #endif
81  useCholmod = false;
82  asize = 0;
83  csize = 0;
84  nnz = 0;
85  }
86 
87  CSparse::~CSparse()
88  {
89  if (A) cs_spfree(A); // free any previous structure
90  }
91 
92 
93  // 6x6 sparse jacobian blocks
94  void CSparse::setupBlockStructure(int n)
95  {
96  if (n > 0) // set up initial structure
97  {
98  diag.clear();
99  diag.resize(n);
100  cols.clear();
101  cols.resize(n);
102  asize = n;
103  csize = 6*n;
104  }
105 
106  // zero out entries
107  B.setZero(csize);
108  for (int i=0; i<(int)diag.size(); i++)
109  diag[i].setZero();
110  for (int i=0; i<(int)cols.size(); i++)
111  {
112  map<int,Matrix<double,6,6>, less<int>,
113  aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
114  if (col.size() > 0)
115  {
116  map<int,Matrix<double,6,6>, less<int>,
117  aligned_allocator<Matrix<double,6,6> > >::iterator it;
118  for (it = col.begin(); it != col.end(); it++)
119  it->second.setZero();
120  }
121  }
122  }
123 
124  void CSparse::incDiagBlocks(double lam)
125  {
126  for (int i=0; i<(int)diag.size(); i++)
127  diag[i].diagonal() *= lam;
128  }
129 
130  // add an off-diagonal block
131  void CSparse::addOffdiagBlock(Matrix<double,6,6> &m, int ii, int jj)
132  {
133  // get column
134  map<int,Matrix<double,6,6>, less<int>,
135  aligned_allocator<Matrix<double,6,6> > > &col = cols[jj];
136  // find current matrix
137  map<int,Matrix<double,6,6>, less<int>,
138  aligned_allocator<Matrix<double,6,6> > >::iterator it;
139  it = col.find(ii);
140  if (it == col.end()) // didn't find it
141  col.insert(pair<int,Matrix<double,6,6> >(ii,m));
142  else // found it, add
143  it->second += m;
144  }
145 
146 
147  // set up CSparse structure; <init> true if first time
148  // <diaginc> is the diagonal multiplier for LM
149 
150  // this version sets upper triangular matrix,
151  void CSparse::setupCSstructure(double diaginc, bool init)
152  {
153 #ifdef SBA_CHOLMOD
154  if (useCholmod) {
155  cholmod_start(&Common); // this is finished in doChol()
156  Common.print = 0;
157  }
158 #endif
159 
160  // reserve space and set things up
161  if (init || useCholmod)
162  {
163  // count entries for cs allocation
164  nnz = 21*asize; // diagonal entries, just upper triangle
165  for (int i=0; i<(int)cols.size(); i++)
166  {
167  map<int,Matrix<double,6,6>, less<int>,
168  aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
169  nnz += 36 * col.size(); // 6x6 matrix
170  }
171 
172 #ifdef SBA_CHOLMOD
173  if (useCholmod)
174  {
175  // cholmod_start(&Common); // this is finished in doChol()
176  // if (chA)
177  // cholmod_free_sparse(&chA, &Common);
178  chA = cholmod_allocate_sparse(csize,csize,nnz,true,true,1,CHOLMOD_REAL,&Common);
179  }
180  else
181 #endif
182  {
183  if (A) cs_spfree(A); // free any previous structure
184  A = cs_spalloc(csize,csize,nnz,1,0); // allocate sparse matrix
185  }
186 
187  // now figure out the column pointers
188  int colp = 0; // index of where the column starts in Ai
189  int *Ap, *Ai;
190 #ifdef SBA_CHOLMOD
191  if (useCholmod)
192  {
193  Ap = (int *)chA->p; // column pointer
194  Ai = (int *)chA->i; // row indices
195  }
196  else
197 #endif
198  {
199  Ap = A->p; // column pointer
200  Ai = A->i; // row indices
201  }
202  for (int i=0; i<(int)cols.size(); i++)
203  {
204  // column i entries
205  map<int,Matrix<double,6,6>, less<int>,
206  aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
207 
208  // do this for 6 columns
209  for (int k=0; k<6; k++)
210  {
211  *Ap++ = colp;
212  int row;
213 
214  // iterate over the map
215  if (col.size() > 0)
216  {
217  // map iterator
218  map<int,Matrix<double,6,6>, less<int>,
219  aligned_allocator<Matrix<double,6,6> > >::iterator it;
220 
221  // iterate over block column entries
222  for (it = col.begin(); it != col.end(); it++)
223  {
224  row = 6*it->first; // which row we're at
225  for (int j=0; j<6; j++)
226  Ai[colp++] = row++;
227  }
228  }
229 
230  // add in diagonal entries
231  row = 6*i;
232  for (int kk=0; kk<k+1; kk++)
233  Ai[colp++] = row++;
234  }
235  }
236  *Ap = nnz; // last entry
237  }
238 
239 
240 
241  // now put the entries in place
242  int colp = 0; // index of where the column starts in Ai
243  double *Ax;
244 #ifdef SBA_CHOLMOD
245  if (useCholmod)
246  Ax = (double *)chA->x; // values
247  else
248 #endif
249  Ax = A->x; // values
250  for (int i=0; i<(int)cols.size(); i++)
251  {
252  // column i entries
253  map<int,Matrix<double,6,6>, less<int>,
254  aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
255 
256  // do this for 6 columns
257  for (int k=0; k<6; k++)
258  {
259  // iterate over the map
260  if (col.size() > 0)
261  {
262  // map iterator
263  map<int,Matrix<double,6,6>, less<int>,
264  aligned_allocator<Matrix<double,6,6> > >::iterator it;
265 
266  // iterate over block column entries
267  for (it = col.begin(); it != col.end(); it++)
268  {
269  Matrix<double,6,6> &m = it->second;
270  for (int j=0; j<6; j++)
271  Ax[colp++] = m(j,k);
272  }
273  }
274 
275  // add in diagonal entries
276  Matrix<double,6,6> &m = diag[i]; // diagonal block
277  for (int kk=0; kk<k+1; kk++)
278  Ax[colp++] = m(kk,k);
279  Ax[colp-1] *= diaginc; // increment diagonal for LM
280  }
281  }
282 
283  }
284 
285 
286  // uncompress the compressed A into a dense Eigen matrix
287  void CSparse::uncompress(MatrixXd &m)
288  {
289  if (!A) return;
290  m.setZero(csize,csize);
291 
292  int *Ap = A->p; // column pointer
293  int *Ai = A->i; // row indices
294  double *Ax = A->x; // values;
295 
296  for (int i=0; i<csize; i++)
297  {
298  int rbeg = Ap[i];
299  int rend = Ap[i+1];
300  if (rend > rbeg)
301  for (int j=rbeg; j<rend; j++)
302  m(Ai[j],i) = Ax[j];
303  }
304  }
305 
306  // solve in place, returns RHS B
307  bool CSparse::doChol()
308  {
309 #ifdef SBA_CHOLMOD
310  if (useCholmod)
311  {
312  cholmod_dense *x, b, *R, *R2;
313  cholmod_factor *L ;
314  double *Xx, *Rx, *bb;
315  double one [2], minusone [2];
316  one [0] = 1 ;
317  one [1] = 0 ;
318  minusone [0] = -1 ;
319  minusone [1] = 0 ;
320 
321  // cholmod_start (&Common) ; // start it up ???
322  cholmod_print_sparse (chA, (char *)"A", &Common) ; // print simple stats
323  b.nrow = csize;
324  b.ncol = 1;
325  b.d = csize; // leading dimension (???)
326  b.nzmax = csize;
327  b.xtype = CHOLMOD_REAL;
328  b.dtype = CHOLMOD_DOUBLE;
329  b.x = B.data();
330  //cout << "CHOLMOD analyze..." << flush;
331  L = cholmod_analyze (chA, &Common) ; // analyze
332  //cout << "factorize..." << flush;
333  cholmod_factorize (chA, L, &Common) ; // factorize
334  //cout << "solve..." << flush;
335  x = cholmod_solve (CHOLMOD_A, L, &b, &Common) ; // solve Ax=b
336  // cholmod_print_factor (L, (char *)"L", &Common) ;
337 
338  //cout << "refine" << endl;
339  // one step of iterative refinement, cheap
340  /* Ax=b was factorized and solved, R = B-A*X */
341  R = cholmod_copy_dense (&b, &Common) ;
342  cholmod_sdmult(chA, 0, minusone, one, x, R, &Common) ;
343  /* R2 = A\(B-A*X) */
344  R2 = cholmod_solve (CHOLMOD_A, L, R, &Common) ;
345  /* compute X = X + A\(B-A*X) */
346  Xx = (double *)x->x ;
347  Rx = (double *)R2->x ;
348  for (int i=0 ; i<csize ; i++)
349  {
350  Xx[i] = Xx[i] + Rx[i] ;
351  }
352  cholmod_free_dense (&R2, &Common) ;
353  cholmod_free_dense (&R, &Common) ;
354 
355  bb = B.data();
356  for (int i=0; i<csize; i++) // transfer answer
357  *bb++ = *Xx++;
358  cholmod_free_factor (&L, &Common) ; // free matrices
359  cholmod_free_dense (&x, &Common) ;
360  cholmod_free_sparse(&chA, &Common);
361  cholmod_finish (&Common) ; // finish it ???
362 
363  return true;
364  }
365  else
366 #endif
367  {
368  // using order 0 here (natural order);
369  // may be better to use "1" for large problems
370  int order = 0;
371  if (csize > 400) order = 1;
372  bool ok = (bool)cs_cholsol(order,A,B.data()); // do the CSparse thang
373  return ok;
374  }
375  }
376 
377 
378  //
379  // block jacobian PCG
380  // max iterations <iter>, ending toleranace <tol>
381  //
382 
383  int
384  CSparse::doBPCG(int iters, double tol, int sba_iter)
385  {
386  int n = B.rows();
387  VectorXd x;
388  x.setZero(n);
389  bool abstol = false;
390  if (sba_iter > 0) abstol = true;
391  int ret;
392  ret = bpcg.doBPCG2(iters, tol, diag, cols, x, B, abstol);
393  B = x; // transfer result data
394  return ret;
395  }
396 
397 
398  //
399  // 2d version
400  //
401 
402  CSparse2d::CSparse2d()
403  {
404  A = NULL;
405  AF = NULL;
406 #ifdef SBA_CHOLMOD
407  chA = NULL;
408  chInited = false;
409  Common.print=0;
410 #endif
411  asize = 0;
412  csize = 0;
413  nnz = 0;
414  Bprev.resize(0);
415  }
416 
417  CSparse2d::~CSparse2d()
418  {
419  if (A) cs_spfree(A); // free any previous structure
420  if (AF) cs_spfree(AF); // free any previous structure
421  }
422 
423 
424  // 3x3 sparse jacobian blocks
425  void CSparse2d::setupBlockStructure(int n, bool eraseit)
426  {
427  if (n > 0) // set up initial structure
428  {
429  diag.resize(n);
430  cols.resize(n);
431  if (eraseit)
432  for (int i=0; i<(int)cols.size(); i++)
433  {
434  map<int,Matrix<double,3,3>, less<int>,
435  aligned_allocator< Matrix <double,3,3> > > &col = cols[i];
436  col.clear();
437  }
438  asize = n;
439  csize = 3*n;
440  }
441 
442  if (eraseit)
443  {
444  // zero out entries
445  B.setZero(csize);
446  for (int i=0; i<(int)diag.size(); i++)
447  diag[i].setZero();
448  for (int i=0; i<(int)cols.size(); i++)
449  {
450  map<int,Matrix<double,3,3>, less<int>,
451  aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
452  if (col.size() > 0)
453  {
454  map<int,Matrix<double,3,3>, less<int>,
455  aligned_allocator<Matrix<double,3,3> > >::iterator it;
456  for (it = col.begin(); it != col.end(); it++)
457  it->second.setZero();
458  }
459  }
460  }
461 
462  else // here we just resize B, saving the old parts
463  {
464  B.setZero(csize);
465  if (Bprev.size() > 0)
466  B.head(Bprev.size()) = Bprev;
467  }
468  }
469 
470 
471  // add an off-diagonal block
472  void CSparse2d::addOffdiagBlock(Matrix<double,3,3> &m, int ii, int jj)
473  {
474  // get column
475  map<int,Matrix<double,3,3>, less<int>,
476  aligned_allocator<Matrix<double,3,3> > > &col = cols[jj];
477  // find current matrix
478  map<int,Matrix<double,3,3>, less<int>,
479  aligned_allocator<Matrix<double,3,3> > >::iterator it;
480  it = col.find(ii);
481  if (it == col.end()) // didn't find it
482  col.insert(pair<int,Matrix<double,3,3> >(ii,m));
483  else // found it, add
484  it->second += m;
485  }
486 
487 
488  void CSparse2d::incDiagBlocks(double lam)
489  {
490  for (int i=0; i<(int)diag.size(); i++)
491  diag[i].diagonal() *= lam;
492  }
493 
494 
495  // set up CSparse2d structure; <init> true if first time
496  // <diaginc> is the diagonal multiplier for LM
497 
498  // this version only sets upper triangular matrix,
499  // should set whole thing
500 
501  void CSparse2d::setupCSstructure(double diaginc, bool init)
502  {
503 #ifdef SBA_CHOLMOD
504  if (useCholmod) {
505  cholmod_start(&Common); // this is finished in doChol()
506  Common.print = 0;
507  }
508 #endif
509 
510  // reserve space and set things up
511  if (init || useCholmod)
512  {
513  if (A) cs_spfree(A); // free any previous structure
514 
515  // count entries for cs allocation
516  nnz = 6*asize; // diagonal entries, just upper triangle
517  for (int i=0; i<(int)cols.size(); i++)
518  {
519  map<int,Matrix<double,3,3>, less<int>,
520  aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
521  nnz += 9 * col.size(); // 3x3 matrix
522  }
523 #ifdef SBA_CHOLMOD
524  if (useCholmod)
525  {
526  // cholmod_start(&Common); // this is finished in doChol()
527  // if (chA)
528  // cholmod_free_sparse(&chA, &Common);
529  chA = cholmod_allocate_sparse(csize,csize,nnz,true,true,1,CHOLMOD_REAL,&Common);
530  }
531  else
532 #endif
533  {
534  A = cs_spalloc(csize,csize,nnz,1,0); // allocate sparse matrix
535  }
536 
537  // now figure out the column pointers
538  int colp = 0; // index of where the column starts in Ai
539  int *Ap, *Ai;
540 #ifdef SBA_CHOLMOD
541  if (useCholmod)
542  {
543  Ap = (int *)chA->p; // column pointer
544  Ai = (int *)chA->i; // row indices
545  }
546  else
547 #endif
548  {
549  Ap = A->p; // column pointer
550  Ai = A->i; // row indices
551  }
552 
553  for (int i=0; i<(int)cols.size(); i++)
554  {
555  // column i entries
556  map<int,Matrix<double,3,3>, less<int>,
557  aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
558 
559  // do this for 3 columns
560  for (int k=0; k<3; k++)
561  {
562  *Ap++ = colp;
563  int row;
564 
565  // iterate over the map
566  if (col.size() > 0)
567  {
568  // map iterator
569  map<int,Matrix<double,3,3>, less<int>,
570  aligned_allocator<Matrix<double,3,3> > >::iterator it;
571 
572  // iterate over block column entries
573  for (it = col.begin(); it != col.end(); it++)
574  {
575  row = 3*it->first; // which row we're at
576  for (int j=0; j<3; j++)
577  Ai[colp++] = row++;
578  }
579  }
580 
581  // add in diagonal entries
582  row = 3*i;
583  for (int kk=0; kk<k+1; kk++)
584  Ai[colp++] = row++;
585  }
586  }
587  *Ap = nnz; // last entry
588  }
589 
590  // now put the entries in place
591  int colp = 0; // index of where the column starts in Ai
592  double *Ax;
593 #ifdef SBA_CHOLMOD
594  if (useCholmod)
595  Ax = (double *)chA->x; // values
596  else
597 #endif
598  Ax = A->x; // values
599 
600  for (int i=0; i<(int)cols.size(); i++)
601  {
602  // column i entries
603  map<int,Matrix<double,3,3>, less<int>,
604  aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
605 
606  // do this for 3 columns
607  for (int k=0; k<3; k++)
608  {
609  // iterate over the map
610  if (col.size() > 0)
611  {
612  // map iterator
613  map<int,Matrix<double,3,3>, less<int>,
614  aligned_allocator<Matrix<double,3,3> > >::iterator it;
615 
616  // iterate over block column entries
617  for (it = col.begin(); it != col.end(); it++)
618  {
619  Matrix<double,3,3> &m = it->second;
620  for (int j=0; j<3; j++)
621  Ax[colp++] = m(j,k);
622  }
623  }
624 
625  // add in diagonal entries
626  Matrix<double,3,3> &m = diag[i]; // diagonal block
627  for (int kk=0; kk<k+1; kk++)
628  Ax[colp++] = m(kk,k);
629  Ax[colp-1] *= diaginc; // increment diagonal for LM
630  }
631  }
632 
633  // make symmetric from upper diagonal
634  // this could be more efficient if AT were eliminated and AF were fixed
635  // oops - chol_sol only needs upper diag
636  }
637 
638 
639  // uncompress the compressed A into a dense Eigen matrix
640  void CSparse2d::uncompress(MatrixXd &m)
641  {
642  if (!A) return;
643  m.setZero(csize,csize);
644 
645  int *Ap = A->p; // column pointer
646  int *Ai = A->i; // row indices
647  double *Ax = A->x; // values;
648 
649  for (int i=0; i<csize; i++)
650  {
651  int rbeg = Ap[i];
652  int rend = Ap[i+1];
653  if (rend > rbeg)
654  for (int j=rbeg; j<rend; j++)
655  m(Ai[j],i) = Ax[j];
656  }
657  }
658 
659  // solve in place, returns RHS B
660  bool CSparse2d::doChol()
661  {
662 #ifdef SBA_CHOLMOD
663  if (useCholmod)
664  {
665  cholmod_dense *x, b, *R, *R2;
666  cholmod_factor *L ;
667  double *Xx, *Rx, *bb;
668  double one [2], minusone [2];
669  one [0] = 1 ;
670  one [1] = 0 ;
671  minusone [0] = -1 ;
672  minusone [1] = 0 ;
673 
674  // cholmod_start (&Common) ; // start it up ???
675  cholmod_print_sparse (chA, (char *)"A", &Common) ; // print simple stats
676  b.nrow = csize;
677  b.ncol = 1;
678  b.d = csize; // leading dimension (???)
679  b.nzmax = csize;
680  b.xtype = CHOLMOD_REAL;
681  b.dtype = CHOLMOD_DOUBLE;
682  b.x = B.data();
683  //cout << "CHOLMOD analyze..." << flush;
684  L = cholmod_analyze (chA, &Common) ; // analyze
685  //cout << "factorize..." << flush;
686  cholmod_factorize (chA, L, &Common) ; // factorize
687  //cout << "solve..." << flush;
688  x = cholmod_solve (CHOLMOD_A, L, &b, &Common) ; // solve Ax=b
689  // cholmod_print_factor (L, (char *)"L", &Common) ;
690 
691  //cout << "refine" << endl;
692  // one step of iterative refinement, cheap
693  /* Ax=b was factorized and solved, R = B-A*X */
694  R = cholmod_copy_dense (&b, &Common) ;
695  cholmod_sdmult(chA, 0, minusone, one, x, R, &Common) ;
696  /* R2 = A\(B-A*X) */
697  R2 = cholmod_solve (CHOLMOD_A, L, R, &Common) ;
698  /* compute X = X + A\(B-A*X) */
699  Xx = (double *)x->x ;
700  Rx = (double *)R2->x ;
701  for (int i=0 ; i<csize ; i++)
702  {
703  Xx[i] = Xx[i] + Rx[i] ;
704  }
705  cholmod_free_dense (&R2, &Common) ;
706  cholmod_free_dense (&R, &Common) ;
707 
708  bb = B.data();
709  for (int i=0; i<csize; i++) // transfer answer
710  *bb++ = *Xx++;
711  cholmod_free_factor (&L, &Common) ; // free matrices
712  cholmod_free_dense (&x, &Common) ;
713  cholmod_free_sparse(&chA, &Common);
714  cholmod_finish (&Common) ; // finish it ???
715 
716  return true;
717  }
718  else
719 #endif
720  {
721 
722  // using order 0 here (natural order);
723  // may be better to use "1" for large problems (AMD)
724  int order = 0;
725  if (csize > 100) order = 1;
726  bool ok = (bool)cs_cholsol(order,A,B.data()); // do the CSparse2d thang
727  return ok;
728  }
729  }
730 
731 
732  //
733  // block jacobian PCG
734  // max iterations <iter>, ending toleranace <tol>
735  //
736 
737  int
738  CSparse2d::doBPCG(int iters, double tol, int sba_iter)
739  {
740  int n = B.rows();
741  VectorXd x;
742  x.setZero(n);
743  bool abstol = false;
744  if (sba_iter > 0) abstol = true;
745  int ret;
746  ret = bpcg.doBPCG2(iters, tol, diag, cols, x, B, abstol);
747  B = x; // transfer result data
748  return ret;
749  }
750 
751 
752 #ifdef SBA_DSIF
753  // solve in place, returns RHS B
754  // PCG algorithm from SparseLib++, IML++
755  int CSparse2d::doPCG(int iters)
756  {
757  // first convert sparse matrix to SparseLib++ format
758  // do we need just upper triangular here???
759 
760  // add in lower triangular part
761  cs *AT;
762  AT = cs_transpose(A,1);
763  cs_fkeep (AT, &dropdiag, NULL); // drop diagonal entries from AT
764  if (AF) cs_spfree(AF); // free any previous structure
765  AF = cs_add (A, AT, 1, 1); // AF = A+AT
766  cs_spfree (AT);
767 
768  // convert to SparseLib objects
769  CompCol_Mat_double Ap(csize, csize, AF->nzmax, AF->x, AF->i, AF->p);
770  VECTOR_double b(B.data(),csize); // Create rhs
771  VECTOR_double x(csize, 0.0); // solution vectors
772 
773  // perform PCG
774  int res;
775  double tol = 1e-6;
776  ICPreconditioner_double D(Ap); // Create diagonal preconditioner
777  res = CG(Ap,x,b,D,iters,tol); // Solve system
778 
779  for (int i=0; i<csize; i++)
780  B[i] = x[i];
781 
782  // cout << "CG flag = " << res << endl;
783  // cout << "iterations performed: " << iters << endl;
784  // cout << "tolerance achieved : " << tol << endl;
785  // cout << x << endl;
786 
787  return res;
788  }
789 #endif
790 
791 
792 } // end namespace sba
Definition: bpcg.h:60


sparse_bundle_adjustment
Author(s):
autogenerated on Fri Mar 15 2019 02:41:45