1 /*
2  *  xnec2c - GTK2-based version of nec2c, the C translation of NEC2
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 /******* Translated to the C language by N. Kyriazis  20 Aug 2003 ******
20 
21   Program NEC(input,tape5=input,output,tape11,tape12,tape13,tape14,
22   tape15,tape16,tape20,tape21)
23 
24   Numerical Electromagnetics Code (NEC2)  developed at Lawrence
25   Livermore lab., Livermore, CA.  (contact G. Burke at 415-422-8414
26   for problems with the NEC code. For problems with the vax implem-
27   entation, contact J. Breakall at 415-422-8196 or E. Domning at 415
28   422-5936)
29   file created 4/11/80.
30 
31  ***********Notice**********
32  This computer code material was prepared as an account of work
33  sponsored by the United States government.  Neither the United
34  States nor the United States Department Of Energy, nor any of
35  their employees, nor any of their contractors, subcontractors,
36  or their employees, makes any warranty, express or implied, or
37  assumes any legal liability or responsibility for the accuracy,
38  completeness or usefulness of any information, apparatus, product
39  or process disclosed, or represents that its use would not infringe
40  privately-owned rights.
41 
42  ***********************************************************************/
43 
44 #include "matrix.h"
45 #include "shared.h"
46 
47 /*-------------------------------------------------------------------*/
48 
49 /* cmset sets up the complex structure matrix in the array cm */
cmset(int nrow,complex double * cmx,double rkhx,int iexkx)50 void cmset( int nrow, complex double *cmx, double rkhx, int iexkx )
51 {
52   int mp2, neq, npeq, it, i, j, i1, i2, in2, im1;
53   int im2, ist, ij, ipr, jss, jm1, jm2, jst, k, ka, kk;
54   complex double zaj, deter, *scm = NULL;
55 
56   mp2=2* data.mp;
57   npeq= data.np+ mp2;
58   neq= data.n+2* data.m;
59   smat.nop = neq/npeq;
60 
61   dataj.rkh= rkhx;
62   dataj.iexk= iexkx;
63   it= matpar.nlast;
64 
65   for( i = 0; i < nrow; i++ )
66 	for( j = 0; j < it; j++ )
67 	  cmx[i+j*nrow]= CPLX_00;
68 
69   i1= 1;
70   i2= it;
71   in2= i2;
72 
73   if( in2 > data.np)
74 	in2= data.np;
75 
76   im1= i1- data.np;
77   im2= i2- data.np;
78 
79   if( im1 < 1)
80 	im1=1;
81 
82   ist=1;
83   if( i1 <= data.np)
84 	ist= data.np- i1+2;
85 
86   /* wire source loop */
87   if( data.n != 0)
88   {
89 	for( j = 1; j <= data.n; j++ )
90 	{
91 	  trio(j);
92 	  for( i = 0; i < segj.jsno; i++ )
93 	  {
94 		ij= segj.jco[i];
95 		segj.jco[i]=(( ij-1)/ data.np)* mp2+ ij;
96 	  }
97 
98 	  if( i1 <= in2)
99 		cmww( j, i1, in2, cmx, nrow, cmx, nrow,1);
100 
101 	  if( im1 <= im2)
102 		cmws( j, im1, im2, &cmx[(ist-1)*nrow], nrow, cmx, 1);
103 
104 	  /* matrix elements modified by loading */
105 	  if( zload.nload == 0)
106 		continue;
107 
108 	  if( j > data.np)
109 		continue;
110 
111 	  ipr= j;
112 	  if( (ipr < 1) || (ipr > it) )
113 		continue;
114 
115 	  zaj= zload.zarray[j-1];
116 
117 	  for( i = 0; i < segj.jsno; i++ )
118 	  {
119 		jss= segj.jco[i];
120 		cmx[(jss-1)+(ipr-1)*nrow] -=
121 		  ( segj.ax[i]+ segj.cx[i])* zaj;
122 	  }
123 
124 	} /* for( j = 1; j <= n; j++ ) */
125 
126   } /* if( n != 0) */
127 
128   if( data.m != 0)
129   {
130 	/* matrix elements for patch current sources */
131 	jm1=1- data.mp;
132 	jm2=0;
133 	jst=1- mp2;
134 
135 	for( i = 0; i < smat.nop; i++ )
136 	{
137 	  jm1 += data.mp;
138 	  jm2 += data.mp;
139 	  jst += npeq;
140 
141 	  if( i1 <= in2)
142 		cmsw( jm1, jm2, i1, in2,
143 			&cmx[(jst-1)], cmx, 0, nrow, 1);
144 
145 	  if( im1 <= im2)
146 		cmss( jm1, jm2, im1, im2,
147 			&cmx[(jst-1)+(ist-1)*nrow], nrow, 1);
148 	}
149 
150   } /* if( m != 0) */
151 
152   if( matpar.icase == 1)
153 	return;
154 
155   /* Allocate to scratch memory */
156   size_t mreq = (size_t)data.np2m * sizeof(complex double);
157   mem_alloc( (void **)&scm, mreq, "in matrix.c");
158 
159   /* combine elements for symmetry modes */
160   for( i = 0; i < it; i++ )
161   {
162 	for( j = 0; j < npeq; j++ )
163 	{
164 	  for( k = 0; k < smat.nop; k++ )
165 	  {
166 		ka= j+ k*npeq;
167 		scm[k]= cmx[ka+i*nrow];
168 	  }
169 
170 	  deter= scm[0];
171 
172 	  for( kk = 1; kk < smat.nop; kk++ )
173 		deter += scm[kk];
174 
175 	  cmx[j+i*nrow]= deter;
176 
177 	  for( k = 1; k < smat.nop; k++ )
178 	  {
179 		ka= j+ k*npeq;
180 		deter= scm[0];
181 
182 		for( kk = 1; kk < smat.nop; kk++ )
183 		{
184 		  deter += scm[kk]* smat.ssx[k+kk*smat.nop];
185 		  cmx[ka+i*nrow]= deter;
186 		}
187 
188 	  } /* for( k = 1; k < smat.nop; k++ ) */
189 
190 	} /* for( j = 0; j < npeq; j++ ) */
191 
192   } /* for( i = 0; i < it; i++ ) */
193 
194   free_ptr( (void **)&scm );
195 
196   return;
197 }
198 
199 /*-----------------------------------------------------------------------*/
200 
201 /* cmss computes matrix elements for surface-surface interactions. */
cmss(int j1,int j2,int im1,int im2,complex double * cmx,int nrow,int itrp)202 void cmss( int j1, int j2, int im1, int im2,
203 	complex double *cmx, int nrow, int itrp )
204 {
205   int i1, i2, icomp, ii1, i, il, ii2, jj1, j, jl, jj2;
206   double t1xi, t1yi, t1zi, t2xi, t2yi, t2zi, xi, yi, zi;
207   complex double g11, g12, g21, g22;
208 
209   i1=( im1+1)/2;
210   i2=( im2+1)/2;
211   icomp= i1*2-3;
212   ii1=-2;
213   if( icomp+2 < im1)
214 	ii1=-3;
215 
216   /* loop over observation patches */
217   il = -1;
218   for( i = i1; i <= i2; i++ )
219   {
220 	il++;
221 	icomp += 2;
222 	ii1 += 2;
223 	ii2 = ii1+1;
224 
225 	t1xi= data.t1x[il]* data.psalp[il];
226 	t1yi= data.t1y[il]* data.psalp[il];
227 	t1zi= data.t1z[il]* data.psalp[il];
228 	t2xi= data.t2x[il]* data.psalp[il];
229 	t2yi= data.t2y[il]* data.psalp[il];
230 	t2zi= data.t2z[il]* data.psalp[il];
231 	xi= data.px[il];
232 	yi= data.py[il];
233 	zi= data.pz[il];
234 
235 	/* loop over source patches */
236 	jj1=-2;
237 	for( j = j1; j <= j2; j++ )
238 	{
239 	  jl=j-1;
240 	  jj1 += 2;
241 	  jj2 = jj1+1;
242 
243 	  dataj.s= data.pbi[jl];
244 	  dataj.xj= data.px[jl];
245 	  dataj.yj= data.py[jl];
246 	  dataj.zj= data.pz[jl];
247 	  dataj.t1xj= data.t1x[jl];
248 	  dataj.t1yj= data.t1y[jl];
249 	  dataj.t1zj= data.t1z[jl];
250 	  dataj.t2xj= data.t2x[jl];
251 	  dataj.t2yj= data.t2y[jl];
252 	  dataj.t2zj= data.t2z[jl];
253 
254 	  hintg( xi, yi, zi);
255 
256 	  g11=-( t2xi* dataj.exk+ t2yi* dataj.eyk+ t2zi* dataj.ezk);
257 	  g12=-( t2xi* dataj.exs+ t2yi* dataj.eys+ t2zi* dataj.ezs);
258 	  g21=-( t1xi* dataj.exk+ t1yi* dataj.eyk+ t1zi* dataj.ezk);
259 	  g22=-( t1xi* dataj.exs+ t1yi* dataj.eys+ t1zi* dataj.ezs);
260 
261 	  if( i == j )
262 	  {
263 		g11 -= .5;
264 		g22 += .5;
265 	  }
266 
267 	  /* normal fill */
268 	  if( itrp == 0)
269 	  {
270 		if( icomp >= im1 )
271 		{
272 		  cmx[ii1+jj1*nrow]= g11;
273 		  cmx[ii1+jj2*nrow]= g12;
274 		}
275 
276 		if( icomp >= im2 )
277 		  continue;
278 
279 		cmx[ii2+jj1*nrow]= g21;
280 		cmx[ii2+jj2*nrow]= g22;
281 		continue;
282 
283 	  } /* if( itrp == 0) */
284 
285 	  /* transposed fill */
286 	  if( icomp >= im1 )
287 	  {
288 		cmx[jj1+ii1*nrow]= g11;
289 		cmx[jj2+ii1*nrow]= g12;
290 	  }
291 
292 	  if( icomp >= im2 )
293 		continue;
294 
295 	  cmx[jj1+ii2*nrow]= g21;
296 	  cmx[jj2+ii2*nrow]= g22;
297 
298 	} /* for( j = j1; j <= j2; j++ ) */
299 
300   } /* for( i = i1; i <= i2; i++ ) */
301 
302   return;
303 }
304 
305 /*-----------------------------------------------------------------------*/
306 
307 /* computes matrix elements for e along wires due to patch current */
cmsw(int j1,int j2,int i1,int i2,complex double * cmx,complex double * cw,int ncw,int nrow,int itrp)308 void cmsw( int j1, int j2, int i1, int i2, complex double *cmx,
309 	complex double *cw, int ncw, int nrow, int itrp )
310 {
311   int jsnox; /* -1 offset to "jsno" for array indexing */
312   static complex double *emel = NULL;
313 
314   size_t mreq = 9 * sizeof(complex double);
315   mem_alloc( (void **)&emel, mreq, "in matrix.c");
316 
317   jsnox = segj.jsno-1;
318 
319   if( itrp >= 0)
320   {
321 	int k, icgo, i, ipch, jl, j, js, il, ip;
322 	double xi, yi, zi, cabi, sabi, salpi, fsign=1.0, pyl, pxl;
323 
324 	k=-1;
325 	icgo=0;
326 
327 	/* observation loop */
328 	for( i = i1-1; i < i2; i++ )
329 	{
330 	  k++;
331 	  xi= data.x[i];
332 	  yi= data.y[i];
333 	  zi= data.z[i];
334 	  cabi= data.cab[i];
335 	  sabi= data.sab[i];
336 	  salpi= data.salp[i];
337 	  ipch=0;
338 
339 	  if( data.icon1[i] >= PCHCON)
340 	  {
341 		ipch= data.icon1[i]-PCHCON;
342 		fsign=-1.0;
343 	  }
344 
345 	  if( data.icon2[i] >= PCHCON)
346 	  {
347 		ipch= data.icon2[i]-PCHCON;
348 		fsign=1.0;
349 	  }
350 
351 	  /* source loop */
352 	  jl = -1;
353 	  for( j = j1; j <= j2; j++ )
354 	  {
355 		jl += 2;
356 		js = j-1;
357 		dataj.t1xj= data.t1x[js];
358 		dataj.t1yj= data.t1y[js];
359 		dataj.t1zj= data.t1z[js];
360 		dataj.t2xj= data.t2x[js];
361 		dataj.t2yj= data.t2y[js];
362 		dataj.t2zj= data.t2z[js];
363 		dataj.xj= data.px[js];
364 		dataj.yj= data.py[js];
365 		dataj.zj= data.pz[js];
366 		dataj.s= data.pbi[js];
367 
368 		/* ground loop */
369 		for( ip = 1; ip <= gnd.ksymp; ip++ )
370 		{
371 		  dataj.ipgnd= ip;
372 
373 		  if( ((ipch == j) || (icgo != 0)) && (ip != 2) )
374 		  {
375 			if( icgo <= 0 )
376 			{
377 			  pcint( xi, yi, zi, cabi, sabi, salpi, emel);
378 
379 			  pyl= PI* data.si[i]* fsign;
380 			  pxl= sin( pyl);
381 			  pyl= cos( pyl);
382 			  dataj.exc= emel[8]* fsign;
383 
384 			  trio(i+1);
385 
386 			  il= i-ncw;
387 			  if( i < data.np)
388 				il += (il/data.np)*2*data.mp;
389 
390 			  if( itrp == 0 )
391 				cw[k+il*nrow] +=
392 				  dataj.exc*( segj.ax[jsnox] +
393 					  segj.bx[jsnox]* pxl+ segj.cx[jsnox]* pyl);
394 			  else
395 				cw[il+k*nrow] +=
396 				  dataj.exc*( segj.ax[jsnox] +
397 					  segj.bx[jsnox]* pxl+ segj.cx[jsnox]* pyl);
398 
399 			} /* if( icgo <= 0 ) */
400 
401 			if( itrp == 0)
402 			{
403 			  cmx[k+(jl-1)*nrow]= emel[icgo];
404 			  cmx[k+jl*nrow]    = emel[icgo+4];
405 			}
406 			else
407 			{
408 			  cmx[(jl-1)+k*nrow]= emel[icgo];
409 			  cmx[jl+k*nrow]    = emel[icgo+4];
410 			}
411 
412 			icgo++;
413 			if( icgo == 4)
414 			  icgo=0;
415 
416 			continue;
417 
418 		  } /* if( ((ipch == (j+1)) || (icgo != 0)) && (ip != 2) ) */
419 
420 		  unere( xi, yi, zi);
421 
422 		  /* normal fill */
423 		  if( itrp == 0)
424 		  {
425 			cmx[k+(jl-1)*nrow] +=
426 			  dataj.exk* cabi+ dataj.eyk* sabi+ dataj.ezk* salpi;
427 			cmx[k+jl*nrow]     +=
428 			  dataj.exs* cabi+ dataj.eys* sabi+ dataj.ezs* salpi;
429 			continue;
430 		  }
431 
432 		  /* transposed fill */
433 		  cmx[(jl-1)+k*nrow] +=
434 			dataj.exk* cabi+ dataj.eyk* sabi+ dataj.ezk* salpi;
435 		  cmx[jl+k*nrow]     +=
436 			dataj.exs* cabi+ dataj.eys* sabi+ dataj.ezs* salpi;
437 
438 		} /* for( ip = 1; ip <= gnd.ksymp; ip++ ) */
439 
440 	  } /* for( j = j1; j <= j2; j++ ) */
441 
442 	} /* for( i = i1-1; i < i2; i++ ) */
443 
444   } /* if( itrp >= 0) */
445 
446   return;
447 }
448 
449 /*-----------------------------------------------------------------------*/
450 
451 /* cmws computes matrix elements for wire-surface interactions */
cmws(int j,int i1,int i2,complex double * cmx,int nr,complex double * cw,int itrp)452 void cmws( int j, int i1, int i2, complex double *cmx,
453 	int nr, complex double *cw, int itrp )
454 {
455   int ipr, i, ipatch, ik, js=0, ij, jx;
456   double xi, yi, zi, tx, ty, tz;
457   complex double etk, ets, etc;
458 
459   j--;
460   dataj.s= data.si[j];
461   dataj.b= data.bi[j];
462   dataj.xj= data.x[j];
463   dataj.yj= data.y[j];
464   dataj.zj= data.z[j];
465   dataj.cabj= data.cab[j];
466   dataj.sabj= data.sab[j];
467   dataj.salpj= data.salp[j];
468 
469   /* observation loop */
470   ipr= -1;
471   for( i = i1; i <= i2; i++ )
472   {
473 	ipr++;
474 	ipatch=(i+1)/2;
475 	ik= i-( i/2)*2;
476 
477 	if( (ik != 0) || (ipr == 0) )
478 	{
479 	  js= ipatch-1;
480 	  xi= data.px[js];
481 	  yi= data.py[js];
482 	  zi= data.pz[js];
483 	  hsfld( xi, yi, zi, 0.0);
484 
485 	  if( ik != 0 )
486 	  {
487 		tx= data.t2x[js];
488 		ty= data.t2y[js];
489 		tz= data.t2z[js];
490 	  }
491 	  else
492 	  {
493 		tx= data.t1x[js];
494 		ty= data.t1y[js];
495 		tz= data.t1z[js];
496 	  }
497 
498 	} /* if( (ik != 0) || (ipr == 0) ) */
499 	else
500 	{
501 	  tx= data.t1x[js];
502 	  ty= data.t1y[js];
503 	  tz= data.t1z[js];
504 
505 	} /* if( (ik != 0) || (ipr == 0) ) */
506 
507 	etk=-( dataj.exk* tx+ dataj.eyk* ty +
508 		dataj.ezk* tz)* data.psalp[js];
509 	ets=-( dataj.exs* tx+ dataj.eys* ty +
510 		dataj.ezs* tz)* data.psalp[js];
511 	etc=-( dataj.exc* tx+ dataj.eyc* ty +
512 		dataj.ezc* tz)* data.psalp[js];
513 
514 	/* fill matrix elements.  element locations */
515 	/* determined by connection data. */
516 
517 	/* normal fill */
518 	if( itrp == 0)
519 	{
520 	  for( ij = 0; ij < segj.jsno; ij++ )
521 	  {
522 		jx= segj.jco[ij]-1;
523 		cmx[ipr+jx*nr] += etk* segj.ax[ij] +
524 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
525 	  }
526 
527 	  continue;
528 	} /* if( itrp == 0) */
529 
530 	/* transposed fill */
531 	if( itrp != 2)
532 	{
533 	  for( ij = 0; ij < segj.jsno; ij++ )
534 	  {
535 		jx= segj.jco[ij]-1;
536 		cmx[jx+ipr*nr] += etk* segj.ax[ij] +
537 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
538 	  }
539 
540 	  continue;
541 	} /* if( itrp != 2) */
542 
543 	/* transposed fill - c(ws) and d(ws)prime (=cw) */
544 	for( ij = 0; ij < segj.jsno; ij++ )
545 	{
546 	  jx= segj.jco[ij]-1;
547 	  if( jx < nr)
548 		cmx[jx+ipr*nr] += etk* segj.ax[ij] +
549 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
550 	  else
551 	  {
552 		jx -= nr;
553 		cw[jx+ipr*nr] += etk* segj.ax[ij] +
554 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
555 	  }
556 	} /* for( ij = 0; ij < segj.jsno; ij++ ) */
557 
558   } /* for( i = i1; i <= i2; i++ ) */
559 
560   return;
561 }
562 
563 /*-----------------------------------------------------------------------*/
564 
565 /* cmww computes matrix elements for wire-wire interactions */
cmww(int j,int i1,int i2,complex double * cmx,int nr,complex double * cw,int nw,int itrp)566 void cmww( int j, int i1, int i2, complex double *cmx,
567 	int nr, complex double *cw, int nw, int itrp)
568 {
569   int ipr, iprx, i, ij, jx;
570   double xi, yi, zi, ai, cabi, sabi, salpi;
571   complex double etk, ets, etc;
572 
573   /* set source segment parameters */
574   jx = j;
575   j--;
576   dataj.s= data.si[j];
577   dataj.b= data.bi[j];
578   dataj.xj= data.x[j];
579   dataj.yj= data.y[j];
580   dataj.zj= data.z[j];
581   dataj.cabj= data.cab[j];
582   dataj.sabj= data.sab[j];
583   dataj.salpj= data.salp[j];
584 
585   /* decide whether ext. t.w. approx. can be used */
586   if( dataj.iexk != 0)
587   {
588 	ipr = data.icon1[j];
589 	if (ipr > PCHCON) dataj.ind1 = 0;
590 	else if( ipr < 0 )
591 	{
592 	  ipr= -ipr;
593 	  iprx= ipr-1;
594 
595 	  if( -data.icon1[iprx] != jx )
596 		dataj.ind1=2;
597 	  else
598 	  {
599 		xi= fabs( dataj.cabj* data.cab[iprx]+ dataj.sabj*
600 			data.sab[iprx]+ dataj.salpj* data.salp[iprx]);
601 		if( (xi < 0.999999) ||
602 			(fabs(data.bi[iprx]/dataj.b-1.0) > 1.0e-6) )
603 		  dataj.ind1=2;
604 		else
605 		  dataj.ind1=0;
606 
607 	  } /* if( -data.icon1[iprx] != jx ) */
608 
609 	} /* if( ipr < 0 ) */
610 	else
611 	{
612 	  iprx = ipr-1;
613 	  if( ipr == 0 )
614 		dataj.ind1=1;
615 	  else
616 	  {
617 		if( ipr != jx )
618 		{
619 		  if( data.icon2[iprx] != jx )
620 			dataj.ind1=2;
621 		  else
622 		  {
623 			xi= fabs( dataj.cabj* data.cab[iprx]+ dataj.sabj*
624 				data.sab[iprx]+ dataj.salpj* data.salp[iprx]);
625 			if( (xi < 0.999999) ||
626 				(fabs(data.bi[iprx]/dataj.b-1.0) > 1.0e-6) )
627 			  dataj.ind1=2;
628 			else
629 			  dataj.ind1=0;
630 
631 		  } /* if( data.icon2[iprx] != jx ) */
632 
633 		} /* if( ipr != jx ) */
634 		else if( (dataj.cabj* dataj.cabj +
635 			  dataj.sabj* dataj.sabj) > 1.0e-8)
636 		  dataj.ind1=2;
637 		else
638 		  dataj.ind1=0;
639 
640 	  } /* if( ipr == 0 ) */
641 
642 	} /* if( ipr < 0 ) */
643 
644 	ipr = data.icon2[j];
645 	if (ipr > PCHCON) dataj.ind2 = 2;
646 	else if( ipr < 0 )
647 	{
648 	  ipr= -ipr;
649 	  iprx = ipr-1;
650 	  if( -data.icon2[iprx] != jx )
651 		dataj.ind2=2;
652 	  else
653 	  {
654 		xi= fabs( dataj.cabj* data.cab[iprx]+ dataj.sabj*
655 			data.sab[iprx]+ dataj.salpj* data.salp[iprx]);
656 		if( (xi < 0.99999) ||
657 			(fabs(data.bi[iprx]/dataj.b-1.0) > 1.0e-6) )
658 		  dataj.ind2=2;
659 		else
660 		  dataj.ind2=0;
661 
662 	  } /* if( -data.icon1[iprx] != jx ) */
663 
664 	} /* if( ipr < 0 ) */
665 	else
666 	{
667 	  iprx = ipr-1;
668 	  if( ipr == 0 )
669 		dataj.ind2=1;
670 	  else
671 	  {
672 		if( ipr != jx )
673 		{
674 		  if( data.icon1[iprx] != jx )
675 			dataj.ind2=2;
676 		  else
677 		  {
678 			xi= fabs( dataj.cabj* data.cab[iprx]+ dataj.sabj*
679 				data.sab[iprx]+ dataj.salpj* data.salp[iprx]);
680 			if( (xi < 0.999999) ||
681 				(fabs(data.bi[iprx]/dataj.b-1.0) > 1.0e-6) )
682 			  dataj.ind2=2;
683 			else
684 			  dataj.ind2=0;
685 
686 		  } /* if( data.icon2[iprx] != jx ) */
687 
688 		} /* if( ipr != jx ) */
689 		else if( (dataj.cabj* dataj.cabj +
690 			  dataj.sabj* dataj.sabj) > 1.0e-8)
691 		  dataj.ind2=2;
692 		else
693 		  dataj.ind2=0;
694 
695 	  } /* if( ipr == 0 ) */
696 
697 	} /* if( ipr < 0 ) */
698 
699   } /* if( dataj.iexk != 0) */
700 
701   /* observation loop */
702   ipr=-1;
703   for( i = i1-1; i < i2; i++ )
704   {
705 	ipr++;
706 	ij= i-j;
707 	xi= data.x[i];
708 	yi= data.y[i];
709 	zi= data.z[i];
710 	ai= data.bi[i];
711 	cabi= data.cab[i];
712 	sabi= data.sab[i];
713 	salpi= data.salp[i];
714 
715 	efld( xi, yi, zi, ai, ij);
716 
717 	etk= dataj.exk* cabi+ dataj.eyk *
718 	  sabi+ dataj.ezk* salpi;
719 	ets= dataj.exs* cabi+ dataj.eys *
720 	  sabi+ dataj.ezs* salpi;
721 	etc= dataj.exc* cabi+ dataj.eyc *
722 	  sabi+ dataj.ezc* salpi;
723 
724 	/* fill matrix elements. element locations */
725 	/* determined by connection data. */
726 
727 	/* normal fill */
728 	if( itrp == 0)
729 	{
730 	  for( ij = 0; ij < segj.jsno; ij++ )
731 	  {
732 		jx = segj.jco[ij]-1;
733 		cmx[ipr+jx*nr] += etk* segj.ax[ij] +
734 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
735 	  }
736 	  continue;
737 	}
738 
739 	/* transposed fill */
740 	if( itrp != 2)
741 	{
742 	  for( ij = 0; ij < segj.jsno; ij++ )
743 	  {
744 		jx= segj.jco[ij]-1;
745 		cmx[jx+ipr*nr] += etk* segj.ax[ij] +
746 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
747 	  }
748 	  continue;
749 	}
750 
751 	/* trans. fill for c(ww) - test for elements for d(ww)prime */
752 	for( ij = 0; ij < segj.jsno; ij++ )
753 	{
754 	  jx= segj.jco[ij]-1;
755 	  if( jx < nr)
756 		cmx[jx+ipr*nr] += etk* segj.ax[ij] +
757 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
758 	  else
759 	  {
760 		jx -= nr;
761 		cw[jx*ipr*nw] += etk* segj.ax[ij] +
762 		  ets* segj.bx[ij]+ etc* segj.cx[ij];
763 	  }
764 
765 	} /* for( ij = 0; ij < segj.jsno; ij++ ) */
766 
767   } /* for( i = i1-1; i < i2; i++ ) */
768 
769   return;
770 }
771 
772 /*-----------------------------------------------------------------------*/
773 
774 /* etmns fills the array e with the negative of the */
775 /* electric field incident on the structure. e is the */
776 /* right hand side of the matrix equation. */
etmns(double p1,double p2,double p3,double p4,double p5,double p6,int ipr,complex double * e)777 void etmns( double p1, double p2, double p3, double p4,
778 	double p5, double p6, int ipr, complex double *e )
779 {
780   int i, is, i1, i2=0, neq;
781   double cth, sth, cph, sph, cet, set, pxl, pyl, pzl, wx;
782   double wy, wz, qx, qy, qz, arg, ds, dsh, rs, r;
783   complex double cx, cy, cz, er, et, ezh;
784   complex double erh, rrv=CPLX_00, rrh=CPLX_00, tt1, tt2;
785 
786   neq= data.n+2*data.m;
787   vsorc.nqds=0;
788 
789   /* applied field of voltage sources for transmitting case */
790   if( (ipr == 0) || (ipr == 5) )
791   {
792 	for( i = 0; i < neq; i++ )
793 	  e[i]=CPLX_00;
794 
795 	if( vsorc.nsant != 0)
796 	{
797 	  for( i = 0; i < vsorc.nsant; i++ )
798 	  {
799 		is= vsorc.isant[i]-1;
800 		e[is]= -vsorc.vsant[i]/( data.si[is]* data.wlam);
801 	  }
802 	}
803 
804 	if( vsorc.nvqd == 0)
805 	  return;
806 
807 	for( i = 0; i < vsorc.nvqd; i++ )
808 	{
809 	  is= vsorc.ivqd[i];
810 	  qdsrc( is, vsorc.vqd[i], e);
811 	}
812 	return;
813 
814   } /* if( (ipr <= 0) || (ipr == 5) ) */
815 
816   /* incident plane wave, linearly polarized. */
817   if( ipr <= 3)
818   {
819 	cth= cos( p1);
820 	sth= sin( p1);
821 	cph= cos( p2);
822 	sph= sin( p2);
823 	cet= cos( p3);
824 	set= sin( p3);
825 	pxl= cth* cph* cet- sph* set;
826 	pyl= cth* sph* cet+ cph* set;
827 	pzl= -sth* cet;
828 	wx= -sth* cph;
829 	wy= -sth* sph;
830 	wz= -cth;
831 	qx= wy* pzl- wz* pyl;
832 	qy= wz* pxl- wx* pzl;
833 	qz= wx* pyl- wy* pxl;
834 
835 	if( gnd.ksymp != 1)
836 	{
837 	  if( gnd.iperf != 1)
838 	  {
839 		rrv= csqrt(1.0- gnd.zrati* gnd.zrati* sth* sth);
840 		rrh= gnd.zrati* cth;
841 		rrh=( rrh- rrv)/( rrh+ rrv);
842 		rrv= gnd.zrati* rrv;
843 		rrv=-( cth- rrv)/( cth+ rrv);
844 	  }
845 	  else
846 	  {
847 		rrv=-CPLX_10;
848 		rrh=-CPLX_10;
849 	  } /* if( gnd.iperf != 1) */
850 
851 	} /* if( gnd.ksymp != 1) */
852 
853 	if( ipr <= 1)
854 	{
855 	  if( data.n != 0)
856 	  {
857 		for( i = 0; i < data.n; i++ )
858 		{
859 		  arg= -TP*( wx* data.x[i]+ wy* data.y[i]+ wz* data.z[i]);
860 		  e[i]=-( pxl* data.cab[i]+ pyl* data.sab[i]+ pzl*
861 			  data.salp[i])* cmplx( cos( arg), sin( arg));
862 		}
863 
864 		if( gnd.ksymp != 1)
865 		{
866 		  tt1=( pyl* cph- pxl* sph)*( rrh- rrv);
867 		  cx= rrv* pxl- tt1* sph;
868 		  cy= rrv* pyl+ tt1* cph;
869 		  cz= -rrv* pzl;
870 
871 		  for( i = 0; i < data.n; i++ )
872 		  {
873 			arg= -TP*( wx* data.x[i]+ wy* data.y[i]- wz* data.z[i]);
874 			e[i]= e[i]-( cx* data.cab[i]+ cy* data.sab[i]+
875 				cz* data.salp[i])* cmplx(cos( arg), sin( arg));
876 		  }
877 
878 		} /* if( gnd.ksymp != 1) */
879 
880 	  } /* if( data.n != 0) */
881 
882 	  if( data.m == 0)
883 		return;
884 
885 	  i= -1;
886 	  i1= data.n-2;
887 	  for( is = 0; is < data.m; is++ )
888 	  {
889 		i++;
890 		i1 += 2;
891 		i2 = i1+1;
892 		arg= -TP*( wx* data.px[i] +
893 			wy* data.py[i]+ wz* data.pz[i]);
894 		tt1= cmplx( cos( arg), sin( arg)) *
895 		  data.psalp[i]* RETA;
896 		e[i2]=( qx* data.t1x[i]+ qy* data.t1y[i] +
897 			qz* data.t1z[i])* tt1;
898 		e[i1]=( qx* data.t2x[i]+ qy* data.t2y[i] +
899 			qz* data.t2z[i])* tt1;
900 	  }
901 
902 	  if( gnd.ksymp == 1)
903 		return;
904 
905 	  tt1=( qy* cph- qx* sph)*( rrv- rrh);
906 	  cx=-( rrh* qx- tt1* sph);
907 	  cy=-( rrh* qy+ tt1* cph);
908 	  cz= rrh* qz;
909 
910 	  i= -1;
911 	  i1= data.n-2;
912 	  for( is = 0; is < data.m; is++ )
913 	  {
914 		i++;
915 		i1 += 2;
916 		i2 = i1+1;
917 		arg= -TP*( wx* data.px[i] +
918 			wy* data.py[i]- wz* data.pz[i]);
919 		tt1= cmplx( cos( arg), sin( arg)) *
920 		  data.psalp[i]* RETA;
921 		e[i2]= e[i2]+( cx* data.t1x[i]+ cy *
922 			data.t1y[i]+ cz* data.t1z[i])* tt1;
923 		e[i1]= e[i1]+( cx* data.t2x[i]+ cy *
924 			data.t2y[i]+ cz* data.t2z[i])* tt1;
925 	  }
926 	  return;
927 
928 	} /* if( ipr <= 1) */
929 
930 	/* incident plane wave, elliptic polarization. */
931 	tt1=-(CPLX_01)* p6;
932 	if( ipr == 3)
933 	  tt1= -tt1;
934 
935 	if( data.n != 0)
936 	{
937 	  cx= pxl+ tt1* qx;
938 	  cy= pyl+ tt1* qy;
939 	  cz= pzl+ tt1* qz;
940 
941 	  for( i = 0; i < data.n; i++ )
942 	  {
943 		arg= -TP*( wx* data.x[i]+ wy* data.y[i] + wz* data.z[i]);
944 		e[i]=-( cx* data.cab[i]+ cy* data.sab[i] +
945 			cz * data.salp[i])* cmplx( cos( arg), sin( arg));
946 	  }
947 
948 	  if( gnd.ksymp != 1)
949 	  {
950 		tt2=( cy* cph- cx* sph)*( rrh- rrv);
951 		cx= rrv* cx- tt2* sph;
952 		cy= rrv* cy+ tt2* cph;
953 		cz= -rrv* cz;
954 
955 		for( i = 0; i < data.n; i++ )
956 		{
957 		  arg= -TP*( wx* data.x[i]+ wy* data.y[i]- wz* data.z[i]);
958 		  e[i]= e[i]-( cx* data.cab[i]+ cy* data.sab[i]+
959 			  cz* data.salp[i])* cmplx(cos( arg), sin( arg));
960 		}
961 
962 	  } /* if( gnd.ksymp != 1) */
963 
964 	} /* if( n != 0) */
965 
966 	if( data.m == 0)
967 	  return;
968 
969 	cx= qx- tt1* pxl;
970 	cy= qy- tt1* pyl;
971 	cz= qz- tt1* pzl;
972 
973 	i= -1;
974 	i1= data.n-2;
975 	for( is = 0; is < data.m; is++ )
976 	{
977 	  i++;
978 	  i1 += 2;
979 	  i2 = i1+1;
980 	  arg= -TP*( wx* data.px[i] +
981 		  wy* data.py[i]+ wz* data.pz[i]);
982 	  tt2= cmplx( cos( arg),
983 		  sin( arg)) * data.psalp[i] * RETA;
984 	  e[i2]=( cx* data.t1x[i] +
985 		  cy* data.t1y[i]+ cz* data.t1z[i])* tt2;
986 	  e[i1]=( cx* data.t2x[i] +
987 		  cy* data.t2y[i]+ cz* data.t2z[i])* tt2;
988 	}
989 
990 	if( gnd.ksymp == 1)
991 	  return;
992 
993 	tt1=( cy* cph- cx* sph)*( rrv- rrh);
994 	cx=-( rrh* cx- tt1* sph);
995 	cy=-( rrh* cy+ tt1* cph);
996 	cz= rrh* cz;
997 
998 	i= -1;
999 	i1= data.n-2;
1000 	for( is=0; is < data.m; is++ )
1001 	{
1002 	  i++;
1003 	  i1 += 2;
1004 	  i2 = i1+1;
1005 	  arg= -TP*( wx* data.px[i] +
1006 		  wy* data.py[i]- wz* data.pz[i]);
1007 	  tt1= cmplx( cos( arg), sin( arg)) *
1008 		data.psalp[i]* RETA;
1009 	  e[i2]= e[i2]+( cx* data.t1x[i]+ cy *
1010 		  data.t1y[i]+ cz* data.t1z[i])* tt1;
1011 	  e[i1]= e[i1]+( cx* data.t2x[i]+ cy *
1012 		  data.t2y[i]+ cz* data.t2z[i])* tt1;
1013 	}
1014 
1015 	return;
1016 
1017   } /* if( ipr <= 3) */
1018 
1019   /* incident field of an elementary current source. */
1020   wz= cos( p4);
1021   wx= wz* cos( p5);
1022   wy= wz* sin( p5);
1023   wz= sin( p4);
1024   ds= p6*59.9580;
1025   dsh= p6/(2.0* TP);
1026 
1027   is= 0;
1028   i1= data.n-2;
1029   for( i = 0; i < data.npm; i++ )
1030   {
1031 	if( i >= data.n )
1032 	{
1033 	  i1 += 2;
1034 	  i2 = i1+1;
1035 	  pxl= data.px[is]- p1;
1036 	  pyl= data.py[is]- p2;
1037 	  pzl= data.pz[is]- p3;
1038 	}
1039 	else
1040 	{
1041 	  pxl= data.x[i]- p1;
1042 	  pyl= data.y[i]- p2;
1043 	  pzl= data.z[i]- p3;
1044 	}
1045 
1046 	rs= pxl* pxl+ pyl* pyl+ pzl* pzl;
1047 	if( rs < 1.0e-30)
1048 	  continue;
1049 
1050 	r= sqrt( rs);
1051 	pxl= pxl/ r;
1052 	pyl= pyl/ r;
1053 	pzl= pzl/ r;
1054 	cth= pxl* wx+ pyl* wy+ pzl* wz;
1055 	sth= sqrt(1.0- cth* cth);
1056 	qx= pxl- wx* cth;
1057 	qy= pyl- wy* cth;
1058 	qz= pzl- wz* cth;
1059 
1060 	arg= sqrt( qx* qx+ qy* qy+ qz* qz);
1061 	if( arg >= 1.0e-30)
1062 	{
1063 	  qx= qx/ arg;
1064 	  qy= qy/ arg;
1065 	  qz= qz/ arg;
1066 	}
1067 	else
1068 	{
1069 	  qx=1.0;
1070 	  qy=0.0;
1071 	  qz=0.0;
1072 
1073 	} /* if( arg >= 1.0e-30) */
1074 
1075 	arg= -TP* r;
1076 	tt1= cmplx( cos( arg), sin( arg));
1077 
1078 	if( i < data.n )
1079 	{
1080 	  tt2= cmplx(1.0,-1.0/( r* TP))/ rs;
1081 	  er= ds* tt1* tt2* cth;
1082 	  et=.5* ds* tt1*((CPLX_01)* TP/ r+ tt2)* sth;
1083 	  ezh= er* cth- et* sth;
1084 	  erh= er* sth+ et* cth;
1085 	  cx= ezh* wx+ erh* qx;
1086 	  cy= ezh* wy+ erh* qy;
1087 	  cz= ezh* wz+ erh* qz;
1088 	  e[i]=-( cx* data.cab[i] +
1089 		  cy* data.sab[i]+ cz* data.salp[i]);
1090 	}
1091 	else
1092 	{
1093 	  pxl= wy* qz- wz* qy;
1094 	  pyl= wz* qx- wx* qz;
1095 	  pzl= wx* qy- wy* qx;
1096 	  tt2= dsh* tt1* cmplx(1.0/ r, TP) /
1097 		r* sth* data.psalp[is];
1098 	  cx= tt2* pxl;
1099 	  cy= tt2* pyl;
1100 	  cz= tt2* pzl;
1101 	  e[i2]= cx* data.t1x[is] +
1102 		cy* data.t1y[is]+ cz* data.t1z[is];
1103 	  e[i1]= cx* data.t2x[is] +
1104 		cy* data.t2y[is]+ cz* data.t2z[is];
1105 	  is++;
1106 	} /* if( i < data.n) */
1107 
1108   } /* for( i = 0; i < npm; i++ ) */
1109 
1110   return;
1111 }
1112 
1113 /*-----------------------------------------------------------------------*/
1114 
1115 /* subroutine to factor a matrix into a unit lower triangular matrix */
1116 /* and an upper triangular matrix using the gauss-doolittle algorithm */
1117 /* presented on pages 411-416 of a. ralston--a first course in */
1118 /* numerical analysis.  comments below refer to comments in ralstons */
1119 /* text.    (matrix transposed.) */
1120 
factr(int n,complex double * a,int * ip,int ndim)1121 void factr( int n, complex double *a, int *ip, int ndim)
1122 {
1123   int r, rm1, rp1, pj, pr, iflg, k, j, jp1, i;
1124   double dmax, elmag;
1125   complex double arj, *scm = NULL;
1126 
1127   /* Allocate to scratch memory */
1128   size_t mreq = (size_t)data.np2m * sizeof(complex double);
1129   mem_alloc( (void **)&scm, mreq, "in matrix.c");
1130 
1131   /* Un-transpose the matrix for Gauss elimination */
1132   for( i = 1; i < n; i++ )
1133 	for( j = 0; j < i; j++ )
1134 	{
1135 	  arj = a[i+j*ndim];
1136 	  a[i+j*ndim] = a[j+i*ndim];
1137 	  a[j+i*ndim] = arj;
1138 	}
1139 
1140   iflg=FALSE;
1141   /* step 1 */
1142   for( r = 0; r < n; r++ )
1143   {
1144 	for( k = 0; k < n; k++ )
1145 	  scm[k]= a[k+r*ndim];
1146 
1147 	/* steps 2 and 3 */
1148 	rm1= r;
1149 	if( rm1 > 0)
1150 	{
1151 	  for( j = 0; j < rm1; j++ )
1152 	  {
1153 		pj= ip[j]-1;
1154 		arj= scm[pj];
1155 		a[j+r*ndim]= arj;
1156 		scm[pj]= scm[j];
1157 		jp1= j+1;
1158 
1159 		for( i = jp1; i < n; i++ )
1160 		  scm[i] -= a[i+j*ndim]* arj;
1161 
1162 	  } /* for( j = 0; j < rm1; j++ ) */
1163 
1164 	} /* if( rm1 >= 0.0) */
1165 
1166 	/* step 4 */
1167 	dmax= creal( scm[r]*conj(scm[r]) );
1168 
1169 	rp1= r+1;
1170 	ip[r]= rp1;
1171 	if( rp1 < n)
1172 	{
1173 	  for( i = rp1; i < n; i++ )
1174 	  {
1175 		elmag= creal( scm[i]* conj(scm[i]) );
1176 		if( elmag >= dmax)
1177 		{
1178 		  dmax= elmag;
1179 		  ip[r]= i+1;
1180 		}
1181 	  }
1182 	} /* if( rp1 < n) */
1183 
1184 	if( dmax < 1.0e-10)
1185 	  iflg=TRUE;
1186 
1187 	pr= ip[r]-1;
1188 	a[r+r*ndim]= scm[pr];
1189 	scm[pr]= scm[r];
1190 
1191 	/* step 5 */
1192 	if( rp1 < n)
1193 	{
1194 	  arj=1.0/ a[r+r*ndim];
1195 
1196 	  for( i = rp1; i < n; i++ )
1197 		a[i+r*ndim]= scm[i]* arj;
1198 	}
1199 
1200 	if( iflg == TRUE )
1201 	{
1202 	  fprintf( stderr,
1203 		  "xnec2c: pivot(%d)= %16.8E\n", r, dmax );
1204 	  iflg=FALSE;
1205 	}
1206 
1207   } /* for( r=0; r < n; r++ ) */
1208 
1209   free_ptr( (void **)&scm );
1210 
1211   return;
1212 }
1213 
1214 /*-----------------------------------------------------------------------*/
1215 
1216 /* factrs, for symmetric structure, transforms submatricies to form */
1217 /* matricies of the symmetric modes and calls routine to factor */
1218 /* matricies.  if no symmetry, the routine is called to factor the */
1219 /* complete matrix. */
factrs(int np,int nrow,complex double * a,int * ip)1220 void factrs( int np, int nrow, complex double *a, int *ip )
1221 {
1222   int kk, ka;
1223 
1224   smat.nop = nrow/np;
1225   for( kk = 0; kk < smat.nop; kk++ )
1226   {
1227 	ka= kk* np;
1228 	factr( np, &a[ka], &ip[ka], nrow );
1229   }
1230   return;
1231 }
1232 
1233 /*-----------------------------------------------------------------------*/
1234 
1235 /* fblock sets parameters for out-of-core */
1236 /* solution for the primary matrix (a) */
1237   void
fblock(int nrow,int ncol,int imax,int ipsym)1238 fblock( int nrow, int ncol, int imax, int ipsym )
1239 {
1240   int i, j, k, ka, kk;
1241   double phaz, arg;
1242   complex double deter;
1243 
1244   if( nrow*ncol <= imax)
1245   {
1246 	matpar.npblk= nrow;
1247 	matpar.nlast= nrow;
1248 	matpar.imat= nrow* ncol;
1249 
1250 	if( nrow == ncol)
1251 	{
1252 	  matpar.icase=1;
1253 	  return;
1254 	}
1255 	else matpar.icase=2;
1256 
1257   } /* if( nrow*ncol <= imax) */
1258 
1259   smat.nop = ncol/nrow;
1260   if( smat.nop*nrow != ncol)
1261   {
1262 	fprintf( stderr,
1263 		"xnec2c: fblock(): symmetry error - nrow:%d ncol:%d\n",nrow, ncol );
1264 	stop( _("fblock(): Symmetry error"), ERR_STOP );
1265   }
1266 
1267   /* set up smat.ssx matrix for rotational symmetry. */
1268   if( ipsym <= 0)
1269   {
1270 	phaz = TP/smat.nop;
1271 
1272 	for( i = 1; i < smat.nop; i++ )
1273 	{
1274 	  for( j= i; j < smat.nop; j++ )
1275 	  {
1276 		arg= phaz* (double)i * (double)j;
1277 		smat.ssx[i+j*smat.nop]= cmplx( cos( arg), sin( arg));
1278 		smat.ssx[j+i*smat.nop]= smat.ssx[i+j*smat.nop];
1279 	  }
1280 	}
1281 	return;
1282 
1283   } /* if( ipsym <= 0) */
1284 
1285   /* set up smat.ssx matrix for plane symmetry */
1286   kk=1;
1287   smat.ssx[0]=CPLX_10;
1288 
1289   k = 2;
1290   for( ka = 1; k != smat.nop; ka++ )
1291 	k *= 2;
1292 
1293   for( k = 0; k < ka; k++ )
1294   {
1295 	for( i = 0; i < kk; i++ )
1296 	{
1297 	  for( j = 0; j < kk; j++ )
1298 	  {
1299 		deter= smat.ssx[i+j*smat.nop];
1300 		smat.ssx[i+(j+kk)*smat.nop]= deter;
1301 		smat.ssx[i+kk+(j+kk)*smat.nop]= -deter;
1302 		smat.ssx[i+kk+j*smat.nop]= deter;
1303 	  }
1304 	}
1305 	kk *= 2;
1306 
1307   } /* for( k = 0; k < ka; k++ ) */
1308 
1309   return;
1310 }
1311 
1312 /*-----------------------------------------------------------------------*/
1313 
1314 
1315 /* subroutine to solve the matrix equation lu*x=b where l is a unit */
1316 /* lower triangular matrix and u is an upper triangular matrix both */
1317 /* of which are stored in a.  the rhs vector b is input and the */
1318 /* solution is returned through vector b.   (matrix transposed) */
1319   void
solve(int n,complex double * a,int * ip,complex double * b,int ndim)1320 solve( int n, complex double *a, int *ip,
1321 	complex double *b, int ndim )
1322 {
1323   int i, ip1, j, k, pia;
1324   complex double sum, *scm = NULL;
1325 
1326   /* Allocate to scratch memory */
1327   size_t mreq = (size_t)data.np2m * sizeof(complex double);
1328   mem_alloc( (void **)&scm, mreq, "in matrix.c");
1329 
1330   /* forward substitution */
1331   for( i = 0; i < n; i++ )
1332   {
1333 	pia= ip[i]-1;
1334 	scm[i]= b[pia];
1335 	b[pia]= b[i];
1336 	ip1= i+1;
1337 
1338 	if( ip1 < n)
1339 	  for( j = ip1; j < n; j++ )
1340 		b[j] -= a[j+i*ndim]* scm[i];
1341   }
1342 
1343   /* backward substitution */
1344   for( k = 0; k < n; k++ )
1345   {
1346 	i= n-k-1;
1347 	sum=CPLX_00;
1348 	ip1= i+1;
1349 
1350 	if( ip1 < n)
1351 	  for( j = ip1; j < n; j++ )
1352 		sum += a[i+j*ndim]* b[j];
1353 
1354 	b[i]=( scm[i]- sum)/ a[i+i*ndim];
1355   }
1356 
1357   free_ptr( (void **)&scm );
1358 
1359   return;
1360 }
1361 
1362 /*-----------------------------------------------------------------------*/
1363 
1364 /* subroutine solves, for symmetric structures, handles the */
1365 /* transformation of the right hand side vector and solution */
1366 /* of the matrix eq. */
1367   void
solves(complex double * a,int * ip,complex double * b,int neq,int nrh,int np,int n,int mp,int m)1368 solves( complex double *a, int *ip,
1369 	complex double *b,	int neq, int nrh,
1370 	int np, int n, int mp, int m)
1371 {
1372   int npeq, nrow, ic, i, kk, ia, ib, j, k;
1373   double fnop, fnorm;
1374   complex double  sum, *scm = NULL;
1375 
1376   npeq= np+ 2*mp;
1377   smat.nop = neq/npeq;
1378   fnop= smat.nop;
1379   fnorm=1.0/ fnop;
1380   nrow= neq;
1381 
1382   /* Allocate to scratch memory */
1383   size_t mreq = (size_t)data.np2m * sizeof(complex double);
1384   mem_alloc( (void **)&scm, mreq, "in matrix.c");
1385 
1386   if( smat.nop != 1)
1387   {
1388 	for( ic = 0; ic < nrh; ic++ )
1389 	{
1390 	  if( (n != 0) && (m != 0) )
1391 	  {
1392 		for( i = 0; i < neq; i++ )
1393 		  scm[i]= b[i+ic*neq];
1394 
1395 		kk=2* mp;
1396 		ia= np-1;
1397 		ib= n-1;
1398 		j= np-1;
1399 
1400 		for( k = 0; k < smat.nop; k++ )
1401 		{
1402 		  if( k != 0 )
1403 		  {
1404 			for( i = 0; i < np; i++ )
1405 			{
1406 			  ia++;
1407 			  j++;
1408 			  b[j+ic*neq]= scm[ia];
1409 			}
1410 
1411 			if( k == (smat.nop-1) )
1412 			  continue;
1413 
1414 		  } /* if( k != 0 ) */
1415 
1416 		  for( i = 0; i < kk; i++ )
1417 		  {
1418 			ib++;
1419 			j++;
1420 			b[j+ic*neq]= scm[ib];
1421 		  }
1422 
1423 		} /* for( k = 0; k < smat.nop; k++ ) */
1424 
1425 	  } /* if( (n != 0) && (m != 0) ) */
1426 
1427 	  /* transform matrix eq. rhs vector according to symmetry modes */
1428 	  for( i = 0; i < npeq; i++ )
1429 	  {
1430 		for( k = 0; k < smat.nop; k++ )
1431 		{
1432 		  ia= i+ k* npeq;
1433 		  scm[k]= b[ia+ic*neq];
1434 		}
1435 
1436 		sum= scm[0];
1437 		for( k = 1; k < smat.nop; k++ )
1438 		  sum += scm[k];
1439 
1440 		b[i+ic*neq]= sum* fnorm;
1441 
1442 		for( k = 1; k < smat.nop; k++ )
1443 		{
1444 		  ia= i+ k* npeq;
1445 		  sum= scm[0];
1446 
1447 		  for( j = 1; j < smat.nop; j++ )
1448 			sum += scm[j]* conj( smat.ssx[k+j*smat.nop]);
1449 
1450 		  b[ia+ic*neq]= sum* fnorm;
1451 		}
1452 
1453 	  } /* for( i = 0; i < npeq; i++ ) */
1454 
1455 	} /* for( ic = 0; ic < nrh; ic++ ) */
1456 
1457   } /* if( smat.nop != 1) */
1458 
1459   /* solve each mode equation */
1460   for( kk = 0; kk < smat.nop; kk++ )
1461   {
1462 	ia= kk* npeq;
1463 	ib= ia;
1464 
1465 	for( ic = 0; ic < nrh; ic++ )
1466 	  solve( npeq, &a[ib], &ip[ia], &b[ia+ic*neq], nrow );
1467 
1468   } /* for( kk = 0; kk < smat.nop; kk++ ) */
1469 
1470   if( smat.nop == 1)
1471   {
1472 	free_ptr( (void **)&scm );
1473 	return;
1474   }
1475 
1476   /* inverse transform the mode solutions */
1477   for( ic = 0; ic < nrh; ic++ )
1478   {
1479 	for( i = 0; i < npeq; i++ )
1480 	{
1481 	  for( k = 0; k < smat.nop; k++ )
1482 	  {
1483 		ia= i+ k* npeq;
1484 		scm[k]= b[ia+ic*neq];
1485 	  }
1486 
1487 	  sum= scm[0];
1488 	  for( k = 1; k < smat.nop; k++ )
1489 		sum += scm[k];
1490 
1491 	  b[i+ic*neq]= sum;
1492 	  for( k = 1; k < smat.nop; k++ )
1493 	  {
1494 		ia= i+ k* npeq;
1495 		sum= scm[0];
1496 
1497 		for( j = 1; j < smat.nop; j++ )
1498 		  sum += scm[j]* smat.ssx[k+j*smat.nop];
1499 
1500 		b[ia+ic*neq]= sum;
1501 	  }
1502 
1503 	} /* for( i = 0; i < npeq; i++ ) */
1504 
1505 	if( (n == 0) || (m == 0) )
1506 	  continue;
1507 
1508 	for( i = 0; i < neq; i++ )
1509 	  scm[i]= b[i+ic*neq];
1510 
1511 	kk=2* mp;
1512 	ia= np-1;
1513 	ib= n-1;
1514 	j= np-1;
1515 
1516 	for( k = 0; k < smat.nop; k++ )
1517 	{
1518 	  if( k != 0 )
1519 	  {
1520 		for( i = 0; i < np; i++ )
1521 		{
1522 		  ia++;
1523 		  j++;
1524 		  b[ia+ic*neq]= scm[j];
1525 		}
1526 
1527 		if( k == smat.nop)
1528 		  continue;
1529 
1530 	  } /* if( k != 0 ) */
1531 
1532 	  for( i = 0; i < kk; i++ )
1533 	  {
1534 		ib++;
1535 		j++;
1536 		b[ib+ic*neq]= scm[j];
1537 	  }
1538 
1539 	} /* for( k = 0; k < smat.nop; k++ ) */
1540 
1541   } /* for( ic = 0; ic < nrh; ic++ ) */
1542 
1543   free_ptr( (void **)&scm );
1544 
1545   return;
1546 }
1547 
1548 /*-----------------------------------------------------------------------*/
1549 
1550