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 "input.h"
45 #include "shared.h"
46 
47 /*------------------------------------------------------------------------*/
48 
49 /* Read_Comments()
50  *
51  * Reads CM comment cards from input file
52  */
53   gboolean
Read_Comments(void)54 Read_Comments( void )
55 {
56   char ain[3], line_buf[LINE_LEN];
57 
58 
59   /* Look for CM or CE card */
60   do
61   {
62 	/* read a line from input file */
63 	if( Load_Line(line_buf, input_fp) == EOF )
64 	{
65 	  fprintf( stderr, "xnec2c: Read_Comments():"
66 		  "unexpected EOF (End of File)\n" );
67 	  stop( _("Read_Comments(): Error reading Comments\n"\
68 			"Unexpected EOF (End of File)"), ERR_OK );
69 	  return( FALSE );
70 	}
71 
72 	/* Check that comment line is not short */
73 	if( strlen(line_buf) < 2 )
74 	{
75 	  fprintf( stderr, "xnec2c: Read_Comments():"
76 		  "error reading Comments: "
77 		  "Comment mnemonic short or missing\n" );
78 	  stop( _("Read_Comments(): Error reading Comments\n"\
79 			"Comment mnemonic short or missing"), ERR_OK );
80 	  return( FALSE );
81 	}
82 
83 	/* separate card's id mnemonic */
84 	Strlcpy( ain, line_buf, sizeof(ain) );
85 
86 	/* Check for incorrect mnemonic */
87 	if( (strcmp(ain, "CM") != 0) && (strcmp(ain, "CE") != 0) )
88 	{
89 	  stop( _("Read_Comments():\n"\
90 			" Error reading input file\n"\
91 			"Comment mnemonic incorrect"), ERR_OK );
92 	  return( FALSE );
93 	}
94   }
95   while( (strcmp(ain, "CE") != 0) );
96 
97   return( TRUE );
98 } /* Read_Comments() */
99 
100 /*-----------------------------------------------------------------------*/
101 
102 /* Read_Geometry()
103  *
104  * Reads geometry data from input file
105  */
106   gboolean
Read_Geometry(void)107 Read_Geometry( void )
108 {
109   int idx;
110   size_t mreq;
111 
112   /* Moved here from Read_Commands() */
113   matpar.imat=0;
114   data.n = data.m = 0;
115   if( !datagn() ) return( FALSE );
116 
117   /* Memory allocation for temporary buffers */
118   mreq = (size_t)data.npm * sizeof(double);
119   mem_realloc( (void **)&save.xtemp,  mreq, "in input.c" );
120   mem_realloc( (void **)&save.ytemp,  mreq, "in input.c" );
121   mem_realloc( (void **)&save.ztemp,  mreq, "in input.c" );
122   mem_realloc( (void **)&save.bitemp, mreq, "in input.c" );
123   if( data.n > 0 )
124   {
125 	mreq = (size_t)data.n * sizeof(double);
126 	mem_realloc( (void **)&save.sitemp, mreq, "in input.c" );
127   }
128 
129   /* Memory allocation for primary interacton matrix. */
130   mreq = (size_t)(data.np2m * (data.np + 2 * data.mp)) * sizeof(complex double);
131   mem_realloc( (void **)&cm, mreq, "in input.c" );
132 
133   /* Memory allocation for current buffers */
134   mreq = (size_t)data.npm * sizeof( double);
135   mem_realloc( (void **)&crnt.air, mreq, "in input.c" );
136   mem_realloc( (void **)&crnt.aii, mreq, "in input.c" );
137   mem_realloc( (void **)&crnt.bir, mreq, "in input.c" );
138   mem_realloc( (void **)&crnt.bii, mreq, "in input.c" );
139   mem_realloc( (void **)&crnt.cir, mreq, "in input.c" );
140   mem_realloc( (void **)&crnt.cii, mreq, "in input.c" );
141   mreq = (size_t)data.np3m * sizeof( complex double);
142   mem_realloc( (void **)&crnt.cur, mreq, "in input.c" );
143 
144   /* Memory allocation for loading buffers */
145   mreq = (size_t)data.npm * sizeof(complex double);
146   mem_realloc( (void **)&zload.zarray, mreq, "in input.c" );
147 
148   /* Save segment and patch data for freq scaling */
149   if( data.n > 0 )
150 	for( idx = 0; idx < data.n; idx++ )
151 	{
152 	  save.xtemp[idx]  = data.x[idx];
153 	  save.ytemp[idx]  = data.y[idx];
154 	  save.ztemp[idx]  = data.z[idx];
155 	  save.sitemp[idx] = data.si[idx];
156 	  save.bitemp[idx] = data.bi[idx];
157 	}
158 
159   if( data.m > 0 )
160 	for( idx = 0; idx < data.m; idx++ )
161 	{
162 	  int j;
163 
164 	  j = idx + data.n;
165 	  save.xtemp[j]  = data.px[idx];
166 	  save.ytemp[j]  = data.py[idx];
167 	  save.ztemp[j]  = data.pz[idx];
168 	  save.bitemp[j] = data.pbi[idx];
169 	}
170 
171   return( TRUE );
172 } /* Read_Geometry() */
173 
174 /*------------------------------------------------------------------------*/
175 
176 /* Read_Commands()
177  *
178  * Reads commands from input file and stores
179  * them for later execution by user command
180  */
181   gboolean
Read_Commands(void)182 Read_Commands( void )
183 {
184   /* input card mnemonic list */
185   char *atst[NUM_CMNDS] =
186   {
187 	"CM", "CP", "EK", "EN", "EX", \
188 	"FR", "GD", "GN", "KH", "LD", \
189 	"NE", "NH", "NT", "PQ", "PT", \
190 	"RP", "SY", "TL", "XQ"
191   };
192 
193   char ain[3];
194   double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
195   int
196 	mpcnt, itmp1, itmp2, itmp3, itmp4,
197 	ain_num;   /* My addition, ain mnemonic as a number */
198   size_t mreq; /* My addition, size req. for malloc's   */
199 
200   /* initializations etc from original fortran code */
201   mpcnt = 0;
202 
203   /* Matrix parameters */
204   if( matpar.imat == 0)
205   {
206 	netcx.neq  = data.n+2*data.m;
207 	netcx.neq2 = 0;
208   }
209 
210   /* default values for input parameters and flags */
211   calc_data.rkh = 1.0;
212   calc_data.iexk = 0;
213   calc_data.iped = 0;
214   calc_data.nfrq = 1;
215   calc_data.fmhz = CVEL;
216   save.fmhz = CVEL;
217   calc_data.mxfrq = 0.0;
218   fpat.dth   = 0.0;
219   fpat.thets = 0.0;
220   fpat.ixtyp = 0;
221   fpat.nfeh  = 0;
222   fpat.nrx   = 0;
223   fpat.nry   = 0;
224   fpat.nry   = 0;
225   fpat.nth   = 0;
226   fpat.nph   = 0;
227   fpat.near = -1;
228   gnd.ifar  = -1;
229   gnd.zrati = CPLX_10;
230   gnd.ksymp = 1;
231   gnd.nradl = 0;
232   gnd.iperf = 0;
233   netcx.nonet = 0;
234   netcx.ntsol = 0;
235   netcx.masym = 0;
236   netcx.npeq = data.np+2*data.mp;
237 
238   /* My additions */
239   vsorc.nvqd   = 0;
240   vsorc.nsant  = 0;
241   zload.nldseg = 0;
242   zload.nload  = 0;
243 
244   /* Allocate some buffers */
245   mreq = (size_t)data.np2m * sizeof(int);
246   mem_realloc( (void **)&save.ip, mreq, "in input.c" );
247 
248   /* Memory allocation for symmetry array */
249   smat.nop = netcx.neq/netcx.npeq;
250   mreq = (size_t)(smat.nop * smat.nop) * sizeof( complex double);
251   mem_realloc( (void **)&smat.ssx, mreq, "in input.c" );
252 
253   /* main input section, exits at various points */
254   /* depending on error conditions or end of job */
255   while( TRUE )
256   {
257 	/* Main input section - standard read statement - jumps */
258 	/* to appropriate section for specific parameter set up */
259 	if( !readmn(
260 		  ain, &itmp1, &itmp2, &itmp3, &itmp4,
261 		  &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6) )
262 	  return( FALSE );
263 
264 	mpcnt++;
265 
266 	/* identify command card id mnemonic */
267 	for( ain_num = 0; ain_num < NUM_CMNDS; ain_num++ )
268 	  if( strncmp( ain, atst[ain_num], 2) == 0 )
269 		break;
270 
271 	/* take action according to card id mnemonic */
272 	switch( ain_num )
273 	{
274 	  case CM: /* "cm" card ignored, comments in data cards as in NEC4 */
275 		fprintf( stderr, "xnec2c: Read_Commands():"
276 			" ignoring CM card in commands\n" );
277 		stop( _("Read_Commands(): Ignoring CM card in commands"),
278 			ERR_OK );
279 		continue;
280 
281 	  case CP: /* "cp" card ignored, maximum coupling between antennas */
282 		stop( _("Read_Commands(): CP card is ignored\n"\
283 			  "Coupling calculation not implemented"), ERR_OK );
284 		continue; /* continue card input loop */
285 
286 	  case EK: /* "ek" card,  extended thin wire kernel option */
287 		if( itmp1 == -1)
288 		  calc_data.iexk = 0;
289 		else
290 		  calc_data.iexk = 1;
291 		continue; /* continue card input loop */
292 
293 	  case EN: /* "en" card, end data input, no action */
294 		break;
295 
296 	  case EX: /* "ex" card, excitation parameters */
297 		netcx.masym = itmp4/10;
298 		fpat.ixtyp  = itmp1;
299 
300 		/* Applied E field or current discontinuity */
301 		if( (fpat.ixtyp == 0) || (fpat.ixtyp == 5) )
302 		{
303 		  netcx.ntsol = 0;
304 
305 		  /* Current discontinuity E source */
306 		  if( fpat.ixtyp == 5 )
307 		  {
308 			vsorc.nvqd++;
309 			mreq = (size_t)vsorc.nvqd * sizeof(int);
310 			mem_realloc( (void **)&vsorc.ivqd, mreq, "in input.c" );
311 			mem_realloc( (void **)&vsorc.iqds, mreq, "in input.c" );
312 			mreq = (size_t)vsorc.nvqd * sizeof(complex double);
313 			mem_realloc( (void **)&vsorc.vqd, mreq, "in input.c" );
314 			mem_realloc( (void **)&vsorc.vqds, mreq, "in input.c" );
315 			{
316 			  int indx = vsorc.nvqd-1;
317 
318 			  if( (vsorc.ivqd[indx] = isegno(itmp2, itmp3)) < 0 )
319 				return( FALSE ); /* my addition, error */
320 			  vsorc.vqd[indx]= cmplx( tmp1, tmp2);
321 			  if( cabs( vsorc.vqd[indx]) < 1.0e-20)
322 				vsorc.vqd[indx] = CPLX_10;
323 
324 			  calc_data.iped   = itmp4- netcx.masym*10;
325 			  calc_data.zpnorm = tmp3;
326 			}
327 
328 		  } /* if( fpat.ixtyp == 5) */
329 		  else
330 		  {
331 			/* Else, applied E field */
332 			vsorc.nsant++;
333 			mreq = (size_t)vsorc.nsant * sizeof(int);
334 			mem_realloc( (void **)&vsorc.isant, mreq, "in input.c" );
335 			mreq = (size_t)vsorc.nsant * sizeof(complex double);
336 			mem_realloc( (void **)&vsorc.vsant, mreq, "in input.c" );
337 			{
338 			  int indx = vsorc.nsant-1;
339 
340 			  if( (vsorc.isant[indx] = isegno(itmp2, itmp3)) < 0 )
341 				  return( FALSE ); /* my addition, error condition */
342 			  vsorc.vsant[indx]= cmplx( tmp1, tmp2);
343 			  if( cabs( vsorc.vsant[indx]) < 1.0e-20)
344 				vsorc.vsant[indx] = CPLX_10;
345 
346 			  calc_data.iped= itmp4- netcx.masym*10;
347 			  calc_data.zpnorm= tmp3;
348 			  if( (calc_data.iped == 1) && (calc_data.zpnorm > 0.0) )
349 				calc_data.iped=2;
350 			}
351 
352 		  } /* if( fpat.ixtyp == 5 ) */
353 
354 		} /* if( (fpat.ixtyp == 0) || (fpat.ixtyp == 5) ) */
355 		else
356 		{
357 		  /* For fpat.ixtyp = 2|3|4 = incident field or current source */
358 		  calc_data.nthi= itmp2;
359 		  calc_data.nphi= itmp3;
360 		  calc_data.xpr1= tmp1;
361 		  calc_data.xpr2= tmp2;
362 		  calc_data.xpr3= tmp3;
363 		  calc_data.xpr4= tmp4;
364 		  calc_data.xpr5= tmp5;
365 		  calc_data.xpr6= tmp6;
366 		  vsorc.nsant=0;
367 		  vsorc.nvqd=0;
368 		  calc_data.thetis= tmp1;
369 		  calc_data.phiss= tmp2;
370 		}
371 
372 		SetFlag( ENABLE_EXCITN );
373 		continue; /* continue card input loop */
374 
375 	  case FR: /* "fr" card, frequency parameters */
376 		if( !CHILD )
377 		{
378 		  calc_data.nfrq = itmp2;
379 		  if( calc_data.nfrq <= 0)
380 			calc_data.nfrq = 1;
381 		}
382 		else calc_data.nfrq = 1;
383 
384 		/* Allocate normalization buffer */
385 		{
386 		  mreq = (size_t)calc_data.nfrq * sizeof(double);
387 		  mem_realloc( (void **)&impedance_data.zreal, mreq, "in input.c" );
388 		  mem_realloc( (void **)&impedance_data.zimag, mreq, "in input.c" );
389 		  mem_realloc( (void **)&impedance_data.zmagn, mreq, "in input.c" );
390 		  mem_realloc( (void **)&impedance_data.zphase, mreq, "in input.c" );
391 		  mem_realloc( (void **)&save.freq, mreq, "in input.c" );
392 		  mreq = (size_t)calc_data.nfrq * sizeof(char);
393 		  mem_realloc( (void **)&save.fstep, mreq, "in input.c" );
394 		}
395 
396 		if( CHILD ) continue;
397 
398 		calc_data.ifrq = itmp1;
399 		calc_data.fmhz = save.fmhz = tmp1;
400 
401 		/* My addition, max frequency */
402 		if( itmp1 == 0 )
403 		  calc_data.mxfrq =
404 			(double)tmp1 + (double)tmp2 * (double)(itmp2-1);
405 		else if( itmp1 == 1 )
406 		  calc_data.mxfrq =
407 			(double)tmp1 * pow( (double)tmp2, (double)(itmp2-1) );
408 
409 		/* My addition, extra features in "fr" card. */
410 		/* Specifies lower and upper value of frequency range */
411 		if( calc_data.ifrq == 2 )
412 		{
413 		  calc_data.nfrq++;
414 		  /* Linear frequency stepping */
415 		  if( calc_data.nfrq > 1 )
416 			calc_data.delfrq =
417 			  (tmp2 - tmp1)/(double)(calc_data.nfrq-1);
418 		  calc_data.ifrq  = 0;
419 		  calc_data.mxfrq = (double)tmp2; /* Max frequency */
420 		}
421 		else if( calc_data.ifrq == 3 )
422 		{
423 		  calc_data.nfrq++;
424 		  /* Multiplicative frequency stepping */
425 		  if( calc_data.nfrq > 1 )
426 			calc_data.delfrq =
427 			  pow( (tmp2-tmp1), 1.0/(double)(calc_data.nfrq-1) );
428 		  calc_data.ifrq  = 1;
429 		  calc_data.mxfrq = (double)tmp2; /* Max frequency */
430 		}
431 		else calc_data.delfrq = tmp2;
432 
433 		if( calc_data.iped == 1)
434 		  calc_data.zpnorm = 0.0;
435 		continue; /* continue card input loop */
436 
437 	  case GD: /* "gd" card, ground representation */
438 		fpat.epsr2 = tmp1;
439 		fpat.sig2  = tmp2;
440 		fpat.clt   = tmp3;
441 		fpat.cht   = tmp4;
442 		continue; /* continue card input loop */
443 
444 	  case GN: /* "gn" card, ground parameters under the antenna */
445 		gnd.iperf = itmp1;
446 		gnd.nradl = itmp2;
447 		gnd.ksymp = 2;
448 		save.epsr = tmp1;
449 		save.sig  = tmp2;
450 
451 		/* Theta must be less than 90 if ground present */
452 		double test = (double)(fpat.nth - 1) * fpat.dth + fpat.thets;
453 		if( (gnd.ifar != 1) && (test > 90.0) )
454 		{
455 		  fprintf( stderr,
456 			  "xnec2c: Read_Commands(): theta > 90 deg. with ground specified\n" );
457 		  stop( _("Read_Commands(): Theta > 90 deg with ground specified\n"\
458 				"Please check RP card data and correct"), ERR_OK );
459 		  return( FALSE );
460 		}
461 
462 		if( gnd.nradl > 0)
463 		{
464 		  if( gnd.iperf == 2)
465 		  {
466 			fprintf( stderr,
467 				"xnec2c: Read_Commands(): radial wire g.s. approximation\n"
468 				"may not be used with Sommerfeld ground option\n" );
469 			stop( _("Read_Commands(): radial wire g.s. approximation\n"\
470 				  "may not be used with Sommerfeld ground option"), ERR_OK );
471 			return( FALSE );
472 		  }
473 
474 		  save.scrwlt = tmp3;
475 		  save.scrwrt = tmp4;
476 		  continue; /* continue card input loop */
477 		} /* if( gnd.nradl > 0) */
478 		else
479 		{
480 		  save.scrwlt = 0.0;
481 		  save.scrwrt = 0.0;
482 		}
483 
484 		fpat.epsr2 = tmp3;
485 		fpat.sig2  = tmp4;
486 		fpat.clt   = tmp5;
487 		fpat.cht   = tmp6;
488 		continue; /* continue card input loop */
489 
490 	  case KH: /* "kh" card, matrix integration limit */
491 		calc_data.rkh = tmp1;
492 		continue; /* continue card input loop */
493 
494 	  case LD: /* "ld" card, loading parameters */
495 		{
496 		  int idx, nseg;
497 
498 		  /* Reallocate loading buffers */
499 		  zload.nload++;
500 		  mreq = (size_t)zload.nload * sizeof(int);
501 		  mem_realloc( (void **)&calc_data.ldtyp,  mreq, "in input.c" );
502 		  mem_realloc( (void **)&calc_data.ldtag,  mreq, "in input.c" );
503 		  mem_realloc( (void **)&calc_data.ldtagf, mreq, "in input.c" );
504 		  mem_realloc( (void **)&calc_data.ldtagt, mreq, "in input.c" );
505 
506 		  mreq = (size_t)zload.nload * sizeof(double);
507 		  mem_realloc( (void **)&calc_data.zlr, mreq, "in input.c" );
508 		  mem_realloc( (void **)&calc_data.zli, mreq, "in input.c" );
509 		  mem_realloc( (void **)&calc_data.zlc, mreq, "in input.c" );
510 
511 		  idx = zload.nload-1;
512 		  calc_data.ldtyp[idx]= itmp1;
513 		  calc_data.ldtag[idx]= itmp2;
514 		  if( itmp4 == 0) itmp4= itmp3;
515 		  calc_data.ldtagf[idx]= itmp3;
516 		  calc_data.ldtagt[idx]= itmp4;
517 
518 		  if( itmp4 < itmp3 )
519 		  {
520 			fprintf( stderr,
521 				"xnec2c: Read_Commands(): data fault on loading card no %d\n"
522 				"itag step1 %d is greater than itag step2 %d\n",
523 				zload.nload, itmp3, itmp4 );
524 			stop( _("Read_Commands(): Data fault on loading card\n"\
525 				  "itag step1 is greater than itag step2"), ERR_OK );
526 			return( FALSE );
527 		  }
528 
529 		  calc_data.zlr[idx]= tmp1;
530 		  calc_data.zli[idx]= tmp2;
531 		  calc_data.zlc[idx]= tmp3;
532 
533 		  /*** My addition, for drawing structure ***/
534 		  /* Work out absolute seg number of loaded segments (!) */
535 		  if( itmp1 == -1 ) /* Null all loads */
536 			zload.nldseg = 0;
537 		  else if( itmp2 == 0 ) /* No tag num */
538 		  {
539 			if( itmp3 == 0 ) /* All segs loaded */
540 			{
541 			  nseg = data.n;
542 			  mreq = (size_t)(nseg + zload.nldseg) * sizeof(int);
543 			  mem_realloc( (void **)&zload.ldsegn, mreq, "in input.c" );
544 			  mem_realloc( (void **)&zload.ldtype, mreq, "in input.c" );
545 			  for( idx = 0; idx < nseg; idx++ )
546 			  {
547 				zload.ldtype[zload.nldseg]   = itmp1;
548 				zload.ldsegn[zload.nldseg++] = idx+1;
549 			  }
550 			}
551 			else /* Absolute seg num specified */
552 			{
553 			  nseg = itmp4 - itmp3 + 1;
554 			  if( nseg <= 0 ) nseg = 1;
555 			  mreq = (size_t)(nseg + zload.nldseg) * sizeof(int);
556 			  mem_realloc( (void **)&zload.ldsegn, mreq, "in input.c" );
557 			  mem_realloc( (void **)&zload.ldtype, mreq, "in input.c" );
558 			  for( idx = 0; idx < nseg; idx++ )
559 			  {
560 				zload.ldtype[zload.nldseg]   = itmp1;
561 				zload.ldsegn[zload.nldseg++] = itmp3+idx;
562 			  }
563 			}
564 
565 		  } /* if( itmp2 == 0 ) */
566 		  else /* Tag num specified */
567 		  {
568 			if( (itmp3 == 0) && (itmp4 == 0) ) /* All segs of tag loaded */
569 			{
570 			  for( idx = 0; idx < data.n; idx++ )
571 				if( data.itag[idx] == itmp2 )
572 				{
573 				  mreq = (size_t)(zload.nldseg + 1) * sizeof(int);
574 				  mem_realloc( (void **)&zload.ldsegn, mreq, "in input.c" );
575 				  mem_realloc( (void **)&zload.ldtype, mreq, "in input.c" );
576 				  zload.ldtype[zload.nldseg]   = itmp1;
577 				  zload.ldsegn[zload.nldseg++] = idx+1;
578 				}
579 			}
580 			else /* A range of segs of tag loaded */
581 			{
582 			  nseg = itmp4 - itmp3 + 1;
583 			  if( nseg <= 0 ) nseg = 1; /* Just one seg of tag (=itmp3) */
584 			  mreq = (size_t)(zload.nldseg + nseg) * sizeof(int);
585 			  mem_realloc( (void **)&zload.ldsegn, mreq, "in input.c" );
586 			  mem_realloc( (void **)&zload.ldtype, mreq, "in input.c" );
587 			  for( idx = 0; idx < nseg; idx++ )
588 			  {
589 				zload.ldtype[zload.nldseg] = itmp1;
590 				if( (zload.ldsegn[zload.nldseg++] =
591 					  isegno(itmp2, itmp3+idx)) < 0 )
592 				  return( FALSE );
593 			  }
594 			}
595 		  }
596 		} /* case 8: */
597 		continue; /* continue card input loop */
598 
599 	  case NE: case NH:  /* "ne"/"nh" cards, near field calculation parameters */
600 		if( ain_num == 11 )
601 		  fpat.nfeh |= NEAR_HFIELD;
602 		else
603 		  fpat.nfeh |= NEAR_EFIELD;
604 
605 		fpat.near = itmp1;
606 		fpat.nrx  = itmp2;
607 		fpat.nry  = itmp3;
608 		fpat.nrz  = itmp4;
609 		fpat.xnr  = tmp1;
610 		fpat.ynr  = tmp2;
611 		fpat.znr  = tmp3;
612 		fpat.dxnr = tmp4;
613 		fpat.dynr = tmp5;
614 		fpat.dznr = tmp6;
615 
616 		if( (fpat.nrx > 0) &&
617 			(fpat.nry > 0) &&
618 			(fpat.nrz > 0) &&
619 			(fpat.near != -1) )
620 		{
621 		  SetFlag( ENABLE_NEAREH );
622 		  SetFlag( ALLOC_NEAREH_BUFF );
623 		  SetFlag( ALLOC_PNTING_BUFF );
624 		}
625 
626 		/* Because of the interactive GUI, program
627 		 * execution is not triggered by any card */
628 		continue; /* continue card input loop */
629 
630 	  case NT: case TL: /* "nt" & "tl" cards, network parameters */
631 		{
632 		  int idx;
633 
634 		  /* Re-allocate network buffers */
635 		  netcx.nonet++;
636 		  mreq = (size_t)netcx.nonet * sizeof(int);
637 		  mem_realloc( (void **)&netcx.ntyp,  mreq, "in input.c" );
638 		  mem_realloc( (void **)&netcx.iseg1, mreq, "in input.c" );
639 		  mem_realloc( (void **)&netcx.iseg2, mreq, "in input.c" );
640 
641 		  mreq = (size_t)netcx.nonet * sizeof(double);
642 		  mem_realloc( (void **)&netcx.x11r, mreq, "in input.c" );
643 		  mem_realloc( (void **)&netcx.x11i, mreq, "in input.c" );
644 		  mem_realloc( (void **)&netcx.x12r, mreq, "in input.c" );
645 		  mem_realloc( (void **)&netcx.x12i, mreq, "in input.c" );
646 		  mem_realloc( (void **)&netcx.x22r, mreq, "in input.c" );
647 		  mem_realloc( (void **)&netcx.x22i, mreq, "in input.c" );
648 
649 		  idx = netcx.nonet-1;
650 		  if( ain_num == 12 )
651 			netcx.ntyp[idx] = 1;
652 		  else
653 		  {
654 			netcx.ntyp[idx] = 2;
655 			if( tmp1 == 0.0 )
656 			{
657 			  fprintf( stderr,
658 				  "xnec2c: Read_Commands(): Transmission Line impedance = 0\n"
659 				  "is not valid. Please correct NT or TL card\n" );
660 			  stop( _("Read_Commands(): Transmission Line impedance = 0\n"\
661 					"is not valid. Please correct NT or TL card"), ERR_OK );
662 			  return( FALSE );
663 			}
664 		  }
665 
666 		  if( ((netcx.iseg1[idx] = isegno(itmp1, itmp2)) < 0) ||
667 			  ((netcx.iseg2[idx] = isegno(itmp3, itmp4)) < 0) )
668 		  {
669 			fprintf( stderr,
670 				"xnec2c: Read_Commands(): Segment number error in TL or NT card\n" );
671 			stop( _("Read_Commands(): Segment number\n"\
672 				"error in NT or TL card"), ERR_OK );
673 			return( FALSE );
674 		  }
675 		  netcx.x11r[idx]  = tmp1;
676 		  netcx.x11i[idx]  = tmp2;
677 		  netcx.x12r[idx]  = tmp3;
678 		  netcx.x12i[idx]  = tmp4;
679 		  netcx.x22r[idx]  = tmp5;
680 		  netcx.x22i[idx]  = tmp6;
681 
682 		  if( (netcx.ntyp[idx] == 1) || (tmp1 > 0.0) )
683 			continue; /* continue card input loop */
684 
685 		  netcx.ntyp[idx] = 3;
686 		  netcx.x11r[idx] = -tmp1;
687 		  continue; /* continue card input loop */
688 
689 		} /* case 12: case 17: */
690 
691 	  case PQ: case PT: /* "pq" and "pt" cards ignored, no printing */
692 		fprintf( stderr,
693 			"xnec2c: Read_Commands(): PQ and PT cards are ignored\n"
694 			"Printing to file not implemented\n" );
695 		stop( _("Read_Commands(): PQ and PT cards are ignored\n"\
696 			  "Printing to file not implemented"), ERR_OK );
697 		continue; /* continue card input loop */
698 
699 	  case RP: /* "rp" card, standard observation angle parameters */
700 		if( itmp1 == 1 )
701 		{
702 		  fprintf( stderr,
703 			  "xnec2c: Read_Commands(): Surface wave option (I1=1)\n"
704 			  "of RP command not implemented\n" );
705 		  stop( _("Read_Commands(): Surface wave option (I1=1)\n"\
706 				"of RP command not implemented"), ERR_OK );
707 		  return( FALSE );
708 		}
709 
710 		gnd.ifar = itmp1;
711 		fpat.nth = itmp2;
712 		fpat.nph = itmp3;
713 
714 		if( fpat.nth <= 0)
715 		  fpat.nth=1;
716 		if( fpat.nph <= 0)
717 		  fpat.nph=1;
718 
719 		fpat.ipd  = itmp4 / 10;
720 		fpat.iavp = itmp4 - fpat.ipd*10;
721 		fpat.inor = fpat.ipd / 10;
722 		fpat.ipd  = fpat.ipd - fpat.inor*10;
723 		fpat.iax  = fpat.inor / 10;
724 		fpat.inor = fpat.inor - fpat.iax*10;
725 
726 		if( fpat.iavp )
727 		{
728 		  fprintf( stderr,
729 			  "xnec2c: Read_Commands(): Gain averaging (XNDA ***1 or ***2)\n"
730 			  "of RP command not implemented\n" );
731 		  stop( _("Read_Commands(): Gain averaging (XNDA ***1 or ***2)\n"\
732 				"of RP command not supported"), ERR_OK );
733 		  return( FALSE );
734 		}
735 		if( fpat.iax != 0) fpat.iax = 1;
736 		if( fpat.ipd != 0) fpat.ipd = 1;
737 		fpat.thets = tmp1;
738 		fpat.phis  = tmp2;
739 		fpat.dth   = tmp3;
740 		fpat.dph   = tmp4;
741 		fpat.rfld  = tmp5;
742 		fpat.gnor  = tmp6;
743 
744 		/* Theta must be less than 90 if ground present */
745 		tmp1 = (double)(fpat.nth - 1) * fpat.dth + fpat.thets;
746 		if( (gnd.ksymp == 2) && (gnd.ifar != 1) && (tmp1 > 90.0) )
747 		{
748 		  fprintf( stderr,
749 			  "xnec2c: Read_Commands(): Theta > 90 deg. with ground specified\n"
750 			  "Please check RP card data and correct\n" );
751 		  stop( _("Read_Commands(): Theta > 90 deg. with ground specified\n"\
752 				"Please check RP card data and correct"), ERR_OK );
753 		  return( FALSE );
754 		}
755 
756 		/* Because of the interactive GUI, program
757 		 * execution is not triggered by any card */
758 		continue; /* continue card input loop */
759 
760 	  case SY: /* "sy" TODO Compatibility with 4nec2.
761 				  Too difficult, may never happen :-( */
762 		continue;
763 
764 	  case XQ: /* "xq" execute card */
765 		/* Because of the interactive GUI, program
766 		 * execution is not triggered by any card.
767 		 * XQ now is the same as EN because of above */
768 		if( itmp1 == 0 )
769 		  break; /* No rad pat, stop reading commands */
770 
771 		/* Read radiation pattern parameters */
772 		gnd.ifar  = 0;
773 		fpat.rfld = 0.0;
774 		fpat.ipd  = 0;
775 		fpat.iavp = 0;
776 		fpat.inor = 0;
777 		fpat.iax  = 0;
778 		fpat.nth  = 91;
779 		fpat.nph  = 1;
780 		fpat.thets= 0.0;
781 		fpat.phis = 0.0;
782 		fpat.dth  = 1.0;
783 		fpat.dph  = 0.0;
784 
785 		if( itmp1 == 2)
786 		  fpat.phis = 90.0;
787 		else if( itmp1 == 3)
788 		{
789 		  fpat.nph = 2;
790 		  fpat.dph = 90.0;
791 		}
792 
793 		SetFlag( ENABLE_RDPAT );
794 
795 		/* Because of the interactive GUI, program
796 		 * execution is not triggered by any card.
797 		 * XQ now is the same as EN because of above */
798 		break;
799 
800 	  default:
801 		fprintf( stderr,
802 			"xnec2c: Read_Commands(): faulty data "
803 			"card label after geometry section\n" );
804 		stop( _("Read_Commands(): Faulty data card\n"\
805 			  "label after geometry section"), ERR_OK );
806 		return( FALSE );
807 	} /* switch( ain_num ) */
808 
809 	/* Disable radiation pattern plots */
810 	if( (fpat.nth < 2) || (fpat.nph < 1) || (gnd.ifar == 1) )
811 	  ClearFlag( ENABLE_RDPAT );
812 	else
813 	{
814 	  /* Allocate radiation pattern buffers */
815 	  Alloc_Rdpattern_Buffers( calc_data.nfrq+1, fpat.nth, fpat.nph );
816 	  SetFlag( ENABLE_RDPAT );
817 	}
818 
819 	return( TRUE );
820   } /* while( TRUE ) */
821 
822 } /* Read_Commands() */
823 
824 /*-----------------------------------------------------------------------*/
825 
826   gboolean
readmn(char * mn,int * i1,int * i2,int * i3,int * i4,double * f1,double * f2,double * f3,double * f4,double * f5,double * f6)827 readmn( char *mn, int *i1, int *i2, int *i3, int *i4,
828 	double *f1, double *f2, double *f3,
829 	double *f4, double *f5, double *f6 )
830 {
831   char
832 	*line_buf = NULL,
833 	*startptr = NULL,
834 	*endptr   = NULL;
835   int len, i, idx;
836   int nint = 4, nflt = 6;
837   int iarr[4] = { 0, 0, 0, 0 };
838   double rarr[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
839   int eof; /* EOF error flag */
840 
841 
842   /* Clear return values */
843   *i1 = *i2 = *i3 = *i4 = 0;
844   *f1 = *f2 = *f3 = *f4 = *f5 = *f6 = 0.0;
845 
846   /* read a line from input file */
847   mem_alloc((void **)&line_buf, LINE_LEN, "in readmn()");
848   if( line_buf == NULL ) return( FALSE );
849   startptr = line_buf;
850   eof = Load_Line( line_buf, input_fp );
851   if( eof == EOF )
852   {
853 	Strlcpy( mn, "EN", 3 );
854 	fprintf( stderr,
855 		"xnec2c: readmn(): command data card error\n"
856 		"Unexpected EOF while reading input file - appending EN card\n" );
857 	stop( _("readmn(): Command data card error\n"\
858 		  "Unexpected EOF while reading input file\n"\
859 			"Uppending a default EN card"), ERR_OK );
860 	free_ptr( (void **)&startptr );
861 	return( FALSE );
862   }
863 
864   /* get line length */
865   len = (int)strlen( line_buf );
866 
867   /* abort if card's mnemonic too short or missing */
868   if( len < 2 )
869   {
870 	Strlcpy( mn, "XX", 3 );
871 	fprintf( stderr,
872 		"xnec2c: readmn(): command data card error\n"
873 		"card's mnemonic code too short or missing\n" );
874 	stop( _("readmn(): Command data card error\n"\
875 		  "Mnemonic code too short or missing"), ERR_OK );
876 	free_ptr( (void **)&startptr );
877 	return( FALSE );
878   }
879 
880   /* extract card's mnemonic code */
881   Strlcpy( mn, line_buf, 3 );
882 
883   /* Return if only mnemonic on card */
884   if( len == 2 )
885   {
886 	free_ptr( (void **)&startptr );
887 	return( TRUE );
888   }
889 
890   /* Compatibility with NEC4, comments between data cards */
891   if( strncmp(mn, "CM", 2) == 0 )
892   {
893 	free_ptr( (void **)&startptr );
894 	return( TRUE );
895   }
896 
897   /* check line for spurious characters */
898   for( idx = 2; idx < len; idx++ )
899   {
900 	if( ((line_buf[idx] >= '0') &&
901 		 (line_buf[idx] <= '9')) ||
902 		 (line_buf[idx] == ' ')  ||
903 		 (line_buf[idx] == '.')  ||
904 		 (line_buf[idx] == ',')  ||
905 		 (line_buf[idx] == '+')  ||
906 		 (line_buf[idx] == '-')  ||
907 		 (line_buf[idx] == 'E')  ||
908 		 (line_buf[idx] == 'e')  ||
909 		 (line_buf[idx] == '\t') ||
910 		 (line_buf[idx] == '\0') )
911 	  continue;
912 	else
913 	  break;
914   }
915   if( idx < len )
916   {
917 	fprintf( stderr,
918 		"xnec2c: readmn(): command data card \"%s\" error\n"
919 		"Spurious character '%c' at column %d\n",
920 		mn, line_buf[idx], idx+1 );
921 	stop( _("readmn(): Command data card error\n"\
922 		  "Spurious character in command card"), ERR_OK );
923 	free_ptr( (void **)&startptr );
924 	return( FALSE );
925   }
926 
927   /* read integers from line */
928   line_buf += 2;
929   for( i = 0; i < nint; i++ )
930   {
931 	/* read an integer from line */
932 	iarr[i] = (int)strtol( line_buf, &endptr, 10 );
933 	if( *endptr == '\0' ) break;
934 	line_buf = endptr + 1;
935   } /* for( i = 0; i < nint; i++ ) */
936 
937   /* Return if no floats are specified in the card */
938   if( *endptr == '\0' )
939   {
940 	*i1= iarr[0];
941 	*i2= iarr[1];
942 	*i3= iarr[2];
943 	*i4= iarr[3];
944 	*f1= rarr[0];
945 	*f2= rarr[1];
946 	*f3= rarr[2];
947 	*f4= rarr[3];
948 	*f5= rarr[4];
949 	*f6= rarr[5];
950 	free_ptr( (void **)&startptr );
951 	return( TRUE );
952   }
953 
954   /* read doubles from line */
955   for( i = 0; i < nflt; i++ )
956   {
957 	/* read a double from line */
958 	rarr[i] = Strtod( line_buf, &endptr );
959 	if( *endptr == '\0' ) break;
960 	line_buf = endptr + 1;
961   } /* for( i = 0; i < nflt; i++ ) */
962 
963   /* Return values on normal exit */
964   *i1= iarr[0];
965   *i2= iarr[1];
966   *i3= iarr[2];
967   *i4= iarr[3];
968   *f1= rarr[0];
969   *f2= rarr[1];
970   *f3= rarr[2];
971   *f4= rarr[3];
972   *f5= rarr[4];
973   *f6= rarr[5];
974 
975   free_ptr( (void **)&startptr );
976   return( TRUE );
977 } /* readmn() */
978 
979 /*-----------------------------------------------------------------------*/
980 
981   gboolean
readgm(char * gm,int * i1,int * i2,double * x1,double * y1,double * z1,double * x2,double * y2,double * z2,double * rad)982 readgm( char *gm, int *i1, int *i2, double *x1,
983 	double *y1, double *z1, double *x2,
984 	double *y2, double *z2, double *rad )
985 {
986   char
987 	*line_buf = NULL,
988 	*startptr = NULL,
989 	*endptr   = NULL;
990   int len, i, idx;
991   int nint = 2, nflt = 7;
992   int iarr[2] = { 0, 0 };
993   double rarr[7] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
994   int eof; /* EOF error flag */
995 
996 
997   /* Clear return values */
998   *i1 = *i2 = 0;
999   *x1 = *y1 = *z1 = *x2 = *y2 = *z2 = *rad = 0.0;
1000 
1001   /* read a line from input file */
1002   mem_alloc((void **)&line_buf, LINE_LEN, "in readgm()");
1003   if( line_buf == NULL ) return( FALSE );
1004   startptr = line_buf;
1005   eof = Load_Line( line_buf, input_fp );
1006   if( eof == EOF )
1007   {
1008 	Strlcpy( gm, "GE", 3 );
1009 	fprintf( stderr,
1010 		"xnec2c: readgm(): geometry data card error\n"
1011 		"Unexpected EOF while reading input file - appending GE card\n" );
1012 	stop( _("readgm(): Geometry data card error\n"\
1013 		  "Unexpected EOF while reading input file\n"\
1014 		  "Uppending a default GE card"), ERR_OK );
1015 	free_ptr( (void **)&startptr );
1016 	return( FALSE );
1017   }
1018 
1019   /* get line length */
1020   len = (int)strlen( line_buf );
1021 
1022   /* abort if card's mnemonic too short or missing */
1023   if( len < 2 )
1024   {
1025 	Strlcpy( gm, "XX", 3 );
1026 	fprintf( stderr,
1027 		"xnec2c: readgm(): geometry data card error\n"
1028 		"card's mnemonic code too short or missing\n" );
1029 	stop( _("readgm(): Geometry data card error\n"\
1030 		  "Card's mnemonic code too short or missing"), ERR_OK );
1031 	free_ptr( (void **)&startptr );
1032 	return( FALSE );
1033   }
1034 
1035   /* extract card's mnemonic code */
1036   Strlcpy( gm, line_buf, 3 );
1037 
1038   /* Return if only mnemonic on card */
1039   if( len == 2 )
1040   {
1041 	free_ptr( (void **)&startptr );
1042 	return( TRUE );
1043   }
1044 
1045   /* Compatibility with NEC4,
1046    * comments between data cards */
1047   if( strcmp(gm, "CM") == 0 )
1048   {
1049 	free_ptr( (void **)&startptr );
1050 	return( TRUE );
1051   }
1052 
1053   /* check line for spurious characters */
1054   for( idx = 2; idx < len; idx++ )
1055   {
1056 	if( ((line_buf[idx] >= '0') &&
1057 		 (line_buf[idx] <= '9')) ||
1058 		 (line_buf[idx] == ' ')  ||
1059 		 (line_buf[idx] == '.')  ||
1060 		 (line_buf[idx] == ',')  ||
1061 		 (line_buf[idx] == '+')  ||
1062 		 (line_buf[idx] == '-')  ||
1063 		 (line_buf[idx] == 'E')  ||
1064 		 (line_buf[idx] == 'e')  ||
1065 		 (line_buf[idx] == '\t') ||
1066 		 (line_buf[idx] == '\0') )
1067 	  continue;
1068 	else
1069 	  break;
1070   }
1071   if( idx < len )
1072   {
1073 	fprintf( stderr,
1074 		"xnec2c: readgm(): geometry data card \"%s\" error\n"
1075 		"Spurious character '%c' at column %d\n",
1076 		gm, line_buf[idx], idx+1 );
1077 	stop( _("readmn(): Geometry data card error\n"\
1078 		  "Spurious character in command card"), ERR_OK );
1079 	free_ptr( (void **)&startptr );
1080 	return( FALSE );
1081   }
1082 
1083   /* read integers from line */
1084   line_buf += 2;
1085   for( i = 0; i < nint; i++ )
1086   {
1087 	/* read an integer from line, reject spurious chars */
1088 	iarr[i] = (int)strtol( line_buf, &endptr, 10 );
1089 	if( *endptr == '\0' ) break;
1090 	line_buf = endptr + 1;
1091   } /* for( i = 0; i < nint; i++ ) */
1092 
1093   /* Return if no floats are specified in the card */
1094   if( *endptr == '\0' )
1095   {
1096 	*i1 = iarr[0];
1097 	*i2 = iarr[1];
1098 	*x1 = rarr[0];
1099 	*y1 = rarr[1];
1100 	*z1 = rarr[2];
1101 	*x2 = rarr[3];
1102 	*y2 = rarr[4];
1103 	*z2 = rarr[5];
1104 	*rad= rarr[6];
1105 	free_ptr( (void **)&startptr );
1106 	return( TRUE );
1107   }
1108 
1109   /* read doubles from line */
1110   for( i = 0; i < nflt; i++ )
1111   {
1112 	/* read a double from line */
1113 	rarr[i] = Strtod( line_buf, &endptr );
1114 	if( *endptr == '\0' ) break;
1115 	line_buf = endptr + 1;
1116   } /* for( i = 0; i < nflt; i++ ) */
1117 
1118   /* Return values on normal exit */
1119   *i1  = iarr[0];
1120   *i2  = iarr[1];
1121   *x1  = rarr[0];
1122   *y1  = rarr[1];
1123   *z1  = rarr[2];
1124   *x2  = rarr[3];
1125   *y2  = rarr[4];
1126   *z2  = rarr[5];
1127   *rad = rarr[6];
1128 
1129   free_ptr( (void **)&startptr );
1130   return( TRUE );
1131 } /* readgm() */
1132 
1133 /*-----------------------------------------------------------------------*/
1134 
1135 /* datagn is the main routine for input of geometry data. */
1136   gboolean
datagn(void)1137 datagn( void )
1138 {
1139   char gm[3];
1140 
1141   /* input card mnemonic list */
1142   char *atst[] =
1143   {
1144 	"GW", "GX", "GR", "GS", "GE","GM", "SP",\
1145 	"SM", "GA", "SC", "GH", "GF", "CT"
1146   };
1147 
1148   int nwire, isct, itg, iy=0, iz;
1149   size_t mreq;
1150   int ix, i, ns, gm_num; /* geometry card id as a number */
1151   double rad, xs1, xs2, ys1, ys2, zs1, zs2;
1152   double x3=0, y3=0, z3=0, x4=0, y4=0, z4=0;
1153   double xw1, xw2, yw1, yw2, zw1, zw2;
1154   double dummy;
1155 
1156   data.ipsym=0;
1157   nwire=0;
1158   data.n=0;
1159   data.np=0;
1160   data.m=0;
1161   data.mp=0;
1162   isct=0;
1163   structure_proj_params.r_max = 0.0;
1164 
1165   /* read geometry data card and branch to */
1166   /* section for operation requested */
1167   do
1168   {
1169 	if( !readgm(gm, &itg, &ns, &xw1, &yw1, &zw1, &xw2, &yw2, &zw2, &rad) )
1170 	  return( FALSE );
1171 
1172 	/* identify card id mnemonic */
1173 	for( gm_num = 0; gm_num < NUM_GEOMN; gm_num++ )
1174 	  if( strncmp( gm, atst[gm_num], 2) == 0 )
1175 		break;
1176 
1177 	if( gm_num != 9 ) isct=0;
1178 
1179 	switch( gm_num )
1180 	{
1181 	  case GW: /* "gw" card, generate segment data for straight wire. */
1182 		if( Tag_Seg_Error(itg, ns) ) return( FALSE );
1183 		nwire++;
1184 
1185 		if( rad != 0.0)
1186 		{
1187 		  xs1=1.0;
1188 		  ys1=1.0;
1189 		}
1190 		else
1191 		{
1192 		  if( !readgm(gm, &ix, &iy, &xs1, &ys1, &zs1,
1193 			  &dummy, &dummy, &dummy, &dummy) )
1194 			  return( FALSE );
1195 
1196 		  if( strcmp(gm, "GC" ) != 0 )
1197 		  {
1198 			fprintf( stderr,
1199 				"xnec2c: datagn(): geometry data card error "
1200 				"no GC card for tapered wire\n" );
1201 			stop( _("datagn(): Geometry data error\n"\
1202 				  "No GC card for tapered wire"), ERR_OK );
1203 			return( FALSE );
1204 		  }
1205 
1206 		  if( (ys1 == 0.0) || (zs1 == 0.0) )
1207 		  {
1208 			fprintf( stderr, "xnec2c: datagn(): geometry GC data card error\n" );
1209 			stop( _("datagn(): Geometry GC data card error"), ERR_OK );
1210 			return( FALSE );
1211 		  }
1212 
1213 		  rad= ys1;
1214 		  ys1= pow( (zs1/ys1), (1.0/(ns-1.0)) );
1215 		}
1216 
1217 		wire( xw1, yw1, zw1, xw2, yw2, zw2, rad, xs1, ys1, ns, itg);
1218 		continue;
1219 
1220 		/* reflect structure along x,y, or z */
1221 		/* axes or rotate to form cylinder.  */
1222 	  case GX: /* "gx" card */
1223 		if( (ns < 0) || (itg < 0) )
1224 		{
1225 		  fprintf( stderr, "xnec2c: datagn(): geometry GX data card error\n" );
1226 		  stop( _("datagn(): Geometry GX data card error"), ERR_OK );
1227 		  return( FALSE );
1228 		}
1229 
1230 		iy= ns/10;
1231 		iz= ns- iy*10;
1232 		ix= iy/10;
1233 		iy= iy- ix*10;
1234 
1235 		if( ix != 0)
1236 		  ix=1;
1237 		if( iy != 0)
1238 		  iy=1;
1239 		if( iz != 0)
1240 		  iz=1;
1241 
1242 		if( !reflc(ix, iy, iz, itg, ns) )
1243 		  return( FALSE );
1244 		continue;
1245 
1246 	  case GR: /* "gr" card */
1247 		if( (ns < 0) || (itg < 0) )
1248 		{
1249 		  fprintf( stderr, "xnec2c: datagn(): geometry GR data card error\n" );
1250 		  stop( _("datagn(): Geometry GR data card error"), ERR_OK );
1251 		  return( FALSE );
1252 		}
1253 
1254 		ix=-1;
1255 		iz = 0;
1256 		if( !reflc(ix, iy, iz, itg, ns) )
1257 		  return( FALSE );
1258 		continue;
1259 
1260 	  case GS: /* "gs" card, scale structure dimensions by factor xw1 */
1261 		if( (itg > 0) && (ns > 0) && (ns >= itg) )
1262 		{
1263 		  for( i = 0; i < data.n; i++ )
1264 		  {
1265 			if( (data.itag[i] >= itg) && (data.itag[i] <= ns) )
1266 			{
1267 			  data.x1[i]= data.x1[i]* xw1;
1268 			  data.y1[i]= data.y1[i]* xw1;
1269 			  data.z1[i]= data.z1[i]* xw1;
1270 			  data.x2[i]= data.x2[i]* xw1;
1271 			  data.y2[i]= data.y2[i]* xw1;
1272 			  data.z2[i]= data.z2[i]* xw1;
1273 			  data.bi[i]= data.bi[i]* xw1;
1274 			}
1275 		  }
1276 		  /* FIXME corrects errors when GS follows GX but this is just a work-around */
1277 		  data.np = data.n;
1278 		  data.ipsym = 0;
1279 		}
1280 		else for( i = 0; i < data.n; i++ )
1281 		{
1282 		  data.x1[i]= data.x1[i]* xw1;
1283 		  data.y1[i]= data.y1[i]* xw1;
1284 		  data.z1[i]= data.z1[i]* xw1;
1285 		  data.x2[i]= data.x2[i]* xw1;
1286 		  data.y2[i]= data.y2[i]* xw1;
1287 		  data.z2[i]= data.z2[i]* xw1;
1288 		  data.bi[i]= data.bi[i]* xw1;
1289 		}
1290 
1291 		yw1= xw1* xw1;
1292 		for( i = 0; i < data.m; i++ )
1293 		{
1294 		  data.px[i] = data.px[i]* xw1;
1295 		  data.py[i] = data.py[i]* xw1;
1296 		  data.pz[i] = data.pz[i]* xw1;
1297 		  data.pbi[i]= data.pbi[i]* yw1;
1298 		}
1299 		continue;
1300 
1301 	  case GE: /* "ge" card, terminate structure geometry input. */
1302 		/* My addition, for drawing */
1303 		if( ((data.n > 0) || (data.m > 0)) && !CHILD )
1304 		  Init_Struct_Drawing();
1305 		else if( (data.n == 0) && (data.m == 0) )
1306 		{
1307 		  stop( _("No geometry data cards"), ERR_OK );
1308 		  return( FALSE );
1309 		}
1310 
1311 		if( !conect(itg) ) return( FALSE );
1312 
1313 		if( data.n != 0)
1314 		{
1315 		  /* Allocate wire buffers */
1316 		  mreq = (size_t)data.n * sizeof(double);
1317 		  mem_realloc( (void **)&data.si,   mreq, "in input.c" );
1318 		  mem_realloc( (void **)&data.sab,  mreq, "in input.c" );
1319 		  mem_realloc( (void **)&data.cab,  mreq, "in input.c" );
1320 		  mem_realloc( (void **)&data.salp, mreq, "in input.c" );
1321 		  mem_realloc( (void **)&data.x, mreq, "in input.c" );
1322 		  mem_realloc( (void **)&data.y, mreq, "in input.c" );
1323 		  mem_realloc( (void **)&data.z, mreq, "in input.c" );
1324 
1325 		  for( i = 0; i < data.n; i++ )
1326 		  {
1327 			xw1= data.x2[i]- data.x1[i];
1328 			yw1= data.y2[i]- data.y1[i];
1329 			zw1= data.z2[i]- data.z1[i];
1330 			data.x[i]=( data.x1[i]+ data.x2[i])/2.0;
1331 			data.y[i]=( data.y1[i]+ data.y2[i])/2.0;
1332 			data.z[i]=( data.z1[i]+ data.z2[i])/2.0;
1333 			xw2= xw1* xw1+ yw1* yw1+ zw1* zw1;
1334 			yw2= sqrt( xw2);
1335 			//yw2=( xw2/yw2 + yw2)/2.0;
1336 			data.si[i]= yw2;
1337 			data.cab[i]= xw1/ yw2;
1338 			data.sab[i]= yw1/ yw2;
1339 
1340 			xw2= zw1/ yw2;
1341 			if( xw2 > 1.0)
1342 			  xw2=1.0;
1343 			if( xw2 < -1.0)
1344 			  xw2=-1.0;
1345 			data.salp[i]= xw2;
1346 
1347 			//xw2= asin( xw2)* TD;
1348 			//yw2= atan2( yw1, xw1)* TD;
1349 
1350 			if( (data.si[i] <= 1.0e-20) || (data.bi[i] <= 0.0) )
1351 			{
1352 			  fprintf( stderr, "xnec2c: datagn(): segment data error\n" );
1353 			  stop( _("datagn(): Segment data error"), ERR_OK );
1354 			  return( FALSE );
1355 			}
1356 
1357 		  } /* for( i = 0; i < data.n; i++ ) */
1358 
1359 		} /* if( data.n != 0) */
1360 
1361 		if( data.m != 0)
1362 		{
1363 		  for( i = 0; i < data.m; i++ )
1364 		  {
1365 			xw1=( data.t1y[i]* data.t2z[i] -
1366 				data.t1z[i]* data.t2y[i])* data.psalp[i];
1367 			yw1=( data.t1z[i]* data.t2x[i] -
1368 				data.t1x[i]* data.t2z[i])* data.psalp[i];
1369 			zw1=( data.t1x[i]* data.t2y[i] -
1370 				data.t1y[i]* data.t2x[i])* data.psalp[i];
1371 		  } /* for( i = 0; i < data.m; i++ ) */
1372 
1373 		} /* if( data.m != 0) */
1374 
1375 		data.npm  = data.n+data.m;
1376 		data.np2m = data.n+2*data.m;
1377 		data.np3m = data.n+3*data.m;
1378 
1379 		return( TRUE );
1380 
1381 		/* "gm" card, move structure or reproduce */
1382 		/* original structure in new positions.   */
1383 	  case GM:
1384 		{
1385 		  int tgf = (int)(rad + 0.5);
1386 		  if( (tgf < 0) || (ns < 0) || (rad < 0.0) )
1387 		  {
1388 			fprintf( stderr, "xnec2c: datagn(): move GM data card error\n" );
1389 			stop( _("datagn(): Move GM data card error"), ERR_OK );
1390 			return( FALSE );
1391 		  }
1392 		  xw1= xw1* TA;
1393 		  yw1= yw1* TA;
1394 		  zw1= zw1* TA;
1395 		  if( !move(xw1, yw1, zw1, xw2, yw2, zw2, (int)(rad+.5), ns, itg) )
1396 			return( FALSE );
1397 		}
1398 		continue;
1399 
1400 	  case SP: /* "sp" card, generate single new patch */
1401 		ns++;
1402 
1403 		if( itg != 0)
1404 		{
1405 		  fprintf( stderr, "xnec2c: datagn(): patch data card error\n" );
1406 		  stop( _("datagn(): Patch data card error"), ERR_OK );
1407 		  return( FALSE );
1408 		}
1409 
1410 		if( (ns == 2) || (ns == 4) )
1411 		  isct=1;
1412 
1413 		if( ns > 1)
1414 		{
1415 		  if( !readgm(gm, &ix, &iy, &x3, &y3,
1416 				&z3, &x4, &y4, &z4, &dummy) )
1417 			return( FALSE );
1418 
1419 		  if( (ns == 2) || (itg > 0) )
1420 		  {
1421 			x4= xw1+ x3- xw2;
1422 			y4= yw1+ y3- yw2;
1423 			z4= zw1+ z3- zw2;
1424 		  }
1425 
1426 		  if( strcmp(gm, "SC") != 0 )
1427 		  {
1428 			fprintf( stderr, "xnec2c: datagn(): patch data error\n" );
1429 			stop( _("datagn(): Patch data error"), ERR_OK );
1430 			return( FALSE );
1431 		  }
1432 
1433 		} /* if( ns > 1) */
1434 		else
1435 		{
1436 		  xw2= xw2* TA;
1437 		  yw2= yw2* TA;
1438 		}
1439 
1440 		if( !patch( itg, ns, xw1, yw1, zw1, xw2,
1441 			yw2, zw2, x3, y3, z3, x4, y4, z4) )
1442 			return( FALSE );
1443 		continue;
1444 
1445 	  case SM: /* "sm" card, generate multiple-patch surface */
1446 		if( (itg < 1) || (ns < 1) )
1447 		{
1448 		  fprintf( stderr, "datagn(): xnec2c: patch card data error\n" );
1449 		  stop( _("datagn(): Patch data card error"), ERR_OK );
1450 		  return( FALSE );
1451 		}
1452 
1453 		if( !readgm(gm, &ix, &iy, &x3, &y3,
1454 			  &z3, &x4, &y4, &z4, &dummy) )
1455 		  return( FALSE );
1456 
1457 		if( (ns == 2) || (itg > 0) )
1458 		{
1459 		  x4= xw1+ x3- xw2;
1460 		  y4= yw1+ y3- yw2;
1461 		  z4= zw1+ z3- zw2;
1462 		}
1463 
1464 		if( strcmp(gm, "SC" ) != 0 )
1465 		{
1466 		  fprintf( stderr, "xnec2c: datagn(): patch card data error\n" );
1467 		  stop( _("datagn(): Patch data card error"), ERR_OK );
1468 		  return( FALSE );
1469 		}
1470 
1471 		if( !patch(itg, ns, xw1, yw1, zw1, xw2,
1472 			yw2, zw2, x3, y3, z3, x4, y4, z4) )
1473 		  return( FALSE );
1474 		continue;
1475 
1476 	  case GA: /* "ga" card, generate segment data for wire arc */
1477 		if( Tag_Seg_Error(itg, ns) ) return( FALSE );
1478 		nwire++;
1479 		if( !arc(itg, ns, xw1, yw1, zw1, xw2) ) return( FALSE );
1480 		continue;
1481 
1482 	  case SC: /* "sc" card */
1483 		if( isct == 0)
1484 		{
1485 		  fprintf( stderr, "xnec2c: datagn(): patch data card error\n" );
1486 		  stop( _("datagn(): Patch data card error"), ERR_OK );
1487 		  return( FALSE );
1488 		}
1489 
1490 		ns++;
1491 
1492 		if( (itg != 0) || ((ns != 2) && (ns != 4)) )
1493 		{
1494 		  fprintf( stderr, "xnec2c: datagn(): patch data card error\n" );
1495 		  stop( _("datagn(): Patch data card error"), ERR_OK );
1496 		  return( FALSE );
1497 		}
1498 
1499 		xs1= x4;
1500 		ys1= y4;
1501 		zs1= z4;
1502 		xs2= x3;
1503 		ys2= y3;
1504 		zs2= z3;
1505 		x3= xw1;
1506 		y3= yw1;
1507 		z3= zw1;
1508 
1509 		if( ns == 4)
1510 		{
1511 		  x4= xw2;
1512 		  y4= yw2;
1513 		  z4= zw2;
1514 		}
1515 
1516 		xw1= xs1;
1517 		yw1= ys1;
1518 		zw1= zs1;
1519 		xw2= xs2;
1520 		yw2= ys2;
1521 		zw2= zs2;
1522 
1523 		if( ns != 4)
1524 		{
1525 		  x4= xw1+ x3- xw2;
1526 		  y4= yw1+ y3- yw2;
1527 		  z4= zw1+ z3- zw2;
1528 		}
1529 
1530 		if( !patch(itg, ns, xw1, yw1, zw1, xw2,
1531 			yw2, zw2, x3, y3, z3, x4, y4, z4) )
1532 		  return( FALSE );
1533 		continue;
1534 
1535 	  case GH: /* "gh" card, generate helix */
1536 		if( Tag_Seg_Error(itg, ns) ) return( FALSE );
1537 		nwire++;
1538 		helix( xw1, yw1, zw1, xw2, yw2, zw2, rad, ns, itg);
1539 		continue;
1540 
1541 	  case GF: /* "gf" card, not supported */
1542 		fprintf( stderr, "xnec2c: datagn(): \"GF\" card (NGF solution) "
1543 				"is not supported\n" );
1544 		stop( _("datagn(): \"GF\" card (NGF solution)\n"\
1545 			  "is not supported"), ERR_OK );
1546 		return( FALSE );
1547 
1548 	  case CT: /* Ignore in-data comments (NEC4 compatibility) */
1549 		fprintf( stderr, "xnec2c: datagn(): ignoring CM card in geometry\n" );
1550 		stop( _("datagn(): Ignoring CM card in geometry"), ERR_OK );
1551 		continue;
1552 
1553 	  default: /* error message */
1554 		fprintf( stderr, "xnec2c: datagn(): geometry data card error\n" );
1555 		fprintf( stderr,
1556 			"%2s %3d %5d %10.5f %10.5f %10.5f"
1557 			" %10.5f %10.5f %10.5f %10.5f\n",
1558 			gm, itg, ns, xw1, yw1, zw1, xw2, yw2, zw2, rad );
1559 
1560 		stop( _("datagn(): Geometry data card error"), ERR_OK );
1561 		return( FALSE );
1562 
1563 	} /* switch( gm_num ) */
1564 
1565   } /* do */
1566   while( TRUE );
1567 
1568 } /* datagn() */
1569 
1570 /*-----------------------------------------------------------------------*/
1571 
1572 /* Tag_Seg_Error()
1573  *
1574  * Checks tag and segments number are valid (>1)
1575  */
1576   gboolean
Tag_Seg_Error(int tag,int segs)1577 Tag_Seg_Error( int tag, int segs )
1578 {
1579   gboolean retv = FALSE;
1580 
1581   if( tag <= 0 )
1582   {
1583 	fprintf( stderr,
1584 		"xnec2c: Tag_Seg_Error(): geometry data card error -"
1585 		"tag number is less than 1\n" );
1586 	stop( _("Tag_Seg_Error(): Geometry data error\n"\
1587 		  "Tag number is less than 1"), ERR_OK );
1588 	retv = TRUE;
1589   }
1590 
1591   if( segs <= 0 )
1592   {
1593 	fprintf( stderr,
1594 		"xnec2c: Tag_Seg_Error(): geometry data card error - "
1595 		"number of segments is less than 1\n" );
1596 	stop( _("Tag_Seg_Error(): Geometry data error\n"\
1597 		  "Number of segments is less than 1"), ERR_OK );
1598 	retv = TRUE;
1599   }
1600 
1601   return( retv );
1602 }
1603 
1604 /*-----------------------------------------------------------------------*/
1605 
1606