root/branches/newmole/source/atom_fe2ovr.cpp

Revision 1830, 5.9 kB (checked in by rjrw, 10 months ago)

Merged from trunk r1803:1829

  • Property svn:eol-style set to native
Line 
1/* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
2 * others.  For conditions of distribution and use see copyright notice in license.txt */
3/*atoms_fe2ovr compute FeII overlap with Lya */
4/*fe2par evaluate FeII partition function */
5#include "cddefines.h"
6#include "doppvel.h"
7#include "dense.h"
8#include "rfield.h"
9#include "iso.h"
10#include "phycon.h"
11#include "hydrogenic.h"
12#include "ipoint.h"
13#include "opacity.h"
14#include "radius.h"
15#include "atomfeii.h"
16#include "thirdparty.h"
17
18const double WLAL = 1215.6845;
19
20/* There are 373 transitions:
21 * Wavelength (A)
22 * absorption oscillator strength
23 * Energy of lower level (Ryd)
24 * Statistical weight of lower level (g) */
25/** t_fe2ovr_la: constructor storing energy levels for Fred's FeII ground */
26t_fe2ovr_la::t_fe2ovr_la()
27{
28        DEBUG_ENTRY( "t_fe2ovr_la()" );
29
30        const long VERSION_MAGIC = 20070717L;
31        const static char chFile[] = "fe2ovr_la.dat";
32
33        FILE *io = open_data( chFile, "r" );
34
35        bool lgErr = false;
36        long i = -1L;
37
38        lgErr = lgErr || ( fscanf( io, "%ld", &i ) != 1 );
39        if( lgErr || i != VERSION_MAGIC )
40        {
41                fprintf( ioQQQ, " File %s has incorrect version: %ld\n", chFile, i );
42                fprintf( ioQQQ, " I expected to find version: %ld\n", VERSION_MAGIC );
43                cdEXIT(EXIT_FAILURE);
44        }
45
46        double help=0;
47        for( i=0; i < NFEII; i++ )
48        {
49                lgErr = lgErr || ( fscanf( io, "%le", &help ) != 1 );
50                fe2lam[i] = (realnum)help;
51        }
52        for( i=0; i < NFEII; i++ )
53        {
54                lgErr = lgErr || ( fscanf( io, "%le", &help ) != 1 );
55                fe2osc[i] = (realnum)help;
56        }
57        for( i=0; i < NFEII; i++ )
58        {
59                lgErr = lgErr || ( fscanf( io, "%le", &help ) != 1 );
60                fe2enr[i] = (realnum)help;
61        }
62        for( i=0; i < NFEII; i++ )
63        {
64                lgErr = lgErr || ( fscanf( io, "%le", &help ) != 1 );
65                fe2gs[i] = (realnum)help;
66        }
67        for( i=0; i < NFE2PR; i++ )
68                lgErr = lgErr || ( fscanf( io, "%le", &fe2pt[i] ) != 1 );
69        for( i=0; i < NFE2PR; i++ )
70                lgErr = lgErr || ( fscanf( io, "%le", &fe2pf[i] ) != 1 );
71
72        fclose( io );
73
74        ASSERT( !lgErr );
75        return;
76}
77
78void t_fe2ovr_la::zero_opacity()
79{
80        DEBUG_ENTRY( "zero_opacity()" );
81
82        for( int i=0; i < NFEII; i++ )
83        {
84                Fe2PopLte[i] = 0.f;
85                feopc[i] = 0.f;
86                Fe2TauLte[i] = opac.taumin;
87        }
88        return;
89}
90
91void t_fe2ovr_la::init_pointers()
92{
93        DEBUG_ENTRY( "init_pointers()" );
94
95        for( int i=0; i < NFEII; i++ )
96                ipfe2[i] = ipoint(fe2enr[i]);
97        return;
98}
99
100/** tau_inc: update line opacities */
101void t_fe2ovr_la::tau_inc()
102{
103        DEBUG_ENTRY( "tau_inc()" );
104
105        for( int i=0; i < NFEII; i++ )
106                /* optical depths for Feii dest of lya when large feii not used */
107                Fe2TauLte[i] += feopc[i]*(realnum)radius.drad_x_fillfac;
108        return;
109}
110
111/** atoms_fe2ovr compute FeII overlap with Lya */
112void t_fe2ovr_la::atoms_fe2ovr(void)
113{
114        DEBUG_ENTRY( "atoms_fe2ovr()" );
115
116        long int i;
117
118        static long int nZoneEval;
119
120        double Fe2Partn,
121          displa,
122          hopc,
123          rate,
124          weight;
125
126        static double BigFeWidth,
127          BigHWidth,
128          oldrat;
129
130        /* wavelength of Lya in Angstroms */
131
132        /* compute efficiency of FeII emission overlapping with Ly-alpha
133         * implemented with Fred Hamann
134         *
135         * make Ly-a width monotonically increasing to avoid oscillation
136         * in deep regions of x-ray ionized clouds.
137         *
138         * do nothing if large FeII atom is used */
139        if( FeII.lgFeIILargeOn )
140        {
141                return;
142        }
143
144        if( nzone <= 1 )
145        {
146                BigHWidth = hydro.HLineWidth;
147                BigFeWidth = DoppVel.doppler[ipIRON];
148                nZoneEval = nzone;
149        }
150
151        /* do not do pumping if no population,line is thin, or turned off */
152        if( (dense.xIonDense[ipIRON][1] <= 0. || !FeII.lgLyaPumpOn) ||
153                hydro.HLineWidth <= 0. )
154        {
155                Fe2Partn = 0.;
156                oldrat = 0.;
157                hydro.dstfe2lya = 0.;
158
159                for( i=0; i < NFEII; i++ )
160                {
161                        Fe2PopLte[i] = 0.;
162                }
163                return;
164        }
165
166        /* only evaluate this one time per zone to avoid oscillations
167         * deep in x-ray ionized clouds */
168        if( nZoneEval == nzone && nzone > 1 )
169        {
170                return;
171        }
172
173        BigHWidth = MAX2(BigHWidth,(double)hydro.HLineWidth);
174        BigFeWidth = MAX2(BigFeWidth,(double)DoppVel.doppler[ipIRON]);
175        nZoneEval = nzone;
176
177        /* check that data is linked in */
178        ASSERT( fe2lam[0] > 0. );
179
180        rate = 0.;
181        Fe2Partn = fe2par(phycon.te);
182        for( i=0; i < NFEII; i++ )
183        {
184                /* this is displacement from line center in units of Lya width */
185                displa = fabs(fe2lam[i]-WLAL)/WLAL*3e10/BigHWidth;
186                if( displa < 1.333 )
187                {
188                        /* have variable weighting factor depending on distance away
189                         * this comes form the Verner's fits to Adam's results */
190                        weight = ( displa <= 0.66666 ) ? 1. : MAX2(0.,1.-(displa-0.666666)/0.66666);
191
192                        Fe2PopLte[i] = (realnum)(fe2gs[i]/Fe2Partn*rfield.ContBoltz[ipfe2[i]-1]*
193                                               dense.xIonDense[ipIRON][1]);
194
195                        feopc[i] = (realnum)(Fe2PopLte[i]*fe2osc[i]*0.0150*(fe2lam[i]*1e-8)/BigFeWidth);
196
197                        /* Ly-alpha line-center opacity */
198                        if( StatesElem[ipH_LIKE][ipHYDROGEN][ipH1s].Pop*dense.xIonDense[ipHYDROGEN][1] > 0. )
199                        {
200                                hopc = 7.60e-8*StatesElem[ipH_LIKE][ipHYDROGEN][ipH1s].Pop*
201                                        dense.xIonDense[ipHYDROGEN][1]/DoppVel.doppler[ipHYDROGEN];
202                        }
203                        else
204                        {
205                                hopc = 7.60e-8*dense.xIonDense[ipHYDROGEN][0]/DoppVel.doppler[0];
206                        }
207                        rate += (feopc[i]/SDIV((feopc[i] + hopc)))*(BigFeWidth/DoppVel.doppler[ipHYDROGEN])*
208                                (1. - 1./(1. + 1.6*Fe2TauLte[i]))*weight;
209                }
210        }
211
212        /* dstfe2lya is total Lya deexcitation probability due to line overlap
213         * damper is to stop feedback between here and hydrogen ionization sln */
214        /** \todo       2       hydro.dstfe2lya is always multiplied by a double and stuffed into a double.
215         * defining it as a realnum causes lost precision here. */
216        hydro.dstfe2lya = (realnum)((rate + oldrat)/2.);
217        oldrat = hydro.dstfe2lya;
218        return;
219}
220
221/** fe2par evaluate FeII partition function */
222double t_fe2ovr_la::fe2par(double te)
223{
224        DEBUG_ENTRY( "fe2par()" );
225
226        double fe2par_v;
227
228        /* function to evaluate partition function for FeII
229         *
230         * Temperature (K) */
231
232        if( te <= fe2pt[0] )
233                fe2par_v = fe2pf[0];
234        else if( te >= fe2pt[NFE2PR-1] )
235                fe2par_v = fe2pf[NFE2PR-1];
236        else
237        {
238                long i = hunt_bisect(fe2pt,NFE2PR,te);
239                double slope = (fe2pf[i+1] - fe2pf[i])/(fe2pt[i+1] - fe2pt[i]);
240                double du = slope*(te - fe2pt[i]);
241                fe2par_v = fe2pf[i] + du;
242        }
243        return( fe2par_v );
244}
Note: See TracBrowser for help on using the browser.