SOURCE CODE FOR RAYLEIGH CALCULATOR
I use textwrangler on the mac to bring it to life (formatting and such is great).
#!/usr/bin/perl
# Written by William Patrick Arnott, 4 July 2009, from Reno NV.
# This is a PERL language script.
# The whole idea of this script is to use it to write html code for a browser, and to
# allow dynamic content where the user may change conditions and easily resubmit the calculation.
# Set the color scheme.
$text_color = "000000";
$page_background_color = "FFFFF0";
$page_links_color = "0000FF";
$page_active_links_color = "FF0000";
$page_visited_links_color = "0000FF";
$table_background_color= "F4E3C8";
$table_cell_color= "FFFFFF";
# The following gets the environmental variable related to the name of this script for use later.
# This is an example of how to define a variable cgu_url in the PERL language.
# CGI is defined as "Common Gateway Interface". It is a standard for interfacing external
# applications such as perl programs to web servers.
$cgi_url = "$ENV{'SCRIPT_NAME'}";
# $header is the HTML header that will be generated by the results page
# of the program. It is nothing more than a general string variable, and could have any name.
# We simply write the string to the web page later.
$header = qq[
<!-- Begin HTML header -->
<html><head><title>RayleighWeb</title>
<meta name="Description" content="Calculates Rayleigh Scattering Coefficients for air, co2, and argon gases">
<meta name="keywords" content="Rayleigh CO2 carbon dioxide air polarization scattering argon coefficient cross section index of refraction">
</head>
<body bgcolor=#$page_background_color
text=#$text_color link=#$page_links_color
vlink=#$page_visited_links_color
alink=#$page_active_links_color>
<center>
<SCRIPT type="text/javascript" src="overlib.js"><!-- overLIB (c) Erik Bosrup
--></SCRIPT>
<!-- End HTML header -->
];
# $footer is the HTML code that will go at the bottom of pages
# generated by the program.
$footer = qq[
<!-- Begin HTML footer -->
<center><font face="Arial" size="-2"><i>Powered by coffee... and tea (:-:)</i></font></center>
</body></html>
<!-- End HTML footer -->
];
# Make HTML code that allows the user to close the window and leave when finished.
# $depart = qq[
# <form method="post">
# <input type="button" value="Press Here to Close Window" onclick="window.close()">
# </form>
# ];
# This line makes it so everything printed by the script is printed
# immediately instead of being buffered and printed whenever.
$| = 1;
# This line calls the parse_form_data subroutine, which grabs all the
# input from the form into an associative style array so we can use the
# variables. This is where data is actually read into the script from the standard input,
# which is the input form itself considering of the pressure, temperature, and wavelength.
%data = &parse_form_data();
# Selectively initialize the associative data array.
if ($data{'pres'} eq "") {
$data{'pres'}=1013.25 ;
$data{'temp'}= 15.00 ;
$data{'wave'}= 532.00 ;
}
#################################################################
############## Here we go, make the web page. ##############
#################################################################
# This line must be in any CGI script: it tells your web browser
# that HTML stuff is coming out. If you had a CGI script that showed
# an image, you might use "Content-type: image/gif", but you have to
# have a content-type (or MIME header) of some kind. If you were using
# the Perl CGI module with "use CGI;" then you could probably do something
# like "print header;" but a lot of servers don't have the
# CGI module, so we're taking no chances.
print "Content-type: text/html\n\n";
# First, print our HTML for the top of the page.
print $header;
# This next set of things is just checking so that if they enter
# strange values. Just show a little red * next to the form
# field, and don't bother trying to calculate anything.
# Coerce values to good operating ranges.
# Pressure coersion.
$errpressure = "<font color=\"#FF0000\"><b>*<sub><small>error</small></sub></b></font>";
if ($data{'pres'} > 0.0 and $data{'pres'} <= 10000.0)
{ $errpressure="" }
elsif ($data{'pres'} < 0.0) { $data{'pres'}=0.0 }
else {$data{'pres'}=10000.0 ; }
$pressure=$data{'pres'} ;
# Temperature coersion.
$errtemperature = "<font color=\"#FF0000\"><b>*<sub><small>error</small></sub></b></font>";
if ($data{'temp'} > -273.0 and $data{'temp'} <= 10000.0)
{ $errtemperature="" }
elsif ($data{'temp'} < -273.) { $data{'temp'}=-273. }
else {$data{'temp'}=10000.0 ; }
$temperature=$data{'temp'} ;
# Wavelength coersion.
$errwavelength = "<font color=\"#FF0000\"><b>*<sub><small>error</small></sub></b></font>";
if ($data{'wave'} > 299.999 and $data{'wave'} <= 1000.0)
{ $errwavelength="" }
elsif ($data{'wave'} < 300.0) { $data{'wave'}=300.0 }
else {$data{'wave'}=1000.0 ; }
$wavelength=$data{'wave'} ;
&RayleighCoefs ; # Calls the subroutine to compute Rayleigh Coefficients.
# Prepare the output of the calculation in table form.
$RAY = qq[
<table border="10" bordercolor="#336699" cellpadding="2" cellspacing="2">
<tr>
<th bgcolor="#cccccc">Property <big><big><b> \\ </b></big></big> Gas</th>
<th bgcolor="#cccccc">Argon
<A href="javascript:void(0);" onClick="return overlib('Direct Measurement of the Rayleigh Scattering Cross Section in Various Gases. J. Quant. Spect. Rad. Tran. <b>92</b>, 2005, 293-310. Eq. 9', STICKY, CAPTION, 'M. Sneep and W. Ubachs', ABOVE);"onmouseout="nd();">*</A></th>
<th bgcolor="#cccccc">Air
<A href="javascript:void(0);" onClick="return overlib('Rayleigh-scattering Calculations for the Terrestrial Atmosphere. Applied Optics <b>34</b>, 1995, 2765-2773. Fk from the table was fit to a 10th order polynomial.', STICKY, CAPTION, 'A. Bucholtz', ABOVE);"onmouseout="nd();">*</A></th>
<th bgcolor="#cccccc">CO<sub><small>2</small></sub>
<A href="javascript:void(0);" onClick="return overlib('Direct Measurement of the Rayleigh Scattering Cross Section in Various Gases. J. Quant. Spect. Rad. Tran. <b>92</b>, 2005, 293-310. Eq. 15 and worked backwards.', STICKY, CAPTION, 'M. Sneep and W. Ubachs', ABOVE);"onmouseout="nd();">*</A></th>
</tr>
<tr>
<th bgcolor="#cccccc">Rayleigh Scattering Coefficient (Mm<sup><small>-1</small></sup>)
<A href="javascript:void(0);" onClick="return overlib('The scattering coefficient for incident natural light is the sum of scattering measured with sensors 1 thru 4, divided by 2.', STICKY, CAPTION, 'Scattering Coefficient', LEFT);"onmouseout="nd();">*</A></th>
<td>$beta[0]</td>
<td>$beta[2]</td>
<td>$beta[1]</td>
</tr>
<tr>
<th bgcolor="#cccccc">Forward and Backward <strong>Parallel</strong> Coefficients (Mm<sup><small>-1</small></sup>)
<A href="javascript:void(0);" onClick="return overlib('The detector is parallel to the plane containing the laser beam polarization and the incident direction. Sensors 1 and 3.', STICKY, CAPTION, 'Parallel Definition', LEFT);"onmouseout="nd();">*</A></th>
<td>$beta_par[0]</td>
<td>$beta_par[2]</td>
<td>$beta_par[1]</td>
</tr>
<tr>
<th bgcolor="#cccccc">Forward and Backward <strong>Perpendicular</strong> Coefficients (Mm<sup><small>-1</small></sup>)
<A href="javascript:void(0);" onClick="return overlib('The detector is perpendicular to the plane containing the laser beam polarization and the incident direction. Sensors 2 and 4.', STICKY, CAPTION, 'Perpendicular Definition', LEFT);"onmouseout="nd();">*</A></th>
<td>$beta_per[0]</td>
<td>$beta_per[2]</td>
<td>$beta_per[1]</td>
</tr>
<tr>
<th bgcolor="#cccccc"><strong>King's Coefficient, F<sub><small>k</small></sub></strong>
<A href="javascript:void(0);" onClick="return overlib('On the Complex Anisotropic Molecule in Relation to the Dispersion and Scattering of Light. Proc. R. Soc. Lond. A <b>104</b> 1923 , 333-357.', STICKY, CAPTION, 'Louis V. King', LEFT);"onmouseout="nd();">*</A></th>
<td>$Fkk[0]</td>
<td>$Fkk[2]</td>
<td>$Fkk[1]</td>
</tr>
<tr>
<th bgcolor="#cccccc"><strong>Refractive Index (n-1)x10<sup><small>4</small></sup><br>
at 1013.25 mb and 15 C </strong></th>
<td>$nm1_10to4th[0]</td>
<td>$nm1_10to4th[2]</td>
<td>$nm1_10to4th[1]</td>
</tr>
<tr>
<th bgcolor="#cccccc"><strong>Rayleigh Scattering Cross Section <br>
(10<sup><small>27</small></sup> cm<sup><small>2</small></sup> molecule<sup><small>-1</small></sup>)<br>
at 1013.25 mb and 15 C </strong></th>
<td>$sig[0]</td>
<td>$sig[2]</td>
<td>$sig[1]</td>
</tr>
<tr>
<th bgcolor="#cccccc"><strong>Atmospheric Column<br>Rayleigh Scattering Optical Depth <br>
at Chosen Pressure </strong>
<A href="javascript:void(0);" onClick="return overlib('Based on their average atmospheric mixing ratios. Their contribution to the optical depth of air.', STICKY, CAPTION, 'Argon and CO2', ABOVE);"onmouseout="nd();">*</A></th>
<td>$Tau[0]</td>
<td>$Tau[2]</td>
<td>$Tau[1]</td>
</tr>
</table>
];
# The get_form subroutine prints out the form, saves whatever
# they entered, etc.
# print &get_form;
print &get_form ;
print "$RAY";
# print $leave;
print $footer;
exit();
# This subroutine write the HTML code for setting up the calculation.
sub get_form {
$form = qq[<table border=8 bordercolor="#336699" cellpadding="2" cellspacing="2" ><tr><td valign=top>
<center><b><A href="javascript:void(0);" onClick="return overlib('Author of this page, written in PERL, and calculations contained therein, with references as noted. Enjoy!', STICKY, CAPTION, 'W. Patrick Arnott', LEFT);"onmouseout="nd();">Rayleigh Scattering Coefficients </A> for <i>Argon, Air, and CO<sub><small>2</small></sub></i></b></center></td></tr>
<tr><td><img src="SuperMiniSketch.gif" width="600" height="100"></td></tr></center></table>
<form action=$cgi_url method=POST>
<table border=10 bordercolor=#ff0000 cellpadding=2 cellspacing=2>
<tr><th align=right>$errpressure Pressure (mb) </th>
<td>
<b><input type=text name=pres size=14 value=\"$data{'pres'}\"></b>
</td>
</tr>
<tr> <th align=right>$errtemperature Temperature (C) </th>
<td>
<b><input type=text name=temp size=14 value=\"$data{'temp'}\"></b>
</td>
</tr>
<tr>
<th align=right>$errwavelength Wavelength (nm) </th>
<td>
<b><input type=text name=wave size=14 value=\"$data{'wave'}\"></b>
</td>
</tr>
<tr><td></td>
<td bgcolor=#$table_cell_color>
<input type=submit value=Calculate>
</td>
</tr></form></table></td>] ;
$form;
}
# This is one amazing subroutine. It unpacks data from the standard input, and makes it useful
# to proceed with the calculation. Note that variable derive their definition in the form
# subroutine.
sub parse_form_data {
my($string,%data,@data);
# get data
if ($ENV{'REQUEST_METHOD'} eq 'GET') {
$_ = $string = $ENV{'QUERY_STRING'};
tr/\"~;/_/;
$string = $_;
}
else { read(STDIN, $string, $ENV{'CONTENT_LENGTH'});
$_ = $string;
$OK_CHARS='a-zA-Z0-9=&%\n\/_\-\.@';
tr/\"~;/_/;
$string = $_;
}
# split data into name=value pairs
# Numerical values are in variable string. They are separated by &.
@data = split(/&/, $string);
# split into name=value pairs in associative array
foreach (@data) {
split(/=/, $_);
$_[0] =~ s/\+/ /g; # plus to space
$_[0] =~ s/%(..)/pack("c", hex($1))/ge; # hex to alphanumeric
$data{"$_[0]"} = $_[1];
}
# translate special characters
foreach (keys %data) {
$data{"$_"} =~ s/\+/ /g; # plus to space
$data{"$_"} =~ s/%(..)/pack("c", hex($1))/ge; # hex to alphanumeric
}
%data; # return associative array of name=value
}
sub RayleighCoefs {
# Arrays are filled as follows: 0=Argon, 1=Carbon Dioxide, 2=Air .
@Rgas=(8.3143*1000.0/39.95,8.3143*1000.0/44.01,8.3143*1000.0/28.98) ; # Gas constants.
@conc=(0.0093,0.000380,1.0) ; # Partial Pressure of Argon, CO2, and air for optical depth calculation.
$g=9.80665 ; # acceleration due to gravity at the surface.
$l=$wavelength ;
$T=$temperature ;
$P=$pressure ;
$nu=1.e-2/($l*1.e-9) ; # Wavenumber in 1/cm.
$nu2=$nu**2 ;
$wl2=$l/1000.0 ; $wl2=$wl2**2 ; # Wavelength in microns, and it squared.
$T=$T+273.15 ; $T0=273.15+15.0 ; $P0=1013.25 ;
$fac=$P*$T0/($P0*$T); # Used to get the gas concentration at T and P.
$N0=25.4743e18 ; # Gas concentration at T0 and P0, 1/cm^3.
$pi=4.0*atan2(1.0,1.0) ;
@Fkk=(1.0,1.0,1.0) ; # Depolarization factor initilization.
@sig=(0.0, 0.0, 0.0) ; # Rayleigh cross section in cm^2 / molecule initilization.
@beta_par=(0.0, 0.0, 0.0) ; # Forward and Backward Scatter parallel in Mm-1.
@beta_per=(0.0, 0.0, 0.0) ; # perpendicular .
@beta=(0.0, 0.0, 0.0) ; # Total scattering cross section.
@nm1_10to4th=(0.0, 0.0, 0.0) ; # Refractive index at 15 C and 1013.25 mb.
@tau=(0.0,0.0,0.0) ; # optical depth of the atmosphere for each gas according to its concentration.
for ($gas=1; $gas <= 3; $gas++) {
if ($gas==1) { # Case of Argon!!!
$f1=6432.135 + 286.06021e12/(14.4e9-$nu2) ;
$ref=1.0 + 1.e-8 * $f1 ;
$Fk=1.0 ;
} elsif ($gas==2) { # case of Carbon Dioxide!!!
$f1= 5799.25/(128908.9**2 - $nu2)
+ 120.05/(89223.8**2 - $nu2)
+ 5.3334/(75037.5**2-$nu2)
+ 4.3244/(67837.7**2-$nu2)
+ 0.1218145e-4/(2418.136**2-$nu2) ;
$ref=1.0 + 1116.63027063992 * $f1 ;
# print("co2 refractive Index From adjusted model = ") ; print($ref) ; print("\n") ;
$Fk=1.1364 + 25.3e-12 * $nu2 ;
$sigCO2= 27.2e-45 * $nu**4.1343 ; # Emperical Rayleigh for CO2 from Eq. 15 of Sneep's paper.
$a=sqrt($sigCO2*$N0**2/($Fk*24.0*$pi**3*$nu**4)) ;
$ref=sqrt((2.0*$a+1.0)/(1.0-$a)) ;
$factor=($ref-1.0)/$f1 ;
# print("emperical factor for ref index = ") ; print($factor) ; print("\n") ;
# print("emperical co2 Rayleigh Cross Section = ") ; print($sigCO2) ; print(" cm-1 \n") ;
$betas=$N0*$sigCO2 ;
$beta=$betas*$fac*1.0e8 ;
# print("emperical co2 Rayleigh Coefficient = ") ; print($beta) ; print(" Mm-1 \n") ;
} else { # assume ($gas==3) # case of Air!!!
if ($l => 230.0) {
$f1=5791817.0/(238.0185-1.0/$wl2) ;
$f1=$f1+167909.0 / (57.362 - 1.0/$wl2 ) ;
} else {
$f1=8060.51+2480990.0/(132.274-1/$wl2)+17455.7/(39.32957-1.0/$wl2);
}
$ref=1.0 + 1.0e-8*$f1 ;
$a=$l;
$Fk=5.427964E-23*$a**8 - 2.806622E-19*$a**7 + 6.207856E-16*$a**6
-7.662177E-13*$a**5 + 5.767936E-10*$a**4 - 2.712549E-7*$a**3 +
7.799646E-5*$a**2 - 1.261146E-2*$a + 1.937987E+0 ;
# $Fk = 1.049 ; # From Table 2 of Bucholtz et. al. for 532 nm.
}
$rhon=6.0*($Fk-1.0)/(3.0+7.0*$Fk) ;
$gamma=$rhon/(2.0-$rhon) ;
$r=(1.0 + 5.0*$gamma) / (3.0*(1.0 + $gamma)) ; # Fpar/Fper = Bpar/Bper .
# print("Refractive Index= ") ; print($ref) ; print(" \n") ;
# print("rho_n= ") ; print($rhon) ; print(" \n") ;
# print("gamma= ") ; print($gamma) ; print(" \n") ;
# print("r=Fparallel/Fperpendicular= ") ; print($r) ; print(" \n") ;
$nm1_10to4th[$gas-1]=($ref-1)*10000.0 ;
$sig[$gas-1]=24.0* $pi**3 * $nu**4 * (($ref**2 - 1.0)/($ref**2 + 2.0))**2 * $Fk / $N0**2 ;
# print("Rayleigh Cross Section STP q= ") ; print($sig) ; print("\n") ;
$Fpar=(1.0+5.0*$gamma)/(4.0*(1.0+2.0*$gamma)) ;
$Bpar=$Fpar ;
$Fper=3.0*(1.0+$gamma)/(4.0*(1.0+2.0*$gamma)) ;
$Bper=$Fper ;
$betas=$N0*$sig[$gas-1] ;
$beta[$gas-1]=$betas*$fac*1.0e8 ;
$beta_par[$gas-1]=$beta[$gas-1]*$Fpar ;
$beta_per[$gas-1]=$beta[$gas-1]*$Fper ;
$Tau[$gas-1]=$conc[$gas-1]*$beta[$gas-1]*$T*$Rgas[$gas-1]/($g*1.0e6) ;
$Fkk[$gas-1] = $Fk ;
} # End the for loop
$Tau[0]=sprintf("%1.3e",$Tau[0]) ; $Tau[1]=sprintf("%1.3e",$Tau[1]) ;
$Tau[2]=&round($Tau[2]) ;
foreach $sig (@sig) { $sig=$sig*1.0e27 ; $sig=&round($sig) ; }
foreach $Fkk (@Fkk) { $Fkk=&round($Fkk) ; }
foreach $beta (@beta) { $beta=&round($beta) ; }
foreach $beta_par (@beta_par) { $beta_par=&round($beta_par) ; }
foreach $beta_per (@beta_per) { $beta_per=&round($beta_per) ; }
foreach $nm1_10to4th (@nm1_10to4th) { $nm1_10to4th=&round($nm1_10to4th) ; }
@Tau ;
@Fkk ;
@sig ;
@beta ;
@beta_par ;
@beta_per ;
@nm1_10to4th ;
}
sub round {
my($number) = @_ ; # The incoming number(s) is(are) stored in the @_ variable.
my($c) = abs($number) ;
if ($c ge 1.0)
{
$number=$number*1000.000 ;
return( int($number + .5 * ($number <=> 0))/1000.0 );
} elsif ($c ge 0.1)
{
$number=$number*10000.000 ;
return( int($number + .5 * ($number <=> 0))/10000.0 );
} elsif ($c ge 0.01)
{
$number=$number*100000.000 ;
return( int($number + .5 * ($number <=> 0))/100000.0 );
} elsif ($c ge 0.001)
{
$number=$number*1000000.000 ;
return( int($number + .5 * ($number <=> 0))/1000000.0 );
}
else
{
$number=$number*10000000.000 ;
return( int($number + .5 * ($number <=> 0))/10000000.0 );
}
}