/* Create the system admittance matrix from power system data. Note that this function is called transparently from GetPSFromFile once power system data has been populated (if the file read is successful). */ int CreateYBus(PS ps, int *ids){ int i, from, to, num_buses = ps->num_buses, num_branches = ps->num_branches, nnz = num_buses + 2*num_branches; double r, x, b; double _Complex y, *diags = malloc(num_buses*sizeof(double _Complex)); //allocate a ybus cs_ci *ybus = cs_ci_spalloc(num_buses, num_buses, nnz, 1, 1), *ybus_comp, *ybus_comp_t; //check memory if(!ybus) return 1; //loop through ybus branches for(i=0; i<num_branches; i++) { //get branch from/to bus indices from = ps->branches[i].from_index; to = ps->branches[i].to_index; //determine line admittance r = ps->branches[i].r; x = ps->branches[i].x; b = ps->branches[i].b; y = (1.0+0.0*I)/(r+x*I); //add off-diagonals to ybus and increment diagonal entries cs_ci_entry(ybus, from, to, -y); cs_ci_entry(ybus, to, from, -y); diags[from]+=(y+I*b/2.0); diags[to]+=(y+I*b/2.0); } //add diogonal entries to ybus. for(i=0; i<num_buses; i++) cs_ci_entry(ybus, i, i, diags[i]); //compress ybus ybus_comp=cs_ci_compress(ybus); //check that memory allocation was okay if(!ybus_comp){cs_ci_spfree(ybus); return 1;} //free the old ybus and sum duplicates in the compressed matrix (i.e., parallel branches) cs_ci_spfree(ybus); cs_ci_dupl(ybus_comp); //sort the columns of ybus using the transpose-transpose trick ybus_comp_t = cs_ci_transpose(ybus_comp, 1); if(!ybus_comp_t){free(ybus_comp); return 1;} free(ybus_comp); ybus_comp = cs_ci_transpose(ybus_comp_t, 1); if(!ybus_comp){free(ybus_comp_t); return 1;} free(ybus_comp_t); //assign the ps ybus pointer to the compressed, summed ybus matrix ps->ybus = ybus_comp; //free the diagonal workspace and return free(diags); return 0; }
/* Cholesky update/downdate */ int demo3 (problem *Prob) { cs_ci *A, *C, *W = NULL, *WW, *WT, *E = NULL, *W2 ; int n, k, *Li, *Lp, *Wi, *Wp, p1, p2, *p = NULL, ok ; cs_complex_t *b, *x, *resid, *y = NULL, *Lx, *Wx, s ; double t, t1 ; cs_cis *S = NULL ; cs_cin *N = NULL ; if (!Prob || !Prob->sym || Prob->A->n == 0) return (0) ; A = Prob->A ; C = Prob->C ; b = Prob->b ; x = Prob->x ; resid = Prob->resid; n = A->n ; if (!Prob->sym || n == 0) return (1) ; rhs (x, b, n) ; /* compute right-hand side */ printf ("\nchol then update/downdate ") ; print_order (1) ; y = cs_ci_malloc (n, sizeof (cs_complex_t)) ; t = tic () ; S = cs_ci_schol (1, C) ; /* symbolic Chol, amd(A+A') */ printf ("\nsymbolic chol time %8.2f\n", toc (t)) ; t = tic () ; N = cs_ci_chol (C, S) ; /* numeric Cholesky */ printf ("numeric chol time %8.2f\n", toc (t)) ; if (!S || !N || !y) return (done3 (0, S, N, y, W, E, p)) ; t = tic () ; cs_ci_ipvec (S->pinv, b, y, n) ; /* y = P*b */ cs_ci_lsolve (N->L, y) ; /* y = L\y */ cs_ci_ltsolve (N->L, y) ; /* y = L'\y */ cs_ci_pvec (S->pinv, y, x, n) ; /* x = P'*y */ printf ("solve chol time %8.2f\n", toc (t)) ; printf ("original: ") ; print_resid (1, C, x, b, resid) ; /* print residual */ k = n/2 ; /* construct W */ W = cs_ci_spalloc (n, 1, n, 1, 0) ; if (!W) return (done3 (0, S, N, y, W, E, p)) ; Lp = N->L->p ; Li = N->L->i ; Lx = N->L->x ; Wp = W->p ; Wi = W->i ; Wx = W->x ; Wp [0] = 0 ; p1 = Lp [k] ; Wp [1] = Lp [k+1] - p1 ; s = Lx [p1] ; srand (1) ; for ( ; p1 < Lp [k+1] ; p1++) { p2 = p1 - Lp [k] ; Wi [p2] = Li [p1] ; Wx [p2] = s * rand () / ((double) RAND_MAX) ; } t = tic () ; ok = cs_ci_updown (N->L, +1, W, S->parent) ; /* update: L*L'+W*W' */ t1 = toc (t) ; printf ("update: time: %8.2f\n", t1) ; if (!ok) return (done3 (0, S, N, y, W, E, p)) ; t = tic () ; cs_ci_ipvec (S->pinv, b, y, n) ; /* y = P*b */ cs_ci_lsolve (N->L, y) ; /* y = L\y */ cs_ci_ltsolve (N->L, y) ; /* y = L'\y */ cs_ci_pvec (S->pinv, y, x, n) ; /* x = P'*y */ t = toc (t) ; p = cs_ci_pinv (S->pinv, n) ; W2 = cs_ci_permute (W, p, NULL, 1) ; /* E = C + (P'W)*(P'W)' */ WT = cs_ci_transpose (W2,1) ; WW = cs_ci_multiply (W2, WT) ; cs_ci_spfree (WT) ; cs_ci_spfree (W2) ; E = cs_ci_add (C, WW, 1, 1) ; cs_ci_spfree (WW) ; if (!E || !p) return (done3 (0, S, N, y, W, E, p)) ; printf ("update: time: %8.2f (incl solve) ", t1+t) ; print_resid (1, E, x, b, resid) ; /* print residual */ cs_ci_nfree (N) ; /* clear N */ t = tic () ; N = cs_ci_chol (E, S) ; /* numeric Cholesky */ if (!N) return (done3 (0, S, N, y, W, E, p)) ; cs_ci_ipvec (S->pinv, b, y, n) ; /* y = P*b */ cs_ci_lsolve (N->L, y) ; /* y = L\y */ cs_ci_ltsolve (N->L, y) ; /* y = L'\y */ cs_ci_pvec (S->pinv, y, x, n) ; /* x = P'*y */ t = toc (t) ; printf ("rechol: time: %8.2f (incl solve) ", t) ; print_resid (1, E, x, b, resid) ; /* print residual */ t = tic () ; ok = cs_ci_updown (N->L, -1, W, S->parent) ; /* downdate: L*L'-W*W' */ t1 = toc (t) ; if (!ok) return (done3 (0, S, N, y, W, E, p)) ; printf ("downdate: time: %8.2f\n", t1) ; t = tic () ; cs_ci_ipvec (S->pinv, b, y, n) ; /* y = P*b */ cs_ci_lsolve (N->L, y) ; /* y = L\y */ cs_ci_ltsolve (N->L, y) ; /* y = L'\y */ cs_ci_pvec (S->pinv, y, x, n) ; /* x = P'*y */ t = toc (t) ; printf ("downdate: time: %8.2f (incl solve) ", t1+t) ; print_resid (1, C, x, b, resid) ; /* print residual */ return (done3 (1, S, N, y, W, E, p)) ; }