awips2/ncep/gov.noaa.nws.ncep.ui.nsharp/nsharp_c/thermo.c
root a02aeb236c Initial revision of AWIPS2 11.9.0-7p5
Former-commit-id: 06a8b51d6d [formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]
Former-commit-id: 9f19e3f712
2012-01-06 08:55:05 -06:00

392 lines
15 KiB
C

/***************************************************************/
/* SHARP-95 */
/* Advanced Interactive Sounding Analysis Program */
/* */
/* Thermodynamic Library */
/* */
/* John A. Hart */
/* National Severe Storms Forecast Center */
/* Kansas City, Missouri */
/* */
/***************************************************************/
#include "gui.h"
#include "sharp95.h"
float lifted ( float pres, float temp, float dwpt, float lvl2 )
/*************************************************************/
/* LIFTED */
/* John Hart NSSFC KCMO */
/* */
/* Calculates a lifted index for a parcel(pres,temp,dwpt) */
/* at level (lvl2). */
/* */
/* pres - Pressure of initial parcel(mb) */
/* temp - Temperature of initial parcel (c) */
/* dwpt - Dew Point of initial parcel (c) */
/* lvl2 - Pressure to lift parcel (mb) */
/*************************************************************/
{
float p2, t2;
printf( "Parcel = %f %f %f\n", pres, temp, dwpt);
drylift(pres, temp, dwpt, &p2, &t2);
printf( "LCL = %f, %f\n", p2, t2);
return wetlift(p2, t2, lvl2);
}
/*NP*/
void drylift ( float p1, float t1, float td1, float *p2, float *t2 )
/*************************************************************/
/* DRYLIFT */
/* John Hart NSSFC KCMO */
/* */
/* Lifts a parcel(p1,t1,td1) to the LCL and returns its */
/* new level(p2) and temperature(t2). */
/* */
/* p1 - Pressure of initial parcel(mb) */
/* t1 - Temperature of initial parcel (c) */
/* td1 - Dew Point of initial parcel (c) */
/* p2 - Pressure at LCL (mb) */
/* t2 - Temperature at LCL (c) */
/*************************************************************/
{
*t2 = -999;
*p2 = -999;
if((t1 != -999)&&(td1 != -999))
*t2 = lcltemp( t1, td1 );
if((p1 != -999)&&(*t2 != -999))
*p2 = thalvl( theta(p1, t1, 1000), *t2);
}
/*NP*/
float lcltemp ( float temp, float dwpt )
/*************************************************************/
/* LCLTEMP */
/* John Hart NSSFC KCMO */
/* */
/* Returns the temperature(c) of a parcel (temp,dwpt) */
/* when raised to its LCL. */
/* */
/* temp - Temperature of initial parcel (c) */
/* dwpt - Dew Point of initial parcel (c) */
/*************************************************************/
{
float s, dlt;
s = temp - dwpt;
dlt = s * (1.2185 + .001278 * temp + s * (-.00219 + 1.173E-05 *
s - .0000052 * temp));
return temp - dlt;
}
/*NP*/
float thalvl ( float thta, float temp )
/*************************************************************/
/* THALVL */
/* John Hart NSSFC KCMO */
/* */
/* Returns the level(mb) of a parcel( thta, temp). */
/* */
/* thta - Potential Temperature of parcel(c) */
/* temp - Temperature of parcel (c) */
/*************************************************************/
{
float level,term1,term2;
temp = temp + 273.15;
thta = thta + 273.15;
term1 = thta/temp;
term2 = 1/ROCP;
level = 1000.0 / pow(term1,term2);
return (level);
}
/*NP*/
float theta ( float pres, float temp, float pres2 )
/*************************************************************/
/* THETA */
/* John Hart NSSFC KCMO */
/* */
/* Returns the potential temperature(c) of the */
/* parcel(pres, temp). */
/* */
/* pres - Pressure of parcel(mb) */
/* temp - Temperature of parcel (c) */
/* pres2 - Reference Level (Usually 1000mb) */
/*************************************************************/
{
float pot;
temp = temp + 273.15;
pot = (temp * pow((pres2 / pres), ROCP)) - 273.15;
return(pot);
}
/*NP*/
float mixratio ( float pres, float temp )
/*************************************************************/
/* MIXRATIO */
/* John Hart NSSFC KCMO */
/* */
/* Returns the mixing ratio (g/kg) of the */
/* parcel(pres, temp). */
/* */
/* pres - Pressure of parcel(mb) */
/* temp - Temperature of parcel (c) */
/*************************************************************/
{
float x, wfw, fwesw;
x = .02 * (temp - 12.5 + 7500.0 / pres);
wfw = 1 + .0000045 * pres + .0014 * x * x;
fwesw = wfw * vappres( temp );
return 621.97 * (fwesw / (pres - fwesw));
}
/*NP*/
float temp_at_mixrat ( float mr, float pres )
/*************************************************************/
/* TEMP_AT_MIXRAT */
/* John Hart NSSFC KCMO */
/* */
/* Returns the temperature(c) of air at the given */
/* mixing ratio (mr, g/kg) and pressure (pres, mb). */
/* */
/*************************************************************/
{
double c1, c2, c3, c4, c5, c6, x, tmrk;
c1 = .0498646455;
c2 = 2.4082965;
c3 = 7.07475;
c4 = 38.9114;
c5 = .0915;
c6 = 1.2035;
x = log10( mr * pres / (622 + mr));
tmrk = pow(10., c1 * x + c2) - c3 + c4 * pow( pow(10., c5 * x) - c6, 2.);
return (float)(tmrk - 273.15);
}
/*NP*/
float vappres ( float temp )
/*************************************************************/
/* VAPPRES */
/* John Hart NSSFC KCMO */
/* */
/* Returns the vapor pressure of dry air at */
/* temperature (temp). */
/* */
/* temp - Temperature of parcel (c) */
/*************************************************************/
{
double pol;
pol = temp * (1.1112018e-17 + temp * (-3.0994571e-20));
pol = temp * (2.1874425e-13 + temp * (-1.789232e-15 + pol));
pol = temp * (4.3884180e-09 + temp * (-2.988388e-11 + pol));
pol = temp * (7.8736169e-05 + temp * (-6.111796e-07 + pol));
pol = .99999683e-00 + temp * (-9.082695e-03 + pol);
pol = (pol * pol);
pol = (pol * pol);
return 6.1078F / (pol * pol);
}
/*NP*/
float wetlift ( float pres, float temp, float pres2 )
/*************************************************************/
/* WETLIFT */
/* John Hart NSSFC KCMO */
/* */
/* Lifts a parcel(pres,temp) moist adiabatically to its */
/* new level(pres2), and returns the temperature(c). */
/* */
/* pres - Pressure of initial parcel(mb) */
/* temp - Temperature of initial parcel (c) */
/* pres2 - Final Pressure (mb) */
/*************************************************************/
{
float tha, thm, woth, wott;
tha = theta(pres, temp, 1000);
woth = wobf(tha);
wott = wobf(temp);
thm = tha - woth + wott;
return satlft(pres2, thm);
}
/*NP*/
float satlft ( float pres, float thm )
/*************************************************************/
/* SATLFT */
/* John Hart NSSFC KCMO */
/* */
/* Returns the temperature (c) of a parcel (thm), */
/* when lifted to level (pres). */
/* */
/* pres - Pressure to raise parcel (mb) */
/* thm - Sat. Pot. Temperature of parcel (c) */
/*************************************************************/
{
float pwrp, t1, t2, woto, wotm, wot2, woe2, e1, e2, rate, eor;
if ((fabs(pres - 1000) -.001) <= 0) return thm;
eor = 999;
while (fabs( eor ) - .1 > 0)
{
if (eor == 999) /* First Pass */
{
pwrp = (float)(pow( pres / 1000.0, ROCP));
t1 = (thm + 273.15) * pwrp - 273.15;
woto = wobf( t1 );
wotm = wobf( thm );
e1 = woto - wotm;
rate = 1;
}
else /* Successive Passes */
{
rate = (t2 - t1) / (e2 - e1);
t1 = t2;
e1 = e2;
}
t2 = t1 - e1 * rate;
e2 = (t2 + 273.15) / pwrp - 273.15;
wot2 = wobf( t2 );
woe2 = wobf( e2 );
e2 = e2 + wot2 - woe2 - thm;
eor = e2 * rate;
}
return t2 - eor;
}
/*NP*/
float wobf ( float temp )
/*************************************************************/
/* WOBF */
/* John Hart NSSFC KCMO */
/* */
/* pres - Pressure to raise parcel (mb) */
/* thm - Sat. Pot. Temperature of parcel (c) */
/*************************************************************/
{
float x;
double pol;
x = temp - 20;
if (x <= 0)
{
pol = 1 + x * (-8.841660499999999e-03 + x * ( 1.4714143e-04
+ x * (-9.671989000000001e-07 + x * (-3.2607217e-08
+ x * (-3.8598073e-10)))));
pol = pol * pol;
return 15.13F / (pol * pol);
}
else
{
pol = x * (4.9618922e-07 + x * (-6.1059365e-09 +
x * (3.9401551e-11 + x * (-1.2588129e-13 +
x * (1.6688280e-16)))));
pol = 1 + x * (3.6182989e-03 + x * (-1.3603273e-05 + pol));
pol = pol * pol;
return 29.93 / (pol * pol) + .96 * x - 14.8;
}
}
/*NP*/
float wetbulb ( float pres, float temp, float dwpt )
/*************************************************************/
/* WETBULB */
/* John Hart NSSFC KCMO */
/* */
/* Calculates the wetbulb temperature (c) for given */
/* parcel (pres, temp, dwpt). */
/* */
/* pres = Pressure of parcel (mb). */
/* temp = Temperature of parcel (c) */
/* dwpt = Dew point of parcel (c) */
/*************************************************************/
{
float p2, t2;
if( !qc(pres)) {return -999;}
if( !qc(temp)) {return -999;}
if( !qc(dwpt)) {return -999;}
drylift( pres, temp, dwpt, &p2, &t2);
return wetlift(p2, t2, pres);
}
/*NP*/
float thetaw ( float pres, float temp, float dwpt )
/*************************************************************/
/* THETAW */
/* John Hart NSSFC KCMO */
/* */
/* Calculates the wet-bulb potential temperature for given */
/* parcel (pres, temp, dwpt). */
/* */
/* pres = Pressure of parcel (mb). */
/* temp = Temperature of parcel (c) */
/* dwpt = Dew point of parcel (c) */
/*************************************************************/
{
float p2, t2;
if( !qc(pres)) {return -999;}
if( !qc(temp)) {return -999;}
if( !qc(dwpt)) {return -999;}
drylift( pres, temp, dwpt, &p2, &t2);
return wetlift(p2, t2, 1000);
}
/*NP*/
float thetae ( float pres, float temp, float dwpt )
/*************************************************************/
/* THETAE */
/* John Hart NSSFC KCMO */
/* */
/* Calculates the equivalent potential temperature */
/* for given parcel (pres, temp, dwpt). */
/* */
/* pres = Pressure of parcel (mb). */
/* temp = Temperature of parcel (c) */
/* dwpt = Dew point of parcel (c) */
/*************************************************************/
{
float p2, t2;
if( !qc(pres)) {return -999;}
if( !qc(temp)) {return -999;}
if( !qc(dwpt)) {return -999;}
drylift( pres, temp, dwpt, &p2, &t2);
return theta(100, wetlift(p2, t2, 100), 1000 );
}
/*NP*/
float esfc ( float val )
/*************************************************************/
/* ESFC */
/* John Hart SPC NORMAN OK */
/* */
/* Calculate effective surface for elevated convection. */
/* Assumes that lowest layer with CAPE >= val is "sfc". */
/* Returns level (mb) of effective surface. */
/* */
/*************************************************************/
{
short i;
struct _parcel pcl;
/* ----- Begin at surface and search upward for instability ----- */
for(i=sfc();i<sndgp->numlev;i++)
{
parcel( -1, -1, sndgp->sndg[i].pres, sndgp->sndg[i].temp, sndgp->sndg[i].dwpt, &pcl);
if(pcl.bplus >= val) return sndgp->sndg[i].pres;
}
return -999.0;
}