/*-------------------------------------------------------------------\ | Thermal Index Calculator (ti) Version 1.60 | | written by Kevin Ford 1-28-94 | | version 1 written Feb. 1992 | | | | VAX/VMS Compatibility added 06/30/93 by Kim Reniska | | | | Six modes of operation: | | Interactive: | | ti read from .uac file (text) | | ti -1 read from .uac file | | ti -3 read from archived file | | Batch | | ti filename station hightemp maxz ; read from .uac (text) | | ti -1 filename station hightemp maxz ; read from .uac file | | ti -3 filename date hightemp maxz ; read from archive file | \-------------------------------------------------------------------*/ /* must use cc ti.c -lm to compile */ #include #include #include #include #ifdef VMS #define O_RDONLY 0 #include #else #include #endif #define t0 (273.15) /* convert from Kelvin to Celcius */ #define RG (29.286) #define GD (-0.00974) /* dry adiabatic lapse rate, deg. C per meter */ #define G0 (-0.0065) /* standard lapse rate */ #define CFM (0.3048) /* convert from feet to meters */ #define spdcvt (1.9458) /* convert from m/s to knots */ /* stored data structure for .uac files */ typedef struct { char ident[12], loc[12], loc2[12]; long idcode; float lat,lon; long ml,sl,wl; /* num. of mand. levels, sig. levels, wind levels */ float mp[20], mh[20], mt[20], mdp[20], mdir[20], mspd[20]; float sp[50], st[50], sdp[50]; float wp[50], wdir[50], wspd[50]; } filerec; filerec rec; /* raw data from the file, for each level */ float p[100], /* pressure in millibars */ t[100], /* temperature in degrees Kelvin */ dp[100]; /* dewpoint in degrees Kelvin */ int ddir[100], /* wind direction, degrees */ dspd[100]; /* wind speed in knots */ /* auxilliary 1000 foot interval wind data from the file */ int winddir[160], /* wind direction, degrees */ windspd[160]; /* wind speed, knots */ /* calculated data for each pressure level */ float h[100], /* height of level in meters MSL */ tv[100]; /* virtual temperature in degrees Celcius */ /* These arrays contain calculated data at 500 foot intervals */ float ti[300], /* thermal index */ alt[300]; /* altimeter reading */ int dir[300], /* wind direction, degrees */ spd[300]; /* wind speed in knots */ int levels; /* total number of pressure levels */ /* calculate the virtual temp given the temp, dewpoint and presure */ float vtemp(t,dp,p) float t,dp,p; { float e; e=6.11 * exp(5423.0*(1.0/t0 - 1.0/dp)); return(t/(1.0-.378*e/p)); } /* altitude for a given pressure in the standard atmosphere */ float stdz(p) float p; { return((-288.0/G0) * (1.0- pow(p/1013.25,-RG*G0))); } /* convert a string to an integer */ int strtoint(buf) char *buf; { int d; char w; d=0; while ((w= *buf++)>0) d=10*d+w-'0'; return(d); } /* decode a coded temperature/dewpoint from an text data file */ tempcvt(n,t,dp) int n; /* coded form */ float *t, *dp; /* decoded temp & dewpoint */ { int q; float h; q=n/100; h=((float) q)/10.0; if (q%2==0) *t=t0+h; else *t=t0-h; q=n%100; h=(float) q; if (q<56) *dp = *t - h/10.0; else if (q<99) *dp = *t - h+50.0; else *dp = t0 - 99.9; } /* virtual temperature at altitude a */ float tempalt(a) float a; { int i; if (a<=h[0]) return(tv[0]); if (a >= h[levels-1]) return(tv[levels-1]); for (i=1; h[i]1) { if (strcmp(argv[1],"-3")==0) { ti3=1; i++; } if (strcmp(argv[1],"-1")==0) { ti1=1; i++; } } if (argc>i) { if (argc='a')&&(station[i]<='z')) station[i] -= ('a'-'A'); for (j=0; j='a')&&(station[i]<='z')) station[i] -= ('a'-'A'); for (j=0; jdspd[j]))) { ftemp=p[i];p[i]=p[j];p[j]=ftemp; ftemp=t[i];t[i]=t[j];t[j]=ftemp; ftemp=dp[i];dp[i]=dp[j];dp[j]=ftemp; itemp=dspd[i];dspd[i]=dspd[j];dspd[j]=itemp; itemp=ddir[i];ddir[i]=ddir[j];ddir[j]=itemp; } p[levels]=9999.0; for (i=0; i 10.0) { printf("ti error: surface data missing\n"); exit(-1); } for (i=0; i= levels) hd=dp[0]; else { ftemp = h[i] - h[i-1]; a = dp[i-1]*(h[i]-(h[0]+500.0))/ftemp + dp[i]*(500.0+h[0]-h[i-1])/ftemp; z += (500.0+h[0]-h[i-1]) * (a + dp[i-1]) / 2.0; hd = z / 500.0; } if (!batch) { printf("\nEnter forecast high temp (F) : "); scanf("%d",&ht); printf("Enter maximum altitude to calculate TI : "); scanf("%f",&maxz); } ftemp = (float) (ht-32.0)/1.8+t0; if (ftempftemp) hd=ftemp; cb = (int) ((ftemp - hd)*4.0 + .5) * 100; /* est. cloud base */ htt = vtemp(ftemp,hd,p[0]); printf("\nSoaring report from %s upper air data\n\n",station); printf("Forecast high : %3d F\n", ht); printf("Surface virtual temp = %4.1f C\n\n",htt-t0+.05); for (i=0; i<199; i++) {dir[i]= -999.0; spd[i]= -999.0; } /*------------------ calculate thermal index ---------------------------*/ lo=(int) (h[0]/CFM/500.0) + 1; hi=(int) ((maxz+250.0)/500.0); if (hi>120) hi=120; /* don't go over 60,000 feet MSL */ if (hi=0) && (dspd[i]>=0)) { j = (int) ((h[i]/CFM+250.0)/500.0); dir[j] = ddir[i]; spd[j] = dspd[i]; } for (i=lo; i<=hi; i++) { k=500.0 * CFM * i; if ((i%2==0)&&(winddir[i/2]>=0)) { dir[i]=winddir[i/2]; spd[i]=windspd[i/2]; } for (j=1; j180.0) printf("%9.1f",dp[i]-t0+.01); else printf(" "); if (dspd[i]>=0) printf("%9d%9d",ddir[i], dspd[i]); printf("\n"); } if (p[0]<500.0) { printf("Insufficient upper air data for thermal index calculations.\n"); exit(-1); } printf("\n\n\n alt(ft MSL) ti wind dir wind spd trig temp (F)\n\n"); for (i=lo; i<=hi; i++) { printf("%10d%10.1f%",i*500, ti[i]+.05); if ((spd[i]<0)||(dir[i]<0)) printf(" "); else printf("%10d%10d",dir[i],spd[i]); printf(" %10d\n", trig[i]); } printf("\nEstimated cloud base: %d feet AGL\n",cb); }