1 /*
2 Copyright (c) 1990 Massachusetts Institute of Technology, Cambridge, MA.
3 All rights reserved.
4
5 This Agreement gives you, the LICENSEE, certain rights and obligations.
6 By using the software, you indicate that you have read, understood, and
7 will comply with the terms.
8
9 Permission to use, copy and modify for internal, noncommercial purposes
10 is hereby granted. Any distribution of this program or any part thereof
11 is strictly prohibited without prior written consent of M.I.T.
12
13 Title to copyright to this software and to any associated documentation
14 shall at all times remain with M.I.T. and LICENSEE agrees to preserve
15 same. LICENSEE agrees not to make any copies except for LICENSEE'S
16 internal noncommercial use, or to use separately any portion of this
17 software without prior written consent of M.I.T. LICENSEE agrees to
18 place the appropriate copyright notice on any such copies.
19
20 Nothing in this Agreement shall be construed as conferring rights to use
21 in advertising, publicity or otherwise any trademark or the name of
22 "Massachusetts Institute of Technology" or "M.I.T."
23
24 M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. By
25 way of example, but not limitation, M.I.T. MAKES NO REPRESENTATIONS OR
26 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR
27 THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS OR DOCUMENTATION WILL
28 NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
29 M.I.T. shall not be held liable for any liability nor for any direct,
30 indirect or consequential damages with respect to any claim by LICENSEE
31 or any third party on account of or arising from this Agreement or use
32 of this software.
33 */
34
35 #include "mulGlobal.h"
36 #include "zbufGlobal.h"
37
disExtrasimpcube(pc)38 disExtrasimpcube(pc)
39 cube *pc;
40 {
41 printf("cubes[%d][%d][%d][%d]\n", pc->level, pc->j, pc->k, pc->l);
42 }
43
disExParsimpcube(pc)44 disExParsimpcube(pc)
45 cube *pc;
46 {
47 cube *pa = pc->parent;
48 printf("cubes[%d][%d][%d][%d], ", pc->level, pc->j, pc->k, pc->l);
49 printf("parent = cubes[%d][%d][%d][%d]\n", pa->level, pa->j, pa->k, pa->l);
50 }
51
dissimpcube(pc)52 dissimpcube(pc)
53 cube *pc;
54 {
55 int i;
56 printf("cube center: x=%g y=%g z=%g\n", pc->x, pc->y, pc->z);
57 printf("index=%d dindex=%d level=%d loc_exact=%d mul_exact=%d numkids=%d\n",
58 pc->index, pc->dindex, pc->level,
59 pc->loc_exact, pc->mul_exact, pc->numkids);
60 printf("numnbrs=%d upnumvects=%d directnumvects=%d downnumvects=%d\n",
61 pc->numnbrs, pc->upnumvects, pc->directnumvects, pc->downnumvects);
62 }
63
discube(pc)64 discube(pc)
65 cube *pc;
66 {
67 int i;
68 printf("cube center: x=%g y=%g z=%g\n", pc->x, pc->y, pc->z);
69 printf("index=%d dindex=%d level=%d loc_exact=%d mul_exact=%d numkids=%d\n",
70 pc->index, pc->dindex, pc->level,
71 pc->loc_exact, pc->mul_exact, pc->numkids);
72 printf("numnbrs=%d upnumvects=%d directnumvects=%d downnumvects=%d\n",
73 pc->numnbrs, pc->upnumvects, pc->directnumvects, pc->downnumvects);
74 if(pc->directnumvects > 0) {
75 printf("num of elements in ");
76 for(i=0; i < pc->directnumvects; i++) {
77 printf("v%d = %d ", i, pc->directnumeles[i]);
78 }
79 printf("\nchgs\n");
80 for(i=0; i < pc->directnumeles[0]; i++) {
81 dischg(pc->chgs[i]);
82 }
83 }
84 if(pc->downnumvects > 0) {
85 printf("num of down elements in ");
86 for(i=0; i < pc->downnumvects; i++) {
87 printf("v%d = %d ", i, pc->downnumeles[i]);
88 }
89 }
90 }
91
disupcube(pc)92 disupcube(pc)
93 cube *pc;
94 {
95
96
97 }
98
disdirectcube(pc)99 disdirectcube(pc)
100 cube *pc;
101 {
102 int i;
103 for(i=0; i < pc->directnumvects; i++) {
104 printf("matrix %d\n", i);
105 dismat(pc->directmats[i], pc->directnumeles[0], pc->directnumeles[i]);
106 if(i==0) {
107 printf("lu factored matrix\n");
108 dismat(pc->directlu, pc->directnumeles[0], pc->directnumeles[i]);
109 }
110 }
111 }
112
113
dissys(sys)114 dissys(sys)
115 ssystem *sys;
116 {
117 int i, j, k, l, side;
118 printf("side=%d depth=%d order=%d\n",
119 sys->side, sys->depth, sys->order);
120 printf("Cube corner is x=%g y=%g z=%g\n", sys->minx, sys->miny, sys->minz);
121 printf("Cube side length= %g\n", sys->length);
122 printf("Printing all the cubes\n");
123 for(i = 0, side = 1; i <= sys->depth; i++, side *= 2) {
124 for(j=0; j < side; j++) {
125 for(k=0; k < side; k++) {
126 for(l=0; l < side; l++) {
127 fprintf(stdout, "\ncubes[%d][%d][%d][%d]\n", i, j, k, l);
128 dissimpcube(&(sys->cubes[i][j][k][l]));
129 /* disdirectcube(&(sys->cubes[i][j][k][l])); */
130 }
131 }
132 }
133 }
134 }
135
136
137
dismat(mat,rows,cols)138 dismat(mat, rows, cols)
139 double **mat;
140 int rows, cols;
141 {
142 int i,j;
143 if(cols != 0) {
144 for(i=0; i < rows; i++) {
145 printf("\n i=%d\n", i);
146 for(j=0; j < cols; j++) {
147 printf("%d %g ", j, mat[i][j]);
148 if(((j+1) % 5) == 0) printf("\n");
149 }
150 }
151 printf("\n");
152 }
153 }
154
155
disvect(v,size)156 disvect(v, size)
157 double *v;
158 int size;
159 {
160 int i;
161 for(i=0; i < size; i++) {
162 printf("i=%d %g ", i, v[i]);
163 if(((i+1) % 5) == 0) printf("\n");
164 }
165 printf("\n");
166 }
167
dischg(pq)168 dischg(pq)
169 charge *pq;
170 {
171 printf("cond=%d index=%d\n", pq->cond, pq->index);
172 }
173
disallchg(pq)174 disallchg(pq)
175 charge *pq;
176 {
177 charge *nq;
178 for(nq = pq; nq != NULL; nq = nq->next) disfchg(pq);
179 }
180
disfchg(pq)181 disfchg(pq)
182 charge *pq;
183 {
184 /*
185 printf("Cond=%d Corners\n", pq->cond);
186 printf("x0=%g y0=%g z0=%g\n", pq->x0, pq->y0, pq->z0);
187 printf("x1=%g y1=%g z1=%g\n", pq->x1, pq->y1, pq->z1);
188 printf("x2=%g y2=%g z2=%g\n", pq->x2, pq->y2, pq->z2);
189 printf("x3=%g y3=%g z3=%g\n", pq->x3, pq->y3, pq->z3);
190 printf("Center\n");
191 printf("x=%g y=%g z=%g\n", pq->x, pq->y, pq->z);
192 */
193 }
194
195 /*
196 dumps a rows x cols matrix of doubles; assumes indices from zero
197 */
dumpMat(mat,rows,cols)198 void dumpMat(mat, rows, cols)
199 int rows, cols;
200 double **mat;
201 {
202 int i, j;
203 for(i = 0; i < rows; i++) {
204 fprintf(stdout, " row%d ", i);
205 for(j = 0; j < cols; j++) {
206 if(mat[i][j] < 0.0) fprintf(stdout, "%.5e ", mat[i][j]);
207 else fprintf(stdout, " %.5e ", mat[i][j]);
208 }
209 fprintf(stdout, "\n");
210 }
211 }
212
213 /*
214 dumps a rows x cols matrix of doubles; assumes indices from zero
215 */
dumpCorners(fp,mat,rows,cols)216 void dumpCorners(fp, mat, rows, cols)
217 int rows, cols;
218 double **mat;
219 FILE *fp;
220 {
221 int i, j;
222 for(i = 0; i < rows; i++) {
223 fprintf(fp, " corner%d ", i);
224 for(j = 0; j < cols; j++) {
225 if(mat[i][j] < 0.0) fprintf(fp, "%.5e ", mat[i][j]);
226 else fprintf(fp, " %.5e ", mat[i][j]);
227 }
228 fprintf(fp, "\n");
229 }
230 }
231
232 /*
233 dumps a vector of itegers along side a vector of doubles, index from zero
234 */
dumpVecs(dblvec,intvec,size)235 void dumpVecs(dblvec, intvec, size)
236 double *dblvec;
237 int *intvec, size;
238 {
239 int i;
240
241 for(i = 0; i < size; i++) {
242 fprintf(stdout, "%d %d %g\n", i, intvec[i], dblvec[i]);
243 }
244 }
245
246 /*
247 dumps the relative coordinates of an array of charges or evaluation pnts
248 */
dumpChgs(chgs,numchgs,x,y,z)249 void dumpChgs(chgs, numchgs, x, y, z)
250 int numchgs;
251 double x, y, z;
252 charge **chgs;
253 {
254 int i;
255 double rho, cosA, beta;
256 for(i = 0; i < numchgs; i++) {
257 xyz2sphere(chgs[i]->x, chgs[i]->y, chgs[i]->z,
258 x, y, z, &rho, &cosA, &beta);
259 fprintf(stdout, " %d %d ", chgs[i]->index, chgs[i]->cond);
260 if(rho < 0) fprintf(stdout, "(%.5e ", rho);
261 else fprintf(stdout, "( %.5e ", rho);
262 if(cosA < 0) fprintf(stdout, "%.5e ", cosA);
263 else fprintf(stdout, " %.5e ", cosA);
264 if(beta < 0) fprintf(stdout, "%.5e) ", beta);
265 else fprintf(stdout, " %.5e) ", beta);
266 if(x < 0) fprintf(stdout, "(%.5e ", chgs[i]->x);
267 else fprintf(stdout, "( %.5e ", chgs[i]->x);
268 if(y < 0) fprintf(stdout, "%.5e ", chgs[i]->y);
269 else fprintf(stdout, " %.5e ", chgs[i]->y);
270 if(z < 0) fprintf(stdout, "%.5e)\n", chgs[i]->z);
271 else fprintf(stdout, " %.5e)\n", chgs[i]->z);
272 }
273 }
274
275 /*
276 dumps the relative coordinates of an array of charges or evaluation pnts
277 - also dumps dummy bit
278 */
dumpChgsWDummy(chgs,numchgs,is_dummy,x,y,z)279 void dumpChgsWDummy(chgs, numchgs, is_dummy, x, y, z)
280 int numchgs, *is_dummy;
281 double x, y, z;
282 charge **chgs;
283 {
284 int i;
285 double rho, cosA, beta;
286 for(i = 0; i < numchgs; i++) {
287 xyz2sphere(chgs[i]->x, chgs[i]->y, chgs[i]->z,
288 x, y, z, &rho, &cosA, &beta);
289 fprintf(stdout, " %d %d(%d) %d ", chgs[i]->index, is_dummy[i],
290 chgs[i]->dummy, chgs[i]->cond);
291 if(rho < 0) fprintf(stdout, "(%.5e ", rho);
292 else fprintf(stdout, "( %.5e ", rho);
293 if(cosA < 0) fprintf(stdout, "%.5e ", cosA);
294 else fprintf(stdout, " %.5e ", cosA);
295 if(beta < 0) fprintf(stdout, "%.5e) ", beta);
296 else fprintf(stdout, " %.5e) ", beta);
297 if(x < 0) fprintf(stdout, "(%.5e ", chgs[i]->x);
298 else fprintf(stdout, "( %.5e ", chgs[i]->x);
299 if(y < 0) fprintf(stdout, "%.5e ", chgs[i]->y);
300 else fprintf(stdout, " %.5e ", chgs[i]->y);
301 if(z < 0) fprintf(stdout, "%.5e)\n", chgs[i]->z);
302 else fprintf(stdout, " %.5e)\n", chgs[i]->z);
303 }
304 }
305
306 /*
307 display the matrix built for a given charge to multipole transformation
308 */
dispQ2M(mat,chgs,numchgs,x,y,z,order)309 void dispQ2M(mat, chgs, numchgs, x, y, z, order)
310 int numchgs, order;
311 double **mat, x, y, z;
312 charge **chgs;
313 {
314 fprintf(stdout, "\nQ2M MATRIX: cube at (%.5e %.5e %.5e)\n", x, y, z);
315 dumpMat(mat, multerms(order), numchgs);
316 fprintf(stdout,
317 " CHARGES IN CUBE # cond (rho_i cos(alpha_i) beta_i) (x y z):\n");
318 dumpChgs(chgs, numchgs, x, y, z);
319 }
320
321 /*
322 display the matrix built for a given multipole to local transformation
323 */
dispM2L(mat,x,y,z,xp,yp,zp,order)324 void dispM2L(mat, x, y, z, xp, yp, zp, order)
325 int order;
326 double **mat, x, y, z, xp, yp, zp;
327 {
328 fprintf(stdout,
329 "\nM2L MATRIX: multi at (%.5e %.5e %.5e) -> local at (%.5e %.5e %.5e)\n",
330 x, y, z, xp, yp, zp);
331 dumpMat(mat, multerms(order), multerms(order));
332 }
333
334 /*
335 display the matrix built for a given charge to local transformation
336 */
dispQ2L(mat,chgs,numchgs,x,y,z,order)337 void dispQ2L(mat, chgs, numchgs, x, y, z, order)
338 int numchgs, order;
339 double **mat, x, y, z;
340 charge **chgs;
341 {
342 fprintf(stdout, "\nQ2L MATRIX: cube at (%.5e %.5e %.5e)\n", x, y, z);
343 dumpMat(mat, multerms(order), numchgs);
344 fprintf(stdout,
345 " CHARGES IN CUBE # cond (rho_i cos(alpha_i) beta_i) (x y z):\n");
346 dumpChgs(chgs, numchgs, x, y, z);
347 }
348
349 /*
350 display the matrix built for a given charge to potential transformation
351 */
dispQ2P(mat,chgs,numchgs,is_dummy,pchgs,numpchgs)352 void dispQ2P(mat, chgs, numchgs, is_dummy, pchgs, numpchgs)
353 int numchgs, numpchgs, *is_dummy;
354 double **mat;
355 charge **chgs, **pchgs;
356 {
357 fprintf(stdout, "\nQ2P MATRIX:\n");
358 dumpMat(mat, numpchgs, numchgs);
359 fprintf(stdout,
360 " PANELS IN CUBE # dummy(real) cond (rho_i cos(alpha_i) beta_i) (x y z):\n");
361 dumpChgsWDummy(chgs, numchgs, is_dummy, 0.0, 0.0, 0.0);
362 fprintf(stdout,
363 " EVALS IN CUBE # cond (rho_i cos(alpha_i) beta_i) (x y z):\n");
364 dumpChgs(pchgs, numpchgs, 0.0, 0.0, 0.0);
365 }
366
367 /*
368 display the matrix built for a given charge to potential transformation
369 */
dispQ2PDiag(mat,chgs,numchgs,is_dummy)370 void dispQ2PDiag(mat, chgs, numchgs, is_dummy)
371 int numchgs, *is_dummy;
372 double **mat;
373 charge **chgs;
374 {
375 fprintf(stdout, "\nQ2PDiag MATRIX:\n");
376 dumpMat(mat, numchgs, numchgs);
377 fprintf(stdout,
378 " PANELS IN CUBE # dummy(real) cond (rho_i cos(alpha_i) beta_i) (x y z):\n");
379 dumpChgsWDummy(chgs, numchgs, is_dummy, 0.0, 0.0, 0.0);
380 }
381
382 /*
383 display the matrix built for a given multipole to multipole transformation
384 */
dispM2M(mat,x,y,z,xp,yp,zp,order)385 void dispM2M(mat, x, y, z, xp, yp, zp, order)
386 int order;
387 double **mat, x, y, z, xp, yp, zp;
388 {
389 fprintf(stdout,
390 "\nM2M MATRIX: cube at (%.5e %.5e %.5e) shifted to (%.5e %.5e %.5e)\n",
391 x, y, z, xp, yp, zp);
392 dumpMat(mat, multerms(order), multerms(order));
393 }
394
395 /*
396 display the matrix built for a given local to local transformation
397 */
dispL2L(mat,x,y,z,xp,yp,zp,order)398 void dispL2L(mat, x, y, z, xp, yp, zp, order)
399 int order;
400 double **mat, x, y, z, xp, yp, zp;
401 {
402 fprintf(stdout,
403 "\nL2L MATRIX: cube at (%.5e %.5e %.5e) shifted to (%.5e %.5e %.5e)\n",
404 x, y, z, xp, yp, zp);
405 dumpMat(mat, multerms(order), multerms(order));
406 }
407
408 /*
409 display the matrix built for a given multipole to potential transformation
410 */
dispM2P(mat,x,y,z,chgs,numchgs,order)411 void dispM2P(mat, x, y, z, chgs, numchgs, order)
412 int numchgs, order;
413 double **mat, x, y, z;
414 charge **chgs;
415 {
416 fprintf(stdout, "\nM2P MATRIX: cube at (%.5e %.5e %.5e)\n", x, y, z);
417 dumpMat(mat, numchgs, multerms(order));
418 fprintf(stdout,
419 " EVAL PNTS IN CUBE # cond (rho_i, cos(alpha_i), beta_i):\n");
420 dumpChgs(chgs, numchgs, x, y, z);
421 }
422
423 /*
424 display the matrix built for a given local to potential transformation
425 */
dispL2P(mat,x,y,z,chgs,numchgs,order)426 void dispL2P(mat, x, y, z, chgs, numchgs, order)
427 int numchgs, order;
428 double **mat, x, y, z;
429 charge **chgs;
430 {
431 fprintf(stdout, "\nL2P MATRIX: cube at (%.5e %.5e %.5e)\n", x, y, z);
432 dumpMat(mat, numchgs, multerms(order));
433 fprintf(stdout,
434 " EVAL PNTS IN CUBE # cond (rho_i, cos(alpha_i), beta_i):\n");
435 dumpChgs(chgs, numchgs, x, y, z);
436 }
437
438 /*
439 displays upward pass and moment vectors associated with a cube - debug only
440 */
dumpUpVecs(pc)441 void dumpUpVecs(pc)
442 cube *pc;
443 {
444 int i, j;
445 fprintf(stdout,
446 "\nUPWARD PASS/MOMENT VECTORS, LEVEL %d CUBE AT (%.5e %.5e %.5e):\n",
447 pc->level, pc->x, pc->y, pc->z);
448 for(i = 0; i < pc->upnumvects; i++) {
449 fprintf(stdout, "%d", i);
450 for(j = 0; j < pc->upnumeles[i]; j++) {
451 if(pc->upvects[i][j] < 0.0)
452 fprintf(stdout, " %.5e", pc->upvects[i][j]);
453 else fprintf(stdout, " %.5e", pc->upvects[i][j]);
454 }
455 fprintf(stdout, "\n");
456 }
457 fprintf(stdout, "M");
458 for(j = 0; j < pc->multisize; j++) {
459 if(pc->multi[j] < 0.0) fprintf(stdout, " %.5e", pc->multi[j]);
460 else fprintf(stdout, " %.5e", pc->multi[j]);
461 }
462 fprintf(stdout, "\n");
463 }
464
465 /*
466 displays the upward pass vectors for the eight level 1 cubes - debug only
467 */
dumpLevOneUpVecs(sys)468 void dumpLevOneUpVecs(sys)
469 ssystem *sys;
470 {
471 int i, j, k;
472 cube *****cubes = sys->cubes;
473 for(i = 0; i < 2; i++) {
474 for(j = 0; j < 2; j++) {
475 for(k = 0; k < 2; k++) {
476 if(cubes[1][i][j][k] != NULL) dumpUpVecs(cubes[1][i][j][k]);
477 }
478 }
479 }
480 }
481
482 /*
483 checks a cube (direct, local or eval) list for bad cube structs - debug only
484 -- doesn't quite do this - always uses direct list for one thing
485 */
chkList(sys,listtype)486 void chkList(sys, listtype)
487 ssystem *sys;
488 int listtype; /* DIRECT, LOCAL or EVAL */
489 {
490 int cnt[BUFSIZ]; /* # of cubes processed by level */
491 int depth = sys->depth;
492 int lev, nn;
493 int i, j, k;
494 cube *nc;
495 for(i = 0; i <= depth; i++) cnt[i] = 0;
496 nc = sys->directlist;
497 while(nc != NULL) {
498 /* check number and level of neighbors */
499 lev = nc->level;
500 nn = nc->numnbrs;
501 for(i = 0; i < nn; i++) {
502 if(lev != ((nc->nbrs)[i])->level) {
503 fprintf(stderr, "chkList: level %d cube has a level %d nbr\n", lev,
504 ((nc->nbrs)[i])->level);
505 fprintf(stderr, " ok cubes ");
506 for(j = 0; j <= depth; j++) fprintf(stderr, "lev%d: %d ", j, cnt[j]);
507 fprintf(stderr, "\n");
508 exit(1);
509 }
510 }
511 /* check number of kids */
512 if(lev == depth && nc->numkids != 0) {
513 fprintf(stderr, "chkList: level %d cube has children\n", lev);
514 fprintf(stderr, " ok cubes ");
515 for(j = 0; j <= depth; j++) fprintf(stderr, "lev%d: %d ", j, cnt[j]);
516 fprintf(stderr, "\n");
517 exit(1);
518 }
519 /* if lowest level, check status of eval and direct vects */
520 if(lev == depth) {
521 if(nc->dindex == 0 || nc->directnumeles == NULL) {
522 fprintf(stderr, "chkList: level %d cube has bad direct info\n", lev);
523 fprintf(stderr, " ok cubes ");
524 for(j = 0; j <= depth; j++) fprintf(stderr, "lev%d: %d ", j, cnt[j]);
525 fprintf(stderr, "\n");
526 exit(1);
527 }
528 if(nc->evalnumvects == 0 && listtype == EVAL) {
529 fprintf(stderr, "chkList: level %d cube has no eval info\n", lev);
530 fprintf(stderr, " ok cubes ");
531 for(j = 0; j <= depth; j++) fprintf(stderr, "lev%d: %d ", j, cnt[j]);
532 fprintf(stderr, "\n");
533 exit(1);
534 }
535 }
536 cnt[lev]++;
537 if(listtype == DIRECT) nc = nc->dnext;
538 else if(listtype == LOCAL) nc = nc->lnext;
539 else if(listtype == EVAL) nc = nc->enext;
540 else {
541 fprintf(stderr, "chkList: bad flag\n");
542 exit(1);
543 }
544 }
545 if(listtype == DIRECT) fprintf(stdout, "\nDirect ");
546 else if(listtype == LOCAL) fprintf(stdout, "\nLocal ");
547 else fprintf(stdout, "\nEval ");
548 fprintf(stdout, "list ok: ");
549 for(j = 0; j <= depth; j++) fprintf(stdout, "lev%d: %d ", j, cnt[j]);
550 fprintf(stdout, "\n\n");
551 }
552
553 /*
554 chks a cube for bad cube struct (direct, local or eval) entries - debug only
555 */
chkCube(sys,nc,listtype)556 void chkCube(sys, nc, listtype)
557 ssystem *sys;
558 cube *nc;
559 int listtype; /* DIRECT, LOCAL or EVAL */
560 {
561 int depth = sys->depth;
562 int lev, nn;
563 int i, j, k;
564 if(nc != NULL) {
565 /* check number and level of neighbors */
566 lev = nc->level;
567 nn = nc->numnbrs;
568 for(i = 0; i < nn; i++) {
569 if(lev != ((nc->nbrs)[i])->level) {
570 fprintf(stdout, "chkCube: level %d cube has a level %d nbr\n", lev,
571 ((nc->nbrs)[i])->level);
572 /* exit(1);*/
573 }
574 }
575 /* check number of kids */
576 if(lev == depth && nc->numkids != 0) {
577 fprintf(stdout, "chkCube: level %d cube has children\n", lev);
578 /* exit(1);*/
579 }
580 /* if lowest level, check status of eval and direct vects */
581 if(lev == depth) {
582 if(nc->dindex == 0) {
583 fprintf(stdout, "chkCube: level %d cube has zero direct index\n", lev);
584 /* exit(1);*/
585 }
586 if(nc->directnumeles == NULL) {
587 fprintf(stdout,
588 "chkCube: level %d cube has NULL directnumeles\n", lev);
589 /* exit(1);*/
590 }
591 if(nc->evalnumvects == 0 && listtype == EVAL) {
592 fprintf(stdout, "chkCube: level %d cube has no eval info\n", lev);
593 /* exit(1);*/
594 }
595 if(nc->eval == NULL && listtype == EVAL) {
596 fprintf(stdout, "chkCube: level %d cube has no eval pntr\n", lev);
597 }
598 }
599 }
600 }
601
602 /*
603 checks the lowest level cubes for trouble using chkCube - debug only
604 */
chkLowLev(sys,listtype)605 void chkLowLev(sys, listtype)
606 ssystem *sys;
607 int listtype; /* DIRECT, LOCAL or EVAL */
608 {
609 int i, j, k, l, side, depth = sys->depth, cnt = 0;
610 cube *nc, *****cubes = sys->cubes;
611 for(i = 1, side = 1; i <= depth; i++, side *= 2);
612 for(j=0; j < side; j++) { /* loop through all cubes at level depth */
613 for(k=0; k < side; k++) {
614 for(l=0; l < side; l++) {
615 nc = cubes[depth][j][k][l];
616 if(nc != NULL) {
617 chkCube(sys, nc, listtype);
618 cnt++;
619 }
620 }
621 }
622 }
623 fprintf(stdout,"Total lowest level (level %d) cubes checked = %d\n",
624 depth, cnt);
625 }
626
627 /*
628 dump the contents of a face struct
629 */
dump_face(fp,fac)630 void dump_face(fp, fac)
631 face *fac;
632 FILE *fp;
633 {
634 int i, j;
635 face **behind = fac->behind;
636
637 fprintf(fp, "Face %d, %d sides, depth %d, mark %d, greylev %d\n",
638 fac->index, fac->numsides, fac->depth, fac->mark, fac->greylev);
639 fprintf(fp, " plane: n = (%g %g %g) rhs = %g\n",
640 fac->normal[0], fac->normal[1], fac->normal[2], fac->rhs);
641 fprintf(fp, " behind [depth(index)]:");
642 for(i = 0; i < fac->numbehind; i++) {
643 fprintf(fp, " %d(%d)", behind[i]->depth, behind[i]->index);
644 if(i % 10 == 0 && i != 0) fprintf(fp, "\n");
645 }
646 i--;
647 if(!(i % 10 && i != 0)) fprintf(fp, "\n");
648 fprintf(fp, " Corners\n");
649 dumpCorners(fp, fac->c, fac->numsides, 3);
650 }
651
652 /*
653 core display routine used below
654 */
dumpSynCore1(str,depth,fcnt,excnt,emcnt,tcnt)655 void dumpSynCore1(str, depth, fcnt, excnt, emcnt, tcnt)
656 int depth, *fcnt, *excnt, *emcnt, *tcnt;
657 char *str;
658 {
659 int i;
660 fprintf(stdout, "%-13s", str);
661 for(i = 0; i <= depth; i++) {
662 sprintf(str, "%d/%d/%d/%d ", fcnt[i], excnt[i], emcnt[i], tcnt[i]);
663 if(i < 2) fprintf(stdout, "%8s", str);
664 else if(i == 2) fprintf(stdout, "%12s", str);
665 else if(i == 3) fprintf(stdout, "%16s", str);
666 else if(i == 4) fprintf(stdout, "%20s", str);
667 else if(i == 5) fprintf(stdout, "%24s", str);
668 else fprintf(stdout, "%28s", str);
669 }
670 fprintf(stdout, "\n");
671 }
672 /*
673 core display rtn used below
674 */
dumpSynCore2(str,depth,cnt)675 dumpSynCore2(str, depth, cnt)
676 int depth, *cnt;
677 char *str;
678 {
679 int i;
680
681 fprintf(stdout, "%-13s", str);
682 for(i = 0; i <= depth; i++) {
683 sprintf(str, "%d ", cnt[i]);
684 if(i < 2) fprintf(stdout, "%8s", str);
685 else if(i == 2) fprintf(stdout, "%12s", str);
686 else if(i == 3) fprintf(stdout, "%16s", str);
687 else if(i == 4) fprintf(stdout, "%20s", str);
688 else if(i == 5) fprintf(stdout, "%24s", str);
689 else fprintf(stdout, "%28s", str);
690 }
691 fprintf(stdout, "\n");
692 }
693
694 /*
695 displays number of exact, full, empty and total cubes per level in
696 all cubes, and eval, direct, multi and local lists
697 */
dumpSynop(sys)698 void dumpSynop(sys)
699 ssystem *sys;
700 {
701 int i, j, k, l, side, depth = sys->depth, lev;
702 int excnt[BUFSIZ], fcnt[BUFSIZ], emcnt[BUFSIZ], tcnt[BUFSIZ];
703 extern int *multicnt, *localcnt;
704 char str[BUFSIZ];
705 cube *****cubes = sys->cubes, *nc;
706
707 for(i = 0; i <= depth; i++) excnt[i] = fcnt[i] = emcnt[i] = tcnt[i] = 0;
708
709 fprintf(stdout,
710 "\nCUBE AND EXPANSION SYNOPSIS (full/mul_exact/empty/ttl):\n");
711 fprintf(stdout, " ");
712 for(i = 0; i <= depth; i++) {
713 sprintf(str, "level%d ", i);
714 if(i < 2) fprintf(stdout, "%8s", str);
715 else if(i == 2) fprintf(stdout, "%12s", str);
716 else if(i == 3) fprintf(stdout, "%16s", str);
717 else if(i == 4) fprintf(stdout, "%20s", str);
718 else if(i == 5) fprintf(stdout, "%24s", str);
719 else fprintf(stdout, "%28s", str);
720 }
721 fprintf(stdout, "\n");
722 /* dump cube usage by level */
723 for(i = 0, side = 1; i <= depth; i++, side *= 2) {
724 for(j=0; j < side; j++) { /* loop through all cubes at levels >= 0 */
725 for(k=0; k < side; k++) {
726 for(l=0; l < side; l++) {
727 nc = cubes[i][j][k][l];
728 tcnt[i]++;
729 if(nc != NULL) {
730 lev = nc->level;
731 fcnt[i]++;
732 if(nc->mul_exact == TRUE) excnt[i]++;
733 }
734 else emcnt[i]++;
735 }
736 }
737 }
738 }
739 sprintf(str, "All cubes");
740 dumpSynCore1(str, depth, fcnt, excnt, emcnt, tcnt);
741
742 for(i = 0; i <= depth; i++) excnt[i] = fcnt[i] = emcnt[i] = tcnt[i] = 0;
743 /* dump cube direct list by level */
744 for(nc = sys->directlist; nc != NULL; nc = nc->dnext) {
745 lev = nc->level;
746 tcnt[lev]++;
747 if(nc->upnumvects > 0) fcnt[lev]++;
748 else emcnt[lev]++;
749 if(nc->mul_exact == TRUE) excnt[lev]++;
750 }
751 sprintf(str, "Direct list");
752 dumpSynCore1(str, depth, fcnt, excnt, emcnt, tcnt);
753
754 for(i = 0; i <= depth; i++) excnt[i] = fcnt[i] = emcnt[i] = tcnt[i] = 0;
755 /* dump cube local list by level */
756 for(i = 0; i <= depth; i++) {
757 for(nc = sys->locallist[i]; nc != NULL; nc = nc->lnext) {
758 lev = nc->level;
759 tcnt[lev]++;
760 if(nc->upnumvects > 0) fcnt[lev]++;
761 else emcnt[lev]++;
762 if(nc->mul_exact == TRUE) excnt[lev]++;
763 }
764 }
765 sprintf(str, "Local list");
766 dumpSynCore1(str, depth, fcnt, excnt, emcnt, tcnt);
767
768 for(i = 0; i <= depth; i++) excnt[i] = fcnt[i] = emcnt[i] = tcnt[i] = 0;
769 /* dump cube multipole list by level */
770 for(i = 0; i <= depth; i++) {
771 for(nc = sys->multilist[i]; nc != NULL; nc = nc->mnext) {
772 lev = nc->level;
773 tcnt[lev]++;
774 if(nc->upnumvects > 0) fcnt[lev]++;
775 else emcnt[lev]++;
776 if(nc->mul_exact == TRUE) excnt[lev]++;
777 }
778 }
779 sprintf(str, "Multi list");
780 dumpSynCore1(str, depth, fcnt, excnt, emcnt, tcnt);
781
782
783 sprintf(str, "Multis built");
784 dumpSynCore2(str, depth, multicnt);
785
786 sprintf(str, "Locals built");
787 dumpSynCore2(str, depth, localcnt);
788
789 }
790
791 /*
792 dumps the Gaussian unit (statcoulombs/meter^2) charge densities on panels
793 */
dumpChgDen(fp,q,chglist)794 void dumpChgDen(fp, q, chglist)
795 double *q;
796 charge *chglist;
797 FILE *fp;
798 {
799 charge *panel;
800
801 for(panel = chglist; panel != NULL; panel = panel->next) {
802 if(panel->dummy) continue;
803 fprintf(fp, "%d\tq/A = %.5e %g", panel->index,
804 q[panel->index]/panel->area, panel->area);
805 if(panel->surf->type == CONDTR) fprintf(fp, " CONDTR");
806 if(panel->surf->type == DIELEC) fprintf(fp, " DIELEC");
807 if(panel->surf->type == BOTH) fprintf(fp, " BOTH");
808 fprintf(fp, " (%.3g %.3g %.3g)", panel->x, panel->y, panel->z);
809 fprintf(fp, " cond = %d\n", panel->cond);
810 }
811 fflush(fp);
812 }
813
814 /*
815 like dumpMat but different formating and row labels (for dumpMatBldCnts)
816 */
dumpMatCnts(mat,depth,type)817 void dumpMatCnts(mat, depth, type)
818 int **mat, depth;
819 char *type;
820 {
821 int i, j;
822 char str[BUFSIZ];
823
824 fprintf(stdout,
825 "\n%s MATRIX BUILD TOTALS (row = from cube, col = to cube):\n",
826 type);
827
828 for(i = 0; i <= depth; i++) {
829 sprintf(str, " to %d ", i);
830 if(i == 0) fprintf(stdout, "%13s", str);
831 else if(i < 10) fprintf(stdout, "%6s", str);
832 else fprintf(stdout, "%7s", str);
833 }
834 fprintf(stdout, "\n");
835
836 for(i = 0; i <= depth; i++) {
837 sprintf(str, "from %d ", i);
838 fprintf(stdout, "%-7s", str); /* print row label */
839 for(j = 0; j <= depth; j++) {
840 sprintf(str, "%d ", mat[i][j]);
841 if(j < 10) fprintf(stdout, "%6s", str);
842 else fprintf(stdout, "%7s", str);
843 }
844 fprintf(stdout, "\n");
845 }
846
847 }
848
849 /*
850 display matrix build count totals
851 */
dumpMatBldCnts(sys)852 void dumpMatBldCnts(sys)
853 ssystem *sys;
854 {
855 int i;
856 char type[BUFSIZ];
857 extern int **Q2Mcnt, **Q2Lcnt, **Q2Pcnt, **L2Lcnt;
858 extern int **M2Mcnt, **M2Lcnt, **M2Pcnt, **L2Pcnt, **Q2PDcnt;
859
860 sprintf(type, "Q2M");
861 dumpMatCnts(Q2Mcnt, sys->depth, type);
862
863 sprintf(type, "Q2L");
864 dumpMatCnts(Q2Lcnt, sys->depth, type);
865
866 sprintf(type, "Q2P");
867 dumpMatCnts(Q2Pcnt, sys->depth, type);
868
869 sprintf(type, "M2M");
870 dumpMatCnts(M2Mcnt, sys->depth, type);
871
872 sprintf(type, "M2L");
873 dumpMatCnts(M2Lcnt, sys->depth, type);
874
875 sprintf(type, "M2P");
876 dumpMatCnts(M2Pcnt, sys->depth, type);
877
878 sprintf(type, "L2L");
879 dumpMatCnts(L2Lcnt, sys->depth, type);
880
881 sprintf(type, "L2P");
882 dumpMatCnts(L2Pcnt, sys->depth, type);
883
884 sprintf(type, "Q2PDiag");
885 dumpMatCnts(Q2PDcnt, sys->depth, type);
886
887 }
888
889 /*
890 dumps state of important compile flags
891 */
dumpConfig(fp,name)892 void dumpConfig(fp, name)
893 char *name;
894 FILE *fp;
895 {
896 int size = -1; /* for '#define MAXITER size' case */
897
898 fprintf(fp, "\n%s CONFIGURATION FLAGS:\n", name);
899
900 fprintf(fp, " DISCRETIZATION CONFIGURATION\n");
901
902 fprintf(fp, " WRMETH");
903 if(WRMETH == COLLOC)
904 fprintf(fp, " == COLLOC (point collocation)\n");
905 else if(WRMETH == SUBDOM)
906 fprintf(fp, " == SUBDOM (not implemented - do collocation)\n");
907 else if(WRMETH == GALKIN)
908 fprintf(fp, " == GALKIN (not implemented - do collocation)\n");
909 fprintf(fp, " ELTYPE");
910 if(ELTYPE == CONST)
911 fprintf(fp, " == CONST (constant panel densities)\n");
912 else if(ELTYPE == AFFINE)
913 fprintf(fp, " == AFFINE (not implemented - use constant)\n");
914 else if(ELTYPE == QUADRA)
915 fprintf(fp, " == QUADRA (not implemented - use constant)\n");
916
917 fprintf(fp, " MULTIPOLE CONFIGURATION\n");
918
919 fprintf(fp, " DNTYPE");
920 if(DNTYPE == NOLOCL)
921 fprintf(fp, " == NOLOCL (no locals in dwnwd pass)\n");
922 else if(DNTYPE == NOSHFT)
923 fprintf(fp, " == NOSHFT (no local2local shift dwnwd pass)\n");
924 else if(DNTYPE == GRENGD)
925 fprintf(fp, " == GRENGD (full Greengard dwnwd pass)\n");
926 fprintf(fp, " MULTI");
927 if(MULTI == ON) fprintf(fp, " == ON (include multipole part of P*q)\n");
928 else fprintf(fp, " == OFF (don't use multipole part of P*q)\n");
929 fprintf(fp, " RADINTER");
930 if(RADINTER == ON)
931 fprintf(fp," == ON (allow parent level interaction list entries)\n");
932 else
933 fprintf(fp," == OFF (use only cube level interaction list entries)\n");
934 fprintf(fp, " NNBRS == %d (max distance to a nrst neighbor)\n", NNBRS);
935 fprintf(fp, " ADAPT");
936 if(ADAPT == ON)
937 fprintf(fp, " == ON (adaptive - no expansions in exact cubes)\n");
938 else fprintf(fp, " == OFF (not adaptive - expansions in all cubes)\n");
939 fprintf(fp, " OPCNT");
940 if(OPCNT == ON)
941 fprintf(fp, " == ON (count P*q ops - exit after mat build)\n");
942 else fprintf(fp, " == OFF (no P*q op count - iterate to convergence)\n");
943
944 fprintf(fp, " MAXDEP");
945 fprintf(fp,
946 " == %d (assume no more than %d partitioning levels are needed)\n",
947 MAXDEP, MAXDEP);
948
949 fprintf(fp, " NUMDPT");
950 fprintf(fp,
951 " == %d (do %d potential evaluations for each dielectric panel)\n",
952 NUMDPT, NUMDPT);
953
954 fprintf(fp, " LINEAR SYSTEM SOLUTION CONFIGURATION\n");
955
956 fprintf(fp, " ITRTYP");
957 if(ITRTYP == GCR)
958 fprintf(fp, " == GCR (generalized conjugate residuals)\n");
959 else if(ITRTYP == GMRES)
960 fprintf(fp, " == GMRES (generalized minimum residuals)\n");
961 else fprintf(fp, " == %d (not implemented - use GCR)\n", ITRTYP);
962
963 fprintf(fp, " PRECOND");
964 if(PRECOND == BD) {
965 fprintf(fp,
966 " == BD (use block diagonal preconditioner)\n");
967 }
968 else if(PRECOND == OL) {
969 fprintf(fp,
970 " == OL (use overlap preconditioner)\n");
971 }
972 else if(PRECOND == NONE) {
973 fprintf(fp,
974 " == NONE (no preconditioner)\n");
975 }
976 else fprintf(fp, " == %d (not implemented - use BD, OL or NONE)\n", PRECOND);
977
978 fprintf(fp, " DIRSOL");
979 if(DIRSOL == ON)
980 fprintf(fp, " == ON (do the whole calculation directly)\n");
981 else fprintf(fp, " == OFF (do the calculation iteratively)\n");
982
983 fprintf(fp, " EXPGCR");
984 if(EXPGCR == ON)
985 fprintf(fp, " == ON (do all P*q's explicitly w/full matrix)\n");
986 else fprintf(fp, " == OFF (do P*q's with multipole)\n");
987
988 fprintf(fp, " MAXITER");
989 if(MAXITER < 0) {
990 fprintf(fp, " == size (for n panel system, do at most n iterations)\n");
991 }
992 else fprintf(fp, " == %d (stop after %d iterations if not converged)\n",
993 MAXITER, MAXITER);
994
995 fprintf(fp, " EXRTSH");
996 fprintf(fp,
997 " == %g (exact/ttl cubes > %g on lowest level => stop refinement)\n",
998 EXRTSH, EXRTSH);
999 }
1000
1001
1002 /*
1003 pads a string on the right up to a given length, truncates if too long
1004 */
padName(tostr,frstr,len)1005 char *padName(tostr, frstr, len)
1006 char *tostr, *frstr;
1007 int len;
1008 {
1009 int i;
1010
1011 for(i = 0; frstr[i] != '\0'; i++) tostr[i] = frstr[i];
1012 if(i > len) tostr[len] = '\0'; /* truncate */
1013 else { /* pad */
1014 for(; i < len; i++) tostr[i] = ' ';
1015 tostr[len] = '\0';
1016 }
1017 return(tostr);
1018 }
1019
1020 /*
1021 returns a string of spaces (doesn't stdio have this somewhere?)
1022 */
spaces(str,num)1023 char *spaces(str, num)
1024 char *str;
1025 int num;
1026 {
1027 int i;
1028
1029 for(i = 0; i < num; i++) str[i] = ' ';
1030 str[num] = '\0';
1031 return(str);
1032 }
1033
1034 /*
1035 prints the capacitance matrix with symmetrized (averaged) off-diagonals
1036 - mks units (Farads) are used
1037 - some attempt to scale (eg pF, nF, uF etc) is made
1038 - also checks for M-matrix sign pattern, diag dominance
1039 */
mksCapDump(capmat,numconds,relperm,name_list)1040 void mksCapDump(capmat, numconds, relperm, name_list)
1041 double **capmat, relperm;
1042 int numconds;
1043 Name **name_list;
1044 {
1045 int i, j, toobig, toosmall, maxlen, sigfig, colwidth, i_killed, j_killed;
1046 int first_offd;
1047 double maxdiag = 0.0, minoffd, rowttl, rowdiag, scale = 1.0, **sym_mat;
1048 double mat_entry;
1049 char unit[BUFSIZ], name[BUFSIZ], *padName(), *spaces(), cond_name[BUFSIZ];
1050 char *getConductorName();
1051 extern NAME *start_name; /* NAME structs giving conductor names */
1052 Name *cname;
1053 extern ITER *kill_num_list, *kinp_num_list;
1054 extern double iter_tol;
1055
1056 first_offd = TRUE;
1057 minoffd = capmat[1][1]; /* this entry is always present */
1058 /* - in the 1 cond case, assign is still ok */
1059
1060 /* set up symetrized matrix storage */
1061 CALLOC(sym_mat, numconds+1, double*, ON, AMSC);
1062 for(i=1; i <= numconds; i++) {
1063 CALLOC(sym_mat[i], numconds+1, double, ON, AMSC);
1064 }
1065
1066 /* get the smallest and largest (absolute value) symmetrized elements */
1067 /* check for non-M-matrix symmetrized capacitance matrix */
1068 for(i = 1; i <= numconds; i++) {
1069
1070 /* skip conductors removed from input */
1071 if(want_this_iter(kinp_num_list, i)) continue;
1072
1073 i_killed = want_this_iter(kill_num_list, i);
1074
1075 if(capmat[i][i] <= 0.0 && !i_killed) {
1076 fprintf(stderr, "\nmksCapDump: Warning - capacitance matrix has non-positive diagonal\n row %d\n", i+1);
1077 }
1078 maxdiag = MAX(maxdiag, fabs(capmat[i][i]));
1079 rowttl = 0.0;
1080 for(j = 1; j <= numconds; j++) {
1081
1082 /* skip conductors removed from input */
1083 if(want_this_iter(kinp_num_list, j)) continue;
1084
1085 if(j == i) {
1086 sym_mat[i][i] = capmat[i][i];
1087 continue;
1088 }
1089
1090 /* if this column was not calculated and neither was the column
1091 with the same number as the current row, then symetrized mat has
1092 no entry at [i][j], [j][i] */
1093 j_killed = want_this_iter(kill_num_list, j);
1094 if(i_killed && j_killed) continue;
1095
1096 /* if this column was calculated but column with the same number
1097 as the current row wasnt, then symmetrized mat has unaveraged entry
1098 at [i][j], [j][i] */
1099 else if(i_killed && !j_killed) mat_entry = capmat[i][j];
1100
1101 /* if this column was not calculated but column with the same number
1102 as the current row was, then symmetrized mat has unaveraged entry
1103 at [i][j], [j][i] */
1104 else if(!i_killed && j_killed) mat_entry = capmat[j][i];
1105
1106 /* if this column was calculated and column with the same number
1107 as the current row was also, then symmetrized mat has averaged entry
1108 at [i][j], [j][i] */
1109 else mat_entry = (capmat[i][j] + capmat[j][i])/2.0;
1110
1111 rowttl += mat_entry;
1112 if(mat_entry >= 0.0) {
1113 fprintf(stderr, "\nmksCapDump: Warning - capacitance matrix has non-negative off-diagonals\n row %d col %d\n", i, j);
1114 }
1115 if(fabs(mat_entry) != 0.0) {
1116 if(first_offd) {
1117 minoffd = fabs(mat_entry);
1118 first_offd = FALSE;
1119 }
1120 else minoffd = MIN(minoffd, fabs(mat_entry));
1121 }
1122
1123 sym_mat[i][j] = mat_entry;
1124 }
1125 if(rowttl + capmat[i][i] <= 0.0 && !i_killed) {
1126 fprintf(stderr, "\nmksCapDump: Warning - capacitance matrix is not strictly diagonally dominant\n due to row %d\n", i);
1127 }
1128 }
1129
1130 /* figure the units to use for the matrix entries
1131 - set up so smallest element is between 0.1 and 10 */
1132 if(minoffd*FPIEPS*relperm*scale > 10.0) toobig = TRUE;
1133 else toobig = FALSE;
1134 if(minoffd*FPIEPS*relperm*scale < 0.1) toosmall = TRUE;
1135 else toosmall = FALSE;
1136 while(toobig == TRUE || toosmall == TRUE) {
1137 if(toobig == TRUE) {
1138 scale *= 1e-3;
1139 if(minoffd*FPIEPS*relperm*scale <= 10.0) break;
1140 }
1141 if(toosmall == TRUE) {
1142 scale *= 1e+3;
1143 if(minoffd*FPIEPS*relperm*scale >= 0.1) break;
1144 }
1145 }
1146
1147 /* get the appropriate unit string */
1148 if(scale == 1e-18) strcpy(unit, "exa");
1149 else if(scale == 1e-15) strcpy(unit, "peta");
1150 else if(scale == 1e-12) strcpy(unit, "tera");
1151 else if(scale == 1e-9) strcpy(unit, "giga");
1152 else if(scale == 1e-6) strcpy(unit, "mega");
1153 else if(scale == 1e-3) strcpy(unit, "kilo");
1154 else if(scale == 1.0) strcpy(unit, "");
1155 else if(scale == 1e+3) strcpy(unit, "milli");
1156 else if(scale == 1e+6) strcpy(unit, "micro");
1157 else if(scale == 1e+9) strcpy(unit, "nano");
1158 else if(scale == 1e+12) strcpy(unit, "pico");
1159 else if(scale == 1e+15) strcpy(unit, "femto");
1160 else if(scale == 1e+18) strcpy(unit, "atto");
1161 else sprintf(unit, "every unit is %g ", 1/scale);
1162
1163 /* get the length of the longest name */
1164 maxlen = 0;
1165 for(i = 1; i <= numconds; i++) {
1166 maxlen = MAX(strlen(getConductorName(i, name_list)), maxlen);
1167 }
1168
1169 /* print the matrix */
1170 sigfig = 2+log10(1.0/iter_tol); /* get no. significant figs to prnt */
1171 colwidth = sigfig+6; /* field width for cap mat columns */
1172 if(ITRDAT == OFF) fprintf(stdout, "\n");
1173 if(kill_num_list != NULL)
1174 fprintf(stdout, "\nPARTIAL CAPACITANCE MATRIX, %sfarads\n", unit);
1175 else fprintf(stdout, "\nCAPACITANCE MATRIX, %sfarads\n", unit);
1176 if(numconds < 10) fprintf(stdout, "%s", spaces(unit, maxlen+2));
1177 else if(numconds < 100) fprintf(stdout, "%s", spaces(unit, maxlen+3));
1178 else fprintf(stdout, "%s", spaces(unit, maxlen+4));
1179 for(j = 1; j <= numconds; j++) { /* column headings */
1180 if(want_this_iter(kinp_num_list, j)) continue;
1181 sprintf(name, "%d ", j);
1182 sprintf(unit, "%%%ds", colwidth+1);
1183 fprintf(stdout, unit, name);
1184 }
1185 fprintf(stdout, "\n");
1186 for(i = 1; i <= numconds; i++) { /* rows */
1187
1188 /* skip conductors removed from input */
1189 if(want_this_iter(kinp_num_list, i)) continue;
1190
1191 sprintf(unit, "%d", i);
1192
1193 strcpy(cond_name, getConductorName(i, name_list));
1194
1195 if(numconds < 10)
1196 fprintf(stdout, "%s %1s", padName(name, cond_name, maxlen), unit);
1197 else if(numconds < 100)
1198 fprintf(stdout, "%s %2s", padName(name, cond_name, maxlen), unit);
1199 else
1200 fprintf(stdout, "%s %3s", padName(name, cond_name, maxlen), unit);
1201
1202 for(j = 1; j <= numconds; j++) {
1203
1204 /* skip conductors removed from input */
1205 if(want_this_iter(kinp_num_list, j)) continue;
1206
1207 if(want_this_iter(kill_num_list, i)
1208 && want_this_iter(kill_num_list, j)) {
1209 /* print a blank if capacitance was not calculated */
1210 fprintf(stdout, "%s", spaces(unit, colwidth+1));
1211 }
1212 else {
1213 sprintf(unit, " %%%d.%dg", colwidth, sigfig);
1214 fprintf(stdout, unit, scale*FPIEPS*relperm*sym_mat[j][i]);
1215 }
1216 }
1217 fprintf(stdout, "\n");
1218 }
1219 }
1220
1221 /*
1222 dumps brief information about multipole set up
1223 */
dumpMulSet(sy,numLev,order)1224 void dumpMulSet(sy, numLev, order)
1225 ssystem *sy;
1226 int numLev, order;
1227 {
1228 int numcubes, numsides, i, multerms();
1229
1230 for(numcubes = 1, i = 0; i < numLev; numcubes *= 8, i++);
1231 for(numsides = 1, i = 0; i < numLev; numsides *= 2, i++);
1232
1233 fprintf(stdout, "\nMULTIPOLE SETUP SUMMARY\n");
1234 fprintf(stdout, "Level 0 cube extremal coordinates\n");
1235 fprintf(stdout, " x: %g to %g\n",
1236 sy->minx, sy->minx + numsides * (sy->length));
1237 fprintf(stdout, " y: %g to %g\n",
1238 sy->miny, sy->miny + numsides * (sy->length));
1239 fprintf(stdout, " z: %g to %g\n",
1240 sy->minz, sy->minz + numsides * (sy->length));
1241 fprintf(stdout, "Level %d (lowest level) cubes\n %d total\n",
1242 numLev, numcubes);
1243 fprintf(stdout,
1244 " side length = %g\n maximum number of panels in each = %d\n",
1245 sy->length, sy->mul_maxlq);
1246 fprintf(stdout, " maximum number of evaluation points in each = %d\n",
1247 sy->loc_maxlq);
1248 fprintf(stdout,
1249 "Maximum number of panels treated with a multipole expansion = %d\n",
1250 sy->max_panel);
1251 fprintf(stdout,
1252 "Maximum number of evaluation points treated with a local expansion = %d\n",
1253 sy->max_eval_pnt);
1254 fprintf(stdout,
1255 "Maximum number of panels treated exactly = %d (limit = %d)\n",
1256 sy->mul_maxq, multerms(order));
1257 fprintf(stdout,
1258 "Maximum number of evaluation points treated exactly = %d (limit = %d)\n",
1259 sy->loc_maxq, multerms(order));
1260 }
1261
1262 /*
1263 dump all the preconditioner matrices in the direct list cubes as one
1264 big matrix for matlab read in "Ctil"
1265 - figures preconditioner by multiplying it by columns of the inverse
1266 and dumping results one column at a time
1267 - figures the unpreconditioned matrix (using calcp) and dumps it to "P"
1268 - type determines which of the matrices to dump
1269 */
dump_preconditioner(sys,chglist,type)1270 void dump_preconditioner(sys, chglist, type)
1271 charge *chglist;
1272 ssystem *sys;
1273 int type; /* 1=>dump P and C; 2=>P only; 3=>C only */
1274 {
1275 int num_panels, i, j;
1276 charge *pp, *pi;
1277 cube *cp;
1278 double calcp();
1279 FILE *fp;
1280
1281 /* find the number of panels */
1282 for(num_panels = 0, pp = chglist; pp != NULL; pp = pp->next, num_panels++);
1283
1284 /* open the output file */
1285 if((fp = fopen("prec.mat","w")) == NULL) {
1286 fprintf(stderr, "dump_preconditioner: can't open `prec.mat'\n");
1287 exit(1);
1288 }
1289
1290 if(type == 1 || type == 3) {
1291 fprintf(stdout, "\nDumping preconditioner to `prec.mat' as `Ctil'\n");
1292 /* dump the preconditioner one column at a time */
1293 /* - savemat arg "type" can be used to make rowwise dumps
1294 type = x0xx => columnwise dumps
1295 type = x1xx => rowwise dumps (see matlab manual) */
1296 for(j = 1; j < num_panels+1; j++) {
1297 /* load I col into q and zero p */
1298 for(i = 0; i < num_panels+1; i++) {
1299 if(i == j) sys->q[i] = 1.0;
1300 else sys->q[i] = 0.0;
1301 }
1302 /* figure the column of C in p (xfered to q after calculation) */
1303 mulPrecond(sys, PRECOND);
1304 /* dump the preconditioner column */
1305 if(j == 1) savemat_mod(fp, 1000, "Ctil", num_panels, num_panels, 0,
1306 &(sys->q[1]), (double *)NULL, 0, num_panels);
1307 else savemat_mod(fp, 1000, "Ctil", num_panels, num_panels, 0,
1308 &(sys->q[1]), (double *)NULL, 1, num_panels);
1309
1310 }
1311 }
1312
1313 if(type == 1 || type == 2) {
1314 fprintf(stdout, "\nDumping pot. coeff. mat. to `prec.mat' as `P'\n");
1315 /* dump the P matrix - DANGER: does n^2 calcp() calls,
1316 but storage is only n */
1317 /* are q indices from 1?? */
1318 for(j = 1; j < num_panels+1; j++) {
1319 /* find the panel with the current index (select column) */
1320 for(pp = chglist; pp != NULL; pp = pp->next) {
1321 if(pp->index == j) break;
1322 }
1323 if(pp == NULL) {
1324 fprintf(stderr, "dump_preconditioner: no charge with index %d\n", j);
1325 exit(1);
1326 }
1327 for(i = 0; i < num_panels+1; i++) sys->p[i] = 0.0;
1328 /* find the column---influence of q_j on potentials at each q_i */
1329 for(i = 1, pi = chglist; pi != NULL; i++, pi = pi->next) {
1330 sys->p[pi->index] = calcp(pp, pi->x, pi->y, pi->z, NULL);
1331 }
1332 /* dump the column */
1333 if(j == 1) savemat_mod(fp, 1000, "P", num_panels, num_panels, 0,
1334 &(sys->p[1]), (double *)NULL, 0, num_panels);
1335 else savemat_mod(fp, 1000, "P", num_panels, num_panels, 0,
1336 &(sys->p[1]), (double *)NULL, 1, num_panels);
1337
1338 }
1339 }
1340
1341 fclose(fp);
1342 }
1343
1344 /*
1345 do an n^2/2 check to see if any panels have the same center points
1346 (debug only)
1347 */
has_duplicate_panels(fp,chglst)1348 int has_duplicate_panels(fp, chglst)
1349 charge *chglst;
1350 FILE *fp;
1351 {
1352 int no_duplicates;
1353 charge *cp, *cpinner;
1354
1355 no_duplicates = TRUE;
1356 for(cp = chglst; cp != NULL; cp = cp->next) {
1357 for(cpinner = cp->next; cpinner != NULL; cpinner = cpinner->next) {
1358 if(cp->x == cpinner->x && cp->y == cpinner->y && cp->z == cpinner->z) {
1359 no_duplicates = FALSE;
1360
1361 if(cp->surf->type == CONDTR) fprintf(fp, "Panels %d(CONDTR)",
1362 cp->index);
1363 if(cp->surf->type == DIELEC) fprintf(fp, "Panels %d(DIELEC)",
1364 cp->index);
1365 if(cp->surf->type == BOTH) fprintf(fp, "Panels %d(BOTH)",
1366 cp->index);
1367
1368 if(cpinner->surf->type == CONDTR) fprintf(fp, " and %d(CONDTR)",
1369 cpinner->index);
1370 if(cpinner->surf->type == DIELEC) fprintf(fp, " and %d(DIELEC)",
1371 cpinner->index);
1372 if(cpinner->surf->type == BOTH) fprintf(fp, " and %d(BOTH)",
1373 cpinner->index);
1374
1375 fprintf(fp, " both have center (%.3g %.3g %.3g)\n",
1376 cp->x, cp->y, cp->z);
1377 }
1378 }
1379 }
1380
1381 if(no_duplicates) return(FALSE);
1382 else return(TRUE);
1383 }
1384
1385 #if DSQ2PD == ON
1386 /*
1387 dump the condensed matrix for matlab use
1388 */
dumpQ2PDiag(nextc)1389 void dumpQ2PDiag(nextc)
1390 cube *nextc;
1391 {
1392 int i, j, ind, pos_d, neg_d;
1393 double temp[BUFSIZ], temp_mat[100][100], **rmat;
1394 double pos_fact, neg_fact, panel_fact;
1395 FILE *fp, *fopen();
1396
1397 /* dump the diag matrix to a matlab file along with its dummy vector */
1398 /* must complie on sobolev with /usr/local/matlab/loadsave/savemat.o */
1399 if((fp = fopen("Q2PDiag.mat", "w")) == NULL) {
1400 fprintf(stderr, "dumpQ2PDiag: can't open `Q2PDiag.mat' to write\n");
1401 exit(1);
1402 }
1403 if(sizeof(temp) < nextc->upnumeles[0]*nextc->upnumeles[0]) {
1404 fprintf(stderr, "dumpQ2PDiag: temporary arrays not big enough\n");
1405 exit(1);
1406 }
1407
1408 /* incorporate the electric field evaluation into the matrix */
1409 /* if a row corresponds to a flux density difference, alter it */
1410 rmat = nextc->directmats[0];
1411 for(i = 0; i < nextc->upnumeles[0]; i++) {
1412 if(nextc->chgs[i]->dummy) {
1413 for(j = 0; j < nextc->upnumeles[0]; j++) temp_mat[i][j] = 0.0;
1414 continue;
1415 }
1416
1417 if(nextc->chgs[i]->surf->type == CONDTR) {
1418 for(j = 0; j < nextc->upnumeles[0]; j++) {
1419 temp_mat[i][j] = rmat[i][j];
1420 }
1421 }
1422 else {
1423
1424 pos_fact
1425 = nextc->chgs[i]->surf->outer_perm/nextc->chgs[i]->pos_dummy->area;
1426 pos_d = nextc->chgs[i]->pos_dummy->index - 1;
1427 neg_fact
1428 = nextc->chgs[i]->surf->inner_perm/nextc->chgs[i]->neg_dummy->area;
1429 neg_d = nextc->chgs[i]->neg_dummy->index - 1;
1430 panel_fact = pos_fact + neg_fact;
1431
1432 for(j = 0; j < nextc->upnumeles[0]; j++) {
1433 temp_mat[i][j] = pos_fact*rmat[pos_d][j] - panel_fact*rmat[i][j]
1434 + neg_fact*rmat[neg_d][j];
1435 }
1436 }
1437 }
1438
1439 /* flatten the Q2PDiag matrix */
1440 for(j = ind = 0; j < nextc->upnumeles[0]; j++) {
1441 for(i = 0; i < nextc->upnumeles[0]; i++) {
1442 temp[ind++] = temp_mat[i][j];
1443 }
1444 }
1445 savemat(fp, 1000, "A", nextc->upnumeles[0], nextc->upnumeles[0],
1446 0, temp, (double *)NULL);
1447
1448 /* make the is_dummy vector a vector of doubles */
1449 for(i = 0; i < nextc->upnumeles[0]; i++)
1450 temp[i] = (double)(nextc->nbr_is_dummy[0][i]);
1451 savemat(fp, 1000, "is_dummy", nextc->upnumeles[0], 1,
1452 0, temp, (double *)NULL);
1453
1454 /* make a vector with 0 => CONDTR 1 => DIELEC 2 => BOTH -1 => dummy */
1455 for(i = 0; i < nextc->upnumeles[0]; i++) {
1456 if(nextc->chgs[i]->dummy) temp[i] = -1.0;
1457 else temp[i] = (double)(nextc->chgs[i]->surf->type);
1458 }
1459 savemat(fp, 1000, "surf_type", nextc->upnumeles[0], 1,
1460 0, temp, (double *)NULL);
1461
1462 fclose(fp);
1463 fprintf(stdout, "Dumped Q2PDiag matrix to `Q2PDiag.mat'\n");
1464 }
1465
1466 #endif
1467
1468 #if 1 == 0
1469 /*
1470 for debug only on SPARC2 -- NaN trap error handler (see man matherr)
1471 */
matherr(exc)1472 int matherr(exc)
1473 struct exception *exc;
1474 {
1475 fprintf(stderr, "matherr: ");
1476
1477 if(exc->type == DOMAIN) fprintf(stderr, "DOMAIN error in");
1478 else if(exc->type == SING) fprintf(stderr, "SING error in");
1479 else if(exc->type == OVERFLOW) fprintf(stderr, "OVERFLOW error in");
1480 else if(exc->type == UNDERFLOW) fprintf(stderr, "UNDERFLOW error in");
1481
1482 fprintf(stderr, " %s\n", exc->name);
1483
1484 fprintf(stderr, " args: %g %g returning: %g\n", exc->arg1, exc->arg2,
1485 exc->retval);
1486 exit(1);
1487 }
1488 #endif
1489
1490 /*
1491 debug only - check a vector to make sure it has zeros in dummy entries
1492 */
chkDummy(vector,is_dummy,size)1493 int chkDummy(vector, is_dummy, size)
1494 double *vector;
1495 int *is_dummy;
1496 int size;
1497 {
1498 int i, first = TRUE;
1499
1500 for(i = 0; i < size; i++) {
1501 if(is_dummy[i] && vector[i] != 0.0) {
1502 if(first) {
1503 first = FALSE;
1504 fprintf(stderr, "\nchkDummy: entries should be 0.0: %d", i);
1505 }
1506 else fprintf(stderr, " %d", i);
1507 }
1508 }
1509 if(!first) fprintf(stderr, "\n");
1510 }
1511
1512 /*
1513 debug only - print message if dummy list doesn't match panel list
1514 */
chkDummyList(panels,is_dummy,n_chgs)1515 void chkDummyList(panels, is_dummy, n_chgs)
1516 charge **panels;
1517 int *is_dummy;
1518 int n_chgs;
1519 {
1520 int i;
1521 int first = TRUE;
1522
1523 for(i = 0; i < n_chgs; i++) {
1524 if(is_dummy[i] && !panels[i]->dummy || !is_dummy[i] && panels[i]->dummy) {
1525 if(first) {
1526 first = FALSE;
1527 fprintf(stderr, "chkDummyList: inconsistent dummy list entries:\n");
1528 }
1529 fprintf(stderr, " %d is_dummy = %d, panel->dummy = %d\n", i,
1530 is_dummy[i], panels[i]->dummy);
1531 }
1532 }
1533
1534 }
1535
1536 /*
1537 print the conductor names to a file
1538 */
dumpCondNames(fp,name_list)1539 void dumpCondNames(fp, name_list)
1540 FILE *fp;
1541 Name *name_list;
1542 {
1543 int i;
1544 char *last_alias();
1545 Name *cur_name;
1546
1547 fprintf(fp, "CONDUCTOR NAMES\n");
1548 for(cur_name = name_list, i = 0; cur_name != NULL;
1549 cur_name = cur_name->next, i++) {
1550 fprintf(fp, " %d `%s'\n", i+1, last_alias(cur_name));
1551 }
1552 }
1553
1554 /*
1555 debug only: dump state of internal conductor name list
1556 */
dumpNameList(name_list)1557 int dumpNameList(name_list)
1558 Name *name_list;
1559 {
1560 Name *cur_name, *cur_alias;
1561
1562 for(cur_name = name_list; cur_name != NULL; cur_name = cur_name->next) {
1563 fprintf(stdout, "`%s'\n", cur_name->name);
1564 for(cur_alias = cur_name->alias_list; cur_alias != NULL;
1565 cur_alias = cur_alias->next) {
1566 fprintf(stdout, " `%s'\n", cur_alias->name);
1567 }
1568 }
1569 return(TRUE);
1570 }
1571
1572