Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | mjames | 1 | /* last change: pgm 8 nov 2000 1:04 pm |
2 | program somnec(input,output,tape21) |
||
3 | |||
4 | program to generate nec interpolation grids for fields due to |
||
5 | ground. field components are computed by numerical evaluation |
||
6 | of modified sommerfeld integrals. |
||
7 | |||
8 | somnec2d is a double precision version of somnec for use with |
||
9 | nec2d. an alternate version (somnec2sd) is also provided in which |
||
10 | computation is in single precision but the output file is written |
||
11 | in double precision for use with nec2d. somnec2sd runs about twic |
||
12 | as fast as the full double precision somnec2d. the difference |
||
13 | between nec2d results using a for021 file from this code rather |
||
14 | than from somnec2sd was insignficant in the cases tested. |
||
15 | |||
16 | changes made by j bergervoet, 31-5-95: |
||
17 | parameter 0. --> 0.d0 in calling of routine test |
||
18 | status of output files set to 'unknown' */ |
||
19 | |||
20 | #include "nec2c.h" |
||
21 | |||
22 | /* common /evlcom/ */ |
||
23 | static int jh; |
||
24 | static double ck2, ck2sq, tkmag, tsmag, ck1r, zph, rho; |
||
25 | static complex double ct1, ct2, ct3, ck1, ck1sq, cksm; |
||
26 | |||
27 | /* common /cntour/ */ |
||
28 | static complex double a, b; |
||
29 | |||
30 | /*common /ggrid/ */ |
||
31 | ggrid_t ggrid; |
||
32 | |||
33 | /*-----------------------------------------------------------------------*/ |
||
34 | |||
35 | /* This is the "main" of somnec */ |
||
36 | void somnec (double epr, double sig, double fmhz) |
||
37 | { |
||
38 | int k, nth, ith, irs, ir, nr; |
||
39 | double tim, wlam, tst, dr, dth, r, rk, thet, tfac1, tfac2; |
||
40 | complex double erv, ezv, erh, eph, cl1, cl2, con; |
||
41 | |||
42 | if (sig >= 0.) |
||
43 | { |
||
44 | wlam = CVEL / fmhz; |
||
45 | ggrid.epscf = cmplx (epr, -sig * wlam * 59.96); |
||
46 | } |
||
47 | else |
||
48 | ggrid.epscf = cmplx (epr, sig); |
||
49 | |||
50 | secnds (&tst); |
||
51 | ck2 = TP; |
||
52 | ck2sq = ck2 * ck2; |
||
53 | |||
54 | /* sommerfeld integral evaluation uses exp(-jwt), nec uses exp(+jwt), */ |
||
55 | /* hence need conjg(ggrid.epscf). conjugate of fields occurs in subroutine */ |
||
56 | /* evlua. */ |
||
57 | |||
58 | ck1sq = ck2sq * conj (ggrid.epscf); |
||
59 | ck1 = csqrtl (ck1sq); |
||
60 | ck1r = creal (ck1); |
||
61 | tkmag = 100. * cabs (ck1); |
||
62 | tsmag = 100. * ck1 * conj (ck1); |
||
63 | cksm = ck2sq / (ck1sq + ck2sq); |
||
64 | ct1 = .5 * (ck1sq - ck2sq); |
||
65 | erv = ck1sq * ck1sq; |
||
66 | ezv = ck2sq * ck2sq; |
||
67 | ct2 = .125 * (erv - ezv); |
||
68 | erv *= ck1sq; |
||
69 | ezv *= ck2sq; |
||
70 | ct3 = .0625 * (erv - ezv); |
||
71 | |||
72 | /* loop over 3 grid regions */ |
||
73 | for (k = 0; k < 3; k++) |
||
74 | { |
||
75 | nr = ggrid.nxa[k]; |
||
76 | nth = ggrid.nya[k]; |
||
77 | dr = ggrid.dxa[k]; |
||
78 | dth = ggrid.dya[k]; |
||
79 | r = ggrid.xsa[k] - dr; |
||
80 | irs = 1; |
||
81 | if (k == 0) |
||
82 | { |
||
83 | r = ggrid.xsa[k]; |
||
84 | irs = 2; |
||
85 | } |
||
86 | |||
87 | /* loop over r. (r=sqrtl(rho**2 + (z+h)**2)) */ |
||
88 | for (ir = irs - 1; ir < nr; ir++) |
||
89 | { |
||
90 | r += dr; |
||
91 | thet = ggrid.ysa[k] - dth; |
||
92 | |||
93 | /* loop over theta. (theta=atan((z+h)/rho)) */ |
||
94 | for (ith = 0; ith < nth; ith++) |
||
95 | { |
||
96 | thet += dth; |
||
97 | rho = r * cosl (thet); |
||
98 | zph = r * sinl (thet); |
||
99 | if (rho < 1.e-7) |
||
100 | rho = 1.e-8; |
||
101 | if (zph < 1.e-7) |
||
102 | zph = 0.; |
||
103 | |||
104 | evlua (&erv, &ezv, &erh, &eph); |
||
105 | |||
106 | rk = ck2 * r; |
||
107 | con = -CONST1 * r / cmplx (cosl (rk), -sinl (rk)); |
||
108 | |||
109 | switch (k) |
||
110 | { |
||
111 | case 0: |
||
112 | ggrid.ar1[ir + ith * 11 + 0] = erv * con; |
||
113 | ggrid.ar1[ir + ith * 11 + 110] = ezv * con; |
||
114 | ggrid.ar1[ir + ith * 11 + 220] = erh * con; |
||
115 | ggrid.ar1[ir + ith * 11 + 330] = eph * con; |
||
116 | break; |
||
117 | |||
118 | case 1: |
||
119 | ggrid.ar2[ir + ith * 17 + 0] = erv * con; |
||
120 | ggrid.ar2[ir + ith * 17 + 85] = ezv * con; |
||
121 | ggrid.ar2[ir + ith * 17 + 170] = erh * con; |
||
122 | ggrid.ar2[ir + ith * 17 + 255] = eph * con; |
||
123 | break; |
||
124 | |||
125 | case 2: |
||
126 | ggrid.ar3[ir + ith * 9 + 0] = erv * con; |
||
127 | ggrid.ar3[ir + ith * 9 + 72] = ezv * con; |
||
128 | ggrid.ar3[ir + ith * 9 + 144] = erh * con; |
||
129 | ggrid.ar3[ir + ith * 9 + 216] = eph * con; |
||
130 | |||
131 | } /* switch( k ) */ |
||
132 | |||
133 | } /* for( ith = 0; ith < nth; ith++ ) */ |
||
134 | |||
135 | } /* for( ir = irs-1; ir < nr; ir++; ) */ |
||
136 | |||
137 | } /* for( k = 0; k < 3; k++; ) */ |
||
138 | |||
139 | /* fill grid 1 for r equal to zero. */ |
||
140 | cl2 = -CONST4 * (ggrid.epscf - 1.) / (ggrid.epscf + 1.); |
||
141 | cl1 = cl2 / (ggrid.epscf + 1.); |
||
142 | ezv = ggrid.epscf * cl1; |
||
143 | thet = -dth; |
||
144 | nth = ggrid.nya[0]; |
||
145 | |||
146 | for (ith = 0; ith < nth; ith++) |
||
147 | { |
||
148 | thet += dth; |
||
149 | if ((ith + 1) != nth) |
||
150 | { |
||
151 | tfac2 = cosl (thet); |
||
152 | tfac1 = (1. - sinl (thet)) / tfac2; |
||
153 | tfac2 = tfac1 / tfac2; |
||
154 | erv = ggrid.epscf * cl1 * tfac1; |
||
155 | erh = cl1 * (tfac2 - 1.) + cl2; |
||
156 | eph = cl1 * tfac2 - cl2; |
||
157 | } |
||
158 | else |
||
159 | { |
||
160 | erv = 0.; |
||
161 | erh = cl2 - .5 * cl1; |
||
162 | eph = -erh; |
||
163 | } |
||
164 | |||
165 | ggrid.ar1[0 + ith * 11 + 0] = erv; |
||
166 | ggrid.ar1[0 + ith * 11 + 110] = ezv; |
||
167 | ggrid.ar1[0 + ith * 11 + 220] = erh; |
||
168 | ggrid.ar1[0 + ith * 11 + 330] = eph; |
||
169 | } |
||
170 | |||
171 | secnds (&tim); |
||
172 | tim -= tst; |
||
173 | |||
174 | return; |
||
175 | } |
||
176 | |||
177 | /*-----------------------------------------------------------------------*/ |
||
178 | |||
179 | /* bessel evaluates the zero-order bessel function */ |
||
180 | /* and its derivative for complex argument z. */ |
||
181 | void bessel (complex double z, complex double *j0, complex double *j0p) |
||
182 | { |
||
183 | int k, i, ib, iz, miz; |
||
184 | static int m[101], init = FALSE; |
||
185 | static double a1[25], a2[25]; |
||
186 | double tst, zms; |
||
187 | complex double p0z, p1z, q0z, q1z, zi, zi2, zk, cz, sz, j0x = CPLX_00, j0px = CPLX_00; |
||
188 | |||
189 | /* initialization of constants */ |
||
190 | if (!init) |
||
191 | { |
||
192 | for (k = 1; k <= 25; k++) |
||
193 | { |
||
194 | i = k - 1; |
||
195 | a1[i] = -.25 / (k * k); |
||
196 | a2[i] = 1.0 / (k + 1.0); |
||
197 | } |
||
198 | |||
199 | for (i = 1; i <= 101; i++) |
||
200 | { |
||
201 | tst = 1.0; |
||
202 | for (k = 0; k < 24; k++) |
||
203 | { |
||
204 | init = k; |
||
205 | tst *= -i * a1[k]; |
||
206 | if (tst < 1.0e-6) |
||
207 | break; |
||
208 | } |
||
209 | |||
210 | m[i - 1] = init + 1; |
||
211 | } /* for( i = 1; i<= 101; i++ ) */ |
||
212 | |||
213 | init = TRUE; |
||
214 | } /* if(init == 0) */ |
||
215 | |||
216 | zms = z * conj (z); |
||
217 | if (zms <= 1.e-12) |
||
218 | { |
||
219 | *j0 = CPLX_10; |
||
220 | *j0p = -.5 * z; |
||
221 | return; |
||
222 | } |
||
223 | |||
224 | ib = 0; |
||
225 | if (zms <= 37.21) |
||
226 | { |
||
227 | if (zms > 36.) |
||
228 | ib = 1; |
||
229 | |||
230 | /* series expansion */ |
||
231 | iz = zms; |
||
232 | miz = m[iz]; |
||
233 | *j0 = CPLX_10; |
||
234 | *j0p = *j0; |
||
235 | zk = *j0; |
||
236 | zi = z * z; |
||
237 | |||
238 | for (k = 0; k < miz; k++) |
||
239 | { |
||
240 | zk *= a1[k] * zi; |
||
241 | *j0 += zk; |
||
242 | *j0p += a2[k] * zk; |
||
243 | } |
||
244 | *j0p *= -.5 * z; |
||
245 | |||
246 | if (ib == 0) |
||
247 | return; |
||
248 | |||
249 | j0x = *j0; |
||
250 | j0px = *j0p; |
||
251 | } |
||
252 | |||
253 | /* asymptotic expansion */ |
||
254 | zi = 1. / z; |
||
255 | zi2 = zi * zi; |
||
256 | p0z = 1. + (P20 * zi2 - P10) * zi2; |
||
257 | p1z = 1. + (P11 - P21 * zi2) * zi2; |
||
258 | q0z = (Q20 * zi2 - Q10) * zi; |
||
259 | q1z = (Q11 - Q21 * zi2) * zi; |
||
260 | zk = cexp (CPLX_01 * (z - POF)); |
||
261 | zi2 = 1. / zk; |
||
262 | cz = .5 * (zk + zi2); |
||
263 | sz = CPLX_01 * .5 * (zi2 - zk); |
||
264 | zk = C3 * csqrtl (zi); |
||
265 | *j0 = zk * (p0z * cz - q0z * sz); |
||
266 | *j0p = -zk * (p1z * sz + q1z * cz); |
||
267 | |||
268 | if (ib == 0) |
||
269 | return; |
||
270 | |||
271 | zms = cosl ((sqrtl (zms) - 6.) * PI10); |
||
272 | *j0 = .5 * (j0x * (1. + zms) + *j0 * (1. - zms)); |
||
273 | *j0p = .5 * (j0px * (1. + zms) + *j0p * (1. - zms)); |
||
274 | |||
275 | return; |
||
276 | } |
||
277 | |||
278 | /*-----------------------------------------------------------------------*/ |
||
279 | |||
280 | /* evlua controls the integration contour in the complex */ |
||
281 | /* lambda plane for evaluation of the sommerfeld integrals */ |
||
282 | void evlua (complex double *erv, complex double *ezv, complex double *erh, complex double *eph) |
||
283 | { |
||
284 | int i, jump; |
||
285 | static double del, slope, rmis; |
||
286 | static complex double cp1, cp2, cp3, bk, delta, delta2, sum[6], ans[6]; |
||
287 | |||
288 | del = zph; |
||
289 | if (rho > del) |
||
290 | del = rho; |
||
291 | |||
292 | if (zph >= 2. * rho) |
||
293 | { |
||
294 | /* bessel function form of sommerfeld integrals */ |
||
295 | jh = 0; |
||
296 | a = CPLX_00; |
||
297 | del = 1. / del; |
||
298 | |||
299 | if (del > tkmag) |
||
300 | { |
||
301 | b = cmplx (.1 * tkmag, -.1 * tkmag); |
||
302 | rom1 (6, sum, 2); |
||
303 | a = b; |
||
304 | b = cmplx (del, -del); |
||
305 | rom1 (6, ans, 2); |
||
306 | for (i = 0; i < 6; i++) |
||
307 | sum[i] += ans[i]; |
||
308 | } |
||
309 | else |
||
310 | { |
||
311 | b = cmplx (del, -del); |
||
312 | rom1 (6, sum, 2); |
||
313 | } |
||
314 | |||
315 | delta = PTP * del; |
||
316 | gshank (b, delta, ans, 6, sum, 0, b, b); |
||
317 | ans[5] *= ck1; |
||
318 | |||
319 | /* conjugate since nec uses exp(+jwt) */ |
||
320 | *erv = conj (ck1sq * ans[2]); |
||
321 | *ezv = conj (ck1sq * (ans[1] + ck2sq * ans[4])); |
||
322 | *erh = conj (ck2sq * (ans[0] + ans[5])); |
||
323 | *eph = -conj (ck2sq * (ans[3] + ans[5])); |
||
324 | |||
325 | return; |
||
326 | |||
327 | } /* if(zph >= 2.*rho) */ |
||
328 | |||
329 | /* hankel function form of sommerfeld integrals */ |
||
330 | jh = 1; |
||
331 | cp1 = cmplx (0.0, .4 * ck2); |
||
332 | cp2 = cmplx (.6 * ck2, -.2 * ck2); |
||
333 | cp3 = cmplx (1.02 * ck2, -.2 * ck2); |
||
334 | a = cp1; |
||
335 | b = cp2; |
||
336 | rom1 (6, sum, 2); |
||
337 | a = cp2; |
||
338 | b = cp3; |
||
339 | rom1 (6, ans, 2); |
||
340 | |||
341 | for (i = 0; i < 6; i++) |
||
342 | sum[i] = -(sum[i] + ans[i]); |
||
343 | |||
344 | /* path from imaginary axis to -infinity */ |
||
345 | if (zph > .001 * rho) |
||
346 | slope = rho / zph; |
||
347 | else |
||
348 | slope = 1000.; |
||
349 | |||
350 | del = PTP / del; |
||
351 | delta = cmplx (-1.0, slope) * del / sqrtl (1. + slope * slope); |
||
352 | delta2 = -conj (delta); |
||
353 | gshank (cp1, delta, ans, 6, sum, 0, bk, bk); |
||
354 | rmis = rho * (creal (ck1) - ck2); |
||
355 | |||
356 | jump = FALSE; |
||
357 | if ((rmis >= 2. * ck2) && (rho >= 1.e-10)) |
||
358 | { |
||
359 | if (zph >= 1.e-10) |
||
360 | { |
||
361 | bk = cmplx (-zph, rho) * (ck1 - cp3); |
||
362 | rmis = -creal (bk) / fabsl (cimag (bk)); |
||
363 | if (rmis > 4. * rho / zph) |
||
364 | jump = TRUE; |
||
365 | } |
||
366 | |||
367 | if (!jump) |
||
368 | { |
||
369 | /* integrate up between branch cuts, then to + infinity */ |
||
370 | cp1 = ck1 - (.1 + .2fj); |
||
371 | cp2 = cp1 + .2; |
||
372 | bk = cmplx (0., del); |
||
373 | gshank (cp1, bk, sum, 6, ans, 0, bk, bk); |
||
374 | a = cp1; |
||
375 | b = cp2; |
||
376 | rom1 (6, ans, 1); |
||
377 | for (i = 0; i < 6; i++) |
||
378 | ans[i] -= sum[i]; |
||
379 | |||
380 | gshank (cp3, bk, sum, 6, ans, 0, bk, bk); |
||
381 | gshank (cp2, delta2, ans, 6, sum, 0, bk, bk); |
||
382 | } |
||
383 | |||
384 | jump = TRUE; |
||
385 | |||
386 | } /* if( (rmis >= 2.*ck2) || (rho >= 1.e-10) ) */ |
||
387 | else |
||
388 | jump = FALSE; |
||
389 | |||
390 | if (!jump) |
||
391 | { |
||
392 | /* integrate below branch points, then to + infinity */ |
||
393 | for (i = 0; i < 6; i++) |
||
394 | sum[i] = -ans[i]; |
||
395 | |||
396 | rmis = creal (ck1) * 1.01; |
||
397 | if ((ck2 + 1.) > rmis) |
||
398 | rmis = ck2 + 1.; |
||
399 | |||
400 | bk = cmplx (rmis, .99 * cimag (ck1)); |
||
401 | delta = bk - cp3; |
||
402 | delta *= del / cabs (delta); |
||
403 | gshank (cp3, delta, ans, 6, sum, 1, bk, delta2); |
||
404 | |||
405 | } /* if( ! jump ) */ |
||
406 | |||
407 | ans[5] *= ck1; |
||
408 | |||
409 | /* conjugate since nec uses exp(+jwt) */ |
||
410 | *erv = conj (ck1sq * ans[2]); |
||
411 | *ezv = conj (ck1sq * (ans[1] + ck2sq * ans[4])); |
||
412 | *erh = conj (ck2sq * (ans[0] + ans[5])); |
||
413 | *eph = -conj (ck2sq * (ans[3] + ans[5])); |
||
414 | |||
415 | return; |
||
416 | } |
||
417 | |||
418 | /*-----------------------------------------------------------------------*/ |
||
419 | |||
420 | /* fbar is sommerfeld attenuation function for numerical distance p */ |
||
421 | void fbar (complex double p, complex double *fbar) |
||
422 | { |
||
423 | int i, minus; |
||
424 | double tms, sms; |
||
425 | complex double z, zs, sum, pow, term; |
||
426 | |||
427 | z = CPLX_01 * csqrtl (p); |
||
428 | if (cabs (z) <= 3.) |
||
429 | { |
||
430 | /* series expansion */ |
||
431 | zs = z * z; |
||
432 | sum = z; |
||
433 | pow = z; |
||
434 | |||
435 | for (i = 1; i <= 100; i++) |
||
436 | { |
||
437 | pow = -pow * zs / (double) i; |
||
438 | term = pow / (2. * i + 1.); |
||
439 | sum = sum + term; |
||
440 | tms = creal (term * conj (term)); |
||
441 | sms = creal (sum * conj (sum)); |
||
442 | if (tms / sms < ACCS) |
||
443 | break; |
||
444 | } |
||
445 | |||
446 | *fbar = 1. - (1. - sum * TOSP) * z * cexp (zs) * SP; |
||
447 | |||
448 | } /* if( cabs( z) <= 3.) */ |
||
449 | |||
450 | /* asymptotic expansion */ |
||
451 | if (creal (z) < 0.) |
||
452 | { |
||
453 | minus = 1; |
||
454 | z = -z; |
||
455 | } |
||
456 | else |
||
457 | minus = 0; |
||
458 | |||
459 | zs = .5 / (z * z); |
||
460 | sum = CPLX_00; |
||
461 | term = CPLX_10; |
||
462 | |||
463 | for (i = 1; i <= 6; i++) |
||
464 | { |
||
465 | term = -term * (2. * i - 1.) * zs; |
||
466 | sum += term; |
||
467 | } |
||
468 | |||
469 | if (minus == 1) |
||
470 | sum -= 2. * SP * z * cexp (z * z); |
||
471 | *fbar = -sum; |
||
472 | } |
||
473 | |||
474 | /*-----------------------------------------------------------------------*/ |
||
475 | |||
476 | /* gshank integrates the 6 sommerfeld integrals from start to */ |
||
477 | /* infinity (until convergence) in lambda. at the break point, bk, */ |
||
478 | /* the step increment may be changed from dela to delb. shank's */ |
||
479 | /* algorithm to accelerate convergence of a slowly converging series */ |
||
480 | /* is used */ |
||
481 | void gshank ( |
||
482 | complex double start, |
||
483 | complex double dela, |
||
484 | complex double *sum, |
||
485 | int nans, |
||
486 | complex double *seed, |
||
487 | int ibk, |
||
488 | complex double bk, |
||
489 | complex double delb) |
||
490 | { |
||
491 | int ibx, j, i, jm, intx, inx, brk = 0; |
||
492 | static double rbk, amg, den, denm; |
||
493 | complex double a1, a2, as1, as2, del, aa; |
||
494 | complex double q1[6][20], q2[6][20], ans1[6], ans2[6]; |
||
495 | |||
496 | rbk = creal (bk); |
||
497 | del = dela; |
||
498 | if (ibk == 0) |
||
499 | ibx = 1; |
||
500 | else |
||
501 | ibx = 0; |
||
502 | |||
503 | for (i = 0; i < nans; i++) |
||
504 | ans2[i] = seed[i]; |
||
505 | |||
506 | b = start; |
||
507 | for (intx = 1; intx <= MAXH; intx++) |
||
508 | { |
||
509 | inx = intx - 1; |
||
510 | a = b; |
||
511 | b += del; |
||
512 | |||
513 | if ((ibx == 0) && (creal (b) >= rbk)) |
||
514 | { |
||
515 | /* hit break point. reset seed and start over. */ |
||
516 | ibx = 1; |
||
517 | b = bk; |
||
518 | del = delb; |
||
519 | rom1 (nans, sum, 2); |
||
520 | if (ibx != 2) |
||
521 | { |
||
522 | for (i = 0; i < nans; i++) |
||
523 | ans2[i] += sum[i]; |
||
524 | intx = 0; |
||
525 | continue; |
||
526 | } |
||
527 | |||
528 | for (i = 0; i < nans; i++) |
||
529 | ans2[i] = ans1[i] + sum[i]; |
||
530 | intx = 0; |
||
531 | continue; |
||
532 | |||
533 | } /* if( (ibx == 0) && (creal(b) >= rbk) ) */ |
||
534 | |||
535 | rom1 (nans, sum, 2); |
||
536 | for (i = 0; i < nans; i++) |
||
537 | ans1[i] = ans2[i] + sum[i]; |
||
538 | a = b; |
||
539 | b += del; |
||
540 | |||
541 | if ((ibx == 0) && (creal (b) >= rbk)) |
||
542 | { |
||
543 | /* hit break point. reset seed and start over. */ |
||
544 | ibx = 2; |
||
545 | b = bk; |
||
546 | del = delb; |
||
547 | rom1 (nans, sum, 2); |
||
548 | if (ibx != 2) |
||
549 | { |
||
550 | for (i = 0; i < nans; i++) |
||
551 | ans2[i] += sum[i]; |
||
552 | intx = 0; |
||
553 | continue; |
||
554 | } |
||
555 | |||
556 | for (i = 0; i < nans; i++) |
||
557 | ans2[i] = ans1[i] + sum[i]; |
||
558 | intx = 0; |
||
559 | continue; |
||
560 | |||
561 | } /* if( (ibx == 0) && (creal(b) >= rbk) ) */ |
||
562 | |||
563 | rom1 (nans, sum, 2); |
||
564 | for (i = 0; i < nans; i++) |
||
565 | ans2[i] = ans1[i] + sum[i]; |
||
566 | |||
567 | den = 0.; |
||
568 | for (i = 0; i < nans; i++) |
||
569 | { |
||
570 | as1 = ans1[i]; |
||
571 | as2 = ans2[i]; |
||
572 | |||
573 | if (intx >= 2) |
||
574 | { |
||
575 | for (j = 1; j < intx; j++) |
||
576 | { |
||
577 | jm = j - 1; |
||
578 | aa = q2[i][jm]; |
||
579 | a1 = q1[i][jm] + as1 - 2. * aa; |
||
580 | |||
581 | if ((creal (a1) != 0.) || (cimag (a1) != 0.)) |
||
582 | { |
||
583 | a2 = aa - q1[i][jm]; |
||
584 | a1 = q1[i][jm] - a2 * a2 / a1; |
||
585 | } |
||
586 | else |
||
587 | a1 = q1[i][jm]; |
||
588 | |||
589 | a2 = aa + as2 - 2. * as1; |
||
590 | if ((creal (a2) != 0.) || (cimag (a2) != 0.)) |
||
591 | a2 = aa - (as1 - aa) * (as1 - aa) / a2; |
||
592 | else |
||
593 | a2 = aa; |
||
594 | |||
595 | q1[i][jm] = as1; |
||
596 | q2[i][jm] = as2; |
||
597 | as1 = a1; |
||
598 | as2 = a2; |
||
599 | |||
600 | } /* for( j = 1; i < intx; i++ ) */ |
||
601 | |||
602 | } /* if(intx >= 2) */ |
||
603 | |||
604 | q1[i][intx - 1] = as1; |
||
605 | q2[i][intx - 1] = as2; |
||
606 | amg = fabsl (creal (as2)) + fabsl (cimag (as2)); |
||
607 | if (amg > den) |
||
608 | den = amg; |
||
609 | |||
610 | } /* for( i = 0; i < nans; i++ ) */ |
||
611 | |||
612 | denm = 1.e-3 * den * CRIT; |
||
613 | jm = intx - 3; |
||
614 | if (jm < 1) |
||
615 | jm = 1; |
||
616 | |||
617 | for (j = jm - 1; j < intx; j++) |
||
618 | { |
||
619 | brk = FALSE; |
||
620 | for (i = 0; i < nans; i++) |
||
621 | { |
||
622 | a1 = q2[i][j]; |
||
623 | den = (fabsl (creal (a1)) + fabsl (cimag (a1))) * CRIT; |
||
624 | if (den < denm) |
||
625 | den = denm; |
||
626 | a1 = q1[i][j] - a1; |
||
627 | amg = fabsl (creal (a1) + fabsl (cimag (a1))); |
||
628 | if (amg > den) |
||
629 | { |
||
630 | brk = TRUE; |
||
631 | break; |
||
632 | } |
||
633 | |||
634 | } /* for( i = 0; i < nans; i++ ) */ |
||
635 | |||
636 | if (brk) |
||
637 | break; |
||
638 | |||
639 | } /* for( j = jm-1; j < intx; j++ ) */ |
||
640 | |||
641 | if (!brk) |
||
642 | { |
||
643 | for (i = 0; i < nans; i++) |
||
644 | sum[i] = .5 * (q1[i][inx] + q2[i][inx]); |
||
645 | return; |
||
646 | } |
||
647 | |||
648 | } /* for( intx = 1; intx <= maxh; intx++ ) */ |
||
649 | |||
650 | /* No convergence */ |
||
651 | abort_on_error (-6); |
||
652 | } |
||
653 | |||
654 | /*-----------------------------------------------------------------------*/ |
||
655 | |||
656 | /* hankel evaluates hankel function of the first kind, */ |
||
657 | /* order zero, and its derivative for complex argument z */ |
||
658 | void hankel (complex double z, complex double *h0, complex double *h0p) |
||
659 | { |
||
660 | int i, k, ib, iz, miz; |
||
661 | static int m[101], init = FALSE; |
||
662 | static double a1[25], a2[25], a3[25], a4[25], psi, tst, zms; |
||
663 | complex double clogz, j0, j0p, p0z, p1z, q0z, q1z, y0 = CPLX_00, y0p = CPLX_00, zi, |
||
664 | zi2, zk; |
||
665 | |||
666 | /* initialization of constants */ |
||
667 | if (!init) |
||
668 | { |
||
669 | psi = -GAMMA; |
||
670 | for (k = 1; k <= 25; k++) |
||
671 | { |
||
672 | i = k - 1; |
||
673 | a1[i] = -.25 / (k * k); |
||
674 | a2[i] = 1.0 / (k + 1.0); |
||
675 | psi += 1.0 / k; |
||
676 | a3[i] = psi + psi; |
||
677 | a4[i] = (psi + psi + 1.0 / (k + 1.0)) / (k + 1.0); |
||
678 | } |
||
679 | |||
680 | for (i = 1; i <= 101; i++) |
||
681 | { |
||
682 | tst = 1.0; |
||
683 | for (k = 0; k < 24; k++) |
||
684 | { |
||
685 | init = k; |
||
686 | tst *= -i * a1[k]; |
||
687 | if (tst * a3[k] < 1.e-6) |
||
688 | break; |
||
689 | } |
||
690 | m[i - 1] = init + 1; |
||
691 | } |
||
692 | |||
693 | init = TRUE; |
||
694 | |||
695 | } /* if( ! init ) */ |
||
696 | |||
697 | zms = z * conj (z); |
||
698 | if (zms == 0.) |
||
699 | abort_on_error (-7); |
||
700 | |||
701 | ib = 0; |
||
702 | if (zms <= 16.81) |
||
703 | { |
||
704 | if (zms > 16.) |
||
705 | ib = 1; |
||
706 | |||
707 | /* series expansion */ |
||
708 | iz = zms; |
||
709 | miz = m[iz]; |
||
710 | j0 = CPLX_10; |
||
711 | j0p = j0; |
||
712 | y0 = CPLX_00; |
||
713 | y0p = y0; |
||
714 | zk = j0; |
||
715 | zi = z * z; |
||
716 | |||
717 | for (k = 0; k < miz; k++) |
||
718 | { |
||
719 | zk *= a1[k] * zi; |
||
720 | j0 += zk; |
||
721 | j0p += a2[k] * zk; |
||
722 | y0 += a3[k] * zk; |
||
723 | y0p += a4[k] * zk; |
||
724 | } |
||
725 | |||
726 | j0p *= -.5 * z; |
||
727 | clogz = clogl (.5 * z); |
||
728 | y0 = (2. * j0 * clogz - y0) / PI + C2; |
||
729 | y0p = (2. / z + 2. * j0p * clogz + .5 * y0p * z) / PI + C1 * z; |
||
730 | *h0 = j0 + CPLX_01 * y0; |
||
731 | *h0p = j0p + CPLX_01 * y0p; |
||
732 | |||
733 | if (ib == 0) |
||
734 | return; |
||
735 | |||
736 | y0 = *h0; |
||
737 | y0p = *h0p; |
||
738 | |||
739 | } /* if(zms <= 16.81) */ |
||
740 | |||
741 | /* asymptotic expansion */ |
||
742 | zi = 1. / z; |
||
743 | zi2 = zi * zi; |
||
744 | p0z = 1. + (P20 * zi2 - P10) * zi2; |
||
745 | p1z = 1. + (P11 - P21 * zi2) * zi2; |
||
746 | q0z = (Q20 * zi2 - Q10) * zi; |
||
747 | q1z = (Q11 - Q21 * zi2) * zi; |
||
748 | zk = cexp (CPLX_01 * (z - POF)) * csqrtl (zi) * C3; |
||
749 | *h0 = zk * (p0z + CPLX_01 * q0z); |
||
750 | *h0p = CPLX_01 * zk * (p1z + CPLX_01 * q1z); |
||
751 | |||
752 | if (ib == 0) |
||
753 | return; |
||
754 | |||
755 | zms = cosl ((sqrtl (zms) - 4.) * 31.41592654); |
||
756 | *h0 = .5 * (y0 * (1. + zms) + *h0 * (1. - zms)); |
||
757 | *h0p = .5 * (y0p * (1. + zms) + *h0p * (1. - zms)); |
||
758 | |||
759 | return; |
||
760 | } |
||
761 | |||
762 | /*-----------------------------------------------------------------------*/ |
||
763 | |||
764 | /* compute integration parameter xlam=lambda from parameter t. */ |
||
765 | void lambda (double t, complex double *xlam, complex double *dxlam) |
||
766 | { |
||
767 | *dxlam = b - a; |
||
768 | *xlam = a + *dxlam * t; |
||
769 | return; |
||
770 | } |
||
771 | |||
772 | /*-----------------------------------------------------------------------*/ |
||
773 | |||
774 | /* rom1 integrates the 6 sommerfeld integrals from a to b in lambda. */ |
||
775 | /* the method of variable interval width romberg integration is used. */ |
||
776 | void rom1 (int n, complex double *sum, int nx) |
||
777 | { |
||
778 | int jump, lstep, nogo, i, ns, nt; |
||
779 | static double z, ze, s, ep, zend, dz = 0., dzot = 0., tr, ti; |
||
780 | static complex double t00, t11, t02; |
||
781 | static complex double g1[6], g2[6], g3[6], g4[6], g5[6], t01[6], t10[6], t20[6]; |
||
782 | |||
783 | lstep = 0; |
||
784 | z = 0.; |
||
785 | ze = 1.; |
||
786 | s = 1.; |
||
787 | ep = s / (1.e4 * NM); |
||
788 | zend = ze - ep; |
||
789 | for (i = 0; i < n; i++) |
||
790 | sum[i] = CPLX_00; |
||
791 | ns = nx; |
||
792 | nt = 0; |
||
793 | saoa (z, g1); |
||
794 | |||
795 | jump = FALSE; |
||
796 | while (TRUE) |
||
797 | { |
||
798 | if (!jump) |
||
799 | { |
||
800 | dz = s / ns; |
||
801 | if ((z + dz) > ze) |
||
802 | { |
||
803 | dz = ze - z; |
||
804 | if (dz <= ep) |
||
805 | return; |
||
806 | } |
||
807 | |||
808 | dzot = dz * .5; |
||
809 | saoa (z + dzot, g3); |
||
810 | saoa (z + dz, g5); |
||
811 | |||
812 | } /* if( ! jump ) */ |
||
813 | |||
814 | nogo = FALSE; |
||
815 | for (i = 0; i < n; i++) |
||
816 | { |
||
817 | t00 = (g1[i] + g5[i]) * dzot; |
||
818 | t01[i] = (t00 + dz * g3[i]) * .5; |
||
819 | t10[i] = (4. * t01[i] - t00) / 3.; |
||
820 | |||
821 | /* test convergence of 3 point romberg result */ |
||
822 | test ( |
||
823 | creal (t01[i]), |
||
824 | creal (t10[i]), |
||
825 | &tr, |
||
826 | cimag (t01[i]), |
||
827 | cimag (t10[i]), |
||
828 | &ti, |
||
829 | 0.); |
||
830 | if ((tr > CRIT) || (ti > CRIT)) |
||
831 | nogo = TRUE; |
||
832 | } |
||
833 | |||
834 | if (!nogo) |
||
835 | { |
||
836 | for (i = 0; i < n; i++) |
||
837 | sum[i] += t10[i]; |
||
838 | |||
839 | nt += 2; |
||
840 | z += dz; |
||
841 | if (z > zend) |
||
842 | return; |
||
843 | |||
844 | for (i = 0; i < n; i++) |
||
845 | g1[i] = g5[i]; |
||
846 | |||
847 | if ((nt >= NTS) && (ns > nx)) |
||
848 | { |
||
849 | ns = ns / 2; |
||
850 | nt = 1; |
||
851 | } |
||
852 | |||
853 | jump = FALSE; |
||
854 | continue; |
||
855 | |||
856 | } /* if( ! nogo ) */ |
||
857 | |||
858 | saoa (z + dz * .25, g2); |
||
859 | saoa (z + dz * .75, g4); |
||
860 | nogo = FALSE; |
||
861 | for (i = 0; i < n; i++) |
||
862 | { |
||
863 | t02 = (t01[i] + dzot * (g2[i] + g4[i])) * .5; |
||
864 | t11 = (4. * t02 - t01[i]) / 3.; |
||
865 | t20[i] = (16. * t11 - t10[i]) / 15.; |
||
866 | |||
867 | /* test convergence of 5 point romberg result */ |
||
868 | test ( |
||
869 | creal (t11), |
||
870 | creal (t20[i]), |
||
871 | &tr, |
||
872 | cimag (t11), |
||
873 | cimag (t20[i]), |
||
874 | &ti, |
||
875 | 0.); |
||
876 | if ((tr > CRIT) || (ti > CRIT)) |
||
877 | nogo = TRUE; |
||
878 | } |
||
879 | |||
880 | if (!nogo) |
||
881 | { |
||
882 | for (i = 0; i < n; i++) |
||
883 | sum[i] += t20[i]; |
||
884 | |||
885 | nt++; |
||
886 | z += dz; |
||
887 | if (z > zend) |
||
888 | return; |
||
889 | |||
890 | for (i = 0; i < n; i++) |
||
891 | g1[i] = g5[i]; |
||
892 | |||
893 | if ((nt >= NTS) && (ns > nx)) |
||
894 | { |
||
895 | ns = ns / 2; |
||
896 | nt = 1; |
||
897 | } |
||
898 | |||
899 | jump = FALSE; |
||
900 | continue; |
||
901 | |||
902 | } /* if( ! nogo ) */ |
||
903 | |||
904 | nt = 0; |
||
905 | if (ns < NM) |
||
906 | { |
||
907 | ns *= 2; |
||
908 | dz = s / ns; |
||
909 | dzot = dz * .5; |
||
910 | |||
911 | for (i = 0; i < n; i++) |
||
912 | { |
||
913 | g5[i] = g3[i]; |
||
914 | g3[i] = g2[i]; |
||
915 | } |
||
916 | |||
917 | jump = TRUE; |
||
918 | continue; |
||
919 | |||
920 | } /* if(ns < nm) */ |
||
921 | |||
922 | if (!lstep) |
||
923 | { |
||
924 | lstep = TRUE; |
||
925 | lambda (z, &t00, &t11); |
||
926 | } |
||
927 | |||
928 | for (i = 0; i < n; i++) |
||
929 | sum[i] += t20[i]; |
||
930 | |||
931 | nt++; |
||
932 | z += dz; |
||
933 | if (z > zend) |
||
934 | return; |
||
935 | |||
936 | for (i = 0; i < n; i++) |
||
937 | g1[i] = g5[i]; |
||
938 | |||
939 | if ((nt >= NTS) && (ns > nx)) |
||
940 | { |
||
941 | ns /= 2; |
||
942 | nt = 1; |
||
943 | } |
||
944 | |||
945 | jump = FALSE; |
||
946 | |||
947 | } /* while( TRUE ) */ |
||
948 | } |
||
949 | |||
950 | /*-----------------------------------------------------------------------*/ |
||
951 | |||
952 | /* saoa computes the integrand for each of the 6 sommerfeld */ |
||
953 | /* integrals for source and observer above ground */ |
||
954 | void saoa (double t, complex double *ans) |
||
955 | { |
||
956 | double xlr, sign; |
||
957 | static complex double xl, dxl, cgam1, cgam2, b0, b0p, com, dgam, den1, den2; |
||
958 | |||
959 | lambda (t, &xl, &dxl); |
||
960 | if (jh == 0) |
||
961 | { |
||
962 | /* bessel function form */ |
||
963 | bessel (xl * rho, &b0, &b0p); |
||
964 | b0 *= 2.; |
||
965 | b0p *= 2.; |
||
966 | cgam1 = csqrtl (xl * xl - ck1sq); |
||
967 | cgam2 = csqrtl (xl * xl - ck2sq); |
||
968 | if (creal (cgam1) == 0.) |
||
969 | cgam1 = cmplx (0., -fabsl (cimag (cgam1))); |
||
970 | if (creal (cgam2) == 0.) |
||
971 | cgam2 = cmplx (0., -fabsl (cimag (cgam2))); |
||
972 | } |
||
973 | else |
||
974 | { |
||
975 | /* hankel function form */ |
||
976 | hankel (xl * rho, &b0, &b0p); |
||
977 | com = xl - ck1; |
||
978 | cgam1 = csqrtl (xl + ck1) * csqrtl (com); |
||
979 | if (creal (com) < 0. && cimag (com) >= 0.) |
||
980 | cgam1 = -cgam1; |
||
981 | com = xl - ck2; |
||
982 | cgam2 = csqrtl (xl + ck2) * csqrtl (com); |
||
983 | if (creal (com) < 0. && cimag (com) >= 0.) |
||
984 | cgam2 = -cgam2; |
||
985 | } |
||
986 | |||
987 | xlr = xl * conj (xl); |
||
988 | if (xlr >= tsmag) |
||
989 | { |
||
990 | if (cimag (xl) >= 0.) |
||
991 | { |
||
992 | xlr = creal (xl); |
||
993 | if (xlr >= ck2) |
||
994 | { |
||
995 | if (xlr <= ck1r) |
||
996 | dgam = cgam2 - cgam1; |
||
997 | else |
||
998 | { |
||
999 | sign = 1.; |
||
1000 | dgam = 1. / (xl * xl); |
||
1001 | dgam = sign * ((ct3 * dgam + ct2) * dgam + ct1) / xl; |
||
1002 | } |
||
1003 | } |
||
1004 | else |
||
1005 | { |
||
1006 | sign = -1.; |
||
1007 | dgam = 1. / (xl * xl); |
||
1008 | dgam = sign * ((ct3 * dgam + ct2) * dgam + ct1) / xl; |
||
1009 | } /* if(xlr >= ck2) */ |
||
1010 | |||
1011 | } /* if(cimag(xl) >= 0.) */ |
||
1012 | else |
||
1013 | { |
||
1014 | sign = 1.; |
||
1015 | dgam = 1. / (xl * xl); |
||
1016 | dgam = sign * ((ct3 * dgam + ct2) * dgam + ct1) / xl; |
||
1017 | } |
||
1018 | |||
1019 | } /* if(xlr < tsmag) */ |
||
1020 | else |
||
1021 | dgam = cgam2 - cgam1; |
||
1022 | |||
1023 | den2 = cksm * dgam / (cgam2 * (ck1sq * cgam2 + ck2sq * cgam1)); |
||
1024 | den1 = 1. / (cgam1 + cgam2) - cksm / cgam2; |
||
1025 | com = dxl * xl * cexp (-cgam2 * zph); |
||
1026 | ans[5] = com * b0 * den1 / ck1; |
||
1027 | com *= den2; |
||
1028 | |||
1029 | if (rho != 0.) |
||
1030 | { |
||
1031 | b0p = b0p / rho; |
||
1032 | ans[0] = -com * xl * (b0p + b0 * xl); |
||
1033 | ans[3] = com * xl * b0p; |
||
1034 | } |
||
1035 | else |
||
1036 | { |
||
1037 | ans[0] = -com * xl * xl * .5; |
||
1038 | ans[3] = ans[0]; |
||
1039 | } |
||
1040 | |||
1041 | ans[1] = com * cgam2 * cgam2 * b0; |
||
1042 | ans[2] = -ans[3] * cgam2 * rho; |
||
1043 | ans[4] = com * b0; |
||
1044 | |||
1045 | return; |
||
1046 | } |