1 /* this is the new fillM 10/92 */
2
3 #include <string.h>
4 #include "induct.h"
5
6 /* this fills the kircoff's voltage law matrix (Mesh matrix) */
7 /* it maps a matrix of mesh currents to branch currents */
8 /* it might actually be what some think of as the transpose of M */
9 /* Here, M*Im = Ib where Im are the mesh currents, and Ib the branch */
10 /* 6/92 I added Mlist which is a vector of linked lists to meshes.
11 This replaces M. But I keep M around for checking things in matlab. */
12
13 /* much of what is commented out is obsolete stuff from an old idea
14 for a preconditioner that never worked */
fillM(indsys)15 void fillM(indsys)
16 SYS *indsys;
17 {
18
19 GROUNDPLANE *plane; /* CMS 6/2/92 */
20
21 int mesh, k, minimeshes;
22 MELEMENT **Mlist, *mend;
23 Minfo *m_info;
24 TREE *atree;
25 PATHLIST *aplist;
26 SPATH *apath;
27 SEGMENT *seg;
28 PSEUDO_SEG *pseg;
29
30 Mlist = indsys->Mlist;
31 m_info = indsys->m_info;
32 mesh = 0;
33
34 /* do all the loops due circuits in the graph */
35 for(atree = indsys->trees; atree != NULL; atree = atree->next)
36 for(aplist = atree->loops; aplist != NULL; aplist = aplist->next) {
37
38 Mlist[mesh] = make_mesh_from_path(aplist->path, mesh, indsys);
39 if (Mlist[mesh] != NULL)
40 /* it's possible that coincident gp nodes cause no path at all */
41 mesh++;
42
43 /* unimplemented junk
44 make_unconstrained(&(m_info[mesh]), mesh);
45 mesh += make_many_meshes_from_path(aplist->path, Mlist, m_info, mesh,
46 indsys);
47 */
48 }
49
50 if (mesh > indsys->extra_meshes) {
51 fprintf(stderr, "Internal Error: Bad estimate for extra_meshes\n");
52 fprintf(stderr, " One solution is to change FILS_PER_MESH to 1\n");
53 exit(1);
54 }
55
56 minimeshes = mesh;
57
58 /* this does all the meshes due to filaments within each segment */
59 for(seg = indsys->segment; seg != NULL; seg = seg->next) {
60 for(k = 1; k < seg->num_fils; k++, mesh++) {
61
62 Mlist[mesh] = make_melement(seg->filaments[k-1].filnumber,
63 &seg->filaments[k-1], 1);
64
65 Mlist[mesh] = insert_in_list(make_melement(seg->filaments[k].filnumber,
66 &seg->filaments[k], -1),
67 Mlist[mesh]);
68 /* unimplemented junk
69 make_unconstrained(&(m_info[mesh]),mesh);
70 */
71 }
72 }
73
74 /* add all the lists to the groundplane */
75 for(plane = indsys->planes; plane != NULL; plane = plane->next) {
76 if (!is_nonuni_gp(plane))
77 mesh += makeMlist(plane, &(Mlist[mesh]), &(m_info[mesh]),mesh);
78 else
79 mesh += make_nonuni_Mlist(plane, &(Mlist[mesh]));
80 }
81
82
83 /* For each tree mesh, pick one mini-mesh to be unconstrained and make it
84 unique (unimplemented)*/
85 /*pick_unconstrained(Mlist, m_info, mesh, indsys->tree_meshes, minimeshes);*/
86
87
88 if (mesh <= indsys->num_mesh)
89 indsys->num_mesh = mesh;
90 else {
91 fprintf(stderr, "uh oh, mesh > num_mesh\n");
92 exit(1);
93 }
94 }
95
96 /* this takes a linked list of segments (path) and makes a row of the */
97 /* mesh matrix out of the filament[0]'s of each segment. */
make_mesh_from_path(path,mesh,indsys)98 MELEMENT *make_mesh_from_path(path, mesh, indsys)
99 SPATH *path;
100 int mesh;
101 SYS *indsys;
102 {
103 SPATH *selem, *temppath, *telem;
104 MELEMENT *m1, *m2, *m3, *mlist;
105 NODES *plusnode, *node, *plus2, *node0, *node1, *actualnode;
106 int i, sign, sign2;
107 SEGMENT *seg;
108 PSEUDO_SEG *pseg, *pseg2;
109
110 mlist = NULL;
111 plusnode = find_first_node(path); /* which node starts the loop */
112 for(selem = path, i = 0; selem != NULL; selem = selem->next, i++) {
113 node0 = getnode(0, selem->seg); /* get original (not real) nodes */
114 node1 = getnode(1, selem->seg);
115 if (getrealnode(plusnode) == getrealnode(node0))
116 sign = 1;
117 else if (getrealnode(plusnode) == getrealnode(node1))
118 sign = -1;
119 else {
120 fprintf(stderr, "make_mesh_from_path: segments don't connect at node %s\n", plusnode->name);
121 exit(1);
122 }
123
124 if (selem->seg.type == NORMAL) {
125 seg = (SEGMENT *)selem->seg.segp;
126
127 m1 = make_melement(seg->filaments[0].filnumber, &seg->filaments[0],
128 sign);
129 mlist = insert_in_list(m1, mlist);
130 }
131 else if (selem->seg.type == PSEUDO) {
132 pseg = (PSEUDO_SEG *)selem->seg.segp;
133
134 if (pseg->type == EXTERNTYPE)
135 add_to_external(pseg, mesh, sign, indsys);
136 else if (pseg->type == GPTYPE) {
137 while( is_next_seg_in_gp(selem, plusnode) == TRUE) {
138 /* this is an ugly addition to make gp meshes smaller if two segs */
139 /* come from the same gp. It was commented out because of a bug */
140 /* which hopefully i've fixed, 3/96 */
141 selem = selem->next;
142 if (sign == 1) {
143 plusnode = node1;
144 node1 = getothernode(node1, selem->seg);
145 }
146 else {
147 plusnode = node0;
148 node0 = getothernode(node0, selem->seg);
149 }
150 if (indsys->opts->debug == ON)
151 printf("Fixing extra long gp mesh in gp %s, mesh %d.\n",
152 node0->gp->name, mesh);
153 }
154 if (sign == 1) {
155 temppath = path_through_gp(node0, node1, node0->gp);
156 plus2 = node0;
157 }
158 else {
159 temppath = path_through_gp(node1, node0, node0->gp);
160 plus2 = node1;
161 }
162 while(temppath != NULL) {
163 telem = temppath;
164 seg = (SEGMENT *)telem->seg.segp;
165 if (is_nonuni_gp(node0->gp)) {
166 /* must compare cell nodes, not actual seg nodes */
167 if (plus2->gp_node == seg->node[0]->gp_node) {
168 sign2 = 1;
169 actualnode = seg->node[0];
170 }
171 else if (plus2->gp_node == seg->node[1]->gp_node) {
172 sign2 = -1;
173 actualnode = seg->node[1];
174 }
175 else {
176 fprintf(stderr, "Hey, path_through_gp made nonconnected path!\n");
177 exit(1);
178 }
179 }
180 else {
181 if (plus2 == seg->node[0])
182 sign2 = 1;
183 else if (plus2 == seg->node[1])
184 sign2 = -1;
185 else {
186 fprintf(stderr, "Hey, path_through_gp made nonconnected path!\n");
187 exit(1);
188 }
189 actualnode = plus2;
190 }
191 m1 = make_melement(seg->filaments[0].filnumber, &seg->filaments[0],
192 sign2);
193 mlist = insert_in_list(m1, mlist);
194 plus2 = getothernode(actualnode, telem->seg);
195 temppath = temppath->next;
196 /* free(telem); */
197 }
198 }
199 else {
200 fprintf(stderr, "make_mesh_from_path: unknown pseudo_seg %d\n",
201 pseg->type);
202 exit(1);
203 }
204 }
205 else {
206 bad_seg_type("make_mesh_from_path", selem->seg);
207 }
208 plusnode = getothernode(plusnode, selem->seg);
209 }
210
211 if (mlist == NULL) {
212 fprintf(stderr,
213 "make_mesh_from_path: Possible loop of .external statements which is not allowed!\n");
214 fprintf(stderr,
215 " .external's (possibly equiv'ed nodes) which may make a loop:\n");
216 for(selem = path, i = 0; selem != NULL; selem = selem->next, i++) {
217 node0 = getnode(0, selem->seg); /* get original (not real) nodes */
218 node1 = getnode(1, selem->seg);
219 fprintf(stderr, " %s %s\n",node0->name, node1->name);
220 /* the above could be made more useful by searching through
221 the master pseudo_nodes list for pseudo_nodes thatpoint to these */
222 }
223 }
224
225 return mlist;
226 }
227
228 /* Check to see if the next segment is also from the same groundplane */
is_next_seg_in_gp(selem,plusnode)229 is_next_seg_in_gp(selem,plusnode)
230 SPATH *selem;
231 NODES *plusnode;
232 {
233 PSEUDO_SEG *pseg2, *pseg1;
234 NODES *othernode;
235
236 if (selem->next != NULL && selem->next->seg.type == PSEUDO) {
237 pseg1 = (PSEUDO_SEG *)selem->seg.segp;
238 pseg2 = (PSEUDO_SEG *)selem->next->seg.segp;
239 if (pseg2->type == GPTYPE
240 && pseg1->node[0]->gp == pseg2->node[0]->gp) {
241 othernode = getothernode(plusnode, selem->seg);
242 if (othernode == pseg2->node[0] || othernode == pseg2->node[1])
243 return TRUE;
244 else if (plusnode == pseg2->node[0] || plusnode == pseg2->node[1])
245 /* segs could be reversed in the path list. added 3/96 */
246 return TRUE;
247 }
248 /*
249 else
250 printf("Not an error: Two adjacent gp segs not in same gp %s, %s.\n",
251 pseg1->node[0]->gp->name, pseg2->node[0]->gp->name);
252 */
253 }
254 return FALSE;
255 }
256
257 /* this inserts melem into the linked list beginning with bigmhead. */
258 /* It inserts it to preserve increasing filindex order. */
insert_in_list(melem,bigmhead)259 MELEMENT *insert_in_list(melem, bigmhead)
260 MELEMENT *melem, *bigmhead;
261 {
262 MELEMENT *melem2;
263
264 if (bigmhead == NULL)
265 return melem;
266 else {
267 /* find where in the list to put melem */
268 melem2 = bigmhead;
269 if (melem2->filindex > melem->filindex) { /* put at beginning */
270 melem->mnext = melem2;
271 bigmhead = melem;
272 }
273 else { /* find its place in the middle of the list */
274 while(melem2->mnext != NULL
275 && melem2->mnext->filindex < melem->filindex)
276 melem2 = melem2->mnext;
277 /* insert it in the middle */
278 melem->mnext = melem2->mnext;
279 melem2->mnext = melem;
280 }
281
282 return bigmhead;
283 }
284 }
285
getnode(number,seg)286 NODES *getnode(number, seg)
287 int number;
288 seg_ptr seg;
289 {
290 if (seg.type == NORMAL)
291 return ((SEGMENT *)seg.segp)->node[number];
292 else if (seg.type == PSEUDO)
293 return ((PSEUDO_SEG *)seg.segp)->node[number];
294 else
295 bad_seg_type("getnode", seg);
296 }
297
bad_seg_type(name,seg)298 bad_seg_type(name, seg)
299 char *name;
300 seg_ptr seg;
301 {
302 fprintf(stderr, "%s: bad seg type: %d\n",name, seg.type);
303 exit(1);
304 }
305
make_melement(filindex,fil,sign)306 MELEMENT *make_melement(filindex, fil, sign)
307 int filindex, sign;
308 FILAMENT *fil;
309 {
310 MELEMENT *melem;
311
312 melem = (MELEMENT *)MattAlloc(1, sizeof(MELEMENT));
313 melem->filindex = filindex;
314 melem->fil = fil;
315 melem->sign = sign;
316 melem->mnext = NULL;
317
318 return melem;
319 }
320
321 /* this keeps track of the meshes which contain the nodes of the */
322 /* .external statement. This will have a voltage source in them */
323 /* and will need a 1 placed in the RHS corresponding to mesh number 'mesh' */
add_to_external(pseg,mesh,sign,indsys)324 add_to_external(pseg, mesh, sign, indsys)
325 PSEUDO_SEG *pseg;
326 int mesh, sign;
327 SYS *indsys;
328 {
329 EXTERNAL *port;
330 int realsign;
331
332 port = indsys->externals;
333 while(port != NULL && port->source != pseg)
334 port = port->next;
335
336 if (port == NULL) {
337 fprintf(stderr, "Hey, supposed external segment isn't in list\n");
338 exit(1);
339 }
340
341 realsign = -1 * sign; /* since this will be moved to RHS, change its sign */
342
343 port->indices = add_to_int_list(make_int_list(mesh, realsign),
344 port->indices);
345
346 }
347
make_int_list(mesh,sign)348 int_list *make_int_list(mesh, sign)
349 int mesh, sign;
350 {
351 int_list *elem;
352
353 elem = (int_list *)Gmalloc(sizeof(int_list));
354 elem->index = mesh;
355 elem->sign = sign;
356 elem->next = NULL;
357
358 return elem;
359 }
360
add_to_int_list(int_elem,list)361 int_list *add_to_int_list(int_elem, list)
362 int_list *int_elem, *list;
363 {
364 int_elem->next = list;
365 return int_elem;
366 }
367
368 /* makes the Mlist for the groundplane given a plane and parameters defining */
369 /* the current location of the overall Mlist. */
makeMlist(plane,pMlist,pm_info,mstart)370 makeMlist(plane, pMlist, pm_info, mstart)
371 GROUNDPLANE *plane;
372 MELEMENT **pMlist;
373 Minfo *pm_info;
374 int mstart;
375 {
376 MELEMENT *melem;
377 SEGMENT *seg;
378 int counter, i, j, k;
379 int signofelem;
380 int a_hole;
381 SEGMENT ***segs1 = plane->segs1;
382 SEGMENT ***segs2 = plane->segs2;
383
384 counter = 0;
385
386 for(i = 0; i < plane->seg2; i++){
387 for(j = 0; j < plane->seg1; j++){
388
389 if (segs1[j][i] != NULL && segs2[j + 1][i] != NULL
390 && segs1[j][i + 1] != NULL && segs2[j][i]!= NULL) {
391 pMlist[counter] = NULL;
392
393 for(k = 0; k < 4; k++){
394 switch (k) {
395 case 0:
396 seg = plane->segs1[j][i];
397 signofelem = -1.0;
398 break;
399 case 1:
400 seg = plane->segs2[j + 1][i];
401 signofelem = -1.0;
402 break;
403 case 2:
404 seg = plane->segs1[j][i + 1];
405 signofelem = 1.0;
406 break;
407 case 3:
408 seg = plane->segs2[j][i];
409 signofelem = 1.0;
410 break;
411 }
412
413 melem = make_melement(seg->filaments[0].filnumber, &seg->filaments[0],
414 signofelem);
415 pMlist[counter] = insert_in_list(melem, pMlist[counter]);
416
417 }
418 /* unimplemented junk
419 make_unconstrained(&(pm_info[counter]), mstart+counter);
420 */
421 counter++;
422 }
423 }
424 }
425
426 if(counter > plane->numesh){
427 printf("something wrong with meshes, numesh != counter \n");
428 exit(1);
429 }
430
431 return counter;
432
433 }
434
fill_b(ext,b)435 fill_b(ext, b)
436 EXTERNAL *ext;
437 CX *b;
438 {
439 int_list *elem;
440
441 for(elem = ext->indices; elem != NULL; elem = elem->next)
442 b[elem->index].real = elem->sign;
443 }
444
extractYcol(mat,x0,extcol,ext_list)445 extractYcol(mat, x0, extcol, ext_list)
446 CX **mat, *x0;
447 EXTERNAL *extcol, *ext_list;
448 {
449 EXTERNAL *ext;
450 int_list *elem;
451
452 CX sum, tmp;
453
454 for(ext = ext_list; ext != NULL; ext = ext->next) {
455 sum = CXZERO;
456 /* for each mesh that contains this voltage source */
457 for(elem = ext->indices; elem != NULL; elem = elem->next) {
458 cx_scalar_mult(tmp, elem->sign, x0[elem->index]);
459 cx_add(sum, sum, tmp);
460 }
461 mat[ext->Yindex][extcol->col_Yindex] = sum;
462 }
463
464 }
465
get_a_name(pseg)466 char *get_a_name(pseg)
467 PSEUDO_SEG *pseg;
468 {
469 return pseg->node[0]->name;
470 }
471
472 /* we wish to find the first node in a path which is the node of
473 the first segment which is not connected to the second segment */
find_first_node(path)474 NODES *find_first_node(path)
475 SPATH *path;
476 {
477 NODES *node0, *node1;
478 int node1_in_middle;
479 int node0_in_middle;
480
481 node0 = getnode(0, path->seg);
482 node1 = getnode(1, path->seg);
483 if (path->next == NULL) /* there is no other segment */
484 return node0;
485
486 #if 1==0
487 the old way
488
489 replaced for the sake of fixing extra long gp meshes, we must
490 handle a two segment loop more carefully /*
491
492 if (getrealnode(node0) == getrealnode(getnode(0, path->next->seg))
493 || getrealnode(node0) == getrealnode(getnode(1, path->next->seg)) )
494 /* node0 is connected to the next segment, so start with node 1 */
495 return node1;
496 else if (getrealnode(node1) == getrealnode(getnode(0, path->next->seg))
497 || getrealnode(node1) == getrealnode(getnode(1, path->next->seg)) )
498 /* node0 is connected to the next segment, so start with node 1 */
499 return node0;
500 else {
501 fprintf(stderr, "find_first_node: first seg not connected to second\n");
502 exit(1);
503 }
504 #endif
505
506 /* is node0 connected to the next segment? */
507 node0_in_middle =
508 (getrealnode(node0) == getrealnode(getnode(0, path->next->seg))
509 || getrealnode(node0) == getrealnode(getnode(1, path->next->seg)) );
510
511 node1_in_middle =
512 (getrealnode(node1) == getrealnode(getnode(0, path->next->seg))
513 || getrealnode(node1) == getrealnode(getnode(1, path->next->seg)) );
514
515 /* return the node that isn't connecting the first and second segs */
516 if (node1_in_middle && !node0_in_middle)
517 return node0;
518 else if (node0_in_middle && !node1_in_middle)
519 return node1;
520 else if (node0_in_middle && node1_in_middle) {
521 /* this is a two segment loop, so it doesn't matter which
522 we return. But if these are two groundplane segments, perhaps
523 this needs to be shortened to one segment and in order to do so
524 we must determine the connectivity based on original, not real, node
525 name */
526 if (node0 == getnode(0, path->next->seg)
527 || node0 == getnode(1, path->next->seg))
528 return node1;
529 else if (node1 == getnode(0, path->next->seg)
530 || node1 == getnode(1, path->next->seg))
531 return node0;
532 else
533 /* it doesn't matter, both are equiv'd */
534 return node0;
535 }
536 else {
537 fprintf(stderr, "find_first_node: first seg not connected to second\n");
538 exit(1);
539 }
540
541 }
542
makegrids(indsys,Im,column,freq_num)543 makegrids(indsys, Im, column, freq_num)
544 SYS *indsys;
545 CX *Im;
546 int column;
547 {
548 static CX *Ib = NULL, current;
549 int fils, meshes;
550 static CX **out1 = NULL;
551 static CX **out2 = NULL;
552 static maxdir1 = 0, maxdir2 = 0;
553 int dir1, dir2, num, i, j;
554 MELEMENT *mtemp;
555 GROUNDPLANE *p;
556 FILE *fp, *fpreal, *fpimag, *fpmag;
557 static char *fname, *tempstr;
558 SEGMENT *seg;
559 FILAMENT *fil;
560 double xv, yv, zv,x,y,z, magcur;
561
562 fils = indsys->num_fils;
563 meshes = indsys->num_mesh;
564
565 if (Ib == NULL) {
566 Ib = (CX *)MattAlloc(fils, sizeof(CX));
567 fname = malloc(100*sizeof(char));
568 tempstr = malloc(100*sizeof(char));
569 }
570
571 /* do Ib = Mtrans*Im */
572 for(i = 0; i < fils; i++) {
573 Ib[i] = CXZERO;
574 for(mtemp = indsys->Mtrans[i]; mtemp != NULL; mtemp = mtemp->mnext) {
575 if (mtemp->sign == 1)
576 cx_add(Ib[i], Ib[i], Im[mtemp->filindex]);
577 else
578 cx_sub(Ib[i], Ib[i], Im[mtemp->filindex]);
579 }
580 }
581
582 printf("saving to Jreal%s.mat, Jimag%s.mat, Jmag%s.mat\n",
583 indsys->opts->suffix,
584 indsys->opts->suffix,
585 indsys->opts->suffix);
586
587 sprintf(fname, "Jreal%s.mat",indsys->opts->suffix);
588 /* SRW -- this is ascii data */
589 fpreal = fopen(fname,"w");
590 if(fpreal == NULL){
591 printf("couldn't open file %s\n",fname);
592 exit(1);
593 }
594 /* fprintf(fpreal, "$ DATA=VECTOR\n");*/
595
596 sprintf(fname, "Jimag%s.mat",indsys->opts->suffix);
597 /* SRW -- this is ascii data */
598 fpimag = fopen(fname,"w");
599 if(fpimag == NULL){
600 printf("couldn't open file %s\n",fname);
601 exit(1);
602 }
603 /* fprintf(fpimag, "$ DATA=VECTOR\n");*/
604
605 sprintf(fname, "Jmag%s.mat",indsys->opts->suffix);
606 /* SRW -- this is ascii data */
607 fpmag = fopen(fname,"w");
608 if(fpmag == NULL){
609 printf("couldn't open file %s\n",fname);
610 exit(1);
611 }
612 /* fprintf(fpmag, "$ DATA=VECTOR\n");*/
613
614 for(seg = indsys->segment; seg != NULL; seg = seg->next)
615 for(i = 0; i < seg->num_fils; i++) {
616 fil = &(seg->filaments[i]);
617 current = Ib[fil->filnumber];
618 magcur = cx_abs(current);
619 xv = fil->lenvect[XX]/fil->length/fil->area;
620 yv = fil->lenvect[YY]/fil->length/fil->area;
621 zv = fil->lenvect[ZZ]/fil->length/fil->area;
622 x = fil->x[0];
623 y = fil->y[0];
624 z = fil->z[0];
625 fprintf(fpreal, "%lg %lg %lg %lg %lg %lg\n",x,y,z,
626 xv*current.real, yv*current.real, zv*current.real);
627 fprintf(fpimag, "%lg %lg %lg %lg %lg %lg\n",x,y,z,
628 xv*current.imag, yv*current.imag, zv*current.imag);
629 fprintf(fpmag, "%lg %lg %lg %lg %lg %lg\n",x,y,z,
630 xv*magcur, yv*magcur, zv*magcur);
631 }
632
633 fclose(fpreal);
634 fclose(fpimag);
635 fclose(fpmag);
636
637 if (indsys->num_planes == 0)
638 return 0;
639
640 printf("saving to file Grid%s%d_%d...\n",indsys->opts->suffix,
641 column+1,freq_num);
642 sprintf(fname, "Grid%s%d_%d.mat",indsys->opts->suffix,column+1,freq_num);
643
644 /* SRW -- this is binary data */
645 fp = fopen(fname,"wb");
646 if(fp == NULL){
647 printf("couldn't open file %s\n",fname);
648 exit(1);
649 }
650
651 for(num = 0, p = indsys->planes; p != NULL; p = p->next, num++){
652 if (is_nonuni_gp(p))
653 dump_nonuni_plane_currents(p->nonuni, Ib, fp);
654 else {
655 dir1 = p->seg1 + 1;
656 dir2 = p->seg2 + 1;
657
658 if (dir1 > maxdir1 || dir2 > maxdir2) {
659 out1 = (CX **)MatrixAlloc(dir2 + 10, dir1 + 10, sizeof(CX));
660 out2 = (CX **)MatrixAlloc(dir2 + 10, dir1 + 10, sizeof(CX));
661 maxdir1 = dir1 + 10;
662 maxdir2 = dir2 + 10;
663 }
664
665 for(i = 0; i < dir2; i++)
666 for(j = 0; j < dir1; j++) {
667 /* do direction 1 */
668 if(j != dir1 - 1 && p->segs1[j][i] != NULL) {
669 out1[i][j] = Ib[p->segs1[j][i]->filaments[0].filnumber];
670 if (p->segs1[j][i]->node[0] != p->pnodes[j][i]) {
671 printf("You goofed 1\n");
672 }
673 }
674 else
675 out1[i][j] = CXZERO;
676
677 /* do direction 2 */
678 if (i != dir2 - 1 && p->segs2[j][i] != NULL) {
679 out2[i][j] = Ib[p->segs2[j][i]->filaments[0].filnumber];
680 if (p->segs2[j][i]->node[0] != p->pnodes[j][i]) {
681 printf("You goofed 2\n");
682 }
683 }
684 else
685 out2[i][j] = CXZERO;
686 }
687
688 printf("saving grid1%s...\n",p->name);
689 strcpy(fname, "grid1");
690 sprintf(tempstr, "%s",p->name);
691 strcat(fname, tempstr);
692
693 savecmplx(fp, fname, out1, dir2, dir1);
694
695 printf("saving grid2%s...\n",p->name);
696 strcpy(fname, "grid2");
697 sprintf(tempstr, "%s",p->name);
698 strcat(fname,tempstr);
699
700 savecmplx(fp, fname, out2, dir2, dir1);
701 }
702 }
703 fclose(fp);
704 }
705 /*------------------------------------------------------------------------*/
706
707
708
709 #if 1==0
710
711 The following is code that was not implemented and never used and is now
712 obsolete.
713
714 /* this takes a linked list of segments (path) and makes many rows of the */
715 /* mesh matrix out of the filament[0]'s of each segment. */
make_many_meshes_from_path(path,Mlist,m_info,mstart,indsys)716 make_many_meshes_from_path(path, Mlist, m_info, mstart, indsys)
717 SPATH *path;
718 MELEMENT **Mlist;
719 Minfo *m_info;
720 int mstart; /* the mesh index at which to start creating meshes. */
721 SYS *indsys;
722 {
723 SPATH *selem, *temppath, *telem, *minipath;
724 MELEMENT *m1, *m2, *m3, *mlist;
725 NODES *plusnode, *node, *plus2, *node0, *node1;
726 int i, sign, sign2;
727 SEGMENT *seg;
728 PSEUDO_SEG *pseg, *pseg2;
729 int mesh, seg_count;
730 int physically_connected;
731 PSEUDO_SEG *extern_seg;
732 int extern_count, extern_sign;
733
734 mlist = NULL;
735 mesh = 0;
736 minipath = NULL;
737 seg_count = 0;
738 extern_count = 0;
739
740 plusnode = find_first_node(path); /* which node starts the loop */
741 for(selem = path, i = 0; selem != NULL; selem = selem->next, i++) {
742 node0 = getnode(0, selem->seg);
743 node1 = getnode(1, selem->seg);
744 if (getrealnode(plusnode) == getrealnode(node0))
745 sign = 1;
746 else if (getrealnode(plusnode) == getrealnode(node1))
747 sign = -1;
748 else {
749 fprintf(stderr, "make_mesh_from_path: segments don't connect at node %s\n", plusnode->name);
750 exit(1);
751 }
752
753 if (selem->seg.type == NORMAL) {
754 physically_connected = seg_count != 0 && (sign==1 && plusnode == node0
755 || sign==-1 && plusnode==node1);
756 if (physically_connected) {
757 minipath = add_seg_to_list(selem->seg, minipath);
758 seg_count++;
759 }
760 if (!physically_connected || seg_count == FILS_PER_MESH) {
761 Mlist[mstart + mesh] = make_mesh_from_path(minipath, mstart+mesh,
762 indsys);
763 mesh++;
764 reset_vars(&seg_count, &minipath);
765 }
766 }
767 else if (selem->seg.type == PSEUDO) {
768 pseg = (PSEUDO_SEG *)selem->seg.segp;
769
770 if (pseg->type == EXTERNTYPE) {
771 extern_count++;
772 extern_seg = pseg;
773 extern_sign = sign;
774 /* add_to_external(pseg, mesh, sign, indsys); */
775 }
776 else if (pseg->type == GPTYPE) {
777 /* flush any mesh which isn't finished yet */
778 if (seg_count != 0) {
779 Mlist[mstart + mesh] = make_mesh_from_path(minipath, mstart+mesh,
780 indsys);
781 mesh++;
782 reset_vars(&seg_count, &minipath);
783 }
784 while( is_next_seg_in_gp(selem) == TRUE && 1==0) {
785 /* this is an ugly addition to make gp meshes smaller if two segs */
786 /* come from the same gp */
787 selem = selem->next;
788 if (sign == 1) {
789 plusnode = node1;
790 node1 = getothernode(node1, selem->seg);
791 }
792 else {
793 plusnode = node0;
794 node0 = getothernode(node0, selem->seg);
795 }
796 if (indsys->opts->debug == ON)
797 printf("Fixing extra long gp mesh in gp %s, mesh %d.\n",
798 node0->gp->name, mesh);
799 }
800 if (sign == 1) {
801 temppath = path_through_gp(node0, node1, node0->gp);
802 plus2 = node0;
803 }
804 else {
805 temppath = path_through_gp(node1, node0, node0->gp);
806 plus2 = node1;
807 }
808 while(temppath != NULL) {
809 telem = temppath;
810 seg = (SEGMENT *)telem->seg.segp;
811 if (plus2 == seg->node[0])
812 sign2 = 1;
813 else if (plus2 == seg->node[1])
814 sign2 = -1;
815 else {
816 fprintf(stderr, "Hey, path_through_gp made nonconnected path!\n");
817 exit(1);
818 }
819 minipath = add_seg_to_list(selem->seg, minipath);
820 seg_count++;
821 if (seg_count == FILS_PER_MESH) {
822 Mlist[mstart + mesh] = make_mesh_from_path(minipath, mstart+mesh,
823 indsys);
824 mesh++;
825 reset_vars(&seg_count, &minipath);
826 }
827
828 plus2 = getothernode(plus2, telem->seg);
829 temppath = temppath->next;
830 }
831 }
832 else {
833 fprintf(stderr, "make_mesh_from_path: unknown pseudo_seg %d\n",
834 pseg->type);
835 exit(1);
836 }
837 }
838 else {
839 bad_seg_type("make_mesh_from_path", selem->seg);
840 }
841 plusnode = getothernode(plusnode, selem->seg);
842 }
843
844 if (seg_count == FILS_PER_MESH) {
845 Mlist[mstart + mesh] = make_mesh_from_path(minipath, mstart+mesh,
846 indsys);
847 mesh++;
848 reset_vars(&seg_count, &minipath);
849 }
850
851 if (extern_count > 0) {
852 if (extern_count == 1)
853 add_to_external(extern_seg, mstart, extern_sign, indsys);
854 else {
855 fprintf(stderr,"Internal Err: More than one voltage source in a mesh\n");
856 exit(1);
857 }
858 }
859
860 #if 1==0
861 /* only the first mini mesh is unconstrained */
862 make_m_info(&(m_info[0]), UNCONSTRAINED, mstart, mstart, mstart, mesh);
863
864 /* make the second one constrained to the first */
865 if (mesh > 1) {
866 make_m_info(&(m_info[1]), CONSTRAINED, mstart+1, mstart, mstart, mesh);
867 }
868
869 /* The first constrained mesh above will have a current for these */
870 /* i.e., they are constrained to mstart+1 */
871 #endif
872
873 for(i = 0; i < mesh; i++) {
874 make_m_info(&(m_info[i]), CONSTRAINED, mstart+i, -1, mstart,mesh, 0);
875 }
876
877 if (mesh == 0) {
878 fprintf(stderr, "make_many_meshes: No meshes made!\n");
879 exit(1);
880 }
881
882 return mesh;
883 }
884
reset_vars(seg_count,minipath)885 reset_vars(seg_count, minipath)
886 int *seg_count;
887 SPATH **minipath;
888 {
889 *seg_count = 0;
890 free_spath(*minipath);
891 *minipath = NULL;
892 }
893
make_unconstrained(pm_info,mesh)894 make_unconstrained(pm_info, mesh)
895 Minfo *pm_info;
896 int mesh;
897 {
898 make_m_info(pm_info, UNCONSTRAINED, mesh, -1, -1, -1, -1);
899 }
900
make_m_info(pm_info,type,mesh_num,constr_mesh,first,num_meshes,other_mesh)901 make_m_info(pm_info, type, mesh_num, constr_mesh, first, num_meshes,
902 other_mesh)
903 Minfo *pm_info;
904 int type, mesh_num, constr_mesh, first, num_meshes, other_mesh;
905 {
906 pm_info->type = type;
907 pm_info->mesh_num = mesh_num;
908 pm_info->constraining_mesh = constr_mesh;
909 pm_info->first = first;
910 pm_info->num_meshes = num_meshes;
911 pm_info->other_mesh = other_mesh;
912 }
913
pick_unconstrained(Mlist,m_info,total_meshes,big_meshes,num_meshes)914 pick_unconstrained(Mlist, m_info, total_meshes, big_meshes, num_meshes)
915 MELEMENT **Mlist;
916 Minfo *m_info;
917 int num_meshes;
918 int big_meshes;
919 int total_meshes;
920 {
921 Minfo **m_undone, *m_one;
922 int i, j, quit;
923 int counter;
924 int last_undone, undone;
925 int first /*, num_meshes*/;
926
927 counter = 0;
928 m_undone = (Minfo **)Gmalloc(big_meshes*sizeof(Minfo *));
929
930 /* This goes through all the big meshes and picks one representative mesh*/
931 for(i = 0; i < num_mesh; i++) {
932 m_undone[counter++] = &(m_info[i]);
933 i += m_info[i].num_meshes;
934 }
935
936 if (counter != big_meshes) {
937 fprintf(stderr, "Error getting representative meshes\n");
938 exit(1);
939 }
940
941 undone = big_meshes;
942 last_undone = undone + 1;
943
944 while(undone < last_undone) {
945 last_undone = undone;
946
947 /* counts duplicates and saves them in m_undone[i]->other_mesh */
948 count_duplicates(m_undone, undone, Mlist, m_info);
949
950 for(i = 0; i < undone; i++) {
951 first = m_undone[i]->first;
952 num_meshes = m_undone[i]->num_meshes;
953 quit = FALSE;
954 for(j = first; j < first + num_meshes && quit == FALSE; j++) {
955 if (!is_duplicated(m_info[j])) {
956 /* This mesh is unique among minimeshes*/
957 if (is_globally_unique(m_info[j], num_mesh, Mlist, total_meshes)) {
958 quit = TRUE;
959
960 choose_this_mesh(m_undone[i], j, m_info);
961 }
962 }
963 }
964 }
965
966 undone = get_undone(m_undone, undone);
967 }
968
969 /* sort in order of increasing number of minimeshes */
970 /* This is a rock sort. Biggest element falls to the bottom */
971 for(i = 0; i < undone - 1; i++)
972 for(j = 1; j < undone - i; j++)
973 if (m_undone[j-1]->num_meshes > m_undone[j]->num_meshes) {
974 m_one = m_undone[j-1];
975 m_undone[j-1] = m_undone[j];
976 m_undone[j] = m_one;
977 }
978
979 /* Go through all the undone meshes and pick the first available mesh */
980 for(i = 0; i < undone; i++) {
981 first = m_undone[i]->first;
982 num_meshes = m_undone[i]->num_meshes;
983 quit = FALSE;
984 for(j = first; j < first + num_meshes && quit == FALSE; j++) {
985 if (is_locally_unique(m_undone, j, Mlist)) {
986 /* This mesh is unique among other selected */
987 if (is_globally_unique(m_info[j], &(Mlist[num_mesh]),
988 total_meshes - num_mesh)) {
989 quit = TRUE;
990
991 choose_this_mesh(m_undone[i], j, m_info);
992 }
993 }
994 }
995 if (quit == FALSE) {
996 fprintf(stderr, "screwed up!\n");
997 exit(1);
998 }
999 }
1000
1001 }
1002
count_duplicates(m_undone,undone,Mlist,m_info)1003 count_duplicates(m_undone, undone, Mlist, m_info)
1004 Minfo **m_undone, *m_undone;
1005 int undone;
1006 MELEMENT **Mlist;
1007 {
1008 int i,j,k,m;
1009 Minfo *m_one;
1010 int first_s, num_meshes_s, first_t, num_meshes_t;
1011
1012 for(i = 0; i < undone; i++) {
1013 first_s = m_undone[i]->first;
1014 num_meshes_s = m_undone[i]->num_meshes;
1015 for(j = first_s; j < first_s + num_meshes_s; j++) {
1016 for(k = 0; k < undone; k++) {
1017 first_t = m_undone[i]->first;
1018 num_meshes_t = m_undone[i]->num_meshes;
1019 for(m = first_t; m < first_t + num_meshes_t; m++)
1020 if(mesh_comp(Mlist[j], Mlist[m]) == TRUE) {
1021 m_info[j].other_mesh += 1;
1022 if (j != m)
1023 m_info[m].other_mesh += 1;
1024 }
1025 }
1026 }
1027 if (m_info[j].other_mesh == 0) {
1028 fprintf(stderr, "Huh? mesh isn't identical to itself?\n");
1029 exit(1);
1030 }
1031 }
1032 }
1033
mesh_comp(m1,m2)1034 mesh_comp(m1, m2)
1035 MELEMENT *m1, *m2;
1036 {
1037 int same;
1038
1039 same = TRUE;
1040 while(m1 != NULL && m2 != NULL && same == TRUE) {
1041 if (m1->filindex != m2->filindex)
1042 same = FALSE;
1043 else {
1044 m1 = m1->next;
1045 m2 = m2->next;
1046 }
1047
1048
1049 if (m1 != NULL || m2 != NULL)
1050 same = FALSE;
1051
1052 return same;
1053 }
1054
1055 is_duplicated(m_one)
1056 Minfo m_one;
1057 {
1058 return (m_one.other_mesh != 1);
1059 }
1060
1061 is_globally_unique(m_one, minimeshes, Mlist, num_mesh)
1062 Minfo m_one;
1063 MELEMENT **Mlist;
1064 int num_mesh, minimeshes;
1065 {
1066 int unique = TRUE;
1067 int i,j;
1068
1069 for(i = minimeshes; i < num_mesh && unique == TRUE; i++)
1070 if (mesh_comp(Mlist[m_one.mesh_num], Mlist[i]) == TRUE)
1071 unique = FALSE;
1072
1073 return unique;
1074 }
1075
1076 choose_this_mesh(m_begin, constraining_mesh, m_info)
1077 Minfo *m_begin, *m_info;
1078 int constraining_mesh;
1079 {
1080 int other_mesh = -1;
1081 int num_dups = 1000000;
1082
1083 m_info[constraining_mesh] = UNCONSTRAINED;
1084
1085 /* find a good other_mesh */
1086 for(i = m_begin->first; i < m_begin->first + m_begin->num_meshes; i++)
1087 if (i != constraining_mesh)
1088 if (m_info[i].other_mesh < num_dups) {
1089 other_mesh = i;
1090 num_dups = m_info[i].other_mesh;
1091 }
1092
1093 if (m_begin->num_meshes != 1) {
1094 if (other_mesh == -1) {
1095 fprintf(stderr, "Huh? other_mesh == -1?\n");
1096 exit(1);
1097 }
1098 for(i = m_begin->first; i < m_begin->first + m_begin->num_meshes; i++) {
1099 m_info[i].constraining_mesh = constraining_mesh;
1100 m_info[i].other_mesh = other_mesh;
1101 }
1102 }
1103 }
1104
1105 /* get all the remaining undone big meshes based on constraing_mesh still -1*/
1106 get_undone(m_undone, undone)
1107 Minfo **m_undone;
1108 int undone;
1109 {
1110 int i, new_undone;
1111
1112 new_undone = 0;
1113 for(i = 0; i < undone; i++)
1114 if (m_undone[i]->constraining_mesh == -1)
1115 m_undone[new_undone++] = m_undone[i];
1116
1117 return new_undone;
1118 }
1119
1120 is_locally_unique(m_undone, mini_mesh, Mlist)
1121 Minfo **m_undone;
1122 int mini_mesh;
1123 MELEMENT **Mlist;
1124 {
1125 int i, k;
1126 int unique = TRUE;
1127
1128 for(i = 0; i < j && unique == TRUE; i++)
1129 if (mesh_comp(Mlist[j], Mlist[m_undone[i]->constraining_mesh]) == TRUE)
1130 unique = FALSE;
1131
1132 return unique;
1133 }
1134
1135 #endif
1136
1137