int main (int argc, char **argv) { /* ---------------------------------------------------------------------- */ /* get the file containing the input matrix */ /* ---------------------------------------------------------------------- */ FILE *ff = NULL ; FILE *fb = NULL ; if (argc <= 1) { printf("Usage is: cholmod_simple A.tri [B.txt (dense)]\n"); exit(0); } if (argc > 1) ff = fopen(argv[1],"r"); if (argc > 2) fb = fopen(argv[2], "r"); cholmod_sparse *A ; cholmod_dense *x, *b, *r ; cholmod_factor *L ; double one [2] = {1,0}, m1 [2] = {-1,0} ; // basic scalars cholmod_common c ; cholmod_start (&c) ; /* start CHOLMOD */ A = cholmod_read_sparse (ff, &c) ; /* read in a matrix */ cholmod_print_sparse (A, (char *)"A", &c) ; /* print the matrix */ if (A->dtype) printf("A is float\n"); else printf("A is double\n"); if (A == NULL || A->stype == 0) /* A must be symmetric */ { cholmod_free_sparse (&A, &c) ; cholmod_finish (&c) ; if (ff) fclose(ff); if (fb) fclose(fb); return (0) ; } if (fb) b = cholmod_read_dense(fb, &c); else b = cholmod_ones (A->nrow, 1, A->xtype, &c) ; /* b = ones(n,1) */ double t0 = CPUTIME; L = cholmod_analyze (A, &c) ; /* analyze */ cholmod_factorize (A, L, &c) ; /* factorize */ x = cholmod_solve (CHOLMOD_A, L, b, &c) ; /* solve Ax=b */ double t1 = CPUTIME; if (c.dtype) printf("Compute is float\n"); else printf("Compute is double\n"); printf("Time: %12.4f \n", t1-t0); r = cholmod_copy_dense (b, &c) ; /* r = b */ cholmod_sdmult (A, 0, m1, one, x, r, &c) ; /* r = r-Ax */ printf ("norm(b-Ax) %8.1e\n", cholmod_norm_dense (r, 0, &c)) ; /* print norm(r) */ cholmod_free_factor (&L, &c) ; /* free matrices */ cholmod_free_sparse (&A, &c) ; cholmod_free_dense (&r, &c) ; cholmod_free_dense (&x, &c) ; cholmod_free_dense (&b, &c) ; cholmod_finish (&c) ; /* finish CHOLMOD */ return (0) ; }
int main (void) { cholmod_sparse *A ; cholmod_dense *x, *b, *r ; cholmod_factor *L ; double one [2] = {1,0}, m1 [2] = {-1,0} ; /* basic scalars */ cholmod_common c ; cholmod_start (&c) ; /* start CHOLMOD */ A = cholmod_read_sparse (stdin, &c) ; /* read in a matrix */ cholmod_print_sparse (A, "A", &c) ; /* print the matrix */ if (A == NULL || A->stype == 0) /* A must be symmetric */ { cholmod_free_sparse (&A, &c) ; cholmod_finish (&c) ; return (0) ; } b = cholmod_ones (A->nrow, 1, A->xtype, &c) ; /* b = ones(n,1) */ L = cholmod_analyze (A, &c) ; /* analyze */ cholmod_factorize (A, L, &c) ; /* factorize */ x = cholmod_solve (CHOLMOD_A, L, b, &c) ; /* solve Ax=b */ r = cholmod_copy_dense (b, &c) ; /* r = b */ cholmod_sdmult (A, 0, m1, one, x, r, &c) ; /* r = r-Ax */ printf ("norm(b-Ax) %8.1e\n", cholmod_norm_dense (r, 0, &c)) ; /* print norm(r) */ cholmod_free_factor (&L, &c) ; /* free matrices */ cholmod_free_sparse (&A, &c) ; cholmod_free_dense (&r, &c) ; cholmod_free_dense (&x, &c) ; cholmod_free_dense (&b, &c) ; cholmod_finish (&c) ; /* finish CHOLMOD */ return (0) ; }
int main() { // define variable cholmod_dense *A; cholmod_common c ; cholmod_start(&c) ; // start CHOLMOD A = cholmod_ones(3, 3, CHOLMOD_REAL, &c) ; // A = ones(3,3) std::cout << "norm(A): " << cholmod_norm_dense(A, 0, &c) << std::endl; cholmod_finish (&c) ; // finish CHOLMOD }
int main (int argc, char **argv) { double resid, t, ta, tf, ts, tot, bnorm, xnorm, anorm, rnorm, fl, anz, axbnorm, rnorm2, resid2 ; FILE *f ; cholmod_sparse *A ; cholmod_dense *X, *B, *W, *R ; double one [2], zero [2], minusone [2], beta [2], xlnz ; cholmod_common Common, *cm ; cholmod_factor *L ; double *Bx, *Rx, *Xx ; int i, n, isize, xsize, ordering, xtype, s, ss, lnz ; /* ---------------------------------------------------------------------- */ /* get the file containing the input matrix */ /* ---------------------------------------------------------------------- */ ff = NULL ; if (argc > 1) { if ((f = fopen (argv [1], "r")) == NULL) { my_handler (CHOLMOD_INVALID, __FILE__, __LINE__, "unable to open file") ; } ff = f ; } else { f = stdin ; } /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_start (cm) ; /* use default parameter settings, except for the error handler. This * demo program terminates if an error occurs (out of memory, not positive * definite, ...). It makes the demo program simpler (no need to check * CHOLMOD error conditions). This non-default parameter setting has no * effect on performance. */ cm->error_handler = my_handler ; /* Note that CHOLMOD will do a supernodal LL' or a simplicial LDL' by * default, automatically selecting the latter if flop/nnz(L) < 40. */ /* ---------------------------------------------------------------------- */ /* create basic scalars */ /* ---------------------------------------------------------------------- */ zero [0] = 0 ; zero [1] = 0 ; one [0] = 1 ; one [1] = 0 ; minusone [0] = -1 ; minusone [1] = 0 ; beta [0] = 1e-6 ; beta [1] = 0 ; /* ---------------------------------------------------------------------- */ /* read in a matrix */ /* ---------------------------------------------------------------------- */ printf ("\n---------------------------------- cholmod_demo:\n") ; A = cholmod_read_sparse (f, cm) ; if (ff != NULL) fclose (ff) ; anorm = cholmod_norm_sparse (A, 0, cm) ; xtype = A->xtype ; printf ("norm (A,inf) = %g\n", anorm) ; printf ("norm (A,1) = %g\n", cholmod_norm_sparse (A, 1, cm)) ; cholmod_print_sparse (A, "A", cm) ; if (A->nrow > A->ncol) { /* Transpose A so that A'A+beta*I will be factorized instead */ cholmod_sparse *C = cholmod_transpose (A, 2, cm) ; cholmod_free_sparse (&A, cm) ; A = C ; printf ("transposing input matrix\n") ; } /* ---------------------------------------------------------------------- */ /* create an arbitrary right-hand-side */ /* ---------------------------------------------------------------------- */ n = A->nrow ; B = cholmod_zeros (n, 1, xtype, cm) ; Bx = B->x ; #if GHS { /* b = A*ones(n,1), used by Gould, Hu, and Scott in their experiments */ cholmod_dense *X0 ; X0 = cholmod_ones (A->ncol, 1, xtype, cm) ; cholmod_sdmult (A, 0, one, zero, X0, B, cm) ; cholmod_free_dense (&X0, cm) ; } #else if (xtype == CHOLMOD_REAL) { /* real case */ for (i = 0 ; i < n ; i++) { double x = n ; Bx [i] = 1 + i / x ; } } else { /* complex case */ for (i = 0 ; i < n ; i++) { double x = n ; Bx [2*i ] = 1 + i / x ; /* real part of B(i) */ Bx [2*i+1] = (x/2 - i) / (3*x) ; /* imag part of B(i) */ } } #endif cholmod_print_dense (B, "B", cm) ; bnorm = cholmod_norm_dense (B, 0, cm) ; /* max norm */ printf ("bnorm %g\n", bnorm) ; /* ---------------------------------------------------------------------- */ /* analyze, factorize, and solve */ /* ---------------------------------------------------------------------- */ t = CPUTIME ; L = cholmod_analyze (A, cm) ; ta = CPUTIME - t ; ta = MAX (ta, 0) ; printf ("Analyze: flop %g lnz %g\n", cm->fl, cm->lnz) ; if (A->stype == 0) { printf ("Factorizing A*A'+beta*I\n") ; t = CPUTIME ; cholmod_factorize_p (A, beta, NULL, 0, L, cm) ; tf = CPUTIME - t ; tf = MAX (tf, 0) ; } else { printf ("Factorizing A\n") ; t = CPUTIME ; cholmod_factorize (A, L, cm) ; tf = CPUTIME - t ; tf = MAX (tf, 0) ; } t = CPUTIME ; X = cholmod_solve (CHOLMOD_A, L, B, cm) ; ts = CPUTIME - t ; ts = MAX (ts, 0) ; tot = ta + tf + ts ; /* ---------------------------------------------------------------------- */ /* compute the residual */ /* ---------------------------------------------------------------------- */ if (A->stype == 0) { /* (AA'+beta*I)x=b is the linear system that was solved */ /* W = A'*X */ W = cholmod_allocate_dense (A->ncol, 1, A->ncol, xtype, cm) ; cholmod_sdmult (A, 2, one, zero, X, W, cm) ; /* R = B - beta*X */ R = cholmod_zeros (n, 1, xtype, cm) ; Rx = R->x ; Xx = X->x ; if (xtype == CHOLMOD_REAL) { for (i = 0 ; i < n ; i++) { Rx [i] = Bx [i] - beta [0] * Xx [i] ; } } else { /* complex case */ for (i = 0 ; i < n ; i++) { Rx [2*i ] = Bx [2*i ] - beta [0] * Xx [2*i ] ; Rx [2*i+1] = Bx [2*i+1] - beta [0] * Xx [2*i+1] ; } } /* R = A*W - R */ cholmod_sdmult (A, 0, one, minusone, W, R, cm) ; cholmod_free_dense (&W, cm) ; } else { /* Ax=b was factorized and solved, R = B-A*X */ R = cholmod_copy_dense (B, cm) ; cholmod_sdmult (A, 0, minusone, one, X, R, cm) ; } rnorm = cholmod_norm_dense (R, 0, cm) ; /* max abs. entry */ xnorm = cholmod_norm_dense (X, 0, cm) ; /* max abs. entry */ axbnorm = (anorm * xnorm + bnorm + ((n == 0) ? 1 : 0)) ; resid = rnorm / axbnorm ; /* ---------------------------------------------------------------------- */ /* iterative refinement (real symmetric case only) */ /* ---------------------------------------------------------------------- */ resid2 = -1 ; if (A->stype != 0 && A->xtype == CHOLMOD_REAL) { cholmod_dense *R2 ; /* R2 = A\(B-A*X) */ R2 = cholmod_solve (CHOLMOD_A, L, R, cm) ; /* compute X = X + A\(B-A*X) */ Xx = X->x ; Rx = R2->x ; for (i = 0 ; i < n ; i++) { Xx [i] = Xx [i] + Rx [i] ; } cholmod_free_dense (&R2, cm) ; cholmod_free_dense (&R, cm) ; /* compute the new residual, R = B-A*X */ R = cholmod_copy_dense (B, cm) ; cholmod_sdmult (A, 0, minusone, one, X, R, cm) ; rnorm2 = cholmod_norm_dense (R, 0, cm) ; resid2 = rnorm2 / axbnorm ; } cholmod_free_dense (&R, cm) ; /* ---------------------------------------------------------------------- */ /* print results */ /* ---------------------------------------------------------------------- */ cholmod_print_factor (L, "L", cm) ; /* determine the # of integers's and reals's in L. See cholmod_free */ if (L->is_super) { s = L->nsuper + 1 ; xsize = L->xsize ; ss = L->ssize ; isize = n /* L->Perm */ + n /* L->ColCount, nz in each column of 'pure' L */ + s /* L->pi, column pointers for L->s */ + s /* L->px, column pointers for L->x */ + s /* L->super, starting column index of each supernode */ + ss ; /* L->s, the pattern of the supernodes */ } else { /* this space can increase if you change parameters to their non- * default values (cm->final_pack, for example). */ lnz = L->nzmax ; xsize = lnz ; isize = n /* L->Perm */ + n /* L->ColCount, nz in each column of 'pure' L */ + n+1 /* L->p, column pointers */ + lnz /* L->i, integer row indices */ + n /* L->nz, nz in each column of L */ + n+2 /* L->next, link list */ + n+2 ; /* L->prev, link list */ } anz = cm->anz ; for (i = 0 ; i < CHOLMOD_MAXMETHODS ; i++) { fl = cm->method [i].fl ; xlnz = cm->method [i].lnz ; cm->method [i].fl = -1 ; cm->method [i].lnz = -1 ; ordering = cm->method [i].ordering ; if (fl >= 0) { printf ("Ordering: ") ; if (ordering == CHOLMOD_POSTORDERED) printf ("postordered ") ; if (ordering == CHOLMOD_NATURAL) printf ("natural ") ; if (ordering == CHOLMOD_GIVEN) printf ("user ") ; if (ordering == CHOLMOD_AMD) printf ("AMD ") ; if (ordering == CHOLMOD_METIS) printf ("METIS ") ; if (ordering == CHOLMOD_NESDIS) printf ("NESDIS ") ; if (xlnz > 0) { printf ("fl/lnz %10.1f", fl / xlnz) ; } if (anz > 0) { printf (" lnz/anz %10.1f", xlnz / anz) ; } printf ("\n") ; } } printf ("ints in L: %d, doubles in L: %d\n", isize, xsize) ; printf ("factor flops %g nnz(L) %15.0f (w/no amalgamation)\n", cm->fl, cm->lnz) ; if (A->stype == 0) { printf ("nnz(A): %15.0f\n", cm->anz) ; } else { printf ("nnz(A*A'): %15.0f\n", cm->anz) ; } if (cm->lnz > 0) { printf ("flops / nnz(L): %8.1f\n", cm->fl / cm->lnz) ; } if (anz > 0) { printf ("nnz(L) / nnz(A): %8.1f\n", cm->lnz / cm->anz) ; } printf ("analyze cputime: %12.4f\n", ta) ; printf ("factor cputime: %12.4f mflop: %8.1f\n", tf, (tf == 0) ? 0 : (1e-6*cm->fl / tf)) ; printf ("solve cputime: %12.4f mflop: %8.1f\n", ts, (ts == 0) ? 0 : (1e-6*4*cm->lnz / ts)) ; printf ("overall cputime: %12.4f mflop: %8.1f\n", tot, (tot == 0) ? 0 : (1e-6 * (cm->fl + 4 * cm->lnz) / tot)) ; printf ("peak memory usage: %12.0f (MB)\n", (double) (cm->memory_usage) / 1048576.) ; printf ("residual %8.1e (|Ax-b|/(|A||x|+|b|))\n", resid) ; if (resid2 >= 0) { printf ("residual %8.1e (|Ax-b|/(|A||x|+|b|))" " after iterative refinement\n", resid2) ; } printf ("rcond %8.1e\n\n", cholmod_rcond (L, cm)) ; cholmod_free_factor (&L, cm) ; cholmod_free_dense (&X, cm) ; /* ---------------------------------------------------------------------- */ /* free matrices and finish CHOLMOD */ /* ---------------------------------------------------------------------- */ cholmod_free_sparse (&A, cm) ; cholmod_free_dense (&B, cm) ; cholmod_finish (cm) ; return (0) ; }
int main (int argc, char **argv) { double resid [4], t, ta, tf, ts [3], tot, bnorm, xnorm, anorm, rnorm, fl, anz, axbnorm, rnorm2, resid2, rcond ; FILE *f ; cholmod_sparse *A ; cholmod_dense *X = NULL, *B, *W, *R ; double one [2], zero [2], minusone [2], beta [2], xlnz ; cholmod_common Common, *cm ; cholmod_factor *L ; double *Bx, *Rx, *Xx ; int i, n, isize, xsize, ordering, xtype, s, ss, lnz ; int trial, method, L_is_super ; int ver [3] ; ts[0] = 0.; ts[1] = 0.; ts[2] = 0.; /* ---------------------------------------------------------------------- */ /* get the file containing the input matrix */ /* ---------------------------------------------------------------------- */ ff = NULL ; if (argc > 1) { if ((f = fopen (argv [1], "r")) == NULL) { my_handler (CHOLMOD_INVALID, __FILE__, __LINE__, "unable to open file") ; } ff = f ; } else { f = stdin ; } /* ---------------------------------------------------------------------- */ /* start CHOLMOD and set parameters */ /* ---------------------------------------------------------------------- */ cm = &Common ; cholmod_start (cm) ; CHOLMOD_FUNCTION_DEFAULTS (cm) ; /* just for testing (not required) */ /* use default parameter settings, except for the error handler. This * demo program terminates if an error occurs (out of memory, not positive * definite, ...). It makes the demo program simpler (no need to check * CHOLMOD error conditions). This non-default parameter setting has no * effect on performance. */ cm->error_handler = my_handler ; /* Note that CHOLMOD will do a supernodal LL' or a simplicial LDL' by * default, automatically selecting the latter if flop/nnz(L) < 40. */ /* ---------------------------------------------------------------------- */ /* create basic scalars */ /* ---------------------------------------------------------------------- */ zero [0] = 0 ; zero [1] = 0 ; one [0] = 1 ; one [1] = 0 ; minusone [0] = -1 ; minusone [1] = 0 ; beta [0] = 1e-6 ; beta [1] = 0 ; /* ---------------------------------------------------------------------- */ /* read in a matrix */ /* ---------------------------------------------------------------------- */ printf ("\n---------------------------------- cholmod_demo:\n") ; cholmod_version (ver) ; printf ("cholmod version %d.%d.%d\n", ver [0], ver [1], ver [2]) ; SuiteSparse_version (ver) ; printf ("SuiteSparse version %d.%d.%d\n", ver [0], ver [1], ver [2]) ; A = cholmod_read_sparse (f, cm) ; if (ff != NULL) { fclose (ff) ; ff = NULL ; } anorm = cholmod_norm_sparse (A, 0, cm) ; xtype = A->xtype ; printf ("norm (A,inf) = %g\n", anorm) ; printf ("norm (A,1) = %g\n", cholmod_norm_sparse (A, 1, cm)) ; cholmod_print_sparse (A, "A", cm) ; if (A->nrow > A->ncol) { /* Transpose A so that A'A+beta*I will be factorized instead */ cholmod_sparse *C = cholmod_transpose (A, 2, cm) ; cholmod_free_sparse (&A, cm) ; A = C ; printf ("transposing input matrix\n") ; } /* ---------------------------------------------------------------------- */ /* create an arbitrary right-hand-side */ /* ---------------------------------------------------------------------- */ n = A->nrow ; B = cholmod_zeros (n, 1, xtype, cm) ; Bx = B->x ; #if GHS { /* b = A*ones(n,1), used by Gould, Hu, and Scott in their experiments */ cholmod_dense *X0 ; X0 = cholmod_ones (A->ncol, 1, xtype, cm) ; cholmod_sdmult (A, 0, one, zero, X0, B, cm) ; cholmod_free_dense (&X0, cm) ; } #else if (xtype == CHOLMOD_REAL) { /* real case */ for (i = 0 ; i < n ; i++) { double x = n ; Bx [i] = 1 + i / x ; } } else { /* complex case */ for (i = 0 ; i < n ; i++) { double x = n ; Bx [2*i ] = 1 + i / x ; /* real part of B(i) */ Bx [2*i+1] = (x/2 - i) / (3*x) ; /* imag part of B(i) */ } } #endif cholmod_print_dense (B, "B", cm) ; bnorm = cholmod_norm_dense (B, 0, cm) ; /* max norm */ printf ("bnorm %g\n", bnorm) ; /* ---------------------------------------------------------------------- */ /* analyze and factorize */ /* ---------------------------------------------------------------------- */ t = CPUTIME ; L = cholmod_analyze (A, cm) ; ta = CPUTIME - t ; ta = MAX (ta, 0) ; printf ("Analyze: flop %g lnz %g\n", cm->fl, cm->lnz) ; if (A->stype == 0) { printf ("Factorizing A*A'+beta*I\n") ; t = CPUTIME ; cholmod_factorize_p (A, beta, NULL, 0, L, cm) ; tf = CPUTIME - t ; tf = MAX (tf, 0) ; } else { printf ("Factorizing A\n") ; t = CPUTIME ; cholmod_factorize (A, L, cm) ; tf = CPUTIME - t ; tf = MAX (tf, 0) ; } cholmod_print_factor (L, "L", cm) ; /* determine the # of integers's and reals's in L. See cholmod_free */ if (L->is_super) { s = L->nsuper + 1 ; xsize = L->xsize ; ss = L->ssize ; isize = n /* L->Perm */ + n /* L->ColCount, nz in each column of 'pure' L */ + s /* L->pi, column pointers for L->s */ + s /* L->px, column pointers for L->x */ + s /* L->super, starting column index of each supernode */ + ss ; /* L->s, the pattern of the supernodes */ } else { /* this space can increase if you change parameters to their non- * default values (cm->final_pack, for example). */ lnz = L->nzmax ; xsize = lnz ; isize = n /* L->Perm */ + n /* L->ColCount, nz in each column of 'pure' L */ + n+1 /* L->p, column pointers */ + lnz /* L->i, integer row indices */ + n /* L->nz, nz in each column of L */ + n+2 /* L->next, link list */ + n+2 ; /* L->prev, link list */ } /* solve with Bset will change L from simplicial to supernodal */ rcond = cholmod_rcond (L, cm) ; L_is_super = L->is_super ; /* ---------------------------------------------------------------------- */ /* solve */ /* ---------------------------------------------------------------------- */ for (method = 0 ; method <= 3 ; method++) { double x = n ; if (method == 0) { /* basic solve, just once */ t = CPUTIME ; X = cholmod_solve (CHOLMOD_A, L, B, cm) ; ts [0] = CPUTIME - t ; ts [0] = MAX (ts [0], 0) ; } else if (method == 1) { /* basic solve, many times, but keep the last one */ t = CPUTIME ; for (trial = 0 ; trial < NTRIALS ; trial++) { cholmod_free_dense (&X, cm) ; Bx [0] = 1 + trial / x ; /* tweak B each iteration */ X = cholmod_solve (CHOLMOD_A, L, B, cm) ; } ts [1] = CPUTIME - t ; ts [1] = MAX (ts [1], 0) / NTRIALS ; } else if (method == 2) { /* solve with reused workspace */ cholmod_dense *Ywork = NULL, *Ework = NULL ; cholmod_free_dense (&X, cm) ; t = CPUTIME ; for (trial = 0 ; trial < NTRIALS ; trial++) { Bx [0] = 1 + trial / x ; /* tweak B each iteration */ cholmod_solve2 (CHOLMOD_A, L, B, NULL, &X, NULL, &Ywork, &Ework, cm) ; } cholmod_free_dense (&Ywork, cm) ; cholmod_free_dense (&Ework, cm) ; ts [2] = CPUTIME - t ; ts [2] = MAX (ts [2], 0) / NTRIALS ; } else { /* solve with reused workspace and sparse Bset */ cholmod_dense *Ywork = NULL, *Ework = NULL ; cholmod_dense *X2 = NULL, *B2 = NULL ; cholmod_sparse *Bset, *Xset = NULL ; int *Bsetp, *Bseti, *Xsetp, *Xseti, xlen, j, k, *Lnz ; double *X1x, *X2x, *B2x, err ; FILE *timelog = fopen ("timelog.m", "w") ; if (timelog) fprintf (timelog, "results = [\n") ; B2 = cholmod_zeros (n, 1, xtype, cm) ; B2x = B2->x ; Bset = cholmod_allocate_sparse (n, 1, 1, FALSE, TRUE, 0, CHOLMOD_PATTERN, cm) ; Bsetp = Bset->p ; Bseti = Bset->i ; Bsetp [0] = 0 ; /* nnz(B) is 1 (it can be anything) */ Bsetp [1] = 1 ; resid [3] = 0 ; for (i = 0 ; i < MIN (100,n) ; i++) { /* B (i) is nonzero, all other entries are ignored (implied to be zero) */ Bseti [0] = i ; if (xtype == CHOLMOD_REAL) { B2x [i] = 3.1 * i + 0.9 ; } else { B2x [2*i ] = i + 0.042 ; B2x [2*i+1] = i - 92.7 ; } /* first get the entire solution, to compare against */ cholmod_solve2 (CHOLMOD_A, L, B2, NULL, &X, NULL, &Ywork, &Ework, cm) ; /* now get the sparse solutions; this will change L from supernodal to simplicial */ if (i == 0) { /* first solve can be slower because it has to allocate space for X2, Xset, etc, and change L. So don't time it */ cholmod_solve2 (CHOLMOD_A, L, B2, Bset, &X2, &Xset, &Ywork, &Ework, cm) ; } t = CPUTIME ; for (trial = 0 ; trial < NTRIALS ; trial++) { /* solve Ax=b but only to get x(i). b is all zero except for b(i). This takes O(xlen) time */ cholmod_solve2 (CHOLMOD_A, L, B2, Bset, &X2, &Xset, &Ywork, &Ework, cm) ; } t = CPUTIME - t ; t = MAX (t, 0) / NTRIALS ; /* check the solution and log the time */ Xsetp = Xset->p ; Xseti = Xset->i ; xlen = Xsetp [1] ; X1x = X->x ; X2x = X2->x ; Lnz = L->nz ; /* printf ("\ni %d xlen %d (%p %p)\n", i, xlen, X1x, X2x) ; */ if (xtype == CHOLMOD_REAL) { fl = 2 * xlen ; for (k = 0 ; k < xlen ; k++) { j = Xseti [k] ; fl += 4 * Lnz [j] ; err = X1x [j] - X2x [j] ; err = ABS (err) ; resid [3] = MAX (resid [3], err) ; } } else { fl = 16 * xlen ; for (k = 0 ; k < xlen ; k++) { j = Xseti [k] ; fl += 16 * Lnz [j] ; err = X1x [2*j ] - X2x [2*j ] ; err = ABS (err) ; resid [3] = MAX (resid [3], err) ; err = X1x [2*j+1] - X2x [2*j+1] ; err = ABS (err) ; resid [3] = MAX (resid [3], err) ; } } if (timelog) fprintf (timelog, "%g %g %g %g\n", (double) i, (double) xlen, fl, t); /* clear B for the next test */ if (xtype == CHOLMOD_REAL) { B2x [i] = 0 ; } else { B2x [2*i ] = 0 ; B2x [2*i+1] = 0 ; } } if (timelog) { fprintf (timelog, "] ; resid = %g ;\n", resid [3]) ; fprintf (timelog, "lnz = %g ;\n", cm->lnz) ; fprintf (timelog, "t = %g ; %% dense solve time\n", ts [2]) ; fclose (timelog) ; } resid [3] = resid [3] / cholmod_norm_dense (X, 1, cm) ; cholmod_free_dense (&Ywork, cm) ; cholmod_free_dense (&Ework, cm) ; cholmod_free_dense (&X2, cm) ; cholmod_free_dense (&B2, cm) ; cholmod_free_sparse (&Xset, cm) ; cholmod_free_sparse (&Bset, cm) ; } /* ------------------------------------------------------------------ */ /* compute the residual */ /* ------------------------------------------------------------------ */ if (method < 3) { if (A->stype == 0) { /* (AA'+beta*I)x=b is the linear system that was solved */ /* W = A'*X */ W = cholmod_allocate_dense (A->ncol, 1, A->ncol, xtype, cm) ; cholmod_sdmult (A, 2, one, zero, X, W, cm) ; /* R = B - beta*X */ R = cholmod_zeros (n, 1, xtype, cm) ; Rx = R->x ; Xx = X->x ; if (xtype == CHOLMOD_REAL) { for (i = 0 ; i < n ; i++) { Rx [i] = Bx [i] - beta [0] * Xx [i] ; } } else { /* complex case */ for (i = 0 ; i < n ; i++) { Rx [2*i ] = Bx [2*i ] - beta [0] * Xx [2*i ] ; Rx [2*i+1] = Bx [2*i+1] - beta [0] * Xx [2*i+1] ; } } /* R = A*W - R */ cholmod_sdmult (A, 0, one, minusone, W, R, cm) ; cholmod_free_dense (&W, cm) ; } else { /* Ax=b was factorized and solved, R = B-A*X */ R = cholmod_copy_dense (B, cm) ; cholmod_sdmult (A, 0, minusone, one, X, R, cm) ; } rnorm = cholmod_norm_dense (R, 0, cm) ; /* max abs. entry */ xnorm = cholmod_norm_dense (X, 0, cm) ; /* max abs. entry */ axbnorm = (anorm * xnorm + bnorm + ((n == 0) ? 1 : 0)) ; resid [method] = rnorm / axbnorm ; } } tot = ta + tf + ts [0] ; /* ---------------------------------------------------------------------- */ /* iterative refinement (real symmetric case only) */ /* ---------------------------------------------------------------------- */ resid2 = -1 ; if (A->stype != 0 && A->xtype == CHOLMOD_REAL) { cholmod_dense *R2 ; /* R2 = A\(B-A*X) */ R2 = cholmod_solve (CHOLMOD_A, L, R, cm) ; /* compute X = X + A\(B-A*X) */ Xx = X->x ; Rx = R2->x ; for (i = 0 ; i < n ; i++) { Xx [i] = Xx [i] + Rx [i] ; } cholmod_free_dense (&R2, cm) ; cholmod_free_dense (&R, cm) ; /* compute the new residual, R = B-A*X */ R = cholmod_copy_dense (B, cm) ; cholmod_sdmult (A, 0, minusone, one, X, R, cm) ; rnorm2 = cholmod_norm_dense (R, 0, cm) ; resid2 = rnorm2 / axbnorm ; } cholmod_free_dense (&R, cm) ; /* ---------------------------------------------------------------------- */ /* print results */ /* ---------------------------------------------------------------------- */ anz = cm->anz ; for (i = 0 ; i < CHOLMOD_MAXMETHODS ; i++) { fl = cm->method [i].fl ; xlnz = cm->method [i].lnz ; cm->method [i].fl = -1 ; cm->method [i].lnz = -1 ; ordering = cm->method [i].ordering ; if (fl >= 0) { printf ("Ordering: ") ; if (ordering == CHOLMOD_POSTORDERED) printf ("postordered ") ; if (ordering == CHOLMOD_NATURAL) printf ("natural ") ; if (ordering == CHOLMOD_GIVEN) printf ("user ") ; if (ordering == CHOLMOD_AMD) printf ("AMD ") ; if (ordering == CHOLMOD_METIS) printf ("METIS ") ; if (ordering == CHOLMOD_NESDIS) printf ("NESDIS ") ; if (xlnz > 0) { printf ("fl/lnz %10.1f", fl / xlnz) ; } if (anz > 0) { printf (" lnz/anz %10.1f", xlnz / anz) ; } printf ("\n") ; } } printf ("ints in L: %15.0f, doubles in L: %15.0f\n", (double) isize, (double) xsize) ; printf ("factor flops %g nnz(L) %15.0f (w/no amalgamation)\n", cm->fl, cm->lnz) ; if (A->stype == 0) { printf ("nnz(A): %15.0f\n", cm->anz) ; } else { printf ("nnz(A*A'): %15.0f\n", cm->anz) ; } if (cm->lnz > 0) { printf ("flops / nnz(L): %8.1f\n", cm->fl / cm->lnz) ; } if (anz > 0) { printf ("nnz(L) / nnz(A): %8.1f\n", cm->lnz / cm->anz) ; } printf ("analyze cputime: %12.4f\n", ta) ; printf ("factor cputime: %12.4f mflop: %8.1f\n", tf, (tf == 0) ? 0 : (1e-6*cm->fl / tf)) ; printf ("solve cputime: %12.4f mflop: %8.1f\n", ts [0], (ts [0] == 0) ? 0 : (1e-6*4*cm->lnz / ts [0])) ; printf ("overall cputime: %12.4f mflop: %8.1f\n", tot, (tot == 0) ? 0 : (1e-6 * (cm->fl + 4 * cm->lnz) / tot)) ; printf ("solve cputime: %12.4f mflop: %8.1f (%d trials)\n", ts [1], (ts [1] == 0) ? 0 : (1e-6*4*cm->lnz / ts [1]), NTRIALS) ; printf ("solve2 cputime: %12.4f mflop: %8.1f (%d trials)\n", ts [2], (ts [2] == 0) ? 0 : (1e-6*4*cm->lnz / ts [2]), NTRIALS) ; printf ("peak memory usage: %12.0f (MB)\n", (double) (cm->memory_usage) / 1048576.) ; printf ("residual (|Ax-b|/(|A||x|+|b|)): ") ; for (method = 0 ; method <= 3 ; method++) { printf ("%8.2e ", resid [method]) ; } printf ("\n") ; if (resid2 >= 0) { printf ("residual %8.1e (|Ax-b|/(|A||x|+|b|))" " after iterative refinement\n", resid2) ; } printf ("rcond %8.1e\n\n", rcond) ; if (L_is_super) { cholmod_gpu_stats (cm) ; } cholmod_free_factor (&L, cm) ; cholmod_free_dense (&X, cm) ; /* ---------------------------------------------------------------------- */ /* free matrices and finish CHOLMOD */ /* ---------------------------------------------------------------------- */ cholmod_free_sparse (&A, cm) ; cholmod_free_dense (&B, cm) ; cholmod_finish (cm) ; return (0) ; }
int main(int argc, char *argv[]) { char *name = "main"; char *seperator = "**********************************************************"; // Setup the data structure with parameters of the problem switch (argc) { case 1: printf("No input file specified. Using dia1P.inp\n"); dia1P_initialize("dia1P.inp",name); break; case 2: dia1P_initialize(argv[1],name); break; default: dia1P_errHandler(errCode_TooManyArguments,name,name,errMesg_TooManyArguments); } // Print the problem to make sure dia1P_printPD(name); /* The prefix M_ is used for components that can be reused in several failure simulations. For example, it is not necessary to compute the first stiffness matrix M_M or its decomposition M_L for each failure simulation. On the other hand, the matrix of fuse strengths, S, needs to be repopulated every time. */ /* START REUSABLE COMPONENTS DECLARATIONS */ // Stiffness matrix M cholmod_sparse *M_M; // J = M_V2C*V; where J = current flowing into the bottom nodes, // and V = vector of voltages of all nodes cholmod_sparse *M_V2C; // Voltages at top and bottom nodes cholmod_sparse *M_vTop, *M_vBot; // Cholesky factor of the stiffness matrix M cholmod_factor *M_L; // Cholmod Common object cholmod_common Common; // Basic scalars, one and minus one double one [2] = {1,0}, m1 [2] = {-1,0} ; /* END REUSABLE COMPONENTS DECLARATIONS */ /* START REUSABLE COMPONENTS INITIALIZATIONS */ // Start cholmod, and the cholmod_common object cholmod_start(&Common); // Populated the top and bottom node voltages // Bottom row is "grounded", thus has zero // voltage by convention. // cholmod_spzeros(NRow,NCol,stype,xtype,*common) M_vBot = cholmod_spzeros(pD.gridSize/2,1,0,CHOLMOD_REAL,&Common); // The top row has voltage = 1. Since cholmod has no inbuild // function to return a sparse vector of all ones (makes sense) // so we first create a dense vector of ones and then // convert it to a sparse vector { // limit the scope of temporary variables cholmod_dense *temp; temp = cholmod_ones(pD.gridSize/2,1,CHOLMOD_REAL,&Common); M_vTop = cholmod_dense_to_sparse(temp,1,&Common); cholmod_free_dense(&temp,&Common); } // Polulate voltage to current matrix and check it for // consistency M_V2C = dia1P_voltageToCurrentMatrix(&Common,name); cholmod_check_sparse(M_V2C,&Common); // Populate stiffness matrix M_M = dia1P_stiffnessMatrix(&Common,name); // Check it for consistency cholmod_check_sparse(M_M,&Common); // Analyze and factorise the stiffness matrix M_L = cholmod_analyze(M_M,&Common); cholmod_factorize(M_M,M_L,&Common); // Check the factor for consistency cholmod_check_factor(M_L,&Common); /* END REUSABLE COMPONENTS INITIALIZATIONS */ // Depending on the mode in which the program is run // various levels of output are given to the user. // The three modes implemented so far are: // 0: Silent, // 1: minimal, // 2: normal // 3: verbose switch (pD.diagMode) { case 0: break; case 1: fprintf(pD.diagFile,"NSim\tnF\t\tnAv\t\tV\t\tC\n"); fflush(pD.diagFile); break; case 2: break; case 3: fprintf(pD.diagFile,"Initial Stiffness Matrix\n"); cholmod_write_sparse(pD.diagFile,M_M,NULL,NULL,&Common); fflush(pD.diagFile); break; default: dia1P_errHandler(errCode_UnknownDiagMode,name,name,errMesg_UnknownDiagMode); } /* START MAIN SIMULATIONS LOOP */ // Number of simulations performed int countSims = 0; while (countSims < pD.NSim) { /* START LOOP COMPONENTS DECLARATIONS */ // The sampleFailed flag remains zeros as long as // the sample is not broken (a spanning crack is // not encountered; it becomes 1 otherwise. int sampleFailed = 0; // nFail counts the number of bonds snapped till // sample failure int nFail = 0; // Cholesky factor L will hold the cholesky factor that will be updated after each bond snapping cholmod_factor *L; // Vector of random fuse strengths double *S; // Matrix that maps the node voltages to the vector of // currents flowing into the bottom nodes. // This matrix is update after every bond breaking cholmod_sparse *V2C; // Load vector b. This vector is to be updated after // every bond breaking cholmod_sparse *b; // A data structure that will store information about the // most recently failed bond dia1P_failureSite FD; // A data structure that will store information about the // sequence of failures in a particular simulation dia1P_brokenBonds *BB; /* END LOOP COMPONENTS DECLARATIONS */ /* START LOOP COMPONENTS INITIALIZATIONS */ // Copy the pre-calculated cholesky factor into the local // cholesky factor L = cholmod_copy_factor(M_L,&Common); // Populate fuse strength vector S = dia1P_strengthVector(name); //FILE *pf = fopen("16.S","r"); S = cholmod_read_sparse(pf,&Common); fclose(pf); // Copy the initial voltage to current matrix V2C = cholmod_copy_sparse(M_V2C,&Common); // Initialize the structure for keeping records of broken bonds BB = dia1P_initializeBrokenBonds(name); // Polulate the load vector b b = dia1P_loadVector(&Common,name); // Check to ensure consistency... cholmod_check_sparse(b,&Common); /* END LOOP COMPONENTS INITIALIZATIONS */ // Write diagonistic output as requested switch (pD.diagMode) { case 0: break; case 1: break; case 2: fprintf(pD.diagFile,"%s\n",seperator); fprintf(pD.diagFile,"Starting Simulation Number %d\n",countSims+1); fprintf(pD.diagFile,"I\t\tJ\t\tV\t\tC\n"); fflush(pD.diagFile); break; case 3: fprintf(pD.diagFile,"%s\n",seperator); fprintf(pD.diagFile,"Starting Simulation Number %d\n",countSims+1); fprintf(pD.diagFile,"Matrix of Random Fuse Strengths:\n"); { int count = 0; for(count = 0; count < (pD.gridSize)*(pD.gridSize); count++) { int n1, n2; dia1P_getNodeNumbers(&n1,&n2,count,name); fprintf(pD.diagFile,"%d\t%d\t%G\n",n1,n2,S[count]); } fprintf(pD.diagFile,"\n"); } //cholmod_write_sparse(pD.diagFile,S,NULL,NULL,&Common); fflush(pD.diagFile); break; default: dia1P_errHandler(errCode_UnknownDiagMode,name,name,errMesg_UnknownDiagMode); } while(sampleFailed == 0) { /* START INNER LOOP COMPONENTS INITIALIZATIONS */ // Vector x will hold the unknown voltages cholmod_sparse *x; // Vectors VNode_s and VNode_d hold the full set // of node voltages (knowns appended to the calculated unknowns) cholmod_sparse *VNode_s; cholmod_dense *VNode_d; // This vector will be used to update the stiffness matrix M // as M_new = M_old - stiffUpdate*transpose(stiffUpdate) // Ofcouse, M is not update, rather its cholesky factor L is cholmod_sparse *stiffUpdate; // This vector updates the load vector as // b_new = b_old + loadUpdate cholmod_sparse *loadUpdate; // This vector is needed for internal cholmod use. // We L = PMP^T, where P is the permuation matrix. // Thus, if U updates M, then PU will update L. // uper = PU. cholmod_sparse *uper; /* END INNER LOOP COMPONENTS INITIALIZATIONS */ // Solve for the unknown voltages x = cholmod_spsolve(CHOLMOD_A,L,b,&Common); // Append the known vectors top and the bottom // row voltages to x to construct the complete // vector of voltages. { // Limit the score of temporary variables cholmod_sparse *temp1; temp1 = cholmod_vertcat(M_vBot,x,1,&Common); VNode_s = cholmod_vertcat(temp1,M_vTop,1,&Common); cholmod_free_sparse(&temp1,&Common); } // Check if the sample is broken, if it is then // we are done if(dia1P_isBroken(VNode_s,V2C,&Common,name)) { sampleFailed = 1; { int count = 0; for(count = 0; count < BB->nFail; count++) { fprintf(pD.outFile,"%d\t%d\t%G\t%G\t%G\n",BB->i[count]+1,BB->j[count]+1,BB->v[count],BB->c[count],BB->bondStrength[count]); } fprintf(pD.outFile,"%d\t%d\t%G\t%G\t%G\n",0,0,0.f,0.f,0.f); } } else { // If the sample is not broken yet, then we need to // to find which bond will be snapped next. // Increment the number of failed bonds, since we know // that one is going to snap nFail++; // Make a dense vector of voltages VNode_d = cholmod_sparse_to_dense(VNode_s,&Common); // Find which bond to break and store the information // in the data structure FD. dia1P_bondToSnap(S,VNode_d,VNode_s,V2C,BB,&FD,&Common,name); // Update the data structure BB, which stores the entire // sequence of broken bonds dia1P_updateBrokenBonds(BB,&FD,name); // Update the voltage to current matrix. // This matrix will change only if a fuse connected to the // bottom edge is blown. dia1P_updateVoltageToCurrentMatrix(V2C,&FD,&Common,name); // Find the vector to update the stiffness matrix. // This vector is never empty, it has either 1 or 2 nonzero components // depending on weather a boundary node is involved in the snapping or not stiffUpdate = dia1P_stiffnessUpdateVector(&FD,&Common,name); // Find the vector to update the load vector. // This vector is non-zero only if a fuse connected to the // top edge is blown. loadUpdate = dia1P_loadUpdateVector(&FD,&Common,name); // Update the load vector { // Limit the score of temporary variables cholmod_sparse *temp; temp = cholmod_copy_sparse(b,&Common); // Free the current memory occupied by b before reallocating cholmod_free_sparse(&b,&Common); // Reallocate b b = cholmod_add(temp,loadUpdate,one,one,1,0,&Common); // Free temp cholmod_free_sparse(&temp,&Common); } // Calculate the permuted update vector for updating the cholesky factor uper = cholmod_submatrix(stiffUpdate,L->Perm,L->n,NULL,-1,1,1,&Common); // update (downdate) the cholesky factor cholmod_updown(0,uper,L,&Common); // Write appropriate diagnostic output switch (pD.diagMode) { case 0: break; case 1: break; case 2: fprintf(pD.diagFile,"%d\t\t%d\t\t%.3f\t%.3f\n",FD.node1+1,FD.node2+1,FD.fVol,FD.fCur); break; case 3: fprintf(pD.diagFile,"\nPass No. %d\nUnknown Node Voltages:\n",nFail); cholmod_write_sparse(pD.diagFile,x,NULL,NULL,&Common); fprintf(pD.diagFile,"\nSnapped Bond: \nI\t\tJ\t\tV\t\tC\n"); fprintf(pD.diagFile,"%d\t\t%d\t\t%.3f\t%.3f\n\n",FD.node1+1,FD.node2+1,FD.fVol,FD.fCur); fprintf(pD.diagFile,"\nStiffNess Update Vector\n"); cholmod_write_sparse(pD.diagFile,stiffUpdate,NULL,NULL,&Common); fprintf(pD.diagFile,"\nLoad Update Vector\n"); cholmod_write_sparse(pD.diagFile,loadUpdate,NULL,NULL,&Common); break; default: dia1P_errHandler(errCode_UnknownDiagMode,name,name,errMesg_UnknownDiagMode); } //Free memory cholmod_free_dense(&VNode_d,&Common); cholmod_free_sparse(&stiffUpdate,&Common); cholmod_free_sparse(&loadUpdate,&Common); cholmod_free_sparse(&uper,&Common); }//ESLE cholmod_free_sparse(&x,&Common); cholmod_free_sparse(&VNode_s,&Common); }//ELIHW, loop for nth simulation // Free memory free(S); cholmod_free_sparse(&b,&Common); cholmod_free_sparse(&V2C,&Common); cholmod_free_factor(&L,&Common); dia1P_freeBrokenBonds(&BB,name); countSims++; }//ELIHW, main loop for NSim simulations // This completes the requested set of NSim simulations. // Free memory cholmod_free_sparse(&M_M,&Common); cholmod_free_sparse(&M_V2C,&Common); cholmod_free_sparse(&M_vBot,&Common); cholmod_free_sparse(&M_vTop,&Common); cholmod_free_factor(&M_L,&Common); // Close dia1P and cholmod dia1P_finish(name); // cholmod_print_common("FuseNet Statistics",&Common); cholmod_finish(&Common); return(0); }