From: yu.dongliang <18588496441@163.com> Date: Mon, 13 May 2024 13:13:10 +0000 (+0800) Subject: add node analysis X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=d66c2749063e1a75df8d92829db205b30969e058;p=ses.git add node analysis --- diff --git a/Makefile b/Makefile index 828f764..06baec2 100644 --- 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 869dd09..c90f356 100644 --- 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 diff --git a/ses_core.h b/ses_core.h index e38ebf3..207da68 100644 --- a/ses_core.h +++ b/ses_core.h @@ -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 index 0000000..0ede069 --- /dev/null +++ b/ses_node_analysis.c @@ -0,0 +1,465 @@ +#include"ses_core.h" +#include + +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; +} diff --git a/ses_step_jr.c b/ses_step_jr.c index 9086dd4..6619e8d 100644 --- a/ses_step_jr.c +++ b/ses_step_jr.c @@ -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]; diff --git a/ses_step_va.c b/ses_step_va.c index cb1e84d..1f20b3a 100644 --- a/ses_step_va.c +++ b/ses_step_va.c @@ -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; } diff --git a/ses_step_va_meshs.c b/ses_step_va_meshs.c index 40afa37..658a4a0 100644 --- a/ses_step_va_meshs.c +++ b/ses_step_va_meshs.c @@ -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; diff --git a/ses_utils.c b/ses_utils.c index a121ca0..0c898ae 100644 --- a/ses_utils.c +++ b/ses_utils.c @@ -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;