xref: /petsc/src/mat/impls/sbaij/seq/cholmod/sbaijcholmod.c (revision 641875f930c9f30c11279648367d1089420d65d5)
1*641875f9SMatthew G Knepley #define PETSCMAT_DLL
2*641875f9SMatthew G Knepley 
3*641875f9SMatthew G Knepley /*
4*641875f9SMatthew G Knepley    Provides an interface to the CHOLMOD 1.7.1 sparse solver
5*641875f9SMatthew G Knepley 
6*641875f9SMatthew G Knepley    When build with PETSC_USE_64BIT_INDICES this will use UF_Long as the
7*641875f9SMatthew G Knepley    integer type in UMFPACK, otherwise it will use int. This means
8*641875f9SMatthew G Knepley    all integers in this file as simply declared as PetscInt. Also it means
9*641875f9SMatthew G Knepley    that UMFPACK UL_Long version MUST be built with 64 bit integers when used.
10*641875f9SMatthew G Knepley 
11*641875f9SMatthew G Knepley */
12*641875f9SMatthew G Knepley 
13*641875f9SMatthew G Knepley #include "../src/mat/impls/sbaij/seq/sbaij.h"
14*641875f9SMatthew G Knepley #include "../src/mat/impls/sbaij/seq/cholmod/cholmodimpl.h"
15*641875f9SMatthew G Knepley 
16*641875f9SMatthew G Knepley /*
17*641875f9SMatthew G Knepley    This is a terrible hack, but it allows the error handler to retain a context.
18*641875f9SMatthew G Knepley    Note that this hack really cannot be made both reentrant and concurrent.
19*641875f9SMatthew G Knepley */
20*641875f9SMatthew G Knepley static Mat static_F;
21*641875f9SMatthew G Knepley 
22*641875f9SMatthew G Knepley #undef __FUNCT__
23*641875f9SMatthew G Knepley #define __FUNCT__ "CholmodErrorHandler"
24*641875f9SMatthew G Knepley static void CholmodErrorHandler(int status,const char *file,int line,const char *message)
25*641875f9SMatthew G Knepley {
26*641875f9SMatthew G Knepley 
27*641875f9SMatthew G Knepley   PetscFunctionBegin;
28*641875f9SMatthew G Knepley   if (status > CHOLMOD_OK) {
29*641875f9SMatthew G Knepley     PetscInfo4(static_F,"CHOLMOD warning %d at %s:%d: %s",status,file,line,message);
30*641875f9SMatthew G Knepley   } else if (status == CHOLMOD_OK) { /* Documentation says this can happen, but why? */
31*641875f9SMatthew G Knepley     PetscInfo3(static_F,"CHOLMOD OK at %s:%d: %s",file,line,message);
32*641875f9SMatthew G Knepley   } else {
33*641875f9SMatthew G Knepley     PetscErrorPrintf("CHOLMOD error %d at %s:%d: %s\n",status,file,line,message);
34*641875f9SMatthew G Knepley   }
35*641875f9SMatthew G Knepley   PetscFunctionReturnVoid();
36*641875f9SMatthew G Knepley }
37*641875f9SMatthew G Knepley 
38*641875f9SMatthew G Knepley #undef __FUNCT__
39*641875f9SMatthew G Knepley #define __FUNCT__ "CholmodStart"
40*641875f9SMatthew G Knepley PetscErrorCode PETSCMAT_DLLEXPORT CholmodStart(Mat F)
41*641875f9SMatthew G Knepley {
42*641875f9SMatthew G Knepley   PetscErrorCode ierr;
43*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol=(Mat_CHOLMOD*)F->spptr;
44*641875f9SMatthew G Knepley   cholmod_common *c;
45*641875f9SMatthew G Knepley   PetscTruth     flg;
46*641875f9SMatthew G Knepley 
47*641875f9SMatthew G Knepley   PetscFunctionBegin;
48*641875f9SMatthew G Knepley   if (chol->common) PetscFunctionReturn(0);
49*641875f9SMatthew G Knepley   ierr = PetscMalloc(sizeof(*chol->common),&chol->common);CHKERRQ(ierr);
50*641875f9SMatthew G Knepley   ierr = !cholmod_X_start(chol->common);CHKERRQ(ierr);
51*641875f9SMatthew G Knepley   c = chol->common;
52*641875f9SMatthew G Knepley   c->error_handler = CholmodErrorHandler;
53*641875f9SMatthew G Knepley 
54*641875f9SMatthew G Knepley #define CHOLMOD_OPTION_DOUBLE(name,help) do {                            \
55*641875f9SMatthew G Knepley     PetscReal tmp = (PetscReal)c->name;                                  \
56*641875f9SMatthew G Knepley     ierr = PetscOptionsReal("-mat_cholmod_" #name,help,"None",tmp,&tmp,0);CHKERRQ(ierr); \
57*641875f9SMatthew G Knepley     c->name = (double)tmp;                                               \
58*641875f9SMatthew G Knepley   } while (0)
59*641875f9SMatthew G Knepley #define CHOLMOD_OPTION_INT(name,help) do {                               \
60*641875f9SMatthew G Knepley     PetscInt tmp = (PetscInt)c->name;                                    \
61*641875f9SMatthew G Knepley     ierr = PetscOptionsInt("-mat_cholmod_" #name,help,"None",tmp,&tmp,0);CHKERRQ(ierr); \
62*641875f9SMatthew G Knepley     c->name = (int)tmp;                                                  \
63*641875f9SMatthew G Knepley   } while (0)
64*641875f9SMatthew G Knepley #define CHOLMOD_OPTION_SIZE_T(name,help) do {                            \
65*641875f9SMatthew G Knepley     PetscInt tmp = (PetscInt)c->name;                                    \
66*641875f9SMatthew G Knepley     ierr = PetscOptionsInt("-mat_cholmod_" #name,help,"None",tmp,&tmp,0);CHKERRQ(ierr); \
67*641875f9SMatthew G Knepley     if (tmp < 0) SETERRQ(((PetscObject)F)->comm,PETSC_ERR_ARG_OUTOFRANGE,"value must be positive"); \
68*641875f9SMatthew G Knepley     c->name = (size_t)tmp;                                               \
69*641875f9SMatthew G Knepley   } while (0)
70*641875f9SMatthew G Knepley #define CHOLMOD_OPTION_TRUTH(name,help) do {                             \
71*641875f9SMatthew G Knepley     PetscTruth tmp = (PetscTruth)!!c->name;                              \
72*641875f9SMatthew G Knepley     ierr = PetscOptionsTruth("-mat_cholmod_" #name,help,"None",tmp,&tmp,0);CHKERRQ(ierr); \
73*641875f9SMatthew G Knepley     c->name = (int)tmp;                                                  \
74*641875f9SMatthew G Knepley   } while (0)
75*641875f9SMatthew G Knepley 
76*641875f9SMatthew G Knepley   ierr = PetscOptionsBegin(((PetscObject)F)->comm,((PetscObject)F)->prefix,"CHOLMOD Options","Mat");CHKERRQ(ierr);
77*641875f9SMatthew G Knepley   /* CHOLMOD handles first-time packing and refactor-packing separately, but we usually want them to be the same. */
78*641875f9SMatthew G Knepley   chol->pack = (PetscTruth)c->final_pack;
79*641875f9SMatthew G Knepley   ierr = PetscOptionsTruth("-mat_cholmod_pack","Pack factors after factorization [disable for frequent repeat factorization]","None",chol->pack,&chol->pack,0);CHKERRQ(ierr);
80*641875f9SMatthew G Knepley   c->final_pack = (int)chol->pack;
81*641875f9SMatthew G Knepley 
82*641875f9SMatthew G Knepley   CHOLMOD_OPTION_DOUBLE(dbound,"Minimum absolute value of diagonal entries of D");
83*641875f9SMatthew G Knepley   CHOLMOD_OPTION_DOUBLE(grow0,"Global growth ratio when factors are modified");
84*641875f9SMatthew G Knepley   CHOLMOD_OPTION_DOUBLE(grow1,"Column growth ratio when factors are modified");
85*641875f9SMatthew G Knepley   CHOLMOD_OPTION_SIZE_T(grow2,"Affine column growth constant when factors are modified");
86*641875f9SMatthew G Knepley   CHOLMOD_OPTION_SIZE_T(maxrank,"Max rank of update, larger values are faster but use more memory [2,4,8]");
87*641875f9SMatthew G Knepley   {
88*641875f9SMatthew G Knepley     static const char *const list[] = {"SIMPLICIAL","AUTO","SUPERNODAL","MatCholmodFactorType","MAT_CHOLMOD_FACTOR_",0};
89*641875f9SMatthew G Knepley     PetscEnum choice = (PetscEnum)c->supernodal;
90*641875f9SMatthew G Knepley     ierr = PetscOptionsEnum("-mat_cholmod_factor","Factorization method","None",list,(PetscEnum)c->supernodal,&choice,0);CHKERRQ(ierr);
91*641875f9SMatthew G Knepley     c->supernodal = (int)choice;
92*641875f9SMatthew G Knepley   }
93*641875f9SMatthew G Knepley   if (c->supernodal) CHOLMOD_OPTION_DOUBLE(supernodal_switch,"flop/nnz_L threshold for switching to supernodal factorization");
94*641875f9SMatthew G Knepley   CHOLMOD_OPTION_TRUTH(final_asis,"Leave factors \"as is\"");
95*641875f9SMatthew G Knepley   CHOLMOD_OPTION_TRUTH(final_pack,"Pack the columns when finished (use FALSE if the factors will be updated later)");
96*641875f9SMatthew G Knepley   if (!c->final_asis) {
97*641875f9SMatthew G Knepley     CHOLMOD_OPTION_TRUTH(final_super,"Leave supernodal factors instead of converting to simplicial");
98*641875f9SMatthew G Knepley     CHOLMOD_OPTION_TRUTH(final_ll,"Turn LDL' factorization into LL'");
99*641875f9SMatthew G Knepley     CHOLMOD_OPTION_TRUTH(final_monotonic,"Ensure columns are monotonic when done");
100*641875f9SMatthew G Knepley     CHOLMOD_OPTION_TRUTH(final_resymbol,"Remove numerically zero values resulting from relaxed supernodal amalgamation");
101*641875f9SMatthew G Knepley   }
102*641875f9SMatthew G Knepley   {
103*641875f9SMatthew G Knepley     PetscReal tmp[] = {(PetscReal)c->zrelax[0],(PetscReal)c->zrelax[1],(PetscReal)c->zrelax[2]};
104*641875f9SMatthew G Knepley     PetscInt n = 3;
105*641875f9SMatthew G Knepley     ierr = PetscOptionsRealArray("-mat_cholmod_zrelax","3 real supernodal relaxed amalgamation parameters","None",tmp,&n,&flg);CHKERRQ(ierr);
106*641875f9SMatthew G Knepley     if (flg && n != 3) SETERRQ(((PetscObject)F)->comm,PETSC_ERR_ARG_OUTOFRANGE,"must provide exactly 3 parameters to -mat_cholmod_zrelax");
107*641875f9SMatthew G Knepley     if (flg) while (n--) c->zrelax[n] = (double)tmp[n];
108*641875f9SMatthew G Knepley   }
109*641875f9SMatthew G Knepley   {
110*641875f9SMatthew G Knepley     PetscInt n,tmp[] = {(PetscInt)c->nrelax[0],(PetscInt)c->nrelax[1],(PetscInt)c->nrelax[2]};
111*641875f9SMatthew G Knepley     ierr = PetscOptionsIntArray("-mat_cholmod_nrelax","3 size_t supernodal relaxed amalgamation parameters","None",tmp,&n,&flg);CHKERRQ(ierr);
112*641875f9SMatthew G Knepley     if (flg && n != 3) SETERRQ(((PetscObject)F)->comm,PETSC_ERR_ARG_OUTOFRANGE,"must provide exactly 3 parameters to -mat_cholmod_nrelax");
113*641875f9SMatthew G Knepley     if (flg) while (n--) c->nrelax[n] = (size_t)tmp[n];
114*641875f9SMatthew G Knepley   }
115*641875f9SMatthew G Knepley   CHOLMOD_OPTION_TRUTH(prefer_upper,"Work with upper triangular form [faster when using fill-reducing ordering, slower in natural ordering]");
116*641875f9SMatthew G Knepley   CHOLMOD_OPTION_TRUTH(default_nesdis,"Use NESDIS instead of METIS for nested dissection");
117*641875f9SMatthew G Knepley   CHOLMOD_OPTION_INT(print,"Verbosity level");
118*641875f9SMatthew G Knepley   ierr = PetscOptionsEnd();CHKERRQ(ierr);
119*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
120*641875f9SMatthew G Knepley }
121*641875f9SMatthew G Knepley 
122*641875f9SMatthew G Knepley #undef __FUNCT__
123*641875f9SMatthew G Knepley #define __FUNCT__ "MatWrapCholmod_seqsbaij"
124*641875f9SMatthew G Knepley static PetscErrorCode MatWrapCholmod_seqsbaij(Mat A,PetscTruth values,cholmod_sparse *C,PetscTruth *aijalloc)
125*641875f9SMatthew G Knepley {
126*641875f9SMatthew G Knepley   Mat_SeqSBAIJ *sbaij = (Mat_SeqSBAIJ*)A->data;
127*641875f9SMatthew G Knepley   PetscErrorCode ierr;
128*641875f9SMatthew G Knepley 
129*641875f9SMatthew G Knepley   PetscFunctionBegin;
130*641875f9SMatthew G Knepley   ierr = PetscMemzero(C,sizeof(*C));CHKERRQ(ierr);
131*641875f9SMatthew G Knepley   /* CHOLMOD uses column alignment, SBAIJ stores the upper factor, so we pass it on as a lower factor, swapping the meaning of row and column */
132*641875f9SMatthew G Knepley   C->nrow  = (size_t)A->cmap->n;
133*641875f9SMatthew G Knepley   C->ncol  = (size_t)A->rmap->n;
134*641875f9SMatthew G Knepley   C->nzmax = (size_t)sbaij->maxnz;
135*641875f9SMatthew G Knepley   C->p     = sbaij->i;
136*641875f9SMatthew G Knepley   C->i     = sbaij->j;
137*641875f9SMatthew G Knepley   C->x     = sbaij->a;
138*641875f9SMatthew G Knepley   C->stype = -1;
139*641875f9SMatthew G Knepley   C->itype = CHOLMOD_INT_TYPE;
140*641875f9SMatthew G Knepley   C->xtype = CHOLMOD_SCALAR_TYPE;
141*641875f9SMatthew G Knepley   C->dtype = CHOLMOD_DOUBLE;
142*641875f9SMatthew G Knepley   C->sorted = 1;
143*641875f9SMatthew G Knepley   C->packed = 1;
144*641875f9SMatthew G Knepley   *aijalloc = PETSC_FALSE;
145*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
146*641875f9SMatthew G Knepley }
147*641875f9SMatthew G Knepley 
148*641875f9SMatthew G Knepley #undef __FUNCT__
149*641875f9SMatthew G Knepley #define __FUNCT__ "VecWrapCholmod"
150*641875f9SMatthew G Knepley static PetscErrorCode VecWrapCholmod(Vec X,cholmod_dense *Y)
151*641875f9SMatthew G Knepley {
152*641875f9SMatthew G Knepley   PetscErrorCode ierr;
153*641875f9SMatthew G Knepley   PetscScalar *x;
154*641875f9SMatthew G Knepley   PetscInt n;
155*641875f9SMatthew G Knepley 
156*641875f9SMatthew G Knepley   PetscFunctionBegin;
157*641875f9SMatthew G Knepley   ierr = PetscMemzero(Y,sizeof(*Y));CHKERRQ(ierr);
158*641875f9SMatthew G Knepley   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
159*641875f9SMatthew G Knepley   ierr = VecGetSize(X,&n);CHKERRQ(ierr);
160*641875f9SMatthew G Knepley   Y->x = (double*)x;
161*641875f9SMatthew G Knepley   Y->nrow = n;
162*641875f9SMatthew G Knepley   Y->ncol = 1;
163*641875f9SMatthew G Knepley   Y->nzmax = n;
164*641875f9SMatthew G Knepley   Y->d = n;
165*641875f9SMatthew G Knepley   Y->x = (double*)x;
166*641875f9SMatthew G Knepley   Y->xtype = CHOLMOD_SCALAR_TYPE;
167*641875f9SMatthew G Knepley   Y->dtype = CHOLMOD_DOUBLE;
168*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
169*641875f9SMatthew G Knepley }
170*641875f9SMatthew G Knepley 
171*641875f9SMatthew G Knepley #undef __FUNCT__
172*641875f9SMatthew G Knepley #define __FUNCT__ "MatDestroy_CHOLMOD"
173*641875f9SMatthew G Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatDestroy_CHOLMOD(Mat F)
174*641875f9SMatthew G Knepley {
175*641875f9SMatthew G Knepley   PetscErrorCode ierr;
176*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol=(Mat_CHOLMOD*)F->spptr;
177*641875f9SMatthew G Knepley 
178*641875f9SMatthew G Knepley   PetscFunctionBegin;
179*641875f9SMatthew G Knepley   ierr = !cholmod_X_free_factor(&chol->factor,chol->common);CHKERRQ(ierr);
180*641875f9SMatthew G Knepley   ierr = !cholmod_X_finish(chol->common);CHKERRQ(ierr);
181*641875f9SMatthew G Knepley   ierr = PetscFree(chol->common);CHKERRQ(ierr);
182*641875f9SMatthew G Knepley   ierr = PetscFree(chol->matrix);CHKERRQ(ierr);
183*641875f9SMatthew G Knepley   ierr = (*chol->Destroy)(F);CHKERRQ(ierr);
184*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
185*641875f9SMatthew G Knepley }
186*641875f9SMatthew G Knepley 
187*641875f9SMatthew G Knepley static PetscErrorCode MatSolve_CHOLMOD(Mat,Vec,Vec);
188*641875f9SMatthew G Knepley 
189*641875f9SMatthew G Knepley static const char *const CholmodOrderingMethods[] = {"User","AMD","METIS","NESDIS(default)","Natural","NESDIS(small=20000)","NESDIS(small=4,no constrained)","NESDIS()"};
190*641875f9SMatthew G Knepley 
191*641875f9SMatthew G Knepley #undef __FUNCT__
192*641875f9SMatthew G Knepley #define __FUNCT__ "MatFactorInfo_CHOLMOD"
193*641875f9SMatthew G Knepley static PetscErrorCode MatFactorInfo_CHOLMOD(Mat F,PetscViewer viewer)
194*641875f9SMatthew G Knepley {
195*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->spptr;
196*641875f9SMatthew G Knepley   const cholmod_common *c = chol->common;
197*641875f9SMatthew G Knepley   PetscErrorCode ierr;
198*641875f9SMatthew G Knepley   PetscInt       i;
199*641875f9SMatthew G Knepley 
200*641875f9SMatthew G Knepley   PetscFunctionBegin;
201*641875f9SMatthew G Knepley   if (F->ops->solve != MatSolve_CHOLMOD) PetscFunctionReturn(0);
202*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"CHOLMOD run parameters:\n");CHKERRQ(ierr);
203*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
204*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Pack factors after symbolic factorization: %s\n",chol->pack?"TRUE":"FALSE");CHKERRQ(ierr);
205*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.dbound            %g  (Smallest absolute value of diagonal entries of D)\n",c->dbound);CHKERRQ(ierr);
206*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.grow0             %g\n",c->grow0);CHKERRQ(ierr);
207*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.grow1             %g\n",c->grow1);CHKERRQ(ierr);
208*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.grow2             %u\n",(unsigned)c->grow2);CHKERRQ(ierr);
209*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.maxrank           %u\n",(unsigned)c->maxrank);CHKERRQ(ierr);
210*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.supernodal_switch %g\n",c->supernodal_switch);CHKERRQ(ierr);
211*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.supernodal        %d\n",c->supernodal);CHKERRQ(ierr);
212*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.final_asis        %d\n",c->final_asis);CHKERRQ(ierr);
213*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.final_super       %d\n",c->final_super);CHKERRQ(ierr);
214*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.final_ll          %d\n",c->final_ll);CHKERRQ(ierr);
215*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.final_pack        %d\n",c->final_pack);CHKERRQ(ierr);
216*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.final_monotonic   %d\n",c->final_monotonic);CHKERRQ(ierr);
217*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.final_resymbol    %d\n",c->final_resymbol);CHKERRQ(ierr);
218*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.zrelax            [%g,%g,%g]\n",c->zrelax[0],c->zrelax[1],c->zrelax[2]);CHKERRQ(ierr);
219*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.nrelax            [%u,%u,%u]\n",(unsigned)c->nrelax[0],(unsigned)c->nrelax[1],(unsigned)c->nrelax[2]);CHKERRQ(ierr);
220*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.prefer_upper      %d\n",c->prefer_upper);CHKERRQ(ierr);
221*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.print             %d\n",c->print);CHKERRQ(ierr);
222*641875f9SMatthew G Knepley   for (i=0; i<c->nmethods; i++) {
223*641875f9SMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer,"Ordering method %D%s:\n",i,i==c->selected?" [SELECTED]":"");CHKERRQ(ierr);
224*641875f9SMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer,"  lnz %g, fl %g, prune_dense %g, prune_dense2 %g\n",
225*641875f9SMatthew G Knepley         c->method[i].lnz,c->method[i].fl,c->method[i].prune_dense,c->method[i].prune_dense2);CHKERRQ(ierr);
226*641875f9SMatthew G Knepley   }
227*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.postorder         %d\n",c->postorder);CHKERRQ(ierr);
228*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.default_nesdis    %d (use NESDIS instead of METIS for nested dissection)\n",c->default_nesdis);CHKERRQ(ierr);
229*641875f9SMatthew G Knepley   /* Statistics */
230*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.fl                %g (flop count from most recent analysis)\n",c->fl);CHKERRQ(ierr);
231*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.lnz               %g (fundamental nz in L)\n",c->lnz);CHKERRQ(ierr);
232*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.anz               %g\n",c->anz);CHKERRQ(ierr);
233*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.modfl             %g (flop count from most recent update)\n",c->modfl);CHKERRQ(ierr);
234*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.malloc_count      %g (number of live objects)\n",(double)c->malloc_count);CHKERRQ(ierr);CHKERRQ(ierr);
235*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.memory_usage      %g (peak memory usage in bytes)\n",(double)c->memory_usage);CHKERRQ(ierr);CHKERRQ(ierr);
236*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.memory_inuse      %g (current memory usage in bytes)\n",(double)c->memory_inuse);CHKERRQ(ierr);CHKERRQ(ierr);
237*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.nrealloc_col      %g (number of column reallocations)\n",c->nrealloc_col);CHKERRQ(ierr);CHKERRQ(ierr);
238*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.nrealloc_factor   %g (number of factor reallocations due to column reallocations)\n",c->nrealloc_factor);CHKERRQ(ierr);CHKERRQ(ierr);
239*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.ndbounds_hit      %g (number of times diagonal was modified by dbound)\n",c->ndbounds_hit);CHKERRQ(ierr);CHKERRQ(ierr);
240*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.rowfacfl          %g (number of flops in last call to cholmod_rowfac)\n",c->rowfacfl);CHKERRQ(ierr);CHKERRQ(ierr);
241*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer,"Common.aatfl             %g (number of flops to compute A(:,f)*A(:,f)')\n",c->aatfl);CHKERRQ(ierr);CHKERRQ(ierr);
242*641875f9SMatthew G Knepley   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
243*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
244*641875f9SMatthew G Knepley }
245*641875f9SMatthew G Knepley 
246*641875f9SMatthew G Knepley #undef __FUNCT__
247*641875f9SMatthew G Knepley #define __FUNCT__ "MatView_CHOLMOD"
248*641875f9SMatthew G Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatView_CHOLMOD(Mat F,PetscViewer viewer)
249*641875f9SMatthew G Knepley {
250*641875f9SMatthew G Knepley   PetscErrorCode    ierr;
251*641875f9SMatthew G Knepley   PetscTruth        iascii;
252*641875f9SMatthew G Knepley   PetscViewerFormat format;
253*641875f9SMatthew G Knepley 
254*641875f9SMatthew G Knepley   PetscFunctionBegin;
255*641875f9SMatthew G Knepley   ierr = MatView_SeqSBAIJ(F,viewer);CHKERRQ(ierr);
256*641875f9SMatthew G Knepley   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
257*641875f9SMatthew G Knepley   if (iascii) {
258*641875f9SMatthew G Knepley     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
259*641875f9SMatthew G Knepley     if (format == PETSC_VIEWER_ASCII_INFO) {
260*641875f9SMatthew G Knepley       ierr = MatFactorInfo_CHOLMOD(F,viewer);CHKERRQ(ierr);
261*641875f9SMatthew G Knepley     }
262*641875f9SMatthew G Knepley   }
263*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
264*641875f9SMatthew G Knepley }
265*641875f9SMatthew G Knepley 
266*641875f9SMatthew G Knepley #undef __FUNCT__
267*641875f9SMatthew G Knepley #define __FUNCT__ "MatSolve_CHOLMOD"
268*641875f9SMatthew G Knepley static PetscErrorCode MatSolve_CHOLMOD(Mat F,Vec B,Vec X)
269*641875f9SMatthew G Knepley {
270*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->spptr;
271*641875f9SMatthew G Knepley   cholmod_dense  cholB,*cholX;
272*641875f9SMatthew G Knepley   PetscScalar    *x;
273*641875f9SMatthew G Knepley   PetscErrorCode ierr;
274*641875f9SMatthew G Knepley 
275*641875f9SMatthew G Knepley   PetscFunctionBegin;
276*641875f9SMatthew G Knepley   ierr = VecWrapCholmod(B,&cholB);CHKERRQ(ierr);
277*641875f9SMatthew G Knepley   static_F = F;
278*641875f9SMatthew G Knepley   cholX = cholmod_X_solve(CHOLMOD_A,chol->factor,&cholB,chol->common);
279*641875f9SMatthew G Knepley   if (!cholX) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CHOLMOD failed");
280*641875f9SMatthew G Knepley   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
281*641875f9SMatthew G Knepley   ierr = PetscMemcpy(x,cholX->x,cholX->nrow*sizeof(*x));CHKERRQ(ierr);
282*641875f9SMatthew G Knepley   ierr = !cholmod_X_free_dense(&cholX,chol->common);CHKERRQ(ierr);
283*641875f9SMatthew G Knepley   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
284*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
285*641875f9SMatthew G Knepley }
286*641875f9SMatthew G Knepley 
287*641875f9SMatthew G Knepley #undef __FUNCT__
288*641875f9SMatthew G Knepley #define __FUNCT__ "MatCholeskyFactorNumeric_CHOLMOD"
289*641875f9SMatthew G Knepley static PetscErrorCode MatCholeskyFactorNumeric_CHOLMOD(Mat F,Mat A,const MatFactorInfo *info)
290*641875f9SMatthew G Knepley {
291*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->spptr;
292*641875f9SMatthew G Knepley   cholmod_sparse cholA;
293*641875f9SMatthew G Knepley   PetscTruth     aijalloc;
294*641875f9SMatthew G Knepley   PetscErrorCode ierr;
295*641875f9SMatthew G Knepley 
296*641875f9SMatthew G Knepley   PetscFunctionBegin;
297*641875f9SMatthew G Knepley   ierr = (*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc);CHKERRQ(ierr);
298*641875f9SMatthew G Knepley   static_F = F;
299*641875f9SMatthew G Knepley   ierr = !cholmod_X_factorize(&cholA,chol->factor,chol->common);
300*641875f9SMatthew G Knepley   if (ierr) SETERRQ1(((PetscObject)F)->comm,PETSC_ERR_LIB,"CHOLMOD factorization failed with status %d",chol->common->status);
301*641875f9SMatthew G Knepley   if (chol->common->status == CHOLMOD_NOT_POSDEF)
302*641875f9SMatthew G Knepley     SETERRQ1(((PetscObject)F)->comm,PETSC_ERR_MAT_CH_ZRPVT,"CHOLMOD detected that the matrix is not positive definite, failure at column %u",(unsigned)chol->factor->minor);
303*641875f9SMatthew G Knepley 
304*641875f9SMatthew G Knepley   if (aijalloc) {ierr = PetscFree3(cholA.p,cholA.i,cholA.x);CHKERRQ(ierr);}
305*641875f9SMatthew G Knepley 
306*641875f9SMatthew G Knepley   F->ops->solve          = MatSolve_CHOLMOD;
307*641875f9SMatthew G Knepley   F->ops->solvetranspose = MatSolve_CHOLMOD;
308*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
309*641875f9SMatthew G Knepley }
310*641875f9SMatthew G Knepley 
311*641875f9SMatthew G Knepley #undef __FUNCT__
312*641875f9SMatthew G Knepley #define __FUNCT__ "MatCholeskyFactorSymbolic_CHOLMOD"
313*641875f9SMatthew G Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatCholeskyFactorSymbolic_CHOLMOD(Mat F,Mat A,IS perm,const MatFactorInfo *info)
314*641875f9SMatthew G Knepley {
315*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->spptr;
316*641875f9SMatthew G Knepley   PetscErrorCode ierr;
317*641875f9SMatthew G Knepley   cholmod_sparse cholA;
318*641875f9SMatthew G Knepley   PetscTruth     aijalloc;
319*641875f9SMatthew G Knepley   PetscInt       *fset = 0;
320*641875f9SMatthew G Knepley   size_t         fsize = 0;
321*641875f9SMatthew G Knepley 
322*641875f9SMatthew G Knepley   PetscFunctionBegin;
323*641875f9SMatthew G Knepley   ierr = (*chol->Wrap)(A,PETSC_FALSE,&cholA,&aijalloc);CHKERRQ(ierr);
324*641875f9SMatthew G Knepley   static_F = F;
325*641875f9SMatthew G Knepley   if (chol->factor) {
326*641875f9SMatthew G Knepley     ierr = !cholmod_X_resymbol(&cholA,fset,fsize,(int)chol->pack,chol->factor,chol->common);
327*641875f9SMatthew G Knepley     if (ierr) SETERRQ1(((PetscObject)F)->comm,PETSC_ERR_LIB,"CHOLMOD analysis failed with status %d",chol->common->status);
328*641875f9SMatthew G Knepley   } else if (perm) {
329*641875f9SMatthew G Knepley     const PetscInt *ip;
330*641875f9SMatthew G Knepley     ierr = ISGetIndices(perm,&ip);CHKERRQ(ierr);
331*641875f9SMatthew G Knepley     chol->factor = cholmod_X_analyze_p(&cholA,(PetscInt*)ip,fset,fsize,chol->common);
332*641875f9SMatthew G Knepley     if (!chol->factor) SETERRQ1(((PetscObject)F)->comm,PETSC_ERR_LIB,"CHOLMOD analysis failed with status %d",chol->common->status);
333*641875f9SMatthew G Knepley     ierr = ISRestoreIndices(perm,&ip);CHKERRQ(ierr);
334*641875f9SMatthew G Knepley   } else {
335*641875f9SMatthew G Knepley     chol->factor = cholmod_X_analyze(&cholA,chol->common);
336*641875f9SMatthew G Knepley     if (!chol->factor) SETERRQ1(((PetscObject)F)->comm,PETSC_ERR_LIB,"CHOLMOD analysis failed with status %d",chol->common->status);
337*641875f9SMatthew G Knepley   }
338*641875f9SMatthew G Knepley 
339*641875f9SMatthew G Knepley   if (aijalloc) {ierr = PetscFree3(cholA.p,cholA.i,cholA.x);CHKERRQ(ierr);}
340*641875f9SMatthew G Knepley 
341*641875f9SMatthew G Knepley   F->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_CHOLMOD;
342*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
343*641875f9SMatthew G Knepley }
344*641875f9SMatthew G Knepley 
345*641875f9SMatthew G Knepley EXTERN_C_BEGIN
346*641875f9SMatthew G Knepley #undef __FUNCT__
347*641875f9SMatthew G Knepley #define __FUNCT__ "MatFactorGetSolverPackage_seqsbaij_cholmod"
348*641875f9SMatthew G Knepley PetscErrorCode MatFactorGetSolverPackage_seqsbaij_cholmod(Mat A,const MatSolverPackage *type)
349*641875f9SMatthew G Knepley {
350*641875f9SMatthew G Knepley   PetscFunctionBegin;
351*641875f9SMatthew G Knepley   *type = MATSOLVERCHOLMOD;
352*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
353*641875f9SMatthew G Knepley }
354*641875f9SMatthew G Knepley EXTERN_C_END
355*641875f9SMatthew G Knepley 
356*641875f9SMatthew G Knepley /*MC
357*641875f9SMatthew G Knepley   MATSOLVERCHOLMOD = "cholmod" - A matrix type providing direct solvers (Cholesky) for sequential matrices
358*641875f9SMatthew G Knepley   via the external package CHOLMOD.
359*641875f9SMatthew G Knepley 
360*641875f9SMatthew G Knepley   ./configure --download-cholmod to install PETSc to use CHOLMOD
361*641875f9SMatthew G Knepley 
362*641875f9SMatthew G Knepley   Consult CHOLMOD documentation for more information about the Common parameters
363*641875f9SMatthew G Knepley   which correspond to the options database keys below.
364*641875f9SMatthew G Knepley 
365*641875f9SMatthew G Knepley   Options Database Keys:
366*641875f9SMatthew G Knepley   -mat_cholmod_dbound <0>: Minimum absolute value of diagonal entries of D (None)
367*641875f9SMatthew G Knepley   -mat_cholmod_grow0 <1.2>: Global growth ratio when factors are modified (None)
368*641875f9SMatthew G Knepley   -mat_cholmod_grow1 <1.2>: Column growth ratio when factors are modified (None)
369*641875f9SMatthew G Knepley   -mat_cholmod_grow2 <5>: Affine column growth constant when factors are modified (None)
370*641875f9SMatthew G Knepley   -mat_cholmod_maxrank <8>: Max rank of update, larger values are faster but use more memory [2,4,8] (None)
371*641875f9SMatthew G Knepley   -mat_cholmod_factor <AUTO> (choose one of) SIMPLICIAL AUTO SUPERNODAL
372*641875f9SMatthew G Knepley   -mat_cholmod_supernodal_switch <40>: flop/nnz_L threshold for switching to supernodal factorization (None)
373*641875f9SMatthew G Knepley   -mat_cholmod_final_asis: <TRUE> Leave factors "as is" (None)
374*641875f9SMatthew G Knepley   -mat_cholmod_final_pack: <TRUE> Pack the columns when finished (use FALSE if the factors will be updated later) (None)
375*641875f9SMatthew G Knepley   -mat_cholmod_zrelax <0.8>: 3 real supernodal relaxed amalgamation parameters (None)
376*641875f9SMatthew G Knepley   -mat_cholmod_nrelax <4>: 3 size_t supernodal relaxed amalgamation parameters (None)
377*641875f9SMatthew G Knepley   -mat_cholmod_prefer_upper: <TRUE> Work with upper triangular form (faster when using fill-reducing ordering, slower in natural ordering) (None)
378*641875f9SMatthew G Knepley   -mat_cholmod_print <3>: Verbosity level (None)
379*641875f9SMatthew G Knepley 
380*641875f9SMatthew G Knepley    Level: beginner
381*641875f9SMatthew G Knepley 
382*641875f9SMatthew G Knepley .seealso: PCCHOLESKY, PCFactorSetMatSolverPackage(), MatSolverPackage
383*641875f9SMatthew G Knepley M*/
384*641875f9SMatthew G Knepley EXTERN_C_BEGIN
385*641875f9SMatthew G Knepley #undef __FUNCT__
386*641875f9SMatthew G Knepley #define __FUNCT__ "MatGetFactor_seqsbaij_cholmod"
387*641875f9SMatthew G Knepley PetscErrorCode MatGetFactor_seqsbaij_cholmod(Mat A,MatFactorType ftype,Mat *F)
388*641875f9SMatthew G Knepley {
389*641875f9SMatthew G Knepley   Mat            B;
390*641875f9SMatthew G Knepley   Mat_CHOLMOD    *chol;
391*641875f9SMatthew G Knepley   PetscErrorCode ierr;
392*641875f9SMatthew G Knepley   PetscInt       m=A->rmap->n,n=A->cmap->n,bs;
393*641875f9SMatthew G Knepley 
394*641875f9SMatthew G Knepley   PetscFunctionBegin;
395*641875f9SMatthew G Knepley   if (ftype != MAT_FACTOR_CHOLESKY) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"CHOLMOD cannot do %s factorization with SBAIJ, only %s",
396*641875f9SMatthew G Knepley                                              MatFactorTypes[ftype],MatFactorTypes[MAT_FACTOR_CHOLESKY]);
397*641875f9SMatthew G Knepley   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
398*641875f9SMatthew G Knepley   if (bs != 1) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_SUP,"CHOLMOD only supports block size=1, given %D",bs);
399*641875f9SMatthew G Knepley   /* Create the factorization matrix F */
400*641875f9SMatthew G Knepley   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
401*641875f9SMatthew G Knepley   ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr);
402*641875f9SMatthew G Knepley   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
403*641875f9SMatthew G Knepley   ierr = MatSeqSBAIJSetPreallocation(B,1,0,PETSC_NULL);CHKERRQ(ierr);
404*641875f9SMatthew G Knepley   ierr = PetscNewLog(B,Mat_CHOLMOD,&chol);CHKERRQ(ierr);
405*641875f9SMatthew G Knepley   chol->Wrap               = MatWrapCholmod_seqsbaij;
406*641875f9SMatthew G Knepley   chol->Destroy            = MatDestroy_SeqSBAIJ;
407*641875f9SMatthew G Knepley   B->spptr                 = chol;
408*641875f9SMatthew G Knepley 
409*641875f9SMatthew G Knepley   B->ops->view             = MatView_CHOLMOD;
410*641875f9SMatthew G Knepley   B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_CHOLMOD;
411*641875f9SMatthew G Knepley   B->ops->destroy          = MatDestroy_CHOLMOD;
412*641875f9SMatthew G Knepley   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqsbaij_cholmod",MatFactorGetSolverPackage_seqsbaij_cholmod);CHKERRQ(ierr);
413*641875f9SMatthew G Knepley   B->factortype            = MAT_FACTOR_CHOLESKY;
414*641875f9SMatthew G Knepley   B->assembled             = PETSC_TRUE;  /* required by -ksp_view */
415*641875f9SMatthew G Knepley   B->preallocated          = PETSC_TRUE;
416*641875f9SMatthew G Knepley 
417*641875f9SMatthew G Knepley   ierr = CholmodStart(B);CHKERRQ(ierr);
418*641875f9SMatthew G Knepley   *F = B;
419*641875f9SMatthew G Knepley   PetscFunctionReturn(0);
420*641875f9SMatthew G Knepley }
421*641875f9SMatthew G Knepley EXTERN_C_END
422