cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mole_h2_coll.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2013 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*H2_CollidRateRead read collision rates */
4 /*H2_CollidRateEvalAll - set H2 collision rates */
5 #include "cddefines.h"
6 #include "atmdat.h"
7 #include "phycon.h"
8 #include "dense.h"
9 #include "taulines.h"
10 #include "input.h"
11 #include "h2.h"
12 #include "h2_priv.h"
13 
14 STATIC realnum GbarRateCoeff( long nColl, double ediff );
15 
16 /*H2_CollidRateEvalAll - set H2 collision rate coefficients */
18 {
19  DEBUG_ENTRY( "H2_CollidRateEvalAll()" );
20 
21  long int numb_coll_trans = 0;
22 
23  if( nTRACE >= n_trace_full )
24  fprintf(ioQQQ,"%s set collision rates\n", label.c_str());
25  /* loop over all possible collisional changes within X
26  * and set collision rates, which only depend on Te
27  * will go through array in energy order since coll trans do not
28  * correspond to a line
29  * collisional dissociation rate coefficient, units cm3 s-1 */
30  H2_coll_dissoc_rate_coef[0][0] = 0.;
31  H2_coll_dissoc_rate_coef_H2[0][0] = 0.;
32  for( long ipHi=0; ipHi<nLevels_per_elec[0]; ++ipHi )
33  {
34  /* obtain the proper indices for the upper level */
35  long iVibHi = ipVib_H2_energy_sort[ipHi];
36  long iRotHi = ipRot_H2_energy_sort[ipHi];
37 
38  /* this is a guess of the collisional dissociation rate coefficient -
39  * will be multiplied by the sum of densities of all colliders
40  * except H2*/
41  double energy = H2_DissocEnergies[0] - states[ipHi].energy().WN();
42  ASSERT( energy > 0. );
43  /* we made this up - Boltzmann factor times rough coefficient */
44  H2_coll_dissoc_rate_coef[iVibHi][iRotHi] =
45  1e-14f * (realnum)sexp(energy/phycon.te_wn) * lgColl_dissoc_coll;
46 
47  /* collisions with H2 - pre coefficient changed from 1e-8
48  * (from umist) to 1e-11 as per extensive discussion with Phillip Stancil */
49  H2_coll_dissoc_rate_coef_H2[iVibHi][iRotHi] =
50  1e-11f * (realnum)sexp(energy/phycon.te_wn) * lgColl_dissoc_coll;
51 
52  /*fprintf(ioQQQ,"DEBUG coll_dissoc_rateee\t%li\t%li\t%.3e\t%.3e\n",
53  iVibHi,iRotHi,
54  H2_coll_dissoc_rate_coef[iVibHi][iRotHi],
55  H2_coll_dissoc_rate_coef_H2[iVibHi][iRotHi]);*/
56 
57  for( long ipLo=0; ipLo<ipHi; ++ipLo )
58  {
59  long iVibLo = ipVib_H2_energy_sort[ipLo];
60  long iRotLo = ipRot_H2_energy_sort[ipLo];
61 
62  ASSERT( states[ipHi].energy().WN() - states[ipLo].energy().WN() > 0. );
63 
64  /* keep track of number of different collision routes */
65  ++numb_coll_trans;
66  for( long nColl=0; nColl<N_X_COLLIDER; ++nColl )
67  {
68  realnum newrate = H2_CollidRateEvalOne( iVibHi,iRotHi,iVibLo,iRotLo,
69  ipHi , ipLo , nColl, phycon.te );
70  CollRateCoeff[ipHi][ipLo][nColl] = newrate;
71  }
72  }
73  }
74 
75  fixit(); // test that this does not matter with new rate table interpolation. Remove if it does not.
76 #if 0
77  /* >>chng 05 nov 30, GS, rates decreases exponentially for low temperature, see Le Bourlot et al. 1999 */
78  /* Phillips mail--Apparently, the SD fit is only valid over the range of their calculations, 100-1000K.
79  * The rate should continue to fall exponentially with decreasing T, something like exp(-3900/T) for 0->1 and
80  * exp[-(3900-170.5)/T] for 1->0. It is definitely, not constant for T lower than 100 K, as far as we know.
81  * There may actually be a quantum tunneling effect which causes the rate to increase at lower T, but no
82  * one has calculated it (as far as I know) and it might happen below 1K or so.???*/
83  if( phycon.te < 100. )
84  {
85  /* first term in exp is suggested by Phillip, second temps in paren is to ensure continuity
86  * across 100K */
87  H2_CollRate[0][1][0][0][0] *= (realnum)(exp(-(3900-170.5)*(1./phycon.te - 1./100.)));
88  H2_CollRate[0][3][0][0][0] *= (realnum)(exp(-(3900-1015.1)*(1./phycon.te - 1./100.)));
89  H2_CollRate[0][2][0][1][0] *= (realnum)(exp(-(3900-339.3)*(1./phycon.te - 1./100.)));
90  }
91 #endif
92 
93  if( nTRACE >= n_trace_full )
94  fprintf(ioQQQ,
95  " collision rates updated for new temp, number of trans is %li\n",
96  numb_coll_trans);
97 
98  return;
99 }
100 
101 /* compute rate coefficient for a single quenching collision */
103  /*returns collision rate coefficient, cm-3 s-1 for quenching collision
104  * from this upper state */
105  long iVibHi, long iRotHi,long iVibLo,
106  /* to this lower state */
107  long iRotLo, long ipHi , long ipLo ,
108  /* colliders are H, He, H2(ortho), H2(para), and H+ */
109  long nColl,
110  double te_K )
111 {
112  DEBUG_ENTRY( "H2_CollidRateEvalOne()" );
113 
114 // realnum rate = 0.f;
115 // if( RateCoefTable[nColl].temps.size() > 0 )
116 
117  realnum rate = InterpCollRate( RateCoefTable[nColl], ipHi, ipLo, te_K );
118 
119  /* this is option to use guess of collision rate coefficient - but only if this is
120  * a downward transition that does not mix ortho and para */
121  /* turn lgColl_gbar on/off with atom h2 gbar on off */
122  if( (rate==0.f) && lgColl_gbar &&
123  ( nColl==4 ||
124  ( ( nColl==0 || nColl==1 ) &&
125  H2_lgOrtho[0][iVibHi][iRotHi]-H2_lgOrtho[0][iVibLo][iRotLo]==0 ) ) )
126  {
127  double ediff = states[ipHi].energy().WN() - states[ipLo].energy().WN();
128  rate = GbarRateCoeff( nColl, ediff );
129  }
130 
131  rate *= lgColl_deexec_Calc;
132 
133  /* >>chng 05 feb 09, add option to kill ortho - para collisions */
134  if( !lgH2_ortho_para_coll_on &&
135  (H2_lgOrtho[0][iVibHi][iRotHi]-H2_lgOrtho[0][iVibLo][iRotLo]) )
136  rate = 0.;
137 
138  if( lgH2_NOISE )
139  rate *= CollRateErrFac[ipHi][ipLo][nColl];
140 
141  return rate;
142 }
143 
144 STATIC realnum GbarRateCoeff( long nColl, double ediff )
145 {
146  // these are fits to the existing collision data
147  // used to create g-bar rates
148  double gbarcoll[N_X_COLLIDER][3] =
149  {
150  {-9.9265 , -0.1048 , 0.456 },
151  {-8.281 , -0.1303 , 0.4931 },
152  {-10.0357, -0.0243 , 0.67 },
153  {-8.6213 , -0.1004 , 0.5291 },
154  {-9.2719 , -0.0001 , 1.0391 }
155  };
156 
157  // do not let energy difference be smaller than 100 wn, the smallest
158  // difference for which we fit the rate coefficients
159  ediff = MAX2(100., ediff );
160 
161  // the fit is log(K)=y_0+a*((x)^b), where K is the rate coefficient,
162  // and x is the energy in wavenumbers
163  realnum rate = (realnum)pow(10. ,
164  gbarcoll[nColl][0] + gbarcoll[nColl][1] *
165  pow(ediff,gbarcoll[nColl][2]) );
166 
167  return rate;
168 }
169 
170 void diatomics::H2_CollidRateRead( long int nColl )
171 {
172  DEBUG_ENTRY( "H2_CollidRateRead()" );
173 
174  if( coll_source[nColl].filename.size() == 0 && coll_source[nColl].magic == 0 )
175  return;
176 
177  const char* chFilename = coll_source[nColl].filename.c_str();
178  long magic_expect = coll_source[nColl].magic;
179  char chLine[INPUT_LINE_LENGTH];
180  char chPath[FILENAME_PATH_LENGTH_2];
181  strcpy( chPath, path.c_str() );
182  strcat( chPath, input.chDelimiter );
183  strcat( chPath, chFilename );
184  FILE *ioDATA = open_data( chPath, "r" );
185 
186  /* read the first line and check that magic number is ok */
187  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
188  {
189  fprintf( ioQQQ, " H2_CollidRateRead could not read first line of %s\n", chFilename );
191  }
192 
193  /* magic number */
194  long n1 = atoi( chLine );
195  if( n1 != magic_expect )
196  {
197  fprintf( ioQQQ, " H2_CollidRateRead: the version of %s is not the current version.\n", chFilename );
198  fprintf( ioQQQ, " I expected to find the number %li and got %li instead.\n", magic_expect, n1 );
199  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
201  }
202 
203  FunctPtr func = new FunctDiatoms( *this );
204  ReadCollisionRateTable( RateCoefTable[nColl], ioDATA, func, nLevels_per_elec[0] );
205  delete func;
206 
207  fclose( ioDATA );
208 
209  return;
210 }
211 
212 void diatomics::GetIndices( long& ipHi, long& ipLo, const char* chLine, long& i ) const
213 {
214  bool lgEOL;
215  long iVibHi = (long)FFmtRead( chLine, &i, strlen(chLine), &lgEOL );
216  long iRotHi = (long)FFmtRead( chLine, &i, strlen(chLine), &lgEOL );
217  long iVibLo = (long)FFmtRead( chLine, &i, strlen(chLine), &lgEOL );
218  long iRotLo = (long)FFmtRead( chLine, &i, strlen(chLine), &lgEOL );
219  ASSERT( iRotHi >= 0 && iVibHi >= 0 && iRotLo >= 0 && iVibLo >=0 );
220 
221  // check that we actually included the levels in the model representation
222  // depending on the potential surface, the collision data set
223  // may not agree with our adopted model - skip those
224  if( ( iVibHi > nVib_hi[0] || iVibLo > nVib_hi[0] ) ||
225  ( iRotHi < Jlowest[0] || iRotLo < Jlowest[0] ) ||
226  ( iRotHi > nRot_hi[0][iVibHi] || iRotLo > nRot_hi[0][iVibLo] ) ||
227  /* some collision rates have the same upper and lower indices - skip them */
228  ( iVibHi == iVibLo && iRotHi == iRotLo ) )
229  {
230  ipHi = -1;
231  ipLo = -1;
232  return;
233  }
234 
235  ipHi = ipEnergySort[0][iVibHi][iRotHi];
236  ipLo = ipEnergySort[0][iVibLo][iRotLo];
237  if( ipHi < ipLo )
238  swap( ipHi, ipLo );
239 
240  return;
241 }
242 
int nTRACE
Definition: h2_priv.h:396
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition: cpu.cpp:616
double H2_DissocEnergies[N_ELEC]
Definition: h2_priv.h:606
const int FILENAME_PATH_LENGTH_2
Definition: cddefines.h:253
t_input input
Definition: input.cpp:12
int n_trace_full
Definition: h2_priv.h:399
t_coll_source coll_source[N_X_COLLIDER]
Definition: h2_priv.h:313
multi_arr< realnum, 2 > H2_coll_dissoc_rate_coef_H2
Definition: h2_priv.h:668
#define MAX2
Definition: cddefines.h:786
valarray< long > ipVib_H2_energy_sort
Definition: h2_priv.h:684
long int Jlowest[N_ELEC]
Definition: h2_priv.h:613
realnum H2_CollidRateEvalOne(long iVibHi, long iRotHi, long iVibLo, long iRotLo, long ipHi, long ipLo, long nColl, double temp_K)
t_phycon phycon
Definition: phycon.cpp:6
void H2_CollidRateRead(long int nColl)
vector< CollRateCoeffArray > RateCoefTable
Definition: h2_priv.h:620
sys_float sexp(sys_float x)
Definition: service.cpp:914
FILE * ioQQQ
Definition: cddefines.cpp:7
multi_arr< realnum, 2 > H2_coll_dissoc_rate_coef
Definition: h2_priv.h:665
void GetIndices(long &ipHi, long &ipLo, const char *chLine, long &i) const
multi_arr< realnum, 3 > CollRateErrFac
Definition: h2_priv.h:619
multi_arr< realnum, 3 > CollRateCoeff
Definition: h2_priv.h:618
multi_arr< long int, 3 > ipEnergySort
Definition: h2_priv.h:687
bool lgH2_ortho_para_coll_on
Definition: h2_priv.h:369
void H2_CollidRateEvalAll(void)
Definition: atmdat.h:399
STATIC realnum GbarRateCoeff(long nColl, double ediff)
bool lgColl_dissoc_coll
Definition: h2_priv.h:359
void swap(count_ptr< T > &a, count_ptr< T > &b)
Definition: count_ptr.h:82
string filename
Definition: h2_priv.h:56
long int nLevels_per_elec[N_ELEC]
Definition: h2_priv.h:615
#define STATIC
Definition: cddefines.h:101
string label
Definition: h2_priv.h:568
string path
Definition: h2_priv.h:570
bool lgH2_NOISE
Definition: h2_priv.h:380
double InterpCollRate(const CollRateCoeffArray &rate_table, const long &ipHi, const long &ipLo, const double &ftemp)
Definition: atmdat.cpp:135
const int N_X_COLLIDER
Definition: h2_priv.h:13
long magic
Definition: h2_priv.h:54
float realnum
Definition: cddefines.h:107
#define EXIT_FAILURE
Definition: cddefines.h:144
const int INPUT_LINE_LENGTH
Definition: cddefines.h:258
#define cdEXIT(FAIL)
Definition: cddefines.h:438
bool lgColl_deexec_Calc
Definition: h2_priv.h:356
#define ASSERT(exp)
Definition: cddefines.h:582
qList states
Definition: h2_priv.h:562
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:688
char chDelimiter[3]
Definition: input.h:42
bool lgColl_gbar
Definition: h2_priv.h:353
valarray< long > nRot_hi[N_ELEC]
Definition: h2_priv.h:610
valarray< long > ipRot_H2_energy_sort
Definition: h2_priv.h:686
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
Definition: service.cpp:70
double te_wn
Definition: phycon.h:20
double te
Definition: phycon.h:11
void ReadCollisionRateTable(CollRateCoeffArray &coll_rate_table, FILE *io, FunctPtr GetIndices, long nMolLevs, long nTemps, long nTrans)
Definition: atmdat.cpp:14
void fixit(void)
Definition: service.cpp:991
long int nVib_hi[N_ELEC]
Definition: h2_priv.h:608
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
Definition: service.cpp:381
multi_arr< bool, 3 > H2_lgOrtho
Definition: h2_priv.h:640