FACT++  1.0
void palRefro ( double  zobs,
double  hm,
double  tdk,
double  pmb,
double  rh,
double  wl,
double  phi,
double  tlr,
double  eps,
double *  ref 
)

Definition at line 185 of file palRefro.c.

References DMAX, DMIN, telData::h, i, pal1Atms(), pal1Atmt(), palDrange(), refi, t, and telData::w.

Referenced by palAopqk(), palOapqk(), palRefco(), and t_ref().

187  {
188 
189  /*
190  * Fixed parameters
191  */
192 
193  /* 93 degrees in radians */
194  const double D93 = 1.623156204;
195  /* Universal gas constant */
196  const double GCR = 8314.32;
197  /* Molecular weight of dry air */
198  const double DMD = 28.9644;
199  /* Molecular weight of water vapour */
200  const double DMW = 18.0152;
201  /* Mean Earth radius (metre) */
202  const double S = 6378120.;
203  /* Exponent of temperature dependence of water vapour pressure */
204  const double DELTA = 18.36;
205  /* Height of tropopause (metre) */
206  const double HT = 11000.;
207  /* Upper limit for refractive effects (metre) */
208  const double HS = 80000.;
209  /* Numerical integration: maximum number of strips. */
210  const int ISMAX=16384l;
211 
212  /* Local variables */
213  int is, k, n, i, j;
214 
215  int optic, loop; /* booleans */
216 
217  double zobs1,zobs2,hmok,tdkok,pmbok,rhok,wlok,alpha,
218  tol,wlsq,gb,a,gamal,gamma,gamm2,delm2,
219  tdc,psat,pwo,w,
220  c1,c2,c3,c4,c5,c6,r0,tempo,dn0,rdndr0,sk0,f0,
221  rt,tt,dnt,rdndrt,sine,zt,ft,dnts,rdndrp,zts,fts,
222  rs,dns,rdndrs,zs,fs,refold,z0,zrange,fb,ff,fo,fe,
223  h,r,sz,rg,dr,tg,dn,rdndr,t,f,refp,reft;
224 
225  /* The refraction integrand */
226 #define refi(DN,RDNDR) RDNDR/(DN+RDNDR)
227 
228  /* Transform ZOBS into the normal range. */
229  zobs1 = palDrange(zobs);
230  zobs2 = DMIN(fabs(zobs1),D93);
231 
232  /* keep other arguments within safe bounds. */
233  hmok = DMIN(DMAX(hm,-1e3),HS);
234  tdkok = DMIN(DMAX(tdk,100.0),500.0);
235  pmbok = DMIN(DMAX(pmb,0.0),10000.0);
236  rhok = DMIN(DMAX(rh,0.0),1.0);
237  wlok = DMAX(wl,0.1);
238  alpha = DMIN(DMAX(fabs(tlr),0.001),0.01);
239 
240  /* tolerance for iteration. */
241  tol = DMIN(DMAX(fabs(eps),1e-12),0.1)/2.0;
242 
243  /* decide whether optical/ir or radio case - switch at 100 microns. */
244  optic = wlok < 100.0;
245 
246  /* set up model atmosphere parameters defined at the observer. */
247  wlsq = wlok*wlok;
248  gb = 9.784*(1.0-0.0026*cos(phi+phi)-0.00000028*hmok);
249  if (optic) {
250  a = (287.6155+(1.62887+0.01360/wlsq)/wlsq) * 273.15e-6/1013.25;
251  } else {
252  a = 77.6890e-6;
253  }
254  gamal = (gb*DMD)/GCR;
255  gamma = gamal/alpha;
256  gamm2 = gamma-2.0;
257  delm2 = DELTA-2.0;
258  tdc = tdkok-273.15;
259  psat = pow(10.0,(0.7859+0.03477*tdc)/(1.0+0.00412*tdc)) *
260  (1.0+pmbok*(4.5e-6+6.0e-10*tdc*tdc));
261  if (pmbok > 0.0) {
262  pwo = rhok*psat/(1.0-(1.0-rhok)*psat/pmbok);
263  } else {
264  pwo = 0.0;
265  }
266  w = pwo*(1.0-DMW/DMD)*gamma/(DELTA-gamma);
267  c1 = a*(pmbok+w)/tdkok;
268  if (optic) {
269  c2 = (a*w+11.2684e-6*pwo)/tdkok;
270  } else {
271  c2 = (a*w+6.3938e-6*pwo)/tdkok;
272  }
273  c3 = (gamma-1.0)*alpha*c1/tdkok;
274  c4 = (DELTA-1.0)*alpha*c2/tdkok;
275  if (optic) {
276  c5 = 0.0;
277  c6 = 0.0;
278  } else {
279  c5 = 375463e-6*pwo/tdkok;
280  c6 = c5*delm2*alpha/(tdkok*tdkok);
281  }
282 
283  /* conditions at the observer. */
284  r0 = S+hmok;
285  pal1Atmt(r0,tdkok,alpha,gamm2,delm2,c1,c2,c3,c4,c5,c6,
286  r0,&tempo,&dn0,&rdndr0);
287  sk0 = dn0*r0*sin(zobs2);
288  f0 = refi(dn0,rdndr0);
289 
290  /* conditions in the troposphere at the tropopause. */
291  rt = S+DMAX(HT,hmok);
292  pal1Atmt(r0,tdkok,alpha,gamm2,delm2,c1,c2,c3,c4,c5,c6,
293  rt,&tt,&dnt,&rdndrt);
294  sine = sk0/(rt*dnt);
295  zt = atan2(sine,sqrt(DMAX(1.0-sine*sine,0.0)));
296  ft = refi(dnt,rdndrt);
297 
298  /* conditions in the stratosphere at the tropopause. */
299  pal1Atms(rt,tt,dnt,gamal,rt,&dnts,&rdndrp);
300  sine = sk0/(rt*dnts);
301  zts = atan2(sine,sqrt(DMAX(1.0-sine*sine,0.0)));
302  fts = refi(dnts,rdndrp);
303 
304  /* conditions at the stratosphere limit. */
305  rs = S+HS;
306  pal1Atms(rt,tt,dnt,gamal,rs,&dns,&rdndrs);
307  sine = sk0/(rs*dns);
308  zs = atan2(sine,sqrt(DMAX(1.0-sine*sine,0.0)));
309  fs = refi(dns,rdndrs);
310 
311  /* variable initialization to avoid compiler warning. */
312  reft = 0.0;
313 
314  /* integrate the refraction integral in two parts; first in the
315  * troposphere (k=1), then in the stratosphere (k=2). */
316 
317  for (k=1; k<=2; k++) {
318 
319  /* initialize previous refraction to ensure at least two iterations. */
320  refold = 1.0;
321 
322  /* start off with 8 strips. */
323  is = 8;
324 
325  /* start z, z range, and start and end values. */
326  if (k==1) {
327  z0 = zobs2;
328  zrange = zt-z0;
329  fb = f0;
330  ff = ft;
331  } else {
332  z0 = zts;
333  zrange = zs-z0;
334  fb = fts;
335  ff = fs;
336  }
337 
338  /* sums of odd and even values. */
339  fo = 0.0;
340  fe = 0.0;
341 
342  /* first time through the loop we have to do every point. */
343  n = 1;
344 
345  /* start of iteration loop (terminates at specified precision). */
346  loop = 1;
347  while (loop) {
348 
349  /* strip width. */
350  h = zrange/((double)is);
351 
352  /* initialize distance from earth centre for quadrature pass. */
353  if (k == 1) {
354  r = r0;
355  } else {
356  r = rt;
357  }
358 
359  /* one pass (no need to compute evens after first time). */
360  for (i=1; i<is; i+=n) {
361 
362  /* sine of observed zenith distance. */
363  sz = sin(z0+h*(double)(i));
364 
365  /* find r (to the nearest metre, maximum four iterations). */
366  if (sz > 1e-20) {
367  w = sk0/sz;
368  rg = r;
369  dr = 1.0e6;
370  j = 0;
371  while ( fabs(dr) > 1.0 && j < 4 ) {
372  j++;
373  if (k==1) {
374  pal1Atmt(r0,tdkok,alpha,gamm2,delm2,
375  c1,c2,c3,c4,c5,c6,rg,&tg,&dn,&rdndr);
376  } else {
377  pal1Atms(rt,tt,dnt,gamal,rg,&dn,&rdndr);
378  }
379  dr = (rg*dn-w)/(dn+rdndr);
380  rg = rg-dr;
381  }
382  r = rg;
383  }
384 
385  /* find the refractive index and integrand at r. */
386  if (k==1) {
387  pal1Atmt(r0,tdkok,alpha,gamm2,delm2,
388  c1,c2,c3,c4,c5,c6,r,&t,&dn,&rdndr);
389  } else {
390  pal1Atms(rt,tt,dnt,gamal,r,&dn,&rdndr);
391  }
392  f = refi(dn,rdndr);
393 
394  /* accumulate odd and (first time only) even values. */
395  if (n==1 && i%2 == 0) {
396  fe += f;
397  } else {
398  fo += f;
399  }
400  }
401 
402  /* evaluate the integrand using simpson's rule. */
403  refp = h*(fb+4.0*fo+2.0*fe+ff)/3.0;
404 
405  /* has the required precision been achieved (or can't be)? */
406  if (fabs(refp-refold) > tol && is < ISMAX) {
407 
408  /* no: prepare for next iteration.*/
409 
410  /* save current value for convergence test. */
411  refold = refp;
412 
413  /* double the number of strips. */
414  is += is;
415 
416  /* sum of all current values = sum of next pass's even values. */
417  fe += fo;
418 
419  /* prepare for new odd values. */
420  fo = 0.0;
421 
422  /* skip even values next time. */
423  n = 2;
424  } else {
425 
426  /* yes: save troposphere component and terminate the loop. */
427  if (k==1) reft = refp;
428  loop = 0;
429  }
430  }
431  }
432 
433  /* result. */
434  *ref = reft+refp;
435  if (zobs1 < 0.0) *ref = -(*ref);
436 
437 }
double palDrange(double angle)
Definition: palDrange.c:68
int i
Definition: db_dim_client.c:21
void pal1Atmt(double r0, double t0, double alpha, double gamm2, double delm2, double c1, double c2, double c3, double c4, double c5, double c6, double r, double *t, double *dn, double *rdndr)
Definition: pal1Atmt.c:103
#define DMIN(A, B)
Definition: palmac.h:129
double w
Definition: palObs.c:168
double h
Definition: palObs.c:170
#define DMAX(A, B)
Definition: palmac.h:126
void pal1Atms(double rt, double tt, double dnt, double gamal, double r, double *dn, double *rdndr)
Definition: pal1Atms.c:83
TT t
Definition: test_client.c:26
#define refi(DN, RDNDR)

+ Here is the call graph for this function:

+ Here is the caller graph for this function: