PLUTO
comp_equil.c
Go to the documentation of this file.
1 #include "pluto.h"
2 #include "cooling_defs.h"
3 
4 #define MAX_NLEVEL 16
5 
6 /* ********************************************************************* */
7 double CompEquil (double N, double T, double *v0)
8 /*!
9  * Compute the equilibrium ionization balance for (rho,T)
10  *
11  *
12  *********************************************************************** */
13 {
14  int nlev, ind_start, i,j, k, nv, nrt;
15  double d, n_el, n_el_old, sT;
16  double v[NVAR];
17  static double **M;
18  static double *rhs;
19  static int *p;
20 
21 /* ---- start index in the ions matrix for each element ---- */
22 
23  int ind_starts[] = {X_HI, X_HeI, X_CI, X_NI, X_OI, X_NeI, X_SI, X_SI+S_IONS};
24 
25 /* ---- number of ions for each element ---- */
26 
27  int nlevs[] = {1, 2, C_IONS, N_IONS, O_IONS, Ne_IONS, S_IONS, Fe_IONS};
28 
29 /* -- Copy solution vector before any modification -- */
30 
31  NVAR_LOOP(nv) v[nv] = v0[nv];
32 
33  sT = sqrt(T);
34 /* N = find_N(rho); -- Total number density -- */
35 
36  if (M == NULL) { /* -- Allocate matrices for the linear eq system -- */
37  M = ARRAY_2D(MAX_NLEVEL, MAX_NLEVEL, double);
38  rhs = ARRAY_1D(MAX_NLEVEL, double);
39  p = ARRAY_1D(MAX_NLEVEL, int);
40  }
41  for (nv = 0; nv < 8; nv++) ind_starts[nv] -= NFLX; /* -- offset index to start from zero -- */
42 
43 /* ---------------------------------------------------------------
44  Initialize the relative abundances.
45  Note: at the first iteration step below the charge-transfer
46  terms will be 0, as the HI and HeII abundances are set to 0.
47  --------------------------------------------------------------- */
48 
49  for (j = 0; j < NIONS; j++) v[NFLX+j] = 0.0;
50 
51 /* --------------------------------------------------------------------------
52  Initially all ion fractions are 0, so also n_el will be zero. As first
53  guess for the iterations though, if T>5000K, let's use a higher value.
54  -------------------------------------------------------------------------- */
55 
56  if (T > 5000.) n_el = N*0.1;
57  else n_el = N*1.e-3;
58 
59  n_el_old = n_el/2.;
60 
61 /* ----------------------------------------------------------------------
62  Start the iteration for finding the equilibrium ionization balance.
63  Stop if n_el converges or is very small, or the number of iterations
64  becomes too large.
65  ---------------------------------------------------------------------- */
66 
67  nrt = 0;
68  while ( fabs(n_el - n_el_old) / n_el_old > 1.e-5 && nrt<500 && n_el > 1.0e-14) {
69 
70  n_el_old = n_el;
71 
72  Find_Rates(T, n_el, N, v);
73  for (k = 1; k < 8; k++) { /* Main loop on elements */
74  nlev = nlevs[k]; /* Number of ionization states for element k */
75  ind_start = ind_starts[k]; /* Start index in the ions matrix for element k */
76 
77  if (nlev == 0) continue; /* Skip element with zero ions */
78 
79  /* -----------------------------------------
80  compute coefficient matrix
81  ----------------------------------------- */
82 
83  for (i = 0; i < MAX_NLEVEL; i++) {
84  for (j = 0; j < MAX_NLEVEL; j++) {
85  M[i][j] = 0.0;
86  }}
87  for (j = 0 ; j < nlev-1 ; j++) {
88  M[j][j+1] += CoolCoeffs.Rrate[ind_start+j];
89  M[j][j] += -CoolCoeffs.Crate[ind_start+j];
90  if (j>0) M[j][j-1] += CoolCoeffs.Lrate[ind_start+j];
91  }
92 
93  /* -------------------------------------
94  Replace 1st eq. with normalization
95  condition and define rhs
96  ------------------------------------- */
97 
98  for (j = 0; j < nlev; j++) {
99  M[nlev-1][j] = 1.0;
100  rhs[j] = 0.0;
101  }
102  rhs[nlev-1] = 1.0;
103 
104  /* ----------------------------------
105  Solve equations by LU decomp
106  ---------------------------------- */
107 
108  LUDecompose (M, nlev, p, &d);
109  LUBackSubst (M, nlev, p, rhs);
110 
111  for (i = 0 ; i < nlev ; i++) {
112  if (rhs[i] >= 0. && rhs[i] <= 1.0) v[NFLX+i+ind_start] = rhs[i];
113  else if (rhs[i] < 0.0) v[NFLX + i + ind_start] = 0.0;
114  else v[NFLX + i + ind_start] = 1.0;
115  }
116 
117  } /* end main loop on elements */
118 
119  /* ------------------------------------------------------
120  ... and now compute the ionization balance for H.
121  ------------------------------------------------------ */
122 
123  v[X_HI] = CoolCoeffs.Rrate[0] / (CoolCoeffs.Crate[0] + CoolCoeffs.Rrate[0]);
124 
125  if (v[X_HI] > 1.0){
126  print ("\n!CompEquil: GR(H) = %12.6e\nDR(H) = %12.6e\n\n",
128  QUIT_PLUTO(1);
129  }
130 
131  /* -----------------------------------
132  compute electron number density
133  ----------------------------------- */
134 
135  n_el = (1.0 - v[X_HI])*elem_ab[el_H]*N; /* contribution from ionized H */
136  for (nv = 0; nv < NIONS; nv++) {
137  n_el += v[NFLX + nv]*(rad_rec_z[nv] - 1.)*elem_ab[elem_part[nv]]*N;
138  }
139 
140  if (n_el != n_el) {
141  print1 ("! CompEquil: error!! n_el NaN\n\n");
142  QUIT_PLUTO(1);
143  }
144  nrt++; /* increment the iteration counter */
145  } /* -- end main iteration -- */
146 
147 /* -- Update input solution vector -- */
148 
149  for (nv = 0; nv < NIONS; nv++) v0[NFLX+nv] = v[NFLX+nv];
150 
151  return (n_el);
152 }
tuple T
Definition: Sph_disk.py:33
#define S_IONS
Definition: cooling.h:17
double Crate[NIONS]
Definition: cooling_defs.h:31
void print1(const char *fmt,...)
Definition: amrPluto.cpp:511
const double elem_ab[8]
Definition: radiat.c:9
void CompEquil(double n, double T, double *v)
Definition: comp_equil.c:44
const double rad_rec_z[31]
Definition: radiat.c:24
COOL_COEFF CoolCoeffs
Definition: radiat.c:38
double Lrate[NIONS]
Definition: cooling_defs.h:30
#define C_IONS
Definition: cooling.h:13
#define O_IONS
Definition: cooling.h:15
void LUBackSubst(double **a, int n, int *indx, double b[])
Definition: cooling.h:110
#define NFLX
Definition: mod_defs.h:32
#define NVAR_LOOP(n)
Definition: pluto.h:618
#define NIONS
Definition: cooling.h:28
int j
Definition: analysis.c:2
Definition: cooling.h:110
int k
Definition: analysis.c:2
const int elem_part[31]
Definition: radiat.c:16
void print(const char *fmt,...)
Definition: amrPluto.cpp:497
double Rrate[NIONS]
Definition: cooling_defs.h:32
#define MAX_NLEVEL
Definition: comp_equil.c:4
PLUTO main header file.
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
#define Ne_IONS
Definition: cooling.h:16
int i
Definition: analysis.c:2
#define Fe_IONS
Definition: cooling.h:18
void Find_Rates(double T, double Ne, double N, double *v)
Definition: radiat.c:413
#define ARRAY_2D(nx, ny, type)
Definition: prototypes.h:171
int LUDecompose(double **a, int n, int *indx, double *d)
#define NVAR
Definition: pluto.h:609
#define QUIT_PLUTO(e_code)
Definition: macros.h:125
#define el_H
Definition: cooling_defs.h:71
#define N_IONS
Definition: cooling.h:14