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
// called from package MatrixModels's R code:
SEXP dgCMatrix_cholsol(SEXP x, SEXP y)
{
    /* Solve Sparse Least Squares X %*% beta ~= y  with dense RHS y,
     * where X = t(x) i.e. we pass  x = t(X)  as argument,
     * via  "Cholesky(X'X)" .. well not really:
     * cholmod_factorize("x", ..) finds L in  X'X = L'L directly */
    CHM_SP cx = AS_CHM_SP(x);
    /* FIXME: extend this to work in multivariate case, i.e. y a matrix with > 1 column ! */
    CHM_DN cy = AS_CHM_DN(coerceVector(y, REALSXP)), rhs, cAns, resid;
    CHM_FR L;
    int n = cx->ncol;/* #{obs.} {x = t(X) !} */
    double one[] = {1,0}, zero[] = {0,0}, neg1[] = {-1,0};
    const char *nms[] = {"L", "coef", "Xty", "resid", ""};
    SEXP ans = PROTECT(Rf_mkNamed(VECSXP, nms));
    R_CheckStack();

    if (n < cx->nrow || n <= 0)
	error(_("dgCMatrix_cholsol requires a 'short, wide' rectangular matrix"));
    if (cy->nrow != n)
	error(_("Dimensions of system to be solved are inconsistent"));
    rhs = cholmod_allocate_dense(cx->nrow, 1, cx->nrow, CHOLMOD_REAL, &c);
    /* cholmod_sdmult(A, transp, alpha, beta, X, Y, &c):
     *		Y := alpha*(A*X) + beta*Y or alpha*(A'*X) + beta*Y ;
     * here: rhs := 1 * x %*% y + 0 =  x %*% y =  X'y  */
    if (!(cholmod_sdmult(cx, 0 /* trans */, one, zero, cy, rhs, &c)))
	error(_("cholmod_sdmult error (rhs)"));
    L = cholmod_analyze(cx, &c);
    if (!cholmod_factorize(cx, L, &c))
	error(_("cholmod_factorize failed: status %d, minor %d from ncol %d"),
	      c.status, L->minor, L->n);
/* FIXME: Do this in stages so an "effects" vector can be calculated */
    if (!(cAns = cholmod_solve(CHOLMOD_A, L, rhs, &c)))
	error(_("cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d"),
	      c.status, L->minor, L->n);
    /* L : */
    SET_VECTOR_ELT(ans, 0, chm_factor_to_SEXP(L, 0));
    /* coef : */
    SET_VECTOR_ELT(ans, 1, allocVector(REALSXP, cx->nrow));
    Memcpy(REAL(VECTOR_ELT(ans, 1)), (double*)(cAns->x), cx->nrow);
    /* X'y : */
/* FIXME: Change this when the "effects" vector is available */
    SET_VECTOR_ELT(ans, 2, allocVector(REALSXP, cx->nrow));
    Memcpy(REAL(VECTOR_ELT(ans, 2)), (double*)(rhs->x), cx->nrow);
    /* resid := y */
    resid = cholmod_copy_dense(cy, &c);
    /* cholmod_sdmult(A, transp, alp, bet, X, Y, &c):
     *		Y := alp*(A*X) + bet*Y or alp*(A'*X) + beta*Y ;
     * here: resid := -1 * x' %*% coef + 1 * y = y - X %*% coef  */
    if (!(cholmod_sdmult(cx, 1/* trans */, neg1, one, cAns, resid, &c)))
	error(_("cholmod_sdmult error (resid)"));
    /* FIXME: for multivariate case, i.e. resid  *matrix* with > 1 column ! */
    SET_VECTOR_ELT(ans, 3, allocVector(REALSXP, n));
    Memcpy(REAL(VECTOR_ELT(ans, 3)), (double*)(resid->x), n);

    cholmod_free_factor(&L, &c);
    cholmod_free_dense(&rhs, &c);
    cholmod_free_dense(&cAns, &c);
    UNPROTECT(1);
    return ans;
}
int CholeskyFactorization::factorize() {
    if (m_matrix_type == Matrix::MATRIX_SPARSE) {
        /* Cholesky decomposition of a SPARSE matrix: */
        if (m_matrix->m_sparse == NULL) {
            m_matrix->_createSparse();
        }
        /* analyze */
        m_factor = cholmod_analyze(m_matrix->m_sparse, Matrix::cholmod_handle());
        /* factorize */
        cholmod_factorize(m_matrix->m_sparse, m_factor, Matrix::cholmod_handle());
        /* Success: status = 0, else 1*/
        return (m_factor->minor == m_matrix->m_nrows) ? ForBESUtils::STATUS_OK : ForBESUtils::STATUS_NUMERICAL_PROBLEMS;
    } else { /* If this is any non-sparse matrix: */
        memcpy(m_L, m_matrix->getData(), m_matrix->length() * sizeof (double)); /* m_L := m_matrix.m_data */
        int info = ForBESUtils::STATUS_OK;
        if (m_matrix_type == Matrix::MATRIX_DENSE) { /* This is a dense matrix */
            info = LAPACKE_dpotrf(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, m_L, m_matrix_nrows);
#ifdef SET_L_OFFDIAG_TO_ZERO
            for (size_t i = 0; i < m_matrix_nrows; i++) {
                for (size_t j = i + 1; j < m_matrix_nrows; j++) {
                    L.set(i, j, 0.0);
                }
            }
#endif
        } else if (m_matrix_type == Matrix::MATRIX_SYMMETRIC) { /* This is a symmetric matrix */
            info = LAPACKE_dpptrf(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, m_L);
        }
        return info;
    }
}
Esempio n. 5
0
SEXP dsCMatrix_Cholesky(SEXP Ap, SEXP permP, SEXP LDLp, SEXP superP)
{
    char *fname = strdup("spdCholesky"); /* template for factorization name */
    int perm = asLogical(permP),
	LDL = asLogical(LDLp),
	super = asLogical(superP);
    SEXP Chol;
    cholmod_sparse *A;
    cholmod_factor *L;
    int sup, ll;

    if (super) fname[0] = 'S';
    if (perm) fname[1] = 'P';
    if (LDL) fname[2] = 'D';
    Chol = get_factors(Ap, "fname");
    if (Chol != R_NilValue) return Chol;
    A = as_cholmod_sparse(Ap);
    sup = c.supernodal;
    ll = c.final_ll;
	
    if (!A->stype) error("Non-symmetric matrix passed to dsCMatrix_chol");
    
    c.final_ll = !LDL;	/* leave as LL' or form LDL' */
    c.supernodal = super ? CHOLMOD_SUPERNODAL : CHOLMOD_SIMPLICIAL; 

    if (perm) {
	L = cholmod_analyze(A, &c); /* get fill-reducing permutation */
    } else {			    /* require identity permutation */
	int nmethods = c.nmethods, ord0 = c.method[0].ordering,
	    postorder = c.postorder;
	c.nmethods = 1;
	c.method[0].ordering = CHOLMOD_NATURAL;
	c.postorder = FALSE;
	L = cholmod_analyze(A, &c);
	c.nmethods = nmethods; c.method[0].ordering = ord0;
	c.postorder = postorder;
    }
    c.supernodal = sup;	/* restore previous setting */
    c.final_ll = ll;
    if (!cholmod_factorize(A, L, &c))
	error(_("Cholesky factorization failed"));
    Free(A);
    Chol = set_factors(Ap, chm_factor_to_SEXP(L, 1), fname);
    free(fname);		/* note, this must be free, not Free */
    return Chol;
}
  bool SparseOptimizerIncremental::computeCholeskyUpdate()
  {
    if (_cholmodFactor) {
      cholmod_free_factor(&_cholmodFactor, &_cholmodCommon);
      _cholmodFactor = 0;
    }

    const SparseBlockMatrix<MatrixXd>& A = _updateMat;
    size_t m = A.rows();
    size_t n = A.cols();

    if (_cholmodSparse->columnsAllocated < n) {
      //std::cerr << __PRETTY_FUNCTION__ << ": reallocating columns" << std::endl;
      _cholmodSparse->columnsAllocated = _cholmodSparse->columnsAllocated == 0 ? n : 2 * n; // pre-allocate more space if re-allocating
      delete[] (int*)_cholmodSparse->p;
      _cholmodSparse->p = new int[_cholmodSparse->columnsAllocated+1];
    }
    size_t nzmax = A.nonZeros();
    if (_cholmodSparse->nzmax < nzmax) {
      //std::cerr << __PRETTY_FUNCTION__ << ": reallocating row + values" << std::endl;
      _cholmodSparse->nzmax = _cholmodSparse->nzmax == 0 ? nzmax : 2 * nzmax; // pre-allocate more space if re-allocating
      delete[] (double*)_cholmodSparse->x;
      delete[] (int*)_cholmodSparse->i;
      _cholmodSparse->i = new int[_cholmodSparse->nzmax];
      _cholmodSparse->x = new double[_cholmodSparse->nzmax];
    }
    _cholmodSparse->ncol = n;
    _cholmodSparse->nrow = m;

    A.fillCCS((int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true);
    //writeCCSMatrix("updatesparse.txt", _cholmodSparse->nrow, _cholmodSparse->ncol, (int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true);

    _cholmodFactor = cholmod_analyze(_cholmodSparse, &_cholmodCommon);
    cholmod_factorize(_cholmodSparse, _cholmodFactor, &_cholmodCommon);

#if 0
    int* p = (int*)_cholmodFactor->Perm;
    for (int i = 0; i < (int)n; ++i)
      if (i != p[i])
        cerr << "wrong permutation" << i << " -> " << p[i] << endl;
#endif

    if (_cholmodCommon.status == CHOLMOD_NOT_POSDEF) {
      //std::cerr << "Cholesky failure, writing debug.txt (Hessian loadable by Octave)" << std::endl;
      //writeCCSMatrix("debug.txt", _cholmodSparse->nrow, _cholmodSparse->ncol, (int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true);
      return false;
    }

    // change to the specific format we need to have a pretty normal L
    int change_status = cholmod_change_factor(CHOLMOD_REAL, 1, 0, 1, 1, _cholmodFactor, &_cholmodCommon);
    if (! change_status) {
      return false;
    }

    return true;
  }
Esempio n. 7
0
// doing cholesky decomposition
void Algebra::CK_decomp(Matrix &A, cholmod_factor *&L, cholmod_common *cm, size_t &peak_mem, size_t & CK_mem){
	// doing factorization first
	cholmod_triplet * T;
	size_t n_row = A.get_row();
	size_t n_col = A.get_row();
	size_t nnz = A.size();
	int *Ti;
	int *Tj;
	double *Tx;
	int stype = -1;// lower triangular storage
	T = cholmod_allocate_triplet(n_row, n_col, nnz, stype, 
			CHOLMOD_REAL, cm);
	Ti = static_cast<int *>(T->i);
	Tj = static_cast<int *>(T->j);
	Tx = static_cast<double *>(T->x);
	// copy data into T
	for(size_t k=0;k<nnz;k++){
		Ti[k] = A.Ti[k];
		Tj[k] = A.Tj[k];
		Tx[k] = A.Tx[k];
	}
	T->nnz = nnz;
	A.Ti.clear();
	A.Tj.clear();
	A.Tx.clear();
	cholmod_sparse * A_cholmod;
	A_cholmod = cholmod_triplet_to_sparse(T, nnz, cm);

	// free the triplet pointer
	cholmod_free_triplet(&T, cm);

	//cm->supernodal = -1;
	L = cholmod_analyze(A_cholmod, cm);
	//L->ordering = CHOLMOD_NATURAL;
	cholmod_factorize(A_cholmod, L, cm);
	//cholmod_print_factor(L, "L", cm);
	//if(peak_mem < cm->memory_usage)
		//peak_mem = cm->memory_usage;
	//CK_mem += cm->lnz;
	cholmod_free_sparse(&A_cholmod, cm);
}
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. 9
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) ;
}
  void MultivariateFNormalSufficientSparse::set_Sigma(
          const SparseMatrix<double>& Sigma)
  {
        if (Sigma.cols() != Sigma.rows()) {
            IMP_THROW("need a square matrix!", ModelException);
            }
        //std::cout << "set_sigma" << std::endl;
        if (Sigma_) cholmod_free_sparse(&Sigma_, c_);
        cholmod_sparse A(Eigen::viewAsCholmod(
                            Sigma.selfadjointView<Eigen::Upper>()));
        Sigma_=cholmod_copy_sparse(&A, c_);
        //cholmod_print_sparse(Sigma_,"Sigma",c_);
        IMP_LOG(TERSE, "MVNsparse:   set Sigma to new matrix" << std::endl);
        IMP_LOG(TERSE, "MVNsparse:   computing Cholesky decomposition"
                << std::endl);
        // compute Cholesky decomposition for determinant and inverse
        //c_->final_asis=1; // setup LDLT calculation
        //c_->supernodal = CHOLMOD_SIMPLICIAL;
        // convert matrix to cholmod format
        //symbolic and numeric factorization
        L_ = cholmod_analyze(Sigma_, c_);
        int success = cholmod_factorize(Sigma_, L_, c_);
        //cholmod_print_factor(L_,"L",c_);

        if (success == 0 || L_->minor < L_->n)
            IMP_THROW("Sigma matrix is not positive semidefinite!",
                    ModelException);
        // determinant and derived constants
        cholmod_factor *Lcp(cholmod_copy_factor(L_, c_));
        cholmod_sparse *Lsp(cholmod_factor_to_sparse(Lcp,c_));
        double logDetSigma=0;
        if ((Lsp->itype != CHOLMOD_INT) &&
                (Lsp->xtype != CHOLMOD_REAL))
            IMP_THROW("types are not int and real, update them here first",
                    ModelException);
        int *p=(int*) Lsp->p;
        double *x=(double*) Lsp->x;
        for (size_t i=0; i < (size_t) M_; ++i)
            logDetSigma += std::log(x[p[i]]);
        cholmod_free_sparse(&Lsp,c_);
        cholmod_free_factor(&Lcp,c_);
        IMP_LOG(TERSE, "MVNsparse:   log det(Sigma) = "
                << logDetSigma << std::endl);
        IMP_LOG(TERSE, "MVNsparse:   det(Sigma) = "
                << exp(logDetSigma) << std::endl);
        norm_= std::pow(2*IMP::PI, -double(N_*M_)/2.0)
                    * exp(-double(N_)/2.0*logDetSigma);
        lnorm_=double(N_*M_)/2 * log(2*IMP::PI) + double(N_)/2 * logDetSigma;
        IMP_LOG(TERSE, "MVNsparse:   norm = " << norm_ << " lnorm = "
                << lnorm_ << std::endl);
        //inverse
        IMP_LOG(TERSE, "MVNsparse:   solving for inverse" << std::endl);
        cholmod_sparse* id = cholmod_speye(M_,M_,CHOLMOD_REAL,c_);
        if (P_) cholmod_free_sparse(&P_, c_);
        P_ = cholmod_spsolve(CHOLMOD_A, L_, id, c_);
        cholmod_free_sparse(&id, c_);
        if (!P_) IMP_THROW("Unable to solve for inverse!", ModelException);
        //WP
        IMP_LOG(TERSE, "MVNsparse:   solving for PW" << std::endl);
        if (PW_) cholmod_free_sparse(&PW_, c_);
        PW_ = cholmod_spsolve(CHOLMOD_A, L_, W_, c_);
        if (!PW_) IMP_THROW("Unable to solve for PW!", ModelException);
        IMP_LOG(TERSE, "MVNsparse:   done" << std::endl);
  }
Esempio n. 11
0
void tele2d::computeVectorField(){

	unsigned time1, time2, time3 ;
	time1 = clock() ;

	std::vector<std::vector<double2>>  allcurves = curves ;
	vector_field.clear() ;
	vector_field.resize(resolution*resolution) ;

	// delete too short curves
	for( int i=0; i<allcurves.size(); ++i ){
		if( allcurves[i].size() < 5 )
			allcurves.erase( allcurves.begin() + i ) ;
	}

	if( allcurves.size() == 0 ){
		std::cout<<"no valid curves!" ;
		exit(1) ;
	}

	// mark constrained vertices
	constrained_vertices_mark.clear() ;
	for( int i=0; i<resolution; ++i ) {
		std::vector<int> a ;
		for( int j=0;j<resolution; ++j )
			a.push_back(0) ;
		constrained_vertices_mark.push_back(a) ;
	}
	for( int i=0; i<allcurves.size(); ++ i){
		for( int j =0; j<allcurves[i].size(); ++ j){
			// get x index of closest vertices
			float x = allcurves[i][j].x * resolution - 0.5 ;
			int ix ;
			if( x-floor(x) < 0.5 ) ix = floor(x) ;
			else	ix = ceil( x ) ;
			// get y index of closest vertices
			float y = allcurves[i][j].y * resolution - 0.5 ;
			int iy ;
			if( y-floor(y) < 0.5 ) iy = floor(y) ;
			else	iy = ceil( y ) ;

			if( ix < 0 ) ix = 0;
			if( ix > resolution-1) ix = resolution -1;
			if( iy < 0 ) iy = 0;
			if( iy > resolution-1) iy = resolution -1;

			constrained_vertices_mark[ix][iy] = 1 ;

		}
	}

	// compute b
	std::vector<double2> b ;
	b.resize(resolution*resolution) ;
	for( int i=0; i<resolution; ++i ){
		for( int j=0; j<resolution; ++j){
			
			if(constrained_vertices_mark[i][j] == 0 ){
				b[i+j*resolution].x = 0; 
				b[i+j*resolution].y = 0; 
				continue ;
			}

			// otherwise, the vertex indexed by (i,j) is constrained
			double vx = ((double)i+0.5)/(double)resolution ; 
			double vy = ((double)j+0.5)/(double)resolution ; 
			
			// search for the closest points
			int curveid_record = 0;
			int pointid_record = 0;
			double mindis = 1000.0f ;
			for( int curveid=0; curveid<allcurves.size(); ++curveid ){				
				for( int pointid=0; pointid<allcurves[curveid].size(); ++pointid  ){
					double quadratic_dis = ( allcurves[curveid][pointid].x - vx )*( allcurves[curveid][pointid].x - vx ) + ( allcurves[curveid][pointid].y - vy )*( allcurves[curveid][pointid].y - vy ) ;
					if( quadratic_dis < mindis ){
							mindis = quadratic_dis ;
							curveid_record = curveid ;
							pointid_record = pointid ;
					}
				}
			}

			// compute the vector of the vertex indexed by (i,j)
			int pid1 = pointid_record-1 > 0 ? pointid_record-1 : 0 ;
			int pid2 = pointid_record+1 <  allcurves[curveid_record].size()-1 ? pointid_record+1 : allcurves[curveid_record].size()-1;

			double2 vector_of_vertex ;
			vector_of_vertex.x = allcurves[curveid_record][pid2].x - allcurves[curveid_record][pid1].x ;
			vector_of_vertex.y = allcurves[curveid_record][pid2].y - allcurves[curveid_record][pid1].y ;
			double norm = sqrt( vector_of_vertex.x * vector_of_vertex.x + vector_of_vertex.y * vector_of_vertex.y) ;
			vector_of_vertex.x /= norm ;
			vector_of_vertex.y /= norm ;


			assert( norm > 0 && norm < 1) ;

			//std::cout<<"norm "<<norm<<std::endl;
			
			b[i+j*resolution ] = vector_of_vertex ;


		}
	}


	// compute Pb
	std::vector<double2> Pb = b ;
	for( int i=0; i<Pb.size(); ++i ){
		Pb[i].x *= 1.0e8 ;
		Pb[i].y *= 1.0e8 ;
	}

	// compute L+P
	int vnum =  resolution*resolution  ;
	sparse_matrix L_add_P(vnum) ;  // create a sparse matrix of vnum rows

	// L_add_P <- D - W
	for( int id_x =0; id_x<resolution; ++id_x ){
		for( int id_y =0; id_y<resolution; ++id_y ){
			int vid = id_x + id_y * resolution ;
			if( id_x != 0 && id_x != resolution-1 && id_y != 0 && id_y != resolution-1 ){ // inner area
				//L_add_P[ vid + vid*vnum] += 6.8284 ;
				L_add_P.pluse(vid,vid,6.8284 ) ;
				int neibour_id_1 =  id_x + id_y * resolution - 1 ;
				int neibour_id_2 =  id_x + id_y * resolution + 1 ;
				int neibour_id_3 =  id_x + (id_y-1) * resolution ;
				int neibour_id_4 =  id_x + (id_y+1) * resolution ;
				int neibour_id_5 =  id_x + (id_y+1) * resolution - 1 ;
				int neibour_id_6 =  id_x + (id_y+1) * resolution + 1 ;
				int neibour_id_7 =  id_x + (id_y-1) * resolution - 1 ;
				int neibour_id_8 =  id_x + (id_y-1) * resolution + 1 ;
				//L_add_P[neibour_id_1+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_1, -1 ) ;
				//L_add_P[neibour_id_2+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_2, -1 ) ;
				//L_add_P[neibour_id_3+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_3, -1 ) ;
				//L_add_P[neibour_id_4+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_4, -1 ) ;
				//L_add_P[neibour_id_5+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_5, -0.7071 ) ;
				//L_add_P[neibour_id_6+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_6, -0.7071 ) ;
				//L_add_P[neibour_id_7+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_7, -0.7071 ) ;
				//L_add_P[neibour_id_8+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_8, -0.7071 ) ;

			}
			else if((id_x == 0 || id_x==resolution-1) && (id_y == 0 || id_y==resolution-1)  ){  // coners
				//L_add_P[ vid + vid*vnum] += 2.7071 ;
				L_add_P.pluse(vid,vid, 2.7071 ) ;
				int neibour_id_1 =  ( id_x == 0 ? ( id_x+id_y * resolution+1) :  ( id_x+id_y * resolution - 1) );
				int neibour_id_2 =  ( id_y == 0 ? ( id_x+ (id_y+1) * resolution) : ( id_x+ (id_y-1) * resolution )) ;
				int neibour_id_3 =  ( id_x == 0 ? 1 : (resolution-2) ) + ( id_y == 0 ? 1 : (resolution - 2)) * resolution ;

				//L_add_P[neibour_id_1+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_1, -1 ) ;
				//L_add_P[neibour_id_2+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_2, -1 ) ;
				//L_add_P[neibour_id_3+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_3, -0.7071 ) ;

			}
			else {																		// boundaries
				//L_add_P[ vid + vid*vnum] += 4.4142 ;
				L_add_P.pluse(vid,vid, 4.4142 ) ;

				int neibour_id_1, neibour_id_2, neibour_id_3, neibour_id_4, neibour_id_5 ;
				if( id_x == 0){
					neibour_id_1 =  id_x + id_y * resolution + 1 ;
					neibour_id_2 =  id_x + (id_y+1) * resolution ;
					neibour_id_3 =  id_x + (id_y-1) * resolution ;
					neibour_id_4 =  id_x + (id_y+1) * resolution + 1;
					neibour_id_5 =  id_x + (id_y-1) * resolution + 1 ;
				}
				else if( id_x == resolution-1 ){
					neibour_id_1 =  id_x + id_y * resolution - 1 ;
					neibour_id_2 =  id_x + (id_y+1) * resolution ;
					neibour_id_3 =  id_x + (id_y-1) * resolution ;
					neibour_id_4 =  id_x + (id_y+1) * resolution - 1;
					neibour_id_5 =  id_x + (id_y-1) * resolution - 1 ;
				}
				else if( id_y == resolution-1 ){
					neibour_id_1 =  id_x + id_y * resolution + 1 ;
					neibour_id_2 =  id_x + id_y * resolution - 1 ;
					neibour_id_3 =  id_x + (id_y-1) * resolution ;
					neibour_id_4 =  id_x + (id_y-1) * resolution + 1;
					neibour_id_5 =  id_x + (id_y-1) * resolution - 1 ;
				}
				else {
					neibour_id_1 =  id_x + id_y * resolution + 1 ;
					neibour_id_2 =  id_x + id_y * resolution - 1 ;
					neibour_id_3 =  id_x + (id_y+1) * resolution ;
					neibour_id_4 =  id_x + (id_y+1) * resolution + 1;
					neibour_id_5 =  id_x + (id_y+1) * resolution - 1 ;
				}
				//L_add_P[neibour_id_1+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_1, -1 ) ;
				//L_add_P[neibour_id_2+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_2, -1 ) ;
				//L_add_P[neibour_id_3+vid*vnum] -= 1 ;
				L_add_P.pluse(vid,neibour_id_3, -1 ) ;
				//L_add_P[neibour_id_4+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_4, -0.7071) ;
				//L_add_P[neibour_id_5+vid*vnum] -=  0.7071;
				L_add_P.pluse(vid,neibour_id_5, -0.7071 ) ;

			}

		}
	}
	// L_add_P <- D - W + P
	for( int i=0; i<resolution; ++i ){
		for( int j=0; j<resolution; ++j){
			if(constrained_vertices_mark[i][j] == 1  ){
				int vid = i + j*resolution ;
				//L_add_P[vid+vid*vnum]+=1e8 ; 
				L_add_P.pluse(vid,vid, 1.0e8  ) ;

			}
		}
	}




	// solve the linear system with cholmod
	cholmod_sparse *A ;
	cholmod_dense *x, *y, *b1 ;
	double one [2] = {1,0}, m1 [2] = {-1,0} ; /* basic scalars */
	cholmod_factor *L ;
	cholmod_common c ;
	cholmod_start (&c) ;; /* start CHOLMOD */
	
	//A = cholmod_read_sparse (pFile, &c) ; /* read in a matrix */
	CMatrix  *SM = new CMatrix( vnum, true, &c) ;
	//for( int i=0; i<vnum; ++i ){
	//	for( int j=0; j<vnum; ++j ){
	//		if( L_add_P.getValue(j,i)!=0 )
	//			SM->set_coef(i, j,L_add_P.getValue(j,i) ) ;
	//	}
	//}
	for( int i=0; i<L_add_P.data.size(); ++i){
		for( int j=0; j<L_add_P.data[i].size(); ++j)
			SM->set_coef(L_add_P.data[i][j].row, i,  L_add_P.data[i][j].val ) ;
	}

	A =(cholmod_sparse *) SM->get_cholmod_sparse();


	time2 = clock() ;

	//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) ;
		std::cout << "fail to load the matrix or it's not symmeric!"<<std::endl;
		exit(1) ;
	}

	b1 = cholmod_zeros(vnum, 1, CHOLMOD_REAL, &c);


	// --------------------- x demension -----------------------
	for( int i =0 ;i<Pb.size(); ++i ){
		((double*)(b1->x))[i] = Pb[i].x ;
	}
	L = cholmod_analyze (A, &c) ; /* analyze */
	cholmod_factorize (A, L, &c) ; /* factorize */
	x = cholmod_solve (CHOLMOD_A, L, b1, &c) ; /* solve Ax=b */


	// write x-values
	for( int i=0; i<vector_field.size(); ++i)
		vector_field[i].x = ((double*)(x->x))[i] ;
	// --------------------- y demension -----------------------
	for( int i =0 ;i<Pb.size(); ++i ){
		((double*)(b1->x))[i] = Pb[i].y ;
	}
	y = cholmod_solve (CHOLMOD_A, L, b1, &c) ; /* solve Ay=b */
	// write y-values
	for( int i=0; i<vector_field.size(); ++i)
		vector_field[i].y = ((double*)(y->x))[i] ;



	cholmod_free_factor (&L, &c) ; 
	cholmod_free_dense (&x, &c) ;
	cholmod_free_dense (&y, &c) ;
	cholmod_free_dense (&b1, &c) ;
	//delete L_add_P ;
	delete SM ;
	cholmod_finish (&c) ; /* finish CHOLMOD */



	double normx2, normy2 ;
	normx2 = normy2 = 0.0 ;

	for( int i=0; i<vnum; ++i ){
		normx2 += vector_field[i].x * vector_field[i].x ; 
		normy2 += vector_field[i].y * vector_field[i].y ; 
	}

	//std::cout<<"|x| = "<<sqrt(normx2) <<"\n|y| = "<<sqrt(normy2) <<std::endl;


	// normalize vector field
	for( int i=0; i<vector_field.size(); ++i){
		double norm = sqrt( vector_field[i].x * vector_field[i].x + vector_field[i].y * vector_field[i].y) ;
		vector_field[i].x /= norm ;
		vector_field[i].y /= norm ;

	}

	time3 = clock() ;


	//std::cout<<"time consumed by computing A and b: " << (double)(time2-time1)/CLOCKS_PER_SEC <<" s" <<std::endl ;
	//std::cout<<"time consumed by solving the system: " << (double)(time3-time2)/CLOCKS_PER_SEC <<" s" <<std::endl ;

	//std::cout<<"vector field computing completed."<<std::endl; ;
	int count = 0;
	for( int i=0; i<L_add_P.data.size(); ++i)
		count += L_add_P.data[i].size() ;

	//std::cout << "nonzero number: " << count <<std::endl; 

}
Esempio n. 12
0
int main(void)
{
    int N = 2 ;
    int i, j, n ;
    int nz = 0;
    double *Ax ;
    double x, error ;
    cholmod_dense *A, *invK, *spinvK, *I ;
    cholmod_sparse *K, *V ;
    cholmod_factor *L ;
    cholmod_common Common,*cm ;
    clock_t start, end;
    double cpu_time_used;
    cm=&Common;
    // Start using CHOLMOD
    cholmod_start(cm) ;
    cm->print=5;
    /* SPARSE COVARIANCE MATRIX CONSTRUCTION */

    // Generate random symmetric positive (semi)definite matrix
    A = cholmod_zeros(N, N, CHOLMOD_REAL, &Common) ;
    Ax =(double*) A->x ;
    nz = N ;

    // Make positive-definite by adding something positive to the
    // diagonal
    for (n = 0; n < N; n++)
    {
        Ax[n+n*N] += 5;
    }

    // Make the matrix sparse
    K = cholmod_dense_to_sparse(A, TRUE, &Common) ;
    K->stype = 1 ; // NEED TO MAKE THE MATRIX SYMMETRIC

    // Identity matrix
    I = cholmod_eye(N,N,CHOLMOD_REAL,&Common) ;

    /* SIMPLICIAL */

    // Factorize
    Common.supernodal = CHOLMOD_SIMPLICIAL ;
    L = cholmod_analyze(K, &Common) ;
    cholmod_factorize(K, L, &Common) ;
    invK = cholmod_solve(CHOLMOD_A, L, I, &Common) ;

    // Compute the sparse inverse and the full inverse
    start = clock();
    V = cholmod_spinv(L, &Common) ;
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

    // Show results
    cholmod_print_sparse(K,"Original",&Common) ;
    cholmod_print_factor(L,"Factor",&Common) ;
    cholmod_print_sparse(V,"Sparse inverse",&Common) ;
    cholmod_print_dense(invK,"Dense inverse",&Common);

    // Free memory
    cholmod_free_factor(&L, &Common) ;
    cholmod_free_sparse(&K, &Common) ;
    cholmod_free_dense(&I, &Common) ;
    cholmod_free_dense(&A, &Common) ;
    cholmod_finish(&Common) ;
    return 0 ;
}
Esempio n. 13
0
int klu_cholmod
(
    /* inputs */
    int n,		    /* A is n-by-n */
    int Ap [ ],		    /* column pointers */
    int Ai [ ],		    /* row indices */
    /* outputs */
    int Perm [ ],	    /* fill-reducing permutation */
    /* user-defined */
    klu_common *Common	    /* user-defined data is in Common->user_data */
)
{
    double one [2] = {1,0}, zero [2] = {0,0}, lnz = 0 ;
    cholmod_sparse Amatrix, *A, *AT, *S ;
    cholmod_factor *L ;
    cholmod_common cm ;
    int *P ;
    int k, symmetric ;

    if (Ap == NULL || Ai == NULL || Perm == NULL || n < 0)
    {
	/* invalid inputs */
	return (0) ;
    }

    /* start CHOLMOD */
    cholmod_start (&cm) ;
    cm.supernodal = CHOLMOD_SIMPLICIAL ;
    cm.print = 0 ;

    /* use KLU memory management routines for CHOLMOD */
    cm.malloc_memory = Common->malloc_memory ;
    cm.realloc_memory = Common->realloc_memory ;
    cm.calloc_memory = Common->calloc_memory ;
    cm.free_memory = Common->free_memory ;

    /* construct a CHOLMOD version of the input matrix A */
    A = &Amatrix ;
    A->nrow = n ;		    /* A is n-by-n */
    A->ncol = n ;
    A->nzmax = Ap [n] ;		    /* with nzmax entries */
    A->packed = TRUE ;		    /* there is no A->nz array */
    A->stype = 0 ;		    /* A is unsymmetric */
    A->itype = CHOLMOD_INT ;
    A->xtype = CHOLMOD_PATTERN ;
    A->dtype = CHOLMOD_DOUBLE ;
    A->nz = NULL ;
    A->p = Ap ;			    /* column pointers */
    A->i = Ai ;			    /* row indices */
    A->x = NULL ;		    /* no numerical values */
    A->z = NULL ;
    A->sorted = FALSE ;		    /* columns of A are not sorted */

    /* get the user_data; default is symmetric if user_data is NULL */
    symmetric = (Common->user_data == NULL) ? TRUE :
	(((int *) (Common->user_data)) [0] != 0) ;

    /* AT = pattern of A' */
    AT = cholmod_transpose (A, 0, &cm) ;
    if (symmetric)
    {
	/* S = the symmetric pattern of A+A' */
	S = cholmod_add (A, AT, one, zero, FALSE, FALSE, &cm) ;
	cholmod_free_sparse (&AT, &cm) ;
	if (S != NULL)
	{
	    S->stype = 1 ;
	}
    }
    else
    {
	/* S = A'.  CHOLMOD will order S*S', which is A'*A */
	S = AT ;
    }

    /* order and analyze S or S*S' */
    L = cholmod_analyze (S, &cm) ;

    /* copy the permutation from L to the output */
    if (L != NULL)
    {
	P = L->Perm ;
	for (k = 0 ; k < n ; k++)
	{
	    Perm [k] = P [k] ;
	}
	lnz = cm.lnz ;
    }

    cholmod_free_sparse (&S, &cm) ;
    cholmod_free_factor (&L, &cm) ;
    cholmod_finish (&cm) ;
    return (lnz) ;
}
Esempio n. 14
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);	
}
Esempio n. 15
0
 static cholmod_factor* analyze(cholmod_sparse* A, cholmod_common* c) {
   return cholmod_analyze(A, c);
 }
BasicMesh MeshTransferer::transfer(const vector<PhGUtils::Matrix3x3d> &S1grad)
{
  if( !(S0set && T0set) ) {
    throw "S0 or T0 not set.";
  }

  auto &S = S1grad;
  auto &T = T0grad;

  int nfaces = S0.faces.nrow;
  int nverts = S0.verts.nrow;

  // assemble sparse matrix A
  int nrowsA = nfaces * 3;
  int nsv = stationary_vertices.size();
  int nrowsC = nsv;
  int nrows = nrowsA + nrowsC;
  int ncols = nverts;
  int ntermsA = nfaces*9;
  int ntermsC = stationary_vertices.size();
  int nterms = ntermsA + ntermsC;
  SparseMatrix A(nrows, ncols, nterms);
  // fill in the deformation gradient part
  for(int i=0, ioffset=0;i<nfaces;++i) {
    /*
     * Ai:
     *     1 2 3 4 5 ... nfaces*3
     *     1 2 3 4 5 ... nfaces*3
     *     1 2 3 4 5 ... nfaces*3
     * Ai = reshape(Ai, 1, nfaces*9)
     *
     * Aj = reshape(repmat(S0.faces', 3, 1), 1, nfaces*9)
     * Av = reshape(cell2mat(T)', 1, nfaces*9)
     */
    int *f = S0.faces.rowptr(i);

    auto Ti = T[i];

    A.append(ioffset, f[0], Ti(0));
    A.append(ioffset, f[1], Ti(1));
    A.append(ioffset, f[2], Ti(2));
    ++ioffset;

    A.append(ioffset, f[0], Ti(3));
    A.append(ioffset, f[1], Ti(4));
    A.append(ioffset, f[2], Ti(5));
    ++ioffset;

    A.append(ioffset, f[0], Ti(6));
    A.append(ioffset, f[1], Ti(7));
    A.append(ioffset, f[2], Ti(8));
    ++ioffset;
  }

  // fill in the lower part of A, stationary vertices part
  for(int i=0;i<nsv;++i) {
    A.append(nrowsA+i, stationary_vertices[i], 1);
  }

  ofstream fA("A.txt");
  fA<<A;
  fA.close();

  // fill in c matrix
  DenseMatrix c(nrows, 3);
  for(int i=0;i<3;++i) {
    for(int j=0, joffset=0;j<nfaces;++j) {
      auto &Sj = S[j];
      c(joffset, i) = Sj(0, i); ++joffset;
      c(joffset, i) = Sj(1, i); ++joffset;
      c(joffset, i) = Sj(2, i); ++joffset;
    }
  }
  for(int i=0;i<3;++i) {
    for(int j=0, joffset=nrowsA;j<nsv;++j,++joffset) {
      auto vj = T0.verts.rowptr(stationary_vertices[j]);
      c(joffset, i) = vj[i];
    }
  }

  cholmod_sparse *G = A.to_sparse();
  cholmod_sparse *Gt = cholmod_transpose(G, 2, global::cm);

  // compute GtD
  // just multiply Dsi to corresponding elemenets
  double *Gtx = (double*)Gt->x;
  const int* Gtp = (const int*)(Gt->p);
  for(int i=0;i<nrowsA;++i) {
    int fidx = i/3;
    for(int j=Gtp[i];j<Gtp[i+1];++j) {
      Gtx[j] *= Ds(fidx);
    }
  }

  // compute GtDG
  cholmod_sparse *GtDG = cholmod_ssmult(Gt, G, 0, 1, 1, global::cm);
  GtDG->stype = 1;

  // compute GtD * c
  cholmod_dense *GtDc = cholmod_allocate_dense(ncols, 3, ncols, CHOLMOD_REAL, global::cm);
  double alpha[2] = {1, 0}; double beta[2] = {0, 0};
  cholmod_sdmult(Gt, 0, alpha, beta, c.to_dense(), GtDc, global::cm);

  // solve for GtDG \ GtDc
  cholmod_factor *L = cholmod_analyze(GtDG, global::cm);
  cholmod_factorize(GtDG, L, global::cm);
  cholmod_dense *x = cholmod_solve(CHOLMOD_A, L, GtDc, global::cm);

  // make a copy of T0
  BasicMesh Td = T0;

  // change the vertices with x
  double *Vx = (double*)x->x;
  for(int i=0;i<nverts;++i) {
    Td.verts(i, 0) = Vx[i];
    Td.verts(i, 1) = Vx[i+nverts];
    Td.verts(i, 2) = Vx[i+nverts*2];
  }

  // release memory
  cholmod_free_sparse(&G, global::cm);
  cholmod_free_sparse(&Gt, global::cm);
  cholmod_free_sparse(&GtDG, global::cm);
  cholmod_free_dense(&GtDc, global::cm);
  cholmod_free_factor(&L, global::cm);
  cholmod_free_dense(&x, global::cm);

  return Td;
}
void KVFModel::calculateVF(const std::set<DisplacedVertex> &disps, double alpha1)
{
    TimeMeasurment total,t;
    cholmod_common* cm = cholmod_get_common();

    unsigned int numFaces = getNumFaces();
    unsigned int numVertices = getNumVertices();

    this->disps = disps;
    std::set<DisplacedVertex> allDisplacements = disps;

    for (auto iter = pinnedVertexes.begin(); iter != pinnedVertexes.end() ; iter++)
    	allDisplacements.insert(DisplacedVertex(*iter, Vector2(0,0)));

    if (allDisplacements.size() <= 1)
    	return;

    if (allDisplacements.size() != lastDispsSize) {
    	cholmod_free_factor(&L1, cholmod_get_common());
    	lastDispsSize = allDisplacements.size();
    }

    /************************************************/
    /* BUILD P matrix */

    P.startMatrixFill();
    P.reshape(3*numFaces,2*numVertices,12*numFaces);

    for (unsigned int f = 0; f < numFaces; f++)
    {
        int i = (*faces)[f][0];
        int j = (*faces)[f][1];
        int k = (*faces)[f][2];

        if (i > j) { std::swap(i,j); }
        if (i > k) { std::swap(i,k); }
        if (j > k) { std::swap(j,k); }

        Vector2 d1 = vertices[i] - vertices[k];
        Vector2 d2 = vertices[j] - vertices[i];

        double area = fabs(d1[1]*d2[0] - d1[0]*d2[1]);

        Vector2 c1(-d1[1]/area,d1[0]/area);
        Vector2 c2(-d2[1]/area,d2[0]/area);

        double gix = -c1[0] - c2[0], gjx = c1[0], gkx = c2[0];
        double giy = -c1[1] - c2[1], gjy = c1[1], gky = c2[1];

        P.addElement(3*f+0,i,gix*2);
        P.addElement(3*f+0,j,gjx*2);
        P.addElement(3*f+0,k,gkx*2);

        P.addElement(3*f+1,i,giy*M_SQRT2);
        P.addElement(3*f+1,j,gjy*M_SQRT2);
        P.addElement(3*f+1,k,gky*M_SQRT2);

        P.addElement(3*f+1,i+numVertices,gix*M_SQRT2);
        P.addElement(3*f+1,j+numVertices,gjx*M_SQRT2);
        P.addElement(3*f+1,k+numVertices,gkx*M_SQRT2);

        P.addElement(3*f+2,i+numVertices,giy*2);
        P.addElement(3*f+2,j+numVertices,gjy*2);
        P.addElement(3*f+2,k+numVertices,gky*2);
    }

    Pcopy.copy(P);

    printf("KVF: P construct time: %f msec\n", t.measure_msec());

    /*++++++++++++++++++++++++++++++++++++++++++++++*/

    CholmodVector B = CholmodVector(2*numVertices);
    std::vector<int> indices2;

    double alpha = alpha1 / (2*allDisplacements.size()) * P.infinityNorm();

    for (auto iter = allDisplacements.begin() ; iter != allDisplacements.end() ; iter++)
    {
        indices2.push_back(iter->v);
        indices2.push_back(iter->v + numVertices);

    	B[iter->v] 				= iter->displacement[0]*alpha*alpha;
    	B[iter->v+numVertices]  = iter->displacement[1]*alpha*alpha;
    }

    P.addConstraint(indices2, alpha);

    printf("KVF: P constraint adding time: %f msec\n", t.measure_msec());

    /*++++++++++++++++++++++++++++++++++++++++++++++*/

    cholmod_sparse cSparse;
    P.getCholmodMatrix(cSparse);
    if (!L1) L1 = cholmod_analyze(&cSparse, cm);
    cholmod_factorize(&cSparse, L1, cm);
    cholmod_dense * Xcholmod = cholmod_solve(CHOLMOD_A, L1, B, cm);
    double* Xx = (double*)Xcholmod->x;

	for (unsigned int i = 0; i < numVertices; i++)
		vfOrig[i] = Vector2D<double>(Xx[i],Xx[i+numVertices]);

    printf("KVF: Solve time: %f msec\n", t.measure_msec());

    /*+++++DIRICHLET SOLVE +++++++++++++++++++++++++++++++++++++++++*/

    CholmodVector boundaryRHS = CholmodVector(2*numVertices);
    for (std::set<int>::iterator it = boundaryVertices->begin(); it != boundaryVertices->end(); ++it)
    {
    	boundaryRHS[*it] = Xx[*it];
    	boundaryRHS[*it + numVertices] = Xx[*it + numVertices];
    }

    CholmodVector rhsMove(Pcopy.numRows());

    Pcopy.multiply(boundaryRHS, rhsMove);
    for (unsigned int i = 0; i < rhsMove.size(); i++)
        rhsMove[i] *= -1;

    Pcopy.zeroOutColumns(*boundaryVertices, 0);
    Pcopy.zeroOutColumns(*boundaryVertices, numVertices);

    Pcopy.transposeMultiply(rhsMove,B);

    std::vector<int> constrained;
    for (std::set<int>::iterator it = boundaryVertices->begin(); it != boundaryVertices->end(); ++it)
    {
        int bv = *it;
        constrained.push_back(*it);
        constrained.push_back(*it+numVertices);
        B[bv] 			  += Xx[bv];
        B[bv+numVertices] += Xx[bv+numVertices];
    }

    Pcopy.addConstraint(constrained,1);


    printf("KVF: Dirichlet prepare time: %f msec\n", t.measure_msec());

    /*++++++++++++++++++++++++++++++++++++++++++++++*/

    Pcopy.getCholmodMatrix(cSparse);
    if (!L2) L2 = cholmod_analyze(&cSparse, cm);
    cholmod_factorize(&cSparse, L2, cm);
    cholmod_dense *Xcholmod2 = cholmod_solve(CHOLMOD_A, L2, B, cm);
    Xx = (double*)Xcholmod2->x;

    printf("KVF: Dirichlet solve time: %f msec\n", t.measure_msec());

	for (unsigned int i = 0; i < numVertices; i++)
		vf[i] = Vector2D<double>(Xx[i],Xx[i+numVertices]);

    cholmod_free_dense(&Xcholmod, cm);
    cholmod_free_dense(&Xcholmod2, cm);

    printf("KVF: Fini time:  %f msec\n", t.measure_msec());

    lastVFCalcTime = total.measure_msec();
}
Esempio n. 18
0
/* Orders rows and saves pointer to matrix.and model */
int
ClpCholeskyUfl::order(ClpInterior * model)
{
     numberRows_ = model->numberRows();
     if (doKKT_) {
          numberRows_ += numberRows_ + model->numberColumns();
          printf("finish coding UFL KKT!\n");
          abort();
     }
     rowsDropped_ = new char [numberRows_];
     memset(rowsDropped_, 0, numberRows_);
     numberRowsDropped_ = 0;
     model_ = model;
     rowCopy_ = model->clpMatrix()->reverseOrderedCopy();
     // Space for starts
     choleskyStart_ = new CoinBigIndex[numberRows_+1];
     const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts();
     const int * columnLength = model_->clpMatrix()->getVectorLengths();
     const int * row = model_->clpMatrix()->getIndices();
     const CoinBigIndex * rowStart = rowCopy_->getVectorStarts();
     const int * rowLength = rowCopy_->getVectorLengths();
     const int * column = rowCopy_->getIndices();
     // We need two arrays for counts
     int * which = new int [numberRows_];
     int * used = new int[numberRows_+1];
     CoinZeroN(used, numberRows_);
     int iRow;
     sizeFactor_ = 0;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int number = 1;
          // make sure diagonal exists
          which[0] = iRow;
          used[iRow] = 1;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         int jRow = row[j];
                         if (jRow >= iRow && !rowsDropped_[jRow]) {
                              if (!used[jRow]) {
                                   used[jRow] = 1;
                                   which[number++] = jRow;
                              }
                         }
                    }
               }
               sizeFactor_ += number;
               int j;
               for (j = 0; j < number; j++)
                    used[which[j]] = 0;
          }
     }
     delete [] which;
     // Now we have size - create arrays and fill in
     try {
          choleskyRow_ = new int [sizeFactor_];
     } catch (...) {
          // no memory
          delete [] choleskyStart_;
          choleskyStart_ = NULL;
          return -1;
     }
     try {
          sparseFactor_ = new double[sizeFactor_];
     } catch (...) {
          // no memory
          delete [] choleskyRow_;
          choleskyRow_ = NULL;
          delete [] choleskyStart_;
          choleskyStart_ = NULL;
          return -1;
     }

     sizeFactor_ = 0;
     which = choleskyRow_;
     for (iRow = 0; iRow < numberRows_; iRow++) {
          int number = 1;
          // make sure diagonal exists
          which[0] = iRow;
          used[iRow] = 1;
          choleskyStart_[iRow] = sizeFactor_;
          if (!rowsDropped_[iRow]) {
               CoinBigIndex startRow = rowStart[iRow];
               CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow];
               for (CoinBigIndex k = startRow; k < endRow; k++) {
                    int iColumn = column[k];
                    CoinBigIndex start = columnStart[iColumn];
                    CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn];
                    for (CoinBigIndex j = start; j < end; j++) {
                         int jRow = row[j];
                         if (jRow >= iRow && !rowsDropped_[jRow]) {
                              if (!used[jRow]) {
                                   used[jRow] = 1;
                                   which[number++] = jRow;
                              }
                         }
                    }
               }
               sizeFactor_ += number;
               int j;
               for (j = 0; j < number; j++)
                    used[which[j]] = 0;
               // Sort
               std::sort(which, which + number);
               // move which on
               which += number;
          }
     }
     choleskyStart_[numberRows_] = sizeFactor_;
     delete [] used;
     permuteInverse_ = new int [numberRows_];
     permute_ = new int[numberRows_];
     cholmod_sparse A ;
     A.nrow = numberRows_;
     A.ncol = numberRows_;
     A.nzmax = choleskyStart_[numberRows_];
     A.p = choleskyStart_;
     A.i = choleskyRow_;
     A.x = NULL;
     A.stype = -1;
     A.itype = CHOLMOD_INT;
     A.xtype = CHOLMOD_PATTERN;
     A.dtype = CHOLMOD_DOUBLE;
     A.sorted = 1;
     A.packed = 1;
     c_->nmethods = 9;
     c_->postorder = true;
     //c_->dbound=1.0e-20;
     L_ = cholmod_analyze (&A, c_) ;
     if (c_->status) {
       COIN_DETAIL_PRINT(std::cout << "CHOLMOD ordering failed" << std::endl);
          return 1;
     } else {
       COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", c_->lnz, c_->fl));
     }
     for (iRow = 0; iRow < numberRows_; iRow++) {
          permuteInverse_[iRow] = iRow;
          permute_[iRow] = iRow;
     }
     return 0;
}