From 20bc6358ffca5fe8b24f06a91fc19c8ac63637b1 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Wed, 28 Nov 2018 10:01:29 -0500 Subject: [PATCH] Restored previous parallel link detection method to smatrix.c --- src/smatrix.c | 141 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 30 deletions(-) diff --git a/src/smatrix.c b/src/smatrix.c index aa368e2..f81f3dc 100755 --- a/src/smatrix.c +++ b/src/smatrix.c @@ -47,7 +47,9 @@ int linsolve(Smatrix *, int); // Local functions static int allocsmatrix(Smatrix *, int, int); static int alloclinsolve(Smatrix *, int); -static void removeparalinks(Project *); +static int localadjlists(Network *, Smatrix *); +static int paralink(Network *, Smatrix *, int, int, int k); +static void xparalinks(Network *); static int reordernodes(Project *); static int factorize(Project *); static int growlist(Project *, int); @@ -97,13 +99,11 @@ int createsparse(Project *pr) errcode = allocsmatrix(sm, net->Nnodes, net->Nlinks); if (errcode) return errcode; - // Build node-link adjacency lists - errcode = buildadjlists(net); + // Build a local version of node-link adjacency lists + // with parallel links removed + errcode = localadjlists(net, sm); if (errcode) return errcode; - // Remove parallel links from adjacency lists - removeparalinks(pr); - // Re-order nodes to minimize number of non-zero coeffs. // in factorized solution matrix ERRCODE(reordernodes(pr)); @@ -117,7 +117,7 @@ int createsparse(Project *pr) // coeffs. and store these positions in vector NZSUB ERRCODE(storesparse(pr, net->Njuncs)); - // Free memory used for adjacency lists and sort + // Free memory used for local adjacency lists and sort // row indexes in NZSUB to optimize linsolve() freeadjlists(net); ERRCODE(sortsparse(sm, net->Njuncs)); @@ -222,7 +222,87 @@ void freesparse(Project *pr) } -void removeparalinks(Project *pr) +int localadjlists(Network *net, Smatrix *sm) +/* +**-------------------------------------------------------------- +** Input: none +** Output: returns error code +** Purpose: builds linked list of non-parallel links adjacent to each node +**-------------------------------------------------------------- +*/ +{ + int i, j, k; + int pmark = 0; // parallel link marker + int errcode = 0; + Padjlist alink; + + // Create an array of adjacency lists + freeadjlists(net); + net->Adjlist = (Padjlist *)calloc(net->Nnodes + 1, sizeof(Padjlist)); + if (net->Adjlist == NULL) return 101; + + // For each link, update adjacency lists of its end nodes + for (k = 1; k <= net->Nlinks; k++) + { + i = net->Link[k].N1; + j = net->Link[k].N2; + pmark = paralink(net, sm, i, j, k); // Parallel link check + + // Include link in start node i's list + alink = (struct Sadjlist *) malloc(sizeof(struct Sadjlist)); + if (alink == NULL) return(101); + if (!pmark) alink->node = j; + else alink->node = 0; // Parallel link marker + alink->link = k; + alink->next = net->Adjlist[i]; + net->Adjlist[i] = alink; + + // Include link in end node j's list + alink = (struct Sadjlist *) malloc(sizeof(struct Sadjlist)); + if (alink == NULL) return(101); + if (!pmark) alink->node = i; + else alink->node = 0; // Parallel link marker + alink->link = k; + alink->next = net->Adjlist[j]; + net->Adjlist[j] = alink; + } + + // Remove parallel links from adjacency lists + xparalinks(net); + return errcode; +} + + +int paralink(Network *net, Smatrix *sm, int i, int j, int k) +/* +**-------------------------------------------------------------- +** Input: i = index of start node of link +** j = index of end node of link +** k = link index +** Output: returns 1 if link k parallels another link, else 0 +** Purpose: checks for parallel links between nodes i and j +** +**-------------------------------------------------------------- +*/ +{ + Padjlist alink; + for (alink = net->Adjlist[i]; alink != NULL; alink = alink->next) + { + // Link || to k (same end nodes) + if (alink->node == j) + { + // Assign Ndx entry to this link + sm->Ndx[k] = alink->link; + return(1); + } + } + // Ndx entry if link not parallel + sm->Ndx[k] = k; + return(0); +} + + +void xparalinks(Network *net) /* **-------------------------------------------------------------- ** Input: none @@ -231,35 +311,36 @@ void removeparalinks(Project *pr) **-------------------------------------------------------------- */ { - Network *net = &pr->network; - Smatrix *sm = &pr->hydraul.smatrix; + int i; + Padjlist alink, // Current item in adjacency list + blink; // Previous item in adjacency list - int i, k; - Padjlist alink, blink; - - // Assign indexes of off-diagonal coeffs. to each link - for (k = 1; k <= net->Nlinks; k++) sm->Ndx[k] = k; - - // Check each node for parallel links + // Scan adjacency list of each node for (i = 1; i <= net->Nnodes; i++) { - // Traverse node's adjacency list - for (alink = net->Adjlist[i]; alink != NULL; alink = alink->next) + alink = net->Adjlist[i]; // First item in list + blink = NULL; + while (alink != NULL) { - // Skip link if it was already marked as parallel - if (alink->node == 0) continue; - - // Check all adjacent links that follow alink - for (blink = alink->next; blink != NULL; blink = blink->next) + if (alink->node == 0) // Parallel link marker found { - // If both links connect to same node, mark blink as parallel - k = blink->link; - if (k > 0 && blink->node == alink->node) + if (blink == NULL) // This holds at start of list { - // Re-assign off-diag. index of parallel link - sm->Ndx[k] = alink->link; - blink->node = 0; + net->Adjlist[i] = alink->next; + free(alink); // Remove item from list + alink = net->Adjlist[i]; } + else // This holds for interior of list + { + blink->next = alink->next; + free(alink); // Remove item from list + alink = blink->next; + } + } + else + { + blink = alink; // Move to next item in list + alink = alink->next; } } }