Esempio n. 1
0
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) ;
}
Esempio n. 2
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) ;
}
Esempio n. 3
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
}
Esempio n. 4
0
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) ;
}
Esempio n. 6
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);	
}