aboutsummaryrefslogtreecommitdiff
path: root/Eqlib.f
blob: 5aec1528ed424b3d22ded9386a48adf5a2f4b77a (plain) (blame)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288

      subroutine eqlib                                                  
c******************************************************************************
c     This routine solves the equations of molecular dissociative           
c     equilibrium. the equations can include neutral and ionized molecules  
c     and atoms 
c******************************************************************************

      implicit real*8 (a-h,o-z)
      include 'Atmos.com'
      include 'Mol.com'
      include 'Quants.com'
      include 'Dummy.com'
      real*8 xfic(30), xcorr(30), deltax(30), c(30,30), ans(30,30)      
      real*8 uu(2)
      real*8 lth
      integer ident(30,110)


c*****clear the arrays 
      iorder(1) = 0                                                
      neq = iorder(1) 
      tdel = (t(ntau)-t(1))/4.0 + 1.0                                   
      do k=1,30                                                       
         iorder(k) = 0                                                  
         xcorr(k) = 0.                                                  
         do kk=1,110                       
            ident(k,kk) = 0                                             
         enddo
      enddo


c*****the number of species to be considered has been defined in "Inmodel";
c*****either read in the dissociation data for a molecular species
      do jmol=1,nmol                                                   
         if (amol(jmol) >= 100.) then
            do k=1,110                                                  
               if (datmol(1,k) == amol(jmol)) go to 11
            enddo
            write (nf1out,1001) amol(jmol)                   
            stop                                                        
11          do kk=1,6                                                   
               const(kk,jmol) = datmol(kk+1,k)                          
            enddo 


c*****or read the ionization data for an atomic species
         else
            iatom1 = amol(jmol) + 0.0001
            atom = iatom1                                            
            const(1,jmol) = xchi1(iatom1)                               
            do kk=1,5               
               ti = t(1) + (kk-1)*tdel 
               it = ti
               do jj=1,2
                  att = atom+0.1*(jj-1)
                  if (partflag(iatom1,jj) > 0) then
                     uu(jj) = partnew(att,jj,it)
                  else
                     uu(jj) = ucalc(att,it)
                  endif
               enddo
               const(kk+1,jmol) = uu(2)/uu(1)
            enddo 
         endif
      enddo
      if (molopt >= 2)
     .   write (nf1out,1002) (amol(i),(const(j,i),j=1,6),i=1,nmol)


c*****set up the molecular equilibrium array. each element of array         
c*****'ident' contains the identifier (subscript of an element of           
c*****array 'amol') of an ion or a molecule. the neutral atom is always     
c*****understood, but is not explicitly contained in 'ident'.               
      nmax = 1                                                          
      do jmol=1,nmol                                                  
         atom = amol(jmol)                                              
2        call sunder(atom,iatom1,iatom2)                                
         do k=1,30                                                      
            if (iatom1 == iorder(k)) go to 4
         enddo
         neq = neq + 1                                                  
         iorder(neq) = iatom1                                           
         ident(neq,1) = jmol                                            
         go to 6                                                        
4        do kk=1,nmax                                                   
            if (ident(k,kk)==0 .or. ident(k,kk)== jmol) go to 7
         enddo 
         nmax = nmax + 1                                                
         kk = nmax                                                
7        ident(k,kk) = jmol                                             
6        if (iatom2 /= 0) then
            atom = iatom2                                               
            go to 2                                                     
         endif
      enddo                                                           
      if (molopt >= 2) then
         do i=1,neq
            dummy1(i) = iorder(i)
         enddo
         write (nf1out,1003) (dummy1(i),i=1,neq),(amol(i),i=1,nmol)
      endif


c*****now begin the loop that goes through all the atmosphere tau layers
      do 21 kev=1,ntau                                                  


c*****calculate *xfic* and make a first guess at *xatom*                    
      i = ntau + 1 - kev                                           
      lev = i
      tk = 1.38065d-16*t(i)                                             
      do k=1,neq                                                      
         korder = iorder(k)                                             
         xfic(k) = xabund(korder)*nhtot(i)                              
      enddo
      if (i < ntau) then
         do k=1,neq                                                     
            xatom(k) = xatom(k)*nhtot(i)/nhtot(i+1)                     
         enddo
      else
         do k=1,neq                                                     
            xatom(k) = xfic(k)                                          
         enddo
      endif


c*****compute the number of molecules:
c*****Here is some information about the equilibrium constants.
c*****The equilibrium constants, Kp, are defined as follows:
c
c
c                 P(A)*P(B)     N(A)*N(B)
c       Kp(AB)  = --------- = kT--------- =
c                  P(AB)         N(AB)
c
c             2*pi*kT 3/2    M(A)*M(B) 3/2   Q(A)*Q(B)
c       = kT*(-------)    * (---------)    * --------- * exp(-D(AB)/kT)
c               h^2            M(AB)           Q(AB)
c
c 
c*****MOOG uses: n(AB)/n(A)n(B) = kt/Kp
c 
c        Kp - dissociation constant, Q - partition functions, M - masses
c        P - partial pressures, N - number densities, T - temperature,
c        D - dissociation energy, h - plank constant. Remember to use
c        masses in grams (1 amu = 1.660540E-24 g) and energy in ergs
c        (1 eV = 1.60219E-12 ergs). Also, k = 1.38065E-16 erg/K,
c        h = 6.626076E-27 erg s, and pi = 3.1415926536.
27    do jmol=1,nmol                                                  
         atom = amol(jmol)                                              
         if (atom >= 100.) then
            if (t(i) > 12000.) then
               xmol(jmol,i) = 1.0d-20
            else   
               xmol(jmol,i) = 1.
               count = 0.      
37             call sunder(atom,iatom1,iatom2)
               count = count + 1.            
               do k=1,neq                   
                  if (iorder(k) == iatom1)
     .               xmol(jmol,i) = xmol(jmol,i)*xatom(k)
               enddo                                    
               if (iatom2 /= 0) then
                  atom = iatom2                        
                  go to 37                                         
               endif
               hion = 10.0*(amol(jmol) - dint(amol(jmol)))  
               th = 5040./t(i)
               lth = log10(th)
               xmol(jmol,i) = xmol(jmol,i)*(((1.38065d-16 * t(i))**
     .             (count-1.0))/(10.0**(const(2,jmol)+(const(3,jmol)*
     .             lth)+(const(4,jmol)*(lth**2))+(const(5,jmol)*
     .             (lth**3))+(const(6,jmol)*(lth**4))-
     .             (const(1,jmol)*th))))/(ne(i)**hion)
            endif


c*****compute the number of ions:
         else
            delt = (t(i)-t(1))/tdel                               
            m = min0(idint(delt)+2,5)                          
            delt = delt - idint(delt)                           
             u1 = const(m,jmol) + 
     .           (const(m+1,jmol)-const(m,jmol))*delt          
            iatom1 = atom                                           
            do k=1,neq         
               if (iorder(k) == iatom1) xmol(jmol,i) =
     .            4.825d15*u1*t(i)**1.5/ne(i)*dexp(-1.1605d4* 
     .            const(1,jmol)/t(i))*xatom(k)               
            enddo
         endif
      enddo


c*****compute matrix *c*, which is the derivative of each equation with     
c*****respect to each atom.                                                 
      do k=1,neq                                                      
         deltax(k) = -xfic(k) + xatom(k)                                
         do kk=1,neq                                                    
            c(k,kk) = 0.                                                
         enddo
         c(k,k) = 1.                                                    
         korder = iorder(k)                                             
         do kk=1,neq                                                    
            kderiv = iorder(kk)                                         
            do 28 j=1,nmax                                              
               jmol = ident(k,j)                                        
               if (jmol == 0) go to 28
               call discov(amol(jmol),kderiv,num2)                      
               if (num2 == 0) go to 28
               call discov(amol(jmol),korder,num1)                      
               c(k,kk) = c(k,kk) + xmol(jmol,i)*num1*num2/xatom(kk)     
               if (k == kk) deltax(k) = deltax(k) + num1*xmol(jmol,i)
28          continue                                                    
         enddo
      enddo


c*****calculate array 'xcorr', the change in 'xatom'. array 'xcorr' is      
c*****'deltax' multiplied by the inverse of 'c'                            
      call invert (neq,c,ans,30)                                        
      do k=1,neq                                                      
         x1 = xcorr(k)                                                  
         xcorr(k) = 0.                                                  
         do kk=1,neq                                                    
            xcorr(k) = xcorr(k) + ans(k,kk)*deltax(kk)                  
         enddo
      enddo


c*****decide if another iteration is needed                                 
      iflag = 0                                                         
      do k=1,neq                                                      
c*****here oscillations are damped out                                      
         if (x1*xcorr(k) < -0.5*x1**2) xcorr(k) = 0.5*xcorr(k)
         x1 = xatom(k)                                                  
         if (dabs(xcorr(k)/xatom(k)) > 0.005) iflag = 1
         xatom(k) = xatom(k) - xcorr(k)                                 
c*****fix element number densities which are ridiculous                     
         if (xatom(k)<=0.0 .or. xatom(k)>=1.001*xfic(k)) then
            iflag = 1                                                   
            xatom(k) = 1.0d-2*dabs(xatom(k)+xcorr(k))                   
         endif
      enddo                                                           
      if (iflag /= 0) go to 27


c*****print out atomic and molecular partial pressures. *xamol* is the      
c*****number density for each neutral atom                                  
      do k=1,neq                                                     
         xamol(k,i) = xatom(k)                                          
         patom(k) = dlog10(xatom(k)*tk)                                 
      enddo
      do jmol=1,nmol                                                 
         pmol(jmol) = dlog10(xmol(jmol,i)*tk)                           
      enddo
      if (molopt >= 2) then
         pglog = dlog10(pgas(lev))
         write (nf1out,1004) lev,int(t(lev)+0.001),pglog,
     .                       (patom(i),i=1,neq), (pmol(i),i=1,nmol)
      endif


c*****here the big loop in tau ends
21    continue                                                          


c*****finally, transfer some of this number density output to other arrays
      call setmols
      return                                                            


c*****format statements
1001  format ('I do not know this molecule: ',f10.0)              
1002  format (/'INPUT EQUILIBRIUM DATA:'/1x, 'species', 2x, 
     .        'D0/Chi ', 3x, 'const1', 6x, 'const2', 6x,
     .        'const3', 6x, 'const4', 6x, 'const5'/
     .        (0pf8.1, f8.3, 1p5d12.4))
1003  format (/'MOLECULAR EQUILIBRIUM SOLUTIONS:  (log partial',
     .        ' pressures listed under names)'/
     .        2x,'i',5x,'T',2x,'Pgas',8f8.1/(15x,8f8.1))
1004  format (i3,i6,f6.2,8f8.2/(15x,8f8.2))

      end