Canoe
Comprehensive Atmosphere N' Ocean Engine
attenuation_h2s.cpp
Go to the documentation of this file.
1 /**************************************************************************
2 
3  ===== JUNO codes =====
4 
5  Copyright (C) 2019 California Institute of Technology (Caltech)
6  All rights reserved.
7 
8  Written by Fabiano Oyafuso (fabiano@jpl.nasa.gov)
9  Adapted by Cheng Li (cli@gps.caltech.edu) to SNAP structure
10 
11 **************************************************************************/
12 
13 // C/C++ headers
14 #include <cmath>
15 
16 // h2s data headers
17 #include "mwr_absorber_h2s.hpp"
18 
19 // cli, 190801
20 inline double SQUARE(double x) { return x * x; }
21 static double const pi = 3.14159265358979;
22 // end
23 
24 inline double Lineshape_BR(double obsfreq, double linefreq, double gamma,
25  double zeta, double delta) {
26  // double const pi = 2.0*acos(0.0);
27  double const c = 2.99792458e10;
28 
29  double obsfreqghz = obsfreq / 1000.0;
30  double linefreqghz = linefreq / 1000.0;
31 
32  double u1 = 2.0 / pi * SQUARE(obsfreqghz / linefreqghz);
33  double u2 = SQUARE(linefreqghz + delta) + SQUARE(gamma) - SQUARE(zeta);
34 
35  u1 *= ((gamma - zeta) * SQUARE(obsfreqghz) + (gamma + zeta) * u2);
36  u2 = SQUARE(obsfreqghz) - SQUARE(linefreqghz + delta) - SQUARE(gamma) +
37  SQUARE(zeta);
38  u2 = SQUARE(u2) + 4.0 * SQUARE(obsfreqghz) * SQUARE(gamma);
39 
40  // The factor c/1.0e9 converts 1/GHz to 1/(cm**-1):
41  return (u1 / u2) * c / 1.0e9;
42 }
43 
44 double attenuation_H2S_Hofstadter(double freq, double P, double T, double XH2,
45  double XHe, double XH2S) {
46  /*
47  code adpated from Mark Hofstadter.
48  Here are some of his comments:
49 
50  * This subroutine calculates H2S opacity, as described in DeBoer
51  * and Steffes 1994 (Icarus 109, 352-366). Inputs are local atmospheric
52  * conditions and observing frequency, output is the opacity in cm-1.
53  *
54  *
55  * COMMENTS:
56  * H2S line information is passed in via the parameter list, presumably
57  * the calling program has also called subroutine ReadLineInfo.
58  *
59  * Line widths have this functional form (Eq. 20 of DeBoer and Steffes
60  * 1994):
61  * delnu = SUM_i [ delnu_o_i * P_i * (T_o/T)**Xi_i ]
62  * where the sum is over all gasses present, the subscript "o" refers
63  * to a reference state, the subscript "i" to the broadening gas in
64  * question, and T is temperature. DeBoer and Steffes, however, only
65  * specify parameters for H2, He, and H2S, so I am forced to neglect
66  * broadening by CH4, and they suggest using Xi_i = 0.7 for all species.
67  *
68  * The absorption at the line center, A, is calculated with Equation 19
69  * from DeBoer and Steffes, having units of cm**-1. Note that in
70  * their equation, P (which is the H2S partial pressure, not the total
71  * atmosphere) is in bar (the leading factor of 1E6 will convert
72  * bar to dyne/cm**2) and delnu must be converted from GHz
73  * to cm**-1. The line intensity in their equation is in units
74  * of cm**-1 / (molecules/cm**2), requiring a conversion from the
75  * Poynter and Picket units of nm**2 MHz. The conversion factor is
76  * to multiply the PandP value by 1E-8 (converting nm**2 MHz to cm**2 Hz)
77  * and divide by the speed of light (converting Hz to cm**-1). The
78  * "per molecule" is just assumed in some way. This intensity unit
79  * conversion is set to the value PPunitsToDS.
80  *
81  * This software was tested against Karuthika Devaraj's code during a
82  * visit to the VLA in June 2008 (while she was a summer intern there).
83  * We were satisfied that our results matched to the precision of our
84  * machines. Our results did differ from those published by DeBoer and
85  * Steffes, but we believe this is due to that paper using
86  * and older version of the JPL ("Poynter and Pickett" for us
87  * old-timers) line catalog. In my notes, I state that the differences
88  * between Karuthika and I were ~1% near line centers, 10x smaller
89  * elsewhere (though it's possible that I wrote that before we
90  * discovered that we were comparing calculations at slightly difference
91  * frequencies, which made us think differences near line centers were
92  * greater than they really were).
93  *
94  *
95  * KNOWN BUGS AND LIMITATIONS:
96  * 1) Does not account for line broadening due to collisions with
97  * CH4.
98  *
99  * 2) I can leave F and delnu in GHz in the final expression rather
100  * than converting both to cm**-1 cuz the units will cancel.
101  *
102  *
103  * SUBROUTINES CALLED:
104  * None.
105  *
106  * FUNCTIONS CALLED:
107  * Lineshape_BR (real): Returns the Ben Reuven line-shape function
108  * as defined in DeBoer and Steffes Eq. 23, in
109  * units of 1/(cm**-1) (note the double
110  * inverse!). See the Function for required
111  * inputs.
112  *
113  *
114  * INTERNALLY SET PARAMETERS
115  * MAXNUMLINE (integer): Max number of spectral lines in input file.
116  *
117  * NUMPARTFUNC (integer): The number of temperatures for which
118  * information on the partition function
119  * is provided (to dimension qlog and tqlog).
120  *
121  * NUMQUANTNUM (integer): The number of quantum numbers used to
122  * specify molecular states in the input file.
123  *
124  *
125  * INPUTS:
126  * EXTMAXLINE (integer): Externally used value to dimension arrays.
127  * Is tested to verify it matches MAXNUMLINE.
128  *
129  * EXTPARTFUNC (integer): Externally used value to dimension arrays.
130  * Is tested to verify it matches NUMPARTFUNC.
131  *
132  * EXTQUANTNUM (integer): Externally used value to dimension arrays.
133  * Is tested to verify it matches NUMQUANTNUM.
134  *
135  * nline (integer): Number of H2S lines to model.
136  *
137  * qlog (real): NUMPARTFUNC-element array of the base 10 log of
138  * the partition function for the temperatures
139  * specifed in tqlog.
140  *
141  * tqlog (real): NUMPARTFUNC-element array of the
142  * temperatures (K) at which the partition functions
143  * in qlog are calculated.
144  *
145  * freq (real): Array of line frequencies, in MHz.
146  *
147  * freqerr (real): Array of line frequency uncertainties, in MHz.
148  *
149  * lgint (real): Array of base 10 log of integrated intensity in
150  * units of nm^2 MHz at 300 K.
151  *
152  * dr (integer): Array of degrees of freedom in the rotational
153  * partition function.
154  *
155  * elo (real): Array of lower energy state (cm-1) relative to
156  * ground state.
157  *
158  * gup (integer): Array of upper state degeneracy.
159  *
160  * qnfmt (integer): Array specifying the format for QNp and QNpp.
161  *
162  * qnp (integer): Array (NUMQUANTNUMxMAXNUMLINE) of upper-state
163  * quantum numbers.
164  *
165  * qnpp (integer): Array (NUMQUANTNUMxMAXNUMLINE) of lower-state
166  * quantum numbers.
167  *
168  * ObsFreq (real): The observing frequency, in MHz.
169  *
170  * T (real): Atmospheric temperature, in Kelvin.
171  *
172  * P (real): Total atmospheric pressure, in mbar.
173  *
174  * Ph2/he/ch4/h2o/nh3/h2s (real): Partial pressures (mbar) of
175  * H2, He, CH4, H2O, NH3, and H2S.
176  *
177  *
178  * OUTPUTS:
179  *
180  * kh2s (real): The total H2S opacity, in 1/cm.
181  *
182  *
183  * LOCAL VARIABLES:
184  * pi (real): 3.1415926.....
185  *
186  * kb (real): Boltzmann's constant in cgs units (erg/K). Taken from
187  * Cohen and Taylor 1995.
188  *
189  * c (real): Speed of light, in cm/s. From Cohen and Taylor 1995.
190  *
191  * h (real): Planck constant, in erg sec. From Cohen and Taylor 1995.
192  *
193  * I (integer): Loop counter.
194  *
195  * Xi (real): Line broadening temperature dependence. As per DeBoer
196  * and Steffes, it is assumed to be 0.7 for all species.
197  * (I see, however, that the Joiner et al. 1992 reference
198  * DS quote really used 0.67. Using it makes a
199  * negligable difference.)
200  *
201  * To_linewidth (real): The reference temperature for calculating
202  * delnu (K). This is never explicitly given
203  * in the DS paper but the Joiner et al. 1992
204  * reference (IEEE Trans. Micro. Theory and
205  * Tech.) indicates they used 296 K. I use 296,
206  * but I tried both it and 300 K and it made
207  * only a trivial difference.
208  *
209  * delnu (real): Total line broadening parameter (GHz) of H2S
210  * due to H2, He, and H2S.
211  *
212  * delnuh2_o (real): Line broadening parameter of H2S by H2, from
213  * DeBoer and Steffes (GHz/bar).
214  *
215  * delnuhe_o (real): Line broadening parameter of H2S by He, from
216  * DeBoer and Steffes (GHz/bar).
217  *
218  * delnuh2s_o (real): Line broadening parameter of H2S by H2S, from
219  * DeBoer and Steffes (GHz/bar) EXCEPT for 4
220  * millimeter lines, where other values are used.
221  *
222  * delnuh2s_168ghz (real): Line broadening parameter of H2S by H2S,
223  * (GHz/bar) from DeBoer and Steffes for the
224  * 168 GHz line. (They reference Helminger and
225  * DeLucia 1977, JQSRT 17, 751-754.)
226  *
227  * delnuh2s_216ghz (real): Line broadening parameter of H2S by H2S,
228  * (GHz/bar) from DeBoer and Steffes for the
229  * 216 GHz line. (They reference Helminger and
230  * DeLucia 1977, JQSRT 17, 751-754.)
231  *
232  * delnuh2s_300ghz (real): Line broadening parameter of H2S by H2S,
233  * (GHz/bar) from DeBoer and Steffes for the
234  * 300 GHz line. (They reference Helminger and
235  * DeLucia 1977, JQSRT 17, 751-754.)
236  *
237  * delnuh2s_393ghz (real): Line broadening parameter of H2S by H2S,
238  * (GHz/bar) from DeBoer and Steffes for the
239  * 393 GHz line. (They reference Helminger and
240  * DeLucia 1977, JQSRT 17, 751-754.)
241  *
242  * delnuh2s (real): Line broadening parameter of H2S by H2S to use
243  * for a particular line, set to one of the above
244  * H2S values.
245  *
246  * eta (real): Constant reflecting the temperature dependence of
247  * the partition function. It is 1 for linear molecules,
248  * and ~1.5 for non-linear and symmetric top molecules.
249  * Here it is set to 1.5. I believe H2S is an
250  * asymmetric top molecule (LeSueur et al., 1992,
251  * Molec. Phys. 76, 1147-1156) so I was not sure whether
252  * 1 or 1.5 is a better value to pick. Since the PandP
253  * catalog indicates there are 3 degrees of freedom
254  * for H2S, it makes sense to use 1.5.
255  *
256  * To_intensity (real): Reference temperature for line intensity
257  * value in the line catalog (300 K).
258  *
259  * A (real): Line intensity, in cm**-1.
260  *
261  * PPunitsToDSunits (real): Conversion factor for taking the line
262  * intensity units of the PandP catlog:
263  * nm**2 MHz
264  * to what DS want:
265  * cm**-1/(molec/cm**2).
266  * It is 1 / (c*1.0E8), where the 1E-8
267  * converts PandP units to cgs, and the
268  * factor of c converts Hz to cm**-1.
269  *
270  * zeta (real): The coupling parameter in the Ben-Reuven lineshape.
271  * As per DandS, it is set equal to delnu (GHz).
272  *
273  * delta (real): The pressure-shift term in the Ben-Reuven lineshape.
274  * As per DandS, it is set equal to
275  * 1.28 * Ph2s/1000
276  * which I think is GHz for Ph2s in bar.
277  *
278  * F (real): The line shape function in cm (think of it as 1/cm**-1).
279 
280  */
281 
282  double T_in = T;
283  // pressures in mbar
284  double Ph2s = 1e3 * P * XH2S;
285  double Phe = 1e3 * P * XHe;
286  double Ph2 = 1e3 * P * XH2;
287 
288  int const Nlines(sizeof(h2s_lines) / sizeof(h2s_lines[0]));
289 
290  // double const pi = 2.0*acos(0.0);
291 
292  // Physical constants in cgs from Cohen and Taylor 1986/1987.
293  double const kb = 1.38066e-16;
294  double const c = 2.99792458e10;
295  double const h = 6.626075e-27;
296 
297  // Other constants:
298  double const PPunitsToDSunits = 1.0 / (c * 1.0e8);
299 
300  // Parameters from DeBoer and Steffes or references therein.
301  // (The calculation of delta has a divisor of 1000 to convert
302  // pressure from mbar to bar.)
303  double const Xi = 0.7;
304  double const To_linewidth = 296.0;
305  double const delnuh2_o = 1.96;
306  double const delnuhe_o = 1.20;
307  double const delnuh2s_o = 5.78;
308  double const delnuh2s_168ghz = 5.38;
309  double const delnuh2s_216ghz = 6.82;
310  double const delnuh2s_300ghz = 5.82;
311  double const delnuh2s_393ghz = 5.08;
312  double const eta = 1.5;
313  double const To_intensity = 300.0;
314  double const delta = 1.28 * Ph2s / 1000.0;
315 
316  double kh2s = 0.0;
317 
318  // Calculate opacity from each H2S line.
319  for (auto I = 0; I < Nlines; I++) {
320  // Calculate linewidth (delnu) as per DeBoer and Steffes Eq. 20.
321  // Factors of 1000 convert mbar to bar.
322  double delnu = delnuh2_o * (Ph2 / 1000.0) * pow(To_linewidth / T_in, Xi) +
323  delnuhe_o * (Phe / 1000.0) * pow(To_linewidth / T_in, Xi);
324 
325  double delnuh2s;
326  if (int(h2s_lines[I].FREQ) == 168762)
327  delnuh2s = delnuh2s_168ghz;
328  else if (int(h2s_lines[I].FREQ) == 216710)
329  delnuh2s = delnuh2s_216ghz;
330  else if (int(h2s_lines[I].FREQ) == 300505)
331  delnuh2s = delnuh2s_300ghz;
332  else if (int(h2s_lines[I].FREQ) == 393450)
333  delnuh2s = delnuh2s_393ghz;
334  else
335  delnuh2s = delnuh2s_o;
336 
337  delnu += delnuh2s * (Ph2s / 1000.0) * pow(To_linewidth / T_in, Xi);
338 
339  // Calculate absorption at line center (A), as per DeBoer and
340  // Steffes Eq. 19. The leading factor of 1E3 converts P in mbar
341  // to dyne/cm**2 (DS had a factor of 1E6 because they give P
342  // in bar). The factor of 1E9/c converts
343  // delnu from GHz to cm**-1, as specified by DS.
344  double A = 1.0e3 * Ph2s / (pi * kb * T_in * delnu * 1.0e9 / c);
345  A *= pow(To_intensity / T_in, eta + 1.0);
346  A *= pow(10.0, h2s_lines[I].LGINT) * PPunitsToDSunits;
347  A *= exp(-(h * c * h2s_lines[I].ELO / kb) *
348  (1.0 / T_in - 1.0 / To_intensity));
349 
350  // Calculate lineshape (F)
351 
352  // As per DandS, set zeta to delnu
353  double zeta = delnu;
354  double F = Lineshape_BR(freq * 1e3, h2s_lines[I].FREQ, delnu, zeta, delta);
355 
356  // Calculate this line's contribution to the final opacity
357  // (the factor of 1E9/c converts delnu in GHz to cm**-1):
358  kh2s += A * pi * delnu * (1.0e9 / c) * F;
359  }
360 
361  return kh2s; // inv(cm)
362 }
static double const pi
double attenuation_H2S_Hofstadter(double freq, double P, double T, double XH2, double XHe, double XH2S)
double Lineshape_BR(double obsfreq, double linefreq, double gamma, double zeta, double delta)
double SQUARE(double x)
#define A(i, j)
Definition: band_back_sub.c:18
static H2SLineList h2s_lines[]