00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 #include <stdio.h>
00040 #include "sba/csparse.h"
00041 
00042 using namespace Eigen;
00043 
00044 #include <iostream>
00045 #include <iomanip>
00046 #include <fstream>
00047 #include <sys/time.h>
00048 #include <algorithm>
00049 
00050 using namespace std;
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 namespace sba
00072 {
00073 
00074   CSparse::CSparse()
00075   {
00076     A = NULL;
00077 #ifdef SBA_CHOLMOD
00078     chA = NULL;
00079     chInited = false;
00080 #endif
00081     useCholmod = false;
00082     asize = 0;
00083     csize = 0;
00084     nnz = 0;
00085   }
00086 
00087   CSparse::~CSparse()
00088   {
00089     if (A) cs_spfree(A);        
00090   }
00091 
00092 
00093   
00094   void CSparse::setupBlockStructure(int n)
00095   {
00096     if (n > 0)                  
00097       {
00098         diag.clear();
00099         diag.resize(n);
00100         cols.clear();
00101         cols.resize(n);
00102         asize = n;
00103         csize = 6*n;
00104       }
00105 
00106     
00107     B.setZero(csize);
00108     for (int i=0; i<(int)diag.size(); i++)
00109       diag[i].setZero();
00110     for (int i=0; i<(int)cols.size(); i++)
00111       {
00112         map<int,Matrix<double,6,6>, less<int>, 
00113           aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
00114         if (col.size() > 0)
00115           {
00116             map<int,Matrix<double,6,6>, less<int>, 
00117               aligned_allocator<Matrix<double,6,6> > >::iterator it;
00118             for (it = col.begin(); it != col.end(); it++)
00119               it->second.setZero();
00120           }
00121       }
00122   }
00123 
00124   void CSparse::incDiagBlocks(double lam)
00125   {
00126     for (int i=0; i<(int)diag.size(); i++)
00127       diag[i].diagonal() *= lam;
00128   }
00129 
00130   
00131   void CSparse::addOffdiagBlock(Matrix<double,6,6> &m, int ii, int jj)
00132   {
00133     
00134     map<int,Matrix<double,6,6>, less<int>, 
00135       aligned_allocator<Matrix<double,6,6> > > &col = cols[jj];
00136     
00137     map<int,Matrix<double,6,6>, less<int>, 
00138       aligned_allocator<Matrix<double,6,6> > >::iterator it;
00139     it = col.find(ii);
00140     if (it == col.end())        
00141       col.insert(pair<int,Matrix<double,6,6> >(ii,m));
00142     else                        
00143       it->second += m;
00144   }
00145 
00146 
00147   
00148   
00149 
00150   
00151   void CSparse::setupCSstructure(double diaginc, bool init)
00152   {
00153 #ifdef SBA_CHOLMOD
00154     if (useCholmod) {
00155       cholmod_start(&Common); 
00156       Common.print = 0;
00157     }
00158 #endif
00159 
00160     
00161     if (init || useCholmod)
00162       {
00163         
00164         nnz = 21*asize;         
00165         for (int i=0; i<(int)cols.size(); i++)
00166           {
00167             map<int,Matrix<double,6,6>, less<int>, 
00168               aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
00169             nnz += 36 * col.size(); 
00170           }
00171 
00172 #ifdef SBA_CHOLMOD
00173         if (useCholmod)
00174           {
00175             
00176             
00177             
00178             chA = cholmod_allocate_sparse(csize,csize,nnz,true,true,1,CHOLMOD_REAL,&Common);
00179           }
00180         else
00181 #endif
00182           {
00183             if (A) cs_spfree(A);    
00184             A = cs_spalloc(csize,csize,nnz,1,0); 
00185           }
00186 
00187         
00188         int colp = 0;           
00189         int *Ap, *Ai;
00190 #ifdef SBA_CHOLMOD
00191         if (useCholmod)
00192           {
00193             Ap = (int *)chA->p; 
00194             Ai = (int *)chA->i; 
00195           }
00196         else
00197 #endif
00198           {
00199             Ap = A->p;          
00200             Ai = A->i;          
00201           }
00202         for (int i=0; i<(int)cols.size(); i++)
00203           {
00204             
00205             map<int,Matrix<double,6,6>, less<int>, 
00206               aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
00207 
00208             
00209             for (int k=0; k<6; k++)
00210               {
00211                 *Ap++ = colp;
00212                 int row;
00213 
00214                 
00215                 if (col.size() > 0)
00216                   {
00217                     
00218                     map<int,Matrix<double,6,6>, less<int>, 
00219                       aligned_allocator<Matrix<double,6,6> > >::iterator it;
00220 
00221                     
00222                     for (it = col.begin(); it != col.end(); it++)
00223                       {
00224                         row = 6*it->first; 
00225                         for (int j=0; j<6; j++)
00226                           Ai[colp++] = row++;
00227                       }
00228                   }
00229 
00230                 
00231                 row = 6*i;
00232                 for (int kk=0; kk<k+1; kk++)
00233                   Ai[colp++] = row++;
00234               }
00235            }        
00236           *Ap = nnz;            
00237        }
00238 
00239 
00240 
00241      
00242      int colp = 0;              
00243      double *Ax;
00244 #ifdef SBA_CHOLMOD
00245      if (useCholmod)
00246        Ax = (double *)chA->x;   
00247      else
00248 #endif
00249        Ax = A->x;               
00250      for (int i=0; i<(int)cols.size(); i++)
00251        {
00252          
00253          map<int,Matrix<double,6,6>, less<int>, 
00254            aligned_allocator<Matrix<double,6,6> > > &col = cols[i];
00255 
00256          
00257          for (int k=0; k<6; k++)
00258            {
00259              
00260              if (col.size() > 0)
00261                {
00262                  
00263                  map<int,Matrix<double,6,6>, less<int>, 
00264                    aligned_allocator<Matrix<double,6,6> > >::iterator it;
00265 
00266                  
00267                  for (it = col.begin(); it != col.end(); it++)
00268                    {
00269                      Matrix<double,6,6> &m = it->second;
00270                      for (int j=0; j<6; j++)
00271                        Ax[colp++] = m(j,k);
00272                    }
00273                } 
00274 
00275              
00276              Matrix<double,6,6> &m = diag[i]; 
00277              for (int kk=0; kk<k+1; kk++)
00278                Ax[colp++] = m(kk,k);
00279              Ax[colp-1] *= diaginc; 
00280            }
00281        }      
00282 
00283   }
00284 
00285 
00286   
00287   void CSparse::uncompress(MatrixXd &m)
00288   {
00289     if (!A) return;
00290     m.setZero(csize,csize);
00291     
00292     int *Ap = A->p;             
00293     int *Ai = A->i;             
00294     double *Ax = A->x;          
00295 
00296     for (int i=0; i<csize; i++)
00297       {
00298         int rbeg = Ap[i];
00299         int rend = Ap[i+1];
00300         if (rend > rbeg)
00301           for (int j=rbeg; j<rend; j++)
00302             m(Ai[j],i) = Ax[j];
00303       }
00304   }
00305 
00306   
00307   bool CSparse::doChol()
00308   {
00309 #ifdef SBA_CHOLMOD
00310     if (useCholmod)
00311       {
00312         cholmod_dense *x, b, *R, *R2;
00313         cholmod_factor *L ;
00314         double *Xx, *Rx, *bb;
00315         double one [2], minusone [2];
00316         one [0] = 1 ;
00317         one [1] = 0 ;
00318         minusone [0] = -1 ;
00319         minusone [1] = 0 ;
00320 
00321         
00322         cholmod_print_sparse (chA, (char *)"A", &Common) ; 
00323         b.nrow = csize;
00324         b.ncol = 1;
00325         b.d = csize;                
00326         b.nzmax = csize;
00327         b.xtype = CHOLMOD_REAL;
00328         b.dtype = CHOLMOD_DOUBLE;
00329         b.x = B.data();
00330         
00331         L = cholmod_analyze (chA, &Common) ; 
00332         
00333         cholmod_factorize (chA, L, &Common) ; 
00334         
00335         x = cholmod_solve (CHOLMOD_A, L, &b, &Common) ; 
00336         
00337 
00338         
00339         
00340         
00341         R = cholmod_copy_dense (&b, &Common) ;
00342         cholmod_sdmult(chA, 0, minusone, one, x, R, &Common) ;
00343         
00344         R2 = cholmod_solve (CHOLMOD_A, L, R, &Common) ;
00345         
00346         Xx = (double *)x->x ;
00347         Rx = (double *)R2->x ;
00348         for (int i=0 ; i<csize ; i++)
00349         {
00350           Xx[i] = Xx[i] + Rx[i] ;
00351         }
00352         cholmod_free_dense (&R2, &Common) ;
00353         cholmod_free_dense (&R, &Common) ;
00354 
00355         bb = B.data();
00356         for (int i=0; i<csize; i++) 
00357           *bb++ = *Xx++;
00358         cholmod_free_factor (&L, &Common) ; 
00359         cholmod_free_dense (&x, &Common) ;
00360         cholmod_free_sparse(&chA, &Common);
00361         cholmod_finish (&Common) ;   
00362 
00363         return true;
00364       }
00365     else
00366 #endif
00367       {
00368         
00369         
00370         int order = 0;
00371         if (csize > 400) order = 1;
00372         bool ok = (bool)cs_cholsol(order,A,B.data()); 
00373         return ok;
00374       }
00375   }
00376 
00377 
00378   
00379   
00380   
00381   
00382 
00383   int 
00384   CSparse::doBPCG(int iters, double tol, int sba_iter)
00385   {
00386     int n = B.rows();
00387     VectorXd x;
00388     x.setZero(n);
00389     bool abstol = false;
00390     if (sba_iter > 0) abstol = true;
00391     int ret;
00392     ret = bpcg.doBPCG2(iters, tol, diag, cols, x, B, abstol);
00393     B = x;                      
00394     return ret;
00395   }
00396 
00397 
00398   
00399   
00400   
00401 
00402   CSparse2d::CSparse2d()
00403   {
00404     A = NULL;
00405     AF = NULL;
00406 #ifdef SBA_CHOLMOD
00407     chA = NULL;
00408     chInited = false;
00409     Common.print=0;
00410 #endif
00411     asize = 0;
00412     csize = 0;
00413     nnz = 0;
00414     Bprev.resize(0);
00415   }
00416 
00417   CSparse2d::~CSparse2d()
00418   {
00419     if (A) cs_spfree(A);        
00420     if (AF) cs_spfree(AF);      
00421   }
00422 
00423 
00424   
00425   void CSparse2d::setupBlockStructure(int n, bool eraseit)
00426   {
00427     if (n > 0)                  
00428       {
00429         diag.resize(n);
00430         cols.resize(n);
00431         if (eraseit)
00432           for (int i=0; i<(int)cols.size(); i++)
00433             {
00434               map<int,Matrix<double,3,3>, less<int>, 
00435                 aligned_allocator< Matrix <double,3,3> > > &col = cols[i];
00436               col.clear();
00437             }
00438         asize = n;
00439         csize = 3*n;
00440       }
00441 
00442     if (eraseit)
00443       {
00444         
00445         B.setZero(csize);
00446         for (int i=0; i<(int)diag.size(); i++)
00447           diag[i].setZero();
00448         for (int i=0; i<(int)cols.size(); i++)
00449           {
00450             map<int,Matrix<double,3,3>, less<int>, 
00451               aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
00452             if (col.size() > 0)
00453               {
00454                 map<int,Matrix<double,3,3>, less<int>, 
00455                   aligned_allocator<Matrix<double,3,3> > >::iterator it;
00456                 for (it = col.begin(); it != col.end(); it++)
00457                   it->second.setZero();
00458               }
00459           }
00460       }
00461 
00462     else                        
00463       {
00464         B.setZero(csize);
00465         if (Bprev.size() > 0)
00466           B.head(Bprev.size()) = Bprev;
00467       }
00468   }
00469 
00470 
00471   
00472   void CSparse2d::addOffdiagBlock(Matrix<double,3,3> &m, int ii, int jj)
00473   {
00474     
00475     map<int,Matrix<double,3,3>, less<int>, 
00476       aligned_allocator<Matrix<double,3,3> > > &col = cols[jj];
00477     
00478     map<int,Matrix<double,3,3>, less<int>, 
00479       aligned_allocator<Matrix<double,3,3> > >::iterator it;
00480     it = col.find(ii);
00481     if (it == col.end())        
00482       col.insert(pair<int,Matrix<double,3,3> >(ii,m));
00483     else                        
00484       it->second += m;
00485   }
00486 
00487 
00488   void CSparse2d::incDiagBlocks(double lam)
00489   {
00490     for (int i=0; i<(int)diag.size(); i++)
00491       diag[i].diagonal() *= lam;
00492   }
00493 
00494 
00495   
00496   
00497 
00498   
00499   
00500 
00501   void CSparse2d::setupCSstructure(double diaginc, bool init)
00502   {
00503 #ifdef SBA_CHOLMOD
00504     if (useCholmod) {
00505       cholmod_start(&Common); 
00506       Common.print = 0;
00507     }
00508 #endif
00509 
00510     
00511     if (init || useCholmod)
00512       {
00513         if (A) cs_spfree(A);    
00514 
00515         
00516         nnz = 6*asize;         
00517         for (int i=0; i<(int)cols.size(); i++)
00518           {
00519             map<int,Matrix<double,3,3>, less<int>, 
00520               aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
00521             nnz += 9 * col.size(); 
00522           }
00523 #ifdef SBA_CHOLMOD
00524         if (useCholmod)
00525           {
00526             
00527             
00528             
00529             chA = cholmod_allocate_sparse(csize,csize,nnz,true,true,1,CHOLMOD_REAL,&Common);
00530           }
00531         else
00532 #endif
00533           {
00534             A = cs_spalloc(csize,csize,nnz,1,0); 
00535           }
00536         
00537         
00538         int colp = 0;           
00539         int *Ap, *Ai;
00540 #ifdef SBA_CHOLMOD
00541         if (useCholmod)
00542           {
00543             Ap = (int *)chA->p; 
00544             Ai = (int *)chA->i; 
00545           }
00546         else
00547 #endif
00548           {
00549             Ap = A->p;          
00550             Ai = A->i;          
00551           }
00552 
00553         for (int i=0; i<(int)cols.size(); i++)
00554           {
00555             
00556             map<int,Matrix<double,3,3>, less<int>, 
00557               aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
00558 
00559             
00560             for (int k=0; k<3; k++)
00561               {
00562                 *Ap++ = colp;
00563                 int row;
00564 
00565                 
00566                 if (col.size() > 0)
00567                   {
00568                     
00569                     map<int,Matrix<double,3,3>, less<int>, 
00570                       aligned_allocator<Matrix<double,3,3> > >::iterator it;
00571 
00572                     
00573                     for (it = col.begin(); it != col.end(); it++)
00574                       {
00575                         row = 3*it->first; 
00576                         for (int j=0; j<3; j++)
00577                           Ai[colp++] = row++;
00578                       }
00579                   }
00580 
00581                 
00582                 row = 3*i;
00583                 for (int kk=0; kk<k+1; kk++)
00584                   Ai[colp++] = row++;
00585               }
00586            }        
00587           *Ap = nnz;       
00588        }
00589 
00590      
00591      int colp = 0;           
00592      double *Ax;
00593 #ifdef SBA_CHOLMOD
00594      if (useCholmod)
00595        Ax = (double *)chA->x;   
00596      else
00597 #endif
00598        Ax = A->x;               
00599 
00600      for (int i=0; i<(int)cols.size(); i++)
00601        {
00602          
00603          map<int,Matrix<double,3,3>, less<int>, 
00604            aligned_allocator<Matrix<double,3,3> > > &col = cols[i];
00605 
00606          
00607          for (int k=0; k<3; k++)
00608            {
00609              
00610              if (col.size() > 0)
00611                {
00612                  
00613                  map<int,Matrix<double,3,3>, less<int>, 
00614                    aligned_allocator<Matrix<double,3,3> > >::iterator it;
00615 
00616                  
00617                  for (it = col.begin(); it != col.end(); it++)
00618                    {
00619                      Matrix<double,3,3> &m = it->second;
00620                      for (int j=0; j<3; j++)
00621                        Ax[colp++] = m(j,k);
00622                    }
00623                } 
00624 
00625              
00626              Matrix<double,3,3> &m = diag[i]; 
00627              for (int kk=0; kk<k+1; kk++)
00628                Ax[colp++] = m(kk,k);
00629              Ax[colp-1] *= diaginc; 
00630            }
00631        }      
00632 
00633      
00634      
00635      
00636   }
00637 
00638 
00639   
00640   void CSparse2d::uncompress(MatrixXd &m)
00641   {
00642     if (!A) return;
00643     m.setZero(csize,csize);
00644     
00645     int *Ap = A->p;             
00646     int *Ai = A->i;             
00647     double *Ax = A->x;          
00648 
00649     for (int i=0; i<csize; i++)
00650       {
00651         int rbeg = Ap[i];
00652         int rend = Ap[i+1];
00653         if (rend > rbeg)
00654           for (int j=rbeg; j<rend; j++)
00655             m(Ai[j],i) = Ax[j];
00656       }
00657   }
00658 
00659   
00660   bool CSparse2d::doChol()
00661   {
00662 #ifdef SBA_CHOLMOD
00663     if (useCholmod)
00664       {
00665         cholmod_dense *x, b, *R, *R2;
00666         cholmod_factor *L ;
00667         double *Xx, *Rx, *bb;
00668         double one [2], minusone [2];
00669         one [0] = 1 ;
00670         one [1] = 0 ;
00671         minusone [0] = -1 ;
00672         minusone [1] = 0 ;
00673 
00674         
00675         cholmod_print_sparse (chA, (char *)"A", &Common) ; 
00676         b.nrow = csize;
00677         b.ncol = 1;
00678         b.d = csize;                
00679         b.nzmax = csize;
00680         b.xtype = CHOLMOD_REAL;
00681         b.dtype = CHOLMOD_DOUBLE;
00682         b.x = B.data();
00683         
00684         L = cholmod_analyze (chA, &Common) ; 
00685         
00686         cholmod_factorize (chA, L, &Common) ; 
00687         
00688         x = cholmod_solve (CHOLMOD_A, L, &b, &Common) ; 
00689         
00690 
00691         
00692         
00693         
00694         R = cholmod_copy_dense (&b, &Common) ;
00695         cholmod_sdmult(chA, 0, minusone, one, x, R, &Common) ;
00696         
00697         R2 = cholmod_solve (CHOLMOD_A, L, R, &Common) ;
00698         
00699         Xx = (double *)x->x ;
00700         Rx = (double *)R2->x ;
00701         for (int i=0 ; i<csize ; i++)
00702         {
00703           Xx[i] = Xx[i] + Rx[i] ;
00704         }
00705         cholmod_free_dense (&R2, &Common) ;
00706         cholmod_free_dense (&R, &Common) ;
00707 
00708         bb = B.data();
00709         for (int i=0; i<csize; i++) 
00710           *bb++ = *Xx++;
00711         cholmod_free_factor (&L, &Common) ; 
00712         cholmod_free_dense (&x, &Common) ;
00713         cholmod_free_sparse(&chA, &Common);
00714         cholmod_finish (&Common) ;   
00715 
00716         return true;
00717       }
00718     else
00719 #endif
00720       {
00721 
00722         
00723         
00724         int order = 0;
00725         if (csize > 100) order = 1;
00726         bool ok = (bool)cs_cholsol(order,A,B.data()); 
00727         return ok;
00728       }
00729   }
00730 
00731 
00732   
00733   
00734   
00735   
00736 
00737   int 
00738   CSparse2d::doBPCG(int iters, double tol, int sba_iter)
00739   {
00740     int n = B.rows();
00741     VectorXd x;
00742     x.setZero(n);
00743     bool abstol = false;
00744     if (sba_iter > 0) abstol = true;
00745     int ret;
00746     ret = bpcg.doBPCG2(iters, tol, diag, cols, x, B, abstol);
00747     B = x;                      
00748     return ret;
00749   }
00750 
00751 
00752 #ifdef SBA_DSIF
00753   
00754   
00755   int CSparse2d::doPCG(int iters)
00756   {
00757     
00758     
00759 
00760     
00761     cs *AT;
00762     AT = cs_transpose(A,1);
00763     cs_fkeep (AT, &dropdiag, NULL); 
00764     if (AF) cs_spfree(AF);      
00765     AF = cs_add (A, AT, 1, 1);  
00766     cs_spfree (AT);
00767 
00768     
00769     CompCol_Mat_double Ap(csize, csize, AF->nzmax, AF->x, AF->i, AF->p); 
00770     VECTOR_double b(B.data(),csize);   
00771     VECTOR_double x(csize, 0.0); 
00772 
00773     
00774     int res;
00775     double tol = 1e-6;
00776     ICPreconditioner_double D(Ap); 
00777     res = CG(Ap,x,b,D,iters,tol); 
00778 
00779     for (int i=0; i<csize; i++)
00780       B[i] = x[i];
00781 
00782     
00783     
00784     
00785     
00786 
00787     return res;
00788   }
00789 #endif
00790 
00791 
00792 }