add node analysis
authoryu.dongliang <18588496441@163.com>
Mon, 13 May 2024 13:13:10 +0000 (21:13 +0800)
committeryu.dongliang <18588496441@163.com>
Mon, 13 May 2024 13:13:10 +0000 (21:13 +0800)
Makefile
main.c
ses_core.h
ses_node_analysis.c [new file with mode: 0644]
ses_step_jr.c
ses_step_va.c
ses_step_va_meshs.c
ses_utils.c

index 828f7642b769166d1b103e0e5170f96dcdf0e3b3..06baec2ac1daf5e3205debd2f29aca97e8bfbfa0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ CFILES += ses_utils.c
 CFILES += ses_path.c
 CFILES += ses_flow.c
 CFILES += ses_mesh_analysis.c
+CFILES += ses_node_analysis.c
 
 CFILES += ses_steps.c
 CFILES += ses_step_battery.c
diff --git a/main.c b/main.c
index 869dd09bb9c2a4995c1146eaeb216883d14a1fb5..c90f35641435f7bc583cef1688d0b0e4127a5377 100644 (file)
--- a/main.c
+++ b/main.c
@@ -107,7 +107,7 @@ int main(int argc, char* argv[])
 
                printf("f: %s\n", f->name);
 
-               ses_steps_analyse(f, 100, 1);
+               ses_steps_analyse(f, 100, 2);
        }
 #endif
 
index e38ebf31ec374c971a59dbb9dee30e42e10f9d84..207da682bd1a78dfee2f6400fb641ebf1e517db3 100644 (file)
@@ -9,6 +9,7 @@ typedef struct ses_step_s    ses_step_t;
 typedef struct ses_path_s    ses_path_t;
 typedef struct ses_edge_s    ses_edge_t;
 typedef struct ses_flow_s    ses_flow_t;
+typedef struct ses_node_s    ses_node_t;
 typedef struct ses_mesh_s    ses_mesh_t;
 
 typedef struct ses_info_s    ses_info_t;
@@ -119,6 +120,7 @@ struct ses_path_s
 struct ses_edge_s
 {
        int            refs;
+       int            index;
 
        ses_path_t*    path;
        int            vip_m;
@@ -127,12 +129,29 @@ struct ses_edge_s
        int            n_diodes;
        int            n_NPNs;
 
+       ses_node_t*    node0;
+       ses_node_t*    node1;
+
        double         cv;
        double         r;
 
        double         v;
        double         a;
        double         a0;
+
+       uint8_t        vflag:1;
+};
+
+struct ses_node_s
+{
+       scf_vector_t*  edges;
+
+       double         v;
+       double         a;
+       double         a0;
+
+       int            index;
+       int            vip_i;
 };
 
 struct ses_mesh_s
@@ -195,6 +214,13 @@ int         ses_mesh_add_edge(ses_mesh_t* mesh, ses_path_t* path, int m, int n,
 void        ses_meshs_print(scf_vector_t* meshs);
 void        ses_meshs_free (scf_vector_t* meshs);
 
+ses_node_t* ses_node_alloc();
+void        ses_node_free (ses_node_t* node);
+void        ses_node_print(ses_node_t* node);
+
+void        ses_nodes_free (scf_vector_t* nodes);
+void        ses_nodes_print(scf_vector_t* nodes);
+
 ses_flow_t* ses_flow_alloc();
 void        ses_flow_free (ses_flow_t* flow);
 void        ses_flow_print(ses_flow_t* flow);
@@ -237,6 +263,9 @@ int __ses_meshs_path (ScfEfunction* f, ses_path_t* path, scf_vector_t** meshs);
 int __ses_meshs_path_solve(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, int* changed, int64_t ns, int64_t count);
 int __ses_meshs_PPN_solve (ScfEfunction* f, ses_flow_t* flow, ses_path_t* bridge, int* changed, int64_t ns, int64_t count);
 
+int __ses_nodes_path(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t** nodes);
+int __ses_nodes_path_solve(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, int* changed, int64_t ns, int64_t count);
+
 int  __ses_path_jr (ScfEfunction* f, ses_path_t* path);
 void __ses_path_pr (ScfEfunction* f, ses_path_t* path, int i, int j, ses_path_t* child, double* r);
 void __ses_path_jpr(ScfEfunction* f, ses_path_t* path, int i, int j, ses_path_t* child, double* jr);
diff --git a/ses_node_analysis.c b/ses_node_analysis.c
new file mode 100644 (file)
index 0000000..0ede069
--- /dev/null
@@ -0,0 +1,465 @@
+#include"ses_core.h"
+#include <gsl/gsl_linalg.h>
+
+int ses_node_ref_edge(ses_node_t* node, ses_edge_t* edge)
+{
+       int ret = scf_vector_add(node->edges, edge);
+       if (ret < 0)
+               return ret;
+
+       edge->refs++;
+       return 0;
+}
+
+int ses_node_add_edge(ses_node_t* node, ses_path_t* path, int m, int n, ses_edge_t** pp)
+{
+       ses_edge_t* edge = ses_edge_alloc(path, m, n);
+       if (!edge)
+               return -ENOMEM;
+
+       int ret = scf_vector_add(node->edges, edge);
+       if (ret < 0) {
+               ses_edge_free(edge);
+               return ret;
+       }
+
+       if (pp)
+               *pp = edge;
+       return 0;
+}
+
+ses_edge_t* ses_nodes_find_edge(scf_vector_t* nodes, ses_path_t* path, int vip_m, int vip_n)
+{
+       ses_node_t* node;
+       ses_edge_t* edge;
+
+       int i;
+       int j;
+
+       for (i = 0; i < nodes->size; i++) {
+               node      = nodes->data[i];
+
+               for (j = 0; j < node->edges->size; j++) {
+                       edge      = node->edges->data[j];
+
+                       if (edge->path == path
+                                       && edge->vip_m == vip_m
+                                       && edge->vip_n == vip_n)
+                               return edge;
+               }
+       }
+
+       return NULL;
+}
+
+int __ses_nodes_path(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t** nodes)
+{
+       scf_vector_t* vec;
+       ses_path_t*   child;
+       ses_path_t*   bridge;
+
+       ses_edge_t*   edge = NULL;
+       ses_node_t*   prev = NULL;
+       ses_node_t*   node = NULL;
+
+       int ret = -1;
+
+       vec = scf_vector_alloc();
+       if (!vec)
+               return -ENOMEM;
+
+       int n_nodes = 0;
+       int n_edges = 0;
+
+       int i;
+       int j = vip_n;
+       int k;
+
+       for (i = vip_n - 1; i > vip_m; i -= 2) {
+
+               ScfEpin* p = path->pins->data[i];
+
+               if (!path->childs)
+                       continue;
+
+               node = ses_node_alloc();
+               if (!node) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+
+               ret = ses_node_add_edge(node, path, i, j, &edge);
+               if (ret < 0) {
+                       ses_node_free(node);
+                       goto error;
+               }
+               edge->index = n_edges++;
+               edge->node1 = node;
+
+               if (prev) {
+                       ret = ses_node_ref_edge(prev, edge);
+                       if (ret < 0) {
+                               ses_node_free(node);
+                               goto error;
+                       }
+                       edge->node0 = prev;
+               }
+
+               for (k = 0; k < path->childs->size; k++) {
+                       child     = path->childs->data[k];
+
+                       if (child->parent_p0 == i) {
+#define CHILD_EDGE_ADD_UNIQUE() \
+                               edge = ses_nodes_find_edge(vec, child, 0, child->pins->size - 1); \
+                               if (edge) { \
+                                       ret = ses_node_ref_edge(node, edge); \
+                                       if (ret < 0) { \
+                                               ses_node_free(node); \
+                                               goto error; \
+                                       } \
+                               } else { \
+                                       ret = ses_node_add_edge(node, child, 0, child->pins->size - 1, &edge); \
+                                       if (ret < 0) { \
+                                               ses_node_free(node); \
+                                               goto error; \
+                                       } \
+                                       edge->index = n_edges++; \
+                               } \
+
+                               CHILD_EDGE_ADD_UNIQUE();
+                               edge->node1 = node;
+
+                       } else if (child->parent_p1 == i - 1) {
+
+                               CHILD_EDGE_ADD_UNIQUE();
+                               edge->node0 = node;
+                       }
+               }
+
+               if (path->bridges) {
+                       for (k = 0; k < path->bridges->size; k++) {
+                               bridge    = path->bridges->data[k];
+
+                               if (bridge->parent_p0 == i) {
+#define BRIDGE_EDGE_ADD_UNIQUE() \
+                                       edge = ses_nodes_find_edge(vec, bridge, 0, bridge->pins->size - 1); \
+                                       if (edge) { \
+                                               ret = ses_node_ref_edge(node, edge); \
+                                               if (ret < 0) { \
+                                                       ses_node_free(node); \
+                                                       goto error; \
+                                               } \
+                                       } else { \
+                                               ret = ses_node_add_edge(node, bridge, 0, bridge->pins->size - 1, &edge); \
+                                               if (ret < 0) { \
+                                                       ses_node_free(node); \
+                                                       goto error; \
+                                               } \
+                                               edge->index = n_edges++; \
+                                               if (prev) { \
+                                                       ret = ses_node_ref_edge(node, edge); \
+                                                       if (ret < 0) { \
+                                                               ses_node_free(node); \
+                                                               goto error; \
+                                                       } \
+                                               } \
+                                       }
+
+                                       BRIDGE_EDGE_ADD_UNIQUE();
+                                       edge->node1 = node;
+
+                               } else if (bridge->parent_p1 == i - 1) {
+
+                                       BRIDGE_EDGE_ADD_UNIQUE();
+                                       edge->node0 = node;
+                               }
+                       }
+               }
+
+               ret = scf_vector_add(vec, node);
+               if (ret < 0) {
+                       ses_node_free(node);
+                       goto error;
+               }
+               node->index = n_nodes++;
+               node->vip_i = i;
+
+               prev = node;
+
+               j = i - 1;
+       }
+
+       if (j > vip_m) {
+               if (!node) {
+                       node = ses_node_alloc();
+                       if (!node) {
+                               ret = -ENOMEM;
+                               goto error;
+                       }
+
+                       ret = scf_vector_add(vec, node);
+                       if (ret < 0) {
+                               ses_node_free(node);
+                               goto error;
+                       }
+                       node->index = n_nodes++;
+                       node->vip_i = j;
+               }
+
+               ret = ses_node_add_edge(node, path, vip_m, j, &edge);
+               if (ret < 0)
+                       goto error;
+               edge->index = n_edges++;
+               edge->node0 = node;
+       }
+
+       *nodes = vec;
+       return 0;
+
+error:
+       scf_vector_clear(vec, (void (*)(void*) )ses_node_free);
+       scf_vector_free(vec);
+       return ret;
+}
+
+/*
+ v[0]
+ v[1]
+ ...
+ v[n - 1]
+
+ i[0]
+ i[1]
+ ...
+ i[m - 1]
+ -------------
+ a[0][0] + a[0][1] + ... + a[0][m] = 0
+...
+ a[n - 1][0] + a[n - 1][1] + ... + a[n - 1][m] = 0
+
+ v[0][0] - v[0][1] - a[0] * R[0] = C[0]
+ ...
+ v[m - 1][0] - v[m - 1][1] - a[m - 1] * R[m - 1] = C[m - 1]
+ */
+static int __ses_nodes_path_solve2(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, scf_vector_t* nodes, int* changed, int64_t ns, int64_t count)
+{
+       ses_node_t*   node;
+       ses_edge_t*   edge;
+
+       ScfEline*     el;
+       ScfEpin*      pm = path->pins->data[vip_m];
+       ScfEpin*      pn = path->pins->data[vip_n];
+       ScfEpin*      p0;
+       ScfEpin*      p1;
+
+       int ret = 0;
+       int i;
+       int j;
+
+       int m = 0;
+       int n = nodes->size;
+
+       for (i = 0; i < nodes->size; i++) {
+               node      = nodes->data[i];
+
+               for (j = 0; j < node->edges->size; j++) {
+                       edge      = node->edges->data[j];
+
+                       if (!edge->vflag) {
+                               m++;
+                               edge->vflag = 1;
+                       }
+               }
+       }
+
+       int N = n + m;
+
+       scf_logi("c%ldp%ld->v: %lg, c%ldp%ld->v: %lg, n_nodes: %d, n_edges: %d, N: %d\n", pm->cid, pm->id, pm->v, pn->cid, pn->id, pn->v, n, m, N);
+
+       double* A = calloc(N * N + N + N, sizeof(double));
+       if (!A)
+               return -ENOMEM;
+
+       double* b = A + N * N;
+       double* X = b + N;
+       double cv;
+       double r;
+
+       __ses_path_jr(f, path);
+
+       for (i = 0; i < nodes->size; i++) {
+               node      = nodes->data[i];
+
+               b[i] = 0;
+
+               for (j = 0; j < node->edges->size; j++) {
+                       edge      = node->edges->data[j];
+
+                       if (edge->path == path) {
+                               if (edge->vip_m < node->vip_i)
+                                       A[i * N + n + edge->index] = 1;
+                               else
+                                       A[i * N + n + edge->index] = -1;
+                       } else {
+                               if (edge->path->parent_p0 < node->vip_i)
+                                       A[i * N + n + edge->index] = 1;
+                               else
+                                       A[i * N + n + edge->index] = -1;
+                       }
+               }
+       }
+
+       for (i = 0; i < nodes->size; i++) {
+               node      = nodes->data[i];
+
+               scf_logd("node->index: %d\n", node->index);
+
+               for (j = 0; j < node->edges->size; j++) {
+                       edge      = node->edges->data[j];
+
+                       if (!edge->vflag)
+                               continue;
+                       edge->vflag = 0;
+
+                       __ses_path_capacitors(f, edge->path, edge->vip_m, edge->vip_n, &cv);
+
+                       if (0 == edge->vip_m && edge->vip_n == edge->path->pins->size - 1)
+                               r  = edge->path->pr;
+                       else
+                               __ses_path_sr(f, edge->path, edge->vip_m, edge->vip_n, &r);
+
+                       edge->r = r;
+
+                       p0 = edge->path->pins->data[edge->vip_m];
+                       p1 = edge->path->pins->data[edge->vip_n];
+
+                       scf_logd("c%ldp%ld-c%ldp%ld, r: %lg, cv: %lg, edge->index: %d\n", p0->cid, p0->id, p1->cid, p1->id, r, cv, edge->index);
+
+                       b[n + edge->index]                         = cv;
+                       A[(n + edge->index) * N + n + edge->index] = -r;
+
+                       if (edge->path == path) {
+
+                               if (edge->node0)
+                                       A[(n + edge->index) * N + edge->node0->index] = -1;
+
+                               else if (edge->vip_n == vip_n)
+                                       b[n + edge->index] += pn->v;
+
+
+                               if (edge->node1)
+                                       A[(n + edge->index) * N + edge->node1->index] = 1;
+
+                               else if (edge->vip_m == vip_m)
+                                       b[n + edge->index] -= pm->v;
+
+                       } else {
+                               if (edge->node0)
+                                       A[(n + edge->index) * N + edge->node0->index] = -1;
+
+                               else if (edge->path->parent_p1 == vip_n)
+                                       b[n + edge->index] -= pn->v;
+
+
+                               if (edge->node1)
+                                       A[(n + edge->index) * N + edge->node1->index] = 1;
+
+                               else if (edge->path->parent_p0 == vip_m)
+                                       b[n + edge->index] -= pm->v;
+                       }
+               }
+       }
+
+       gsl_matrix_view _A = gsl_matrix_view_array(A, N, N);
+       gsl_vector_view _b = gsl_vector_view_array(b, N);
+       gsl_vector_view _X = gsl_vector_view_array(X, N);
+
+       int s;
+       gsl_permutation* _P = gsl_permutation_alloc(N);
+       if (!_P) {
+               ret = -ENOMEM;
+               goto P_failed;
+       }
+
+       gsl_linalg_LU_decomp(&_A.matrix, _P, &s);
+       gsl_linalg_LU_solve (&_A.matrix, _P, &_b.vector, &_X.vector);
+
+#if 0
+       for (i = 0; i < N; i++) {
+               for (j = 0; j < N; j++)
+                       printf("%5lg ", A[i * N + j]);
+               printf("\n");
+       }
+       scf_logi("b:\n");
+       gsl_vector_fprintf(stdout, &_b.vector, "%lg");
+#endif
+
+       scf_logi("X:\n");
+       gsl_vector_fprintf(stdout, &_X.vector, "%lg");
+
+       for (i = 0; i < nodes->size; i++) {
+               node      = nodes->data[i];
+
+               p0    = path->pins->data[node->vip_i];
+
+               el    = f->elines[p0->lid];
+               el->v = X[i];
+       }
+
+#if 1
+       for (i = 0; i < nodes->size; i++) {
+               node      = nodes->data[i];
+
+               for (j = 0; j < node->edges->size; j++) {
+                       edge      = node->edges->data[j];
+
+                       p0 = edge->path->pins->data[edge->vip_m];
+                       p1 = edge->path->pins->data[edge->vip_n];
+
+                       scf_logi("c%ldp%ld--c%ldp%ld, edge->vflag: %d\n", p0->cid, p0->id, p1->cid, p1->id, edge->vflag);
+
+                       if (edge->vflag)
+                               continue;
+                       edge->vflag = 1;
+
+                       p0->v = f->elines[p0->lid]->v;
+                       p1->v = f->elines[p1->lid]->v;
+
+                       ret = __ses_path_va_branch(f, edge->path, edge->vip_m, edge->vip_n, edge->r, changed, ns, count);
+                       if (ret < 0)
+                               goto error;
+               }
+       }
+#endif
+error:
+       gsl_permutation_free(_P);
+P_failed:
+       free(A);
+       return ret;
+}
+
+int __ses_nodes_path_solve(ScfEfunction* f, ses_path_t* path, int vip_m, int vip_n, int* changed, int64_t ns, int64_t count)
+{
+       scf_vector_t* nodes = NULL;
+       ses_node_t*   node;
+       ses_edge_t*   edge;
+
+       ScfEline*     el;
+       ScfEpin*      pm = path->pins->data[vip_m];
+       ScfEpin*      pn = path->pins->data[vip_n];
+       ScfEpin*      p0;
+       ScfEpin*      p1;
+
+       int ret = __ses_nodes_path(f, path, vip_m, vip_n, &nodes);
+       if (ret < 0)
+               return ret;
+
+       ses_nodes_print(nodes);
+
+       ret = __ses_nodes_path_solve2(f, path, vip_m, vip_n, nodes, changed, ns, count);
+
+       scf_vector_clear(nodes, (void (*)(void*) )ses_node_free);
+       scf_vector_free(nodes);
+
+       return ret;
+}
index 9086dd440765f25849c81d6dae79d2764643a0be..6619e8d1984f33a159d39890881264c128651482 100644 (file)
@@ -69,6 +69,16 @@ int __ses_path_jr(ScfEfunction* f, ses_path_t* path)
        int    i;
        int    j;
 
+       if (path->bridges) {
+               for (i = 0; i < path->bridges->size; i++) {
+                       child     = path->bridges->data[i];
+
+                       int ret = __ses_path_jr(f, child);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
        if (path->childs) {
                for (i = 0; i < path->childs->size; i++) {
                        child     = path->childs->data[i];
index cb1e84dc9aeea8ec91a9c64c7e70084c34a6e929..1f20b3a8247273bd80195eeec705b97c25c9d478 100644 (file)
@@ -182,6 +182,21 @@ int __ses_path_va_branch(ScfEfunction* f, ses_path_t* path, int m, int n, double
        ScfEpin*       p0 = path->pins->data[m];
        ScfEpin*       p1 = path->pins->data[n];
 
+       double _sr0 = p0->sr;
+       double _pr0 = p0->pr;
+       double _sr1 = p1->sr;
+       double _pr1 = p1->pr;
+
+       if (0 == m) {
+               p0->sr = 0;
+               p0->pr = 0;
+       }
+
+       if (path->pins->size - 1 == n) {
+               p1->sr = path->sr;
+               p1->pr = path->pr;
+       }
+
        double cv = 0;
        double a  = 0;
        double v  = p0->v - p1->v;
@@ -277,6 +292,16 @@ int __ses_path_va_branch(ScfEfunction* f, ses_path_t* path, int m, int n, double
        }
        printf("\n");
 
+       if (0 == m) {
+               p0->sr = _sr0;
+               p0->pr = _pr0;
+       }
+
+       if (path->pins->size - 1 == n) {
+               p1->sr = _sr1;
+               p1->pr = _pr1;
+       }
+
        path->vflag = 1;
        return 0;
 }
index 40afa37fefde333f75b79bb97fa735150fad93e8..658a4a01b5b8c2b4bdafc96e2f77904a537f99eb 100644 (file)
@@ -24,7 +24,9 @@ int __ses_path_va_meshs(ScfEfunction* f, ses_path_t* path, int* changed, scf_vec
        p1->pr = path->pr;
 
        scf_logi("---------------\n");
-       int ret = __ses_meshs_path_solve(f, path, 0, path->pins->size - 1, changed, ns, count);
+//     int ret = __ses_meshs_path_solve(f, path, 0, path->pins->size - 1, changed, ns, count);
+
+       int ret = __ses_nodes_path_solve(f, path, 0, path->pins->size - 1, changed, ns, count);
        if (ret < 0) {
                scf_loge("\n");
                return ret;
index a121ca06cf7101b17488fc2e38e4db9b79bba7fe..0c898aebc0d772f2c370717dbf3b98f4d7c023b9 100644 (file)
@@ -61,6 +61,8 @@ void ses_edge_print(ses_edge_t* edge)
        ScfEpin* p;
        int      j;
 
+       printf("[%d] ", edge->index);
+
        if (edge->vip_m < edge->vip_n) {
 
                for (j = edge->vip_m; j <= edge->vip_n; j++) {
@@ -146,6 +148,70 @@ void ses_meshs_print(scf_vector_t* meshs)
        }
 }
 
+ses_node_t* ses_node_alloc()
+{
+       ses_node_t* node = calloc(1, sizeof(ses_node_t));
+       if (!node)
+               return NULL;
+
+       node->edges = scf_vector_alloc();
+       if (!node->edges) {
+               free(node);
+               return NULL;
+       }
+
+       return node;
+}
+
+void ses_node_free(ses_node_t* node)
+{
+       if (node) {
+               scf_vector_clear(node->edges, (void (*)(void*) )ses_edge_free);
+               scf_vector_free(node->edges);
+
+               free(node);
+       }
+}
+
+void ses_nodes_free(scf_vector_t* nodes)
+{
+       if (nodes) {
+               scf_vector_clear(nodes, (void (*)(void*) )ses_node_free);
+               scf_vector_free(nodes);
+       }
+}
+
+void ses_node_print(ses_node_t* node)
+{
+       if (!node)
+               return;
+
+       ses_edge_t* edge;
+
+       int i;
+
+       printf("node %d: ", node->index);
+
+       for (i = 0; i < node->edges->size; i++) {
+               edge      = node->edges->data[i];
+
+               ses_edge_print(edge);
+       }
+       printf("\n");
+}
+
+void ses_nodes_print(scf_vector_t* nodes)
+{
+       if (!nodes)
+               return;
+
+       int i;
+       for (i = 0; i < nodes->size; i++) {
+
+               ses_node_print(nodes->data[i]);
+       }
+}
+
 void __ses_pn_dr(ScfEcomponent* c, ScfEpin* pb, ScfEpin* pe)
 {
        double v = pb->v - pe->v;