int main (void) { cholmod_sparse *A ; cholmod_dense *x, *b, *r ; cholmod_factor *L ; double one [2] = {1,0}, m1 [2] = {-1,0} ; /* basic scalars */ cholmod_common c ; cholmod_start (&c) ; /* start CHOLMOD */ A = cholmod_read_sparse (stdin, &c) ; /* read in a matrix */ cholmod_print_sparse (A, "A", &c) ; /* print the matrix */ if (A == NULL || A->stype == 0) /* A must be symmetric */ { cholmod_free_sparse (&A, &c) ; cholmod_finish (&c) ; return (0) ; } b = cholmod_ones (A->nrow, 1, A->xtype, &c) ; /* b = ones(n,1) */ L = cholmod_analyze (A, &c) ; /* analyze */ cholmod_factorize (A, L, &c) ; /* factorize */ x = cholmod_solve (CHOLMOD_A, L, b, &c) ; /* solve Ax=b */ r = cholmod_copy_dense (b, &c) ; /* r = b */ cholmod_sdmult (A, 0, m1, one, x, r, &c) ; /* r = r-Ax */ printf ("norm(b-Ax) %8.1e\n", cholmod_norm_dense (r, 0, &c)) ; /* print norm(r) */ cholmod_free_factor (&L, &c) ; /* free matrices */ cholmod_free_sparse (&A, &c) ; cholmod_free_dense (&r, &c) ; cholmod_free_dense (&x, &c) ; cholmod_free_dense (&b, &c) ; cholmod_finish (&c) ; /* finish CHOLMOD */ return (0) ; }
int main (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) ; }
// 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; }
/* Uses factorization to solve. */ void ClpCholeskyUfl::solve (double * region) { cholmod_dense *x, *b; b = cholmod_allocate_dense (numberRows_, 1, numberRows_, CHOLMOD_REAL, c_) ; CoinMemcpyN(region, numberRows_, (double *) b->x); x = cholmod_solve (CHOLMOD_A, L_, b, c_) ; CoinMemcpyN((double *) x->x, numberRows_, region); cholmod_free_dense (&x, c_) ; cholmod_free_dense (&b, c_) ; }
cholmod_dense * MultivariateFNormalSufficientSparse::evaluate_derivative_FM() const { // d(-log(p))/d(FM) = - N * P * epsilon IMP_LOG(TERSE, "MVNsparse: evaluate_derivative_FM() = " << std::endl); cholmod_dense *tmp = cholmod_solve(CHOLMOD_A, L_, epsilon_, c_); if (L_->xtype != CHOLMOD_REAL) IMP_THROW("matrix type is not real, update the code first", ModelException); double *x = (double *)tmp->x; for (size_t i=0; i<tmp->nzmax; ++i) x[i] *= -N_; return tmp; }
// compute trans(epsilon)*Sigma^{-1}*epsilon by solving for the // rhs product and multiplying by trans(epsilon) // could be made more stable by using a LLt factorization and // solving for LPepsilon and then multiplying by // its transpose. double MultivariateFNormalSufficientSparse::mean_dist() const { cholmod_dense *tmp = cholmod_solve(CHOLMOD_A, L_, epsilon_, c_); if (tmp->xtype != CHOLMOD_REAL) IMP_THROW("matrix type is not real, update code first", ModelException); double dist=0; double *x1 = (double *) tmp->x; double *x2 = (double *) epsilon_->x; for (size_t i=0; i<tmp->nzmax; ++i) dist += x1[i]*x2[i]; cholmod_free_dense(&tmp, c_); IMP_LOG(TERSE, "MVNsparse: mean_dist = " << dist << std::endl); return dist; }
int CholeskyFactorization::solve(Matrix& rhs, Matrix& solution) { if (m_matrix_type == Matrix::MATRIX_SPARSE) { cholmod_dense *x; /* cast the RHS as a cholmod_dense b = rhs */ if (rhs.m_type == Matrix::MATRIX_DENSE) { cholmod_dense *b; b = cholmod_allocate_dense(rhs.m_nrows, rhs.m_ncols, rhs.m_nrows, CHOLMOD_REAL, Matrix::cholmod_handle()); b->x = rhs.m_data; /* Solve - rhs is dense*/ x = cholmod_solve(CHOLMOD_A, m_factor, b, Matrix::cholmod_handle()); solution = Matrix(rhs.m_nrows, rhs.m_ncols); solution.m_delete_data = false; memcpy(solution.m_data, static_cast<double*> (x->x), rhs.m_nrows * rhs.m_ncols * sizeof (double)); cholmod_free_dense(&x, Matrix::cholmod_handle()); } else if (rhs.m_type == Matrix::MATRIX_SPARSE) { // still untested! cholmod_sparse * rhs_sparse; if (rhs.m_sparse == NULL) { const_cast<Matrix&> (rhs)._createSparse(); } rhs_sparse = rhs.m_sparse; cholmod_sparse * result = cholmod_spsolve(CHOLMOD_LDLt, m_factor, rhs_sparse, Matrix::cholmod_handle()); solution = Matrix(rhs.m_nrows, rhs.m_ncols, Matrix::MATRIX_SPARSE); solution.m_sparse = result; solution._createTriplet(); } else { throw std::logic_error("Not supported"); } return ForBESUtils::STATUS_OK; } else { /* the matrix to be factorized is not sparse */ int info = ForBESUtils::STATUS_UNDEFINED_FUNCTION; solution = Matrix(rhs); if (m_matrix_type == Matrix::MATRIX_DENSE) { info = LAPACKE_dpotrs(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, rhs.m_ncols, m_L, m_matrix_nrows, solution.m_data, m_matrix_nrows); } else if (m_matrix_type == Matrix::MATRIX_SYMMETRIC) { info = LAPACKE_dpptrs(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, rhs.m_ncols, m_L, solution.m_data, m_matrix_nrows); } else { throw std::invalid_argument("This matrix type is not supported - only DENSE, SPARSE and SYMMETRIC are supported"); } return info; } }
SEXP CHMfactor_solve(SEXP a, SEXP b, SEXP system) { CHM_FR L = AS_CHM_FR(a); SEXP bb = PROTECT(dup_mMatrix_as_dgeMatrix(b)); CHM_DN B = AS_CHM_DN(bb), X; int sys = asInteger(system); R_CheckStack(); if (!(sys--)) /* align with CHOLMOD defs: R's {1:9} --> {0:8}, see ./CHOLMOD/Cholesky/cholmod_solve.c */ error(_("system argument is not valid")); X = cholmod_solve(sys, L, B, &c); UNPROTECT(1); return chm_dense_to_SEXP(X, 1/*do_free*/, 0/*Rkind*/, GET_SLOT(bb, Matrix_DimNamesSym), FALSE); }
SEXP dsCMatrix_matrix_solve(SEXP a, SEXP b) { SEXP Chol = get_factor_pattern(a, "spdCholesky", 3); cholmod_factor *L; cholmod_dense *cx, *cb = as_cholmod_dense(PROTECT(mMatrix_as_dgeMatrix(b))); if (Chol == R_NilValue) Chol = dsCMatrix_Cholesky(a, ScalarLogical(1), /* permuted */ ScalarLogical(1), /* LDL' */ ScalarLogical(0)); /* simplicial */ L = as_cholmod_factor(Chol); cx = cholmod_solve(CHOLMOD_A, L, cb, &c); Free(cb); Free(L); UNPROTECT(1); return chm_dense_to_SEXP(cx, 1); }
// deliver the address of x void Algebra::solve_CK(Matrix & A, cholmod_dense *&x, cholmod_dense *b, cholmod_common *cm, size_t &peak_mem, size_t &CK_mem){ cholmod_factor *L; cm->final_ll = true; // stay in LL' format clock_t t1, t2; t1 = clock(); CK_decomp(A, L, cm, peak_mem, CK_mem); t2 = clock(); clog<<"decomp time for CK is: "<<1.0*(t2-t1) / CLOCKS_PER_SEC<<endl; // then solve t1 = clock(); x = cholmod_solve(CHOLMOD_A, L, b, cm); t2 = clock(); clog<<"solve time is: "<<1.0*(t2-t1)/ CLOCKS_PER_SEC<<endl; //cholmod_print_dense(x, "x", cm); //cholmod_print_dense(b, "b", cm); //cholmod_print_factor(L, "L", cm); cholmod_free_factor(&L, cm); }
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 Block::solve_CK(cholmod_common *cm){ x_ck = cholmod_solve(CHOLMOD_A, L, b_new_ck, cm); }
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 ; }
static cholmod_dense* solve(int sys, cholmod_factor* L, cholmod_dense* B, cholmod_common* c) { return cholmod_solve(sys, L, B, c); }
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) ; }
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(); }
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; }