root/branches/newmole/source/cdspec.cpp

Revision 2582, 8.5 kB (checked in by rporter, 2 weeks ago)

branches/newmole - bring in trunk r2541:2581

  • 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/*cdSPEC returns the spectrum needed for Keith Arnaud's XSPEC */
4/*Spec_cont called by cdSPEC to generate actual spectrum */
5#include "cddefines.h"
6#include "cddrive.h"
7#include "physconst.h"
8#include "geometry.h"
9#include "radius.h"
10#include "rfield.h"
11#include "opacity.h"
12#include "grid.h"
13
14/*
15 * this routine returns the spectrum needed for Keith Arnaud's XSPEC
16 * X-Ray analysis code.  It should be called after cdDrive has successfully
17 * computed a model.  the calling routine must ensure that the vectors
18 * have enough space to store the resulting spectrum,
19 * given the bounds and energy resolution
20 */
21
22/* array index within energy array in Cloudy grids -  this has file scope */
23static long int iplo , iphi;
24
25/* energies of lower and upper bound of XSPEC cell we are considering */
26static double Elo , Ehi;
27
28void cdSPEC(
29        /* option - the type of spectrum to be returned
30         * 1    the incident continuum 4\pi nuJ_nu, , erg cm-2 s-1
31         *
32         * 2    the attenuated incident continuum, same units
33         * 3    the reflected continuum, same units
34         *
35         * 4    diffuse continuous emission outward direction
36         * 5    diffuse continuous emission, reflected
37         *
38         * 6    collisional+recombination lines, outward
39         * 7    collisional+recombination lines, reflected
40         *
41         * 8    pumped lines, outward <= not implemented
42         * 9    pumped lines, reflected <= not implemented
43         *
44         *              all lines and continuum emitted by the cloud assume full coverage of
45         *              continuum source */
46        int nOption ,
47
48        /* the energy of the lower edge of each cell
49         * (in Ryd to be consistent with all the rest of Cloudy) */
50        double EnergyLow[] ,
51
52        /* the number of cells + 1*/
53        long int nEnergy ,
54
55        /* the returned spectrum, same size is two energy spectra (see option), returns nEnergy -1 pts */
56        double ReturnedSpectrum[] )
57
58{
59        /* this pointer will bet set to one of the cloudy continuum arrays */
60        realnum *cont ,
61                refac;
62        long int ncell , j;
63
64        /* flag saying whether we will need to free cont at the end */
65        bool lgFREE;
66
67        DEBUG_ENTRY( "cdSPEC()" );
68
69        ASSERT( nEnergy <= rfield.nflux );
70
71        if( nOption == 1 )
72        {
73                /* this is the incident continuum, col 2 of punch continuum command */
74                cont = rfield.flux_total_incident[0];
75                lgFREE = false;
76        }
77        else if( nOption == 2 )
78        {
79                /* the attenuated transmitted continuum, no diffuse emission,
80                 * col 3 of punch continuum command */
81                cont = rfield.flux[0];
82                lgFREE = false;
83        }
84        else if( nOption == 3 )
85        {
86                /* reflected incident continuum, col 6 of punch continuum command */
87                lgFREE = false;
88                cont = rfield.ConRefIncid[0];
89        }
90        else if( nOption == 4 )
91        {
92                /* diffuse continuous emission outward direction  */
93                cont = (realnum*)MALLOC( sizeof(realnum)*(size_t)rfield.nupper );
94
95                /* need to free the vector once done */
96                lgFREE = true;
97                refac = (realnum)radius.r1r0sq*geometry.covgeo;
98                for( j=0; j<rfield.nflux; ++j)
99                {
100                        cont[j] = rfield.ConEmitOut[0][j]*refac;
101                }
102        }
103        else if( nOption == 5 )
104        {
105                /* reflected diffuse continuous emission */
106                cont = (realnum*)MALLOC( sizeof(realnum)*(size_t)rfield.nupper );
107                /* need to free the vector once done */
108                lgFREE = true;
109                refac = (realnum)radius.r1r0sq*geometry.covgeo;
110                for( j=0; j<rfield.nflux; ++j)
111                {
112                        cont[j] = rfield.ConEmitReflec[0][j]*refac;
113                }
114        }
115        else if( nOption == 6 )
116        {
117                /* all outward lines,   */
118                cont = (realnum*)MALLOC( sizeof(realnum)*(size_t)rfield.nupper );
119                /* need to free the vector once done */
120                lgFREE = true;
121                /* correct back to inner radius */
122                refac = (realnum)radius.r1r0sq*geometry.covgeo;
123                for( j=0; j<rfield.nflux; ++j)
124                {
125                        /* units of lines here are to cancel out with tricks applied to continuum cells
126                         * when finally extracted below */
127                        cont[j] = rfield.outlin[0][j] *rfield.widflx[j]/rfield.anu[j]*refac;
128                }
129        }
130        else if( nOption == 7 )
131        {
132                /* all reflected lines */
133                if( geometry.lgSphere )
134                {
135                        refac = 0.;
136                }
137                else
138                {
139                        refac = 1.;
140                }
141
142                cont = (realnum*)MALLOC( sizeof(realnum)*(size_t)rfield.nupper );
143                /* need to free the vector once done */
144                lgFREE = true;
145                for( j=0; j<rfield.nflux; ++j)
146                {
147                        /* units of lines here are to cancel out with tricks applied to continuum cells
148                         * when finally extracted below */
149                        cont[j] = rfield.reflin[0][j] *rfield.widflx[j]/rfield.anu[j]*refac;
150                }
151        }
152        else
153        {
154                fprintf(ioQQQ," cdSPEC called with impossible nOption (%i)\n", nOption);
155                cdEXIT(EXIT_FAILURE);
156        }
157
158        /* this is array index used in Spec_cont */
159        iplo = 0;
160        iphi = 0;
161        /* now generate the continua */
162        for( ncell = 0; ncell < nEnergy-1; ++ncell )
163        {
164                /* Spec_cont will find the spectrum between these two energies */
165                Elo = EnergyLow[ncell];
166                Ehi = EnergyLow[ncell+1];
167                ReturnedSpectrum[ncell] = cont[ncell] * EN1RYD * rfield.anu2[ncell] / rfield.widflx[ncell];
168        }
169
170        /* need to free the vector once done if this flag was set */
171        if( lgFREE )
172        {
173                free(cont);
174        }
175        return;
176}
177
178
179/* returns in units photons/cm^2/s/bin */
180void cdSPEC2(
181        /* option - the type of spectrum to be returned
182         * 1    the incident continuum 4\pi nuJ_nu, , erg cm-2 s-1
183         *
184         * 2    the attenuated incident continuum, same units
185         * 3    the reflected continuum, same units
186         *
187         * 4    diffuse emission, lines + continuum, outward
188         * 5    diffuse emission, lines + continuum, reflected
189         *
190         * 6    diffuse continuous emission outward direction
191         * 7    diffuse continuous emission, reflected
192         *
193         * 8    total transmitted, lines and continuum
194         * 9    total reflected, lines and continuum
195         *
196         *10    exp(-tau) to the illuminated face
197         *
198         *              all lines and continuum emitted by the cloud assume full coverage of
199         *              continuum source */
200        int nOption ,
201
202        /* the number of cells */
203        long int nEnergy,
204
205        /* the index of the lowest and highest energy bounds to use. */
206        long ipLoEnergy,
207        long ipHiEnergy,
208
209        /* the returned spectrum, same size is two energy spectra (see option), returns nEnergy -1 pts */
210        realnum ReturnedSpectrum[] )
211
212{
213        realnum refac;
214
215        DEBUG_ENTRY( "cdSPEC2()" );
216
217        ASSERT( ipLoEnergy >= 0 );
218        ASSERT( ipLoEnergy < ipHiEnergy );
219        ASSERT( ipHiEnergy < rfield.nupper );
220        ASSERT( nEnergy == (ipHiEnergy-ipLoEnergy+1) );
221        ASSERT( nEnergy >= 2 );
222
223        ASSERT( nOption <= NUM_OUTPUT_TYPES );
224
225        for( long i = 0; i < nEnergy; i++ )
226        {
227                long j = ipLoEnergy + i;
228
229                if( j >= rfield.nflux )
230                {
231                        ReturnedSpectrum[i] = SMALLFLOAT;
232                        continue;
233                }
234
235                if( nOption == 1 )
236                {
237                        /* this is the incident continuum, col 2 of punch continuum command */
238                        ReturnedSpectrum[i] = rfield.flux_total_incident[0][j];
239                }
240                else if( nOption == 2 )
241                {
242                        /* the attenuated transmitted continuum, no diffuse emission,
243                         * col 3 of punch continuum command */
244                        ReturnedSpectrum[i] = rfield.flux[0][j];
245                }
246                else if( nOption == 3 )
247                {
248                        /* reflected incident continuum, col 6 of punch continuum command */
249                        ReturnedSpectrum[i] = rfield.ConRefIncid[0][j];
250                }
251                else if( nOption == 4 )
252                {
253                        /* all outward diffuse emission */
254                        /* correct back to inner radius */
255                        refac = (realnum)radius.r1r0sq*geometry.covgeo;
256                        ReturnedSpectrum[i] = (rfield.outlin[0][j]+rfield.ConEmitOut[0][j])*refac;
257                }
258                else if( nOption == 5 )
259                {
260                        /* all reflected diffuse emission */
261                        if( geometry.lgSphere )
262                        {
263                                refac = 0.;
264                        }
265                        else
266                        {
267                                refac = 1.;
268                        }
269
270                        ReturnedSpectrum[i] = (rfield.reflin[0][j]+rfield.ConEmitReflec[0][j])*refac;
271                }
272                else if( nOption == 6 )
273                {
274                        /* all outward line emission */
275                        /* correct back to inner radius */
276                        refac = (realnum)radius.r1r0sq*geometry.covgeo;
277                        ReturnedSpectrum[i] = rfield.outlin[0][j]*refac;
278                }
279                else if( nOption == 7 )
280                {
281                        /* all reflected line emission */
282                        if( geometry.lgSphere )
283                        {
284                                refac = 0.;
285                        }
286                        else
287                        {
288                                refac = 1.;
289                        }
290
291                        ReturnedSpectrum[i] = rfield.reflin[0][j]*refac;
292                }
293                else if( nOption == 8 )
294                {
295                        /* total transmitted continuum */
296                        /* correct back to inner radius */
297                        refac = (realnum)radius.r1r0sq*geometry.covgeo;
298                        ReturnedSpectrum[i] = (rfield.ConEmitOut[0][j]+ rfield.outlin[0][j])*refac
299                                + rfield.flux[0][j]*(realnum)radius.r1r0sq;
300                }
301                else if( nOption == 9 )
302                {
303                        /* total reflected continuum */
304                        ReturnedSpectrum[i] = ((rfield.ConRefIncid[0][j]+rfield.ConEmitReflec[0][j]) +
305                                rfield.reflin[0][j]);
306                }
307                else if( nOption == 10 )
308                {
309                        /* this is exp(-tau) */
310                        /* This is the TOTAL attenuation in both the continuum and lines. 
311                         * Jon Miller discovered that the line attenuation was missing in 07.02 */
312                        ReturnedSpectrum[i] = opac.ExpmTau[j]*rfield.trans_coef_total[j];
313                }
314                else
315                {
316                        fprintf(ioQQQ," cdSPEC called with impossible nOption (%i)\n", nOption);
317                        cdEXIT(EXIT_FAILURE);
318                }
319
320                ASSERT( ReturnedSpectrum[i] >=0.f );
321        }
322
323        return;
324}
Note: See TracBrowser for help on using the browser.