cholmod_sparse * MultivariateFNormalSufficientSparse::evaluate_derivative_Sigma() const { //d(-log(p))/dSigma = 1/2 (N P - N P epsilon transpose(epsilon) P - P W P) IMP_LOG(TERSE, "MVNsparse: evaluate_derivative_Sigma() = " << std::endl); cholmod_sparse *ptp(compute_PTP()); cholmod_sparse *pwp(compute_PWP()); //std::cout << " ptp " << std::endl << ptp << std::endl << std::endl; //std::cout << " pwp " << std::endl << pwp << std::endl << std::endl; static double one[2]={1,0}; static double minusone[2]={-1,0}; cholmod_sparse *tmp = cholmod_add(P_, ptp, one, minusone, true, false, c_); double enn[2]={0.5*N_,0}; static double ptfive[2]={-0.5,0}; cholmod_sparse *R = cholmod_add(tmp, pwp, enn, ptfive, true, false, c_); cholmod_free_sparse(&ptp, c_); cholmod_free_sparse(&pwp, c_); cholmod_free_sparse(&tmp, c_); return R; }
void get_ordering(cholmod_sparse* const NNE, const int MIS_method, const bool directed, std::list<int>& ordering, cholmod_common* const cholmod_c) { cholmod_sparse* adja_mat; switch(MIS_method) { case FSTPOWORDER: if (directed) { // adja_mat = NNE | t(NNE) cholmod_sparse* NNEt = cholmod_transpose(NNE, CHOLMOD_PATTERN, cholmod_c); adja_mat = cholmod_add(NNE, NNEt, NULL, NULL, false, false, cholmod_c); cholmod_free_sparse(&NNEt, cholmod_c); } else { // adja_mat = NNE adja_mat = cholmod_copy_sparse(NNE, cholmod_c); } break; case SNDPOWORDER: case HEURISTIC: adja_mat = get_second_power(NNE, directed, cholmod_c); break; default: error("Unknown MIS method."); } // adja_mat_p: array with pointer to elements for each column // where `i' is start and `i+1' is finish. // Can thus be used to get col sums. const int* const adja_mat_p = static_cast<const int*>(adja_mat->p); std::list<std::pair<int,int> > tmp_order; int n_vertices = static_cast<int>(NNE->ncol); for (int i = 0; i < n_vertices; ++i) { tmp_order.push_back(std::make_pair(adja_mat_p[i + 1] - adja_mat_p[i], i)); } cholmod_free_sparse(&adja_mat, cholmod_c); // sorts first according to colsum (i.e., first el) // then by vertex id. As ID is unique, sorting is stable. tmp_order.sort(); for (std::list<std::pair<int,int> >::const_iterator it = tmp_order.begin(); it != tmp_order.end(); ++it) { ordering.push_back(it->second); } }
cholmod_sparse* get_second_power(cholmod_sparse* const NNE, const bool directed, cholmod_common* const cholmod_c) { cholmod_sparse* out; if (directed) { // out = (NNE | t(NNE) | t(NNE) %*% NNE) & !I cholmod_sparse* NNEt = cholmod_transpose(NNE, CHOLMOD_PATTERN, cholmod_c); cholmod_sparse* NNEtNNE = cholmod_aat(NNEt, NULL, 0, -1, cholmod_c); // -1 = no diagnol cholmod_sparse* tmp = cholmod_add(NNE, NNEt, NULL, NULL, false, false, cholmod_c); cholmod_free_sparse(&NNEt, cholmod_c); out = cholmod_add(tmp, NNEtNNE, NULL, NULL, false, false, cholmod_c); cholmod_free_sparse(&NNEtNNE, cholmod_c); cholmod_free_sparse(&tmp, cholmod_c); } else { // out = (NNE | t(NNE) %*% NNE) & !I cholmod_sparse* NNEtNNE = cholmod_aat(NNE, NULL, 0, -1, cholmod_c); // -1 = no diagnol out = cholmod_add(NNE, NNEtNNE, NULL, NULL, false, false, cholmod_c); cholmod_free_sparse(&NNEtNNE, cholmod_c); } return out; }
SEXP Csparse_diagU2N(SEXP x) { const char *cl = class_P(x); /* dtCMatrix, etc; [1] = the second character =?= 't' for triangular */ if (cl[1] != 't' || *diag_P(x) != 'U') { /* "trivially fast" when not triangular (<==> no 'diag' slot), or not *unit* triangular */ return (x); } else { /* unit triangular (diag='U'): "fill the diagonal" & diag:= "N" */ CHM_SP chx = AS_CHM_SP__(x); CHM_SP eye = cholmod_speye(chx->nrow, chx->ncol, chx->xtype, &c); double one[] = {1, 0}; CHM_SP ans = cholmod_add(chx, eye, one, one, TRUE, TRUE, &c); int uploT = (*uplo_P(x) == 'U') ? 1 : -1; int Rkind = (chx->xtype != CHOLMOD_PATTERN) ? Real_kind(x) : 0; R_CheckStack(); cholmod_free_sparse(&eye, &c); return chm_sparse_to_SEXP(ans, 1, uploT, Rkind, "N", GET_SLOT(x, Matrix_DimNamesSym)); } }
int get_blocking_internal(const int n_vertices, const int n_edges, const SEXP NNE_R, const bool directed, const int MIS_method, const int unassinged_method, std::list<int>& seeds, int* const blocks) { cholmod_common cholmod_c; cholmod_start(&cholmod_c); cholmod_sparse* NNE = get_cholmod_NNE(n_vertices, n_edges, NNE_R, &cholmod_c); if (!directed) { // NNE = NNE | t(NNE) cholmod_sparse* NNEt = cholmod_transpose(NNE, CHOLMOD_PATTERN, &cholmod_c); cholmod_sparse* NNE_tmp = cholmod_add(NNE, NNEt, NULL, NULL, false, false, &cholmod_c); cholmod_free_sparse(&NNEt, &cholmod_c); NNE->i = NULL; // Remove pointer to R object before freeing memory cholmod_free_sparse(&NNE, &cholmod_c); NNE = NNE_tmp; } switch(MIS_method) { case LEXICAL: findMIS_in_sp_lex(NNE, seeds); break; case FSTPOWORDER: case SNDPOWORDER: case HEURISTIC: { std::list<int> ordering; get_ordering(NNE, MIS_method, directed, ordering, &cholmod_c); if (MIS_method == HEURISTIC) { heuristic_search(NNE, ordering, seeds); } else { findMIS_in_sp_order(NNE, ordering, seeds); } } break; case MAXIS: findMaxIS_in_sp(NNE, directed, seeds, &cholmod_c); break; default: error("Unknown MIS method."); } const int* const NNE_p = static_cast<const int*>(NNE->p); const int* const NNE_i = static_cast<const int*>(NNE->i); int n_unassigned = n_vertices; int block_label = 1; for (std::list<int>::const_iterator it = seeds.begin(); it != seeds.end(); ++it, ++block_label) { // Set block for seed blocks[*it] = block_label; --n_unassigned; // Set block for adjacent to seed const int* const a_stop = NNE_i + NNE_p[*it + 1]; for (const int* a = NNE_i + NNE_p[*it]; a != a_stop; ++a) { blocks[*a] = block_label; --n_unassigned; } } if (unassinged_method == ADJACENT_S) { // Assign unassigned to the block that contains // a neighbor in the NNE. Set to negative first as // unassigned cannot be match to another unassigned // that just been assigned. // If NNE is directed, it is ordered by closeness. // I.e. the unassigned will be assigned to the blocks // that contain their closest neighbor. // When NNE is undirected, the matrix multiplication // has scrambled the ordering. Then the unassigned are // assigned to neighbors lexically. if (directed) { for (int i = 0; i < n_vertices; ++i) { if (blocks[i] == 0) { --n_unassigned; const int* const a_stop = NNE_i + NNE_p[i + 1]; for (const int* a = NNE_i + NNE_p[i]; a != a_stop; ++a) { if (blocks[*a] > 0) { blocks[i] = -blocks[*a]; break; } } } } } else { for (int i = 0; i < n_vertices; ++i) { if (blocks[i] == 0) { --n_unassigned; int lowest_adjacent = n_vertices; const int* const a_stop = NNE_i + NNE_p[i + 1]; for (const int* a = NNE_i + NNE_p[i]; a != a_stop; ++a) { if (*a < lowest_adjacent && blocks[*a] > 0) { blocks[i] = -blocks[*a]; lowest_adjacent = *a; } } } } } for (int i = 0; i < n_vertices; ++i) { if (blocks[i] < 0) { blocks[i] = -blocks[i]; } } } if (directed) { // This is already done for undirected case NNE->i = NULL; // Remove pointer to R object before freeing memory } cholmod_free_sparse(&NNE, &cholmod_c); cholmod_finish(&cholmod_c); return n_unassigned; }
/** * Populate ans with the pointers from x and modify its scalar * elements accordingly. Note that later changes to the contents of * ans will change the contents of the SEXP. * * In most cases this function is called through the macros * AS_CHM_SP() or AS_CHM_SP__(). It is unusual to call it directly. * * @param ans a CHM_SP pointer * @param x pointer to an object that inherits from CsparseMatrix * @param check_Udiag boolean - should a check for (and consequent * expansion of) a unit diagonal be performed. * @param sort_in_place boolean - if the i and x slots are to be sorted * should they be sorted in place? If the i and x slots are pointers * to an input SEXP they should not be modified. * * @return ans containing pointers to the slots of x, *unless* * check_Udiag and x is unitriangular. */ CHM_SP as_cholmod_sparse(CHM_SP ans, SEXP x, Rboolean check_Udiag, Rboolean sort_in_place) { static const char *valid[] = { MATRIX_VALID_Csparse, ""}; int *dims = INTEGER(GET_SLOT(x, Matrix_DimSym)), ctype = R_check_class_etc(x, valid); SEXP islot = GET_SLOT(x, Matrix_iSym); if (ctype < 0) error(_("invalid class of object to as_cholmod_sparse")); if (!isValid_Csparse(x)) error(_("invalid object passed to as_cholmod_sparse")); memset(ans, 0, sizeof(cholmod_sparse)); /* zero the struct */ ans->itype = CHOLMOD_INT; /* characteristics of the system */ ans->dtype = CHOLMOD_DOUBLE; ans->packed = TRUE; /* slots always present */ ans->i = INTEGER(islot); ans->p = INTEGER(GET_SLOT(x, Matrix_pSym)); /* dimensions and nzmax */ ans->nrow = dims[0]; ans->ncol = dims[1]; /* Allow for over-allocation of the i and x slots. Needed for * sparse X form in lme4. Right now it looks too difficult to * check for the length of the x slot, because of the xpt * utility, but the lengths of x and i should agree. */ ans->nzmax = LENGTH(islot); /* values depending on ctype */ ans->x = xpt(ctype, x); ans->stype = stype(ctype, x); ans->xtype = xtype(ctype); /* are the columns sorted (increasing row numbers) ?*/ ans->sorted = check_sorted_chm(ans); if (!(ans->sorted)) { /* sort columns */ if(sort_in_place) { if (!cholmod_sort(ans, &c)) error(_("in_place cholmod_sort returned an error code")); ans->sorted = 1; } else { CHM_SP tmp = cholmod_copy_sparse(ans, &c); if (!cholmod_sort(tmp, &c)) error(_("cholmod_sort returned an error code")); #ifdef DEBUG_Matrix /* This "triggers" exactly for return values of dtCMatrix_sparse_solve():*/ /* Don't want to translate this: want it report */ Rprintf("Note: as_cholmod_sparse() needed cholmod_sort()ing\n"); #endif chm2Ralloc(ans, tmp); cholmod_free_sparse(&tmp, &c); } } if (check_Udiag && ctype % 3 == 2 // triangular && (*diag_P(x) == 'U')) { /* diagU2N(.) "in place" : */ double one[] = {1, 0}; CHM_SP eye = cholmod_speye(ans->nrow, ans->ncol, ans->xtype, &c); CHM_SP tmp = cholmod_add(ans, eye, one, one, TRUE, TRUE, &c); #ifdef DEBUG_Matrix_verbose /* happens quite often, e.g. in ../tests/indexing.R : */ Rprintf("Note: as_cholmod_sparse(<ctype=%d>) - diagU2N\n", ctype); #endif chm2Ralloc(ans, tmp); cholmod_free_sparse(&tmp, &c); cholmod_free_sparse(&eye, &c); } /* else : * NOTE: if(*diag_P(x) == 'U'), the diagonal is lost (!); * ---- that may be ok, e.g. if we are just converting from/to Tsparse, * but is *not* at all ok, e.g. when used before matrix products */ return ans; }
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); }