int main (int argc, char **argv) { /* ---------------------------------------------------------------------- */ /* get the file containing the input matrix */ /* ---------------------------------------------------------------------- */ FILE *ff = NULL ; FILE *fb = NULL ; if (argc <= 1) { printf("Usage is: cholmod_simple A.tri [B.txt (dense)]\n"); exit(0); } if (argc > 1) ff = fopen(argv[1],"r"); if (argc > 2) fb = fopen(argv[2], "r"); cholmod_sparse *A ; cholmod_dense *x, *b, *r ; cholmod_factor *L ; double one [2] = {1,0}, m1 [2] = {-1,0} ; // basic scalars cholmod_common c ; cholmod_start (&c) ; /* start CHOLMOD */ A = cholmod_read_sparse (ff, &c) ; /* read in a matrix */ cholmod_print_sparse (A, (char *)"A", &c) ; /* print the matrix */ if (A->dtype) printf("A is float\n"); else printf("A is double\n"); if (A == NULL || A->stype == 0) /* A must be symmetric */ { cholmod_free_sparse (&A, &c) ; cholmod_finish (&c) ; if (ff) fclose(ff); if (fb) fclose(fb); return (0) ; } if (fb) b = cholmod_read_dense(fb, &c); else b = cholmod_ones (A->nrow, 1, A->xtype, &c) ; /* b = ones(n,1) */ double t0 = CPUTIME; L = cholmod_analyze (A, &c) ; /* analyze */ cholmod_factorize (A, L, &c) ; /* factorize */ x = cholmod_solve (CHOLMOD_A, L, b, &c) ; /* solve Ax=b */ double t1 = CPUTIME; if (c.dtype) printf("Compute is float\n"); else printf("Compute is double\n"); printf("Time: %12.4f \n", t1-t0); r = cholmod_copy_dense (b, &c) ; /* r = b */ cholmod_sdmult (A, 0, m1, one, x, r, &c) ; /* r = r-Ax */ printf ("norm(b-Ax) %8.1e\n", cholmod_norm_dense (r, 0, &c)) ; /* print norm(r) */ cholmod_free_factor (&L, &c) ; /* free matrices */ cholmod_free_sparse (&A, &c) ; cholmod_free_dense (&r, &c) ; cholmod_free_dense (&x, &c) ; cholmod_free_dense (&b, &c) ; cholmod_finish (&c) ; /* finish CHOLMOD */ return (0) ; }
int main (void) { cholmod_sparse *A ; cholmod_dense *x, *b, *r ; cholmod_factor *L ; double one [2] = {1,0}, m1 [2] = {-1,0} ; /* basic scalars */ cholmod_common c ; cholmod_start (&c) ; /* start CHOLMOD */ A = cholmod_read_sparse (stdin, &c) ; /* read in a matrix */ cholmod_print_sparse (A, "A", &c) ; /* print the matrix */ if (A == NULL || A->stype == 0) /* A must be symmetric */ { cholmod_free_sparse (&A, &c) ; cholmod_finish (&c) ; return (0) ; } b = cholmod_ones (A->nrow, 1, A->xtype, &c) ; /* b = ones(n,1) */ L = cholmod_analyze (A, &c) ; /* analyze */ cholmod_factorize (A, L, &c) ; /* factorize */ x = cholmod_solve (CHOLMOD_A, L, b, &c) ; /* solve Ax=b */ r = cholmod_copy_dense (b, &c) ; /* r = b */ cholmod_sdmult (A, 0, m1, one, x, r, &c) ; /* r = r-Ax */ printf ("norm(b-Ax) %8.1e\n", cholmod_norm_dense (r, 0, &c)) ; /* print norm(r) */ cholmod_free_factor (&L, &c) ; /* free matrices */ cholmod_free_sparse (&A, &c) ; cholmod_free_dense (&r, &c) ; cholmod_free_dense (&x, &c) ; cholmod_free_dense (&b, &c) ; cholmod_finish (&c) ; /* finish CHOLMOD */ return (0) ; }
// 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; } }
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; }
// 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) ; }
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); }
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; }
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 ; }
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) ; }
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); }
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(); }
/* 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; }