-
Notifications
You must be signed in to change notification settings - Fork 17
/
nemetals.c
122 lines (82 loc) · 3.42 KB
/
nemetals.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* ------- file: -------------------------- nemetals.c --------------
Version: rh1.0
Author: Han Uitenbroek (huitenbroek@nso.edu)
Last modified: Tue Oct 13 10:49:53 2009 --
-------------------------- ----------RH-- */
#include <stdlib.h>
#include "rh.h"
#include "atom.h"
#include "atmos.h"
#include "background.h"
#define NEFRACTION 0.01
/* --- Function prototypes -- -------------- */
/* --- Global variables -- -------------- */
extern Atmosphere atmos;
/* ------- begin -------------------------- neMetals.c -------------- */
void FMetals(double *F)
{
/* --- Calculates the effective ionization fraction F_met for all
background metals (i.e. excluding hydrogen) under the
assumption of fixed temperature and total electron density.
i.e. F_met = F_met(T, ne)
ne_metal = nHtot * Sum_n (A_n Sum_l (l * f_nl)) = nHtot * F_met
Note: Populations of background metals may be either LTE or NonLTE!
-- -------------- */
register int k, i, n;
double *f_n;
Atom *metal;
f_n = (double *) malloc(atmos.Nspace * sizeof(double));
for (k = 0; k < atmos.Nspace; k++) F[k] = 0.0;
for (n = 1; n < atmos.Natom; n++) {
metal = &atmos.atoms[n];
for (k = 0; k < atmos.Nspace; k++) f_n[k] = 0.0;
for (i = 0; i < metal->Nlevel; i++) {
if (metal->stage[i] > 0) {
for (k = 0; k < atmos.Nspace; k++)
f_n[k] += metal->stage[i] * metal->n[i][k];
}
}
for (k = 0; k < atmos.Nspace; k++)
F[k] += metal->abundance * f_n[k] / metal->ntotal[k];
}
free(f_n);
}
/* ------- end ---------------------------- neMetals.c -------------- */
/* ------- begin -------------------------- dFMetals.c -------------- */
void dFMetals(double *dFdne)
{
register int n, k;
bool_t Debeye;
double *neold, *Fmin, *Fplus;
/* --- Numerically evaluate the derivative dF/dne -- -------------- */
neold = (double *) malloc(atmos.Nspace * sizeof(double));
Fmin = (double *) malloc(atmos.Nspace * sizeof(double));
Fplus = (double *) malloc(atmos.Nspace * sizeof(double));
/* --- Store electron densities, evaluate LTE populations for reduced
electron density -- -------------- */
for (k = 0; k < atmos.Nspace; k++) {
neold[k] = atmos.ne[k];
atmos.ne[k] = (1.0 - NEFRACTION) * neold[k];
}
for (n = 1; n < atmos.Natom; n++)
LTEpops(&atmos.atoms[n], Debeye=TRUE);
/* --- Get reduced ionization fraction F -- -------------- */
FMetals(Fmin);
/* --- evaluate LTE populations for enhanced electron density -- -- */
for (k = 0; k < atmos.Nspace; k++)
atmos.ne[k] = (1.0 + NEFRACTION) * neold[k];
for (n = 1; n < atmos.Natom; n++)
LTEpops(&atmos.atoms[n], Debeye=TRUE);
/* --- Get enhanced ionization fraction F -- -------------- */
FMetals(Fplus);
/* --- get the numerical derivative, restore electron densities - - */
for (k = 0; k < atmos.Nspace; k++) {
dFdne[k] = (Fplus[k] - Fmin[k]) / (2.0 * NEFRACTION * neold[k]);
atmos.ne[k] = neold[k];
}
/* --- Restore the LTE populations -- ------------- */
for (n = 1; n < atmos.Natom; n++)
LTEpops(&atmos.atoms[n], Debeye=TRUE);
free(neold); free(Fmin); free(Fplus);
}
/* ------- end ---------------------------- dFMetals.c -------------- */