@@ -31,41 +31,56 @@ module phase_separation
31
31
32
32
implicit none
33
33
34
- private
35
- public :: do_phase_separation
36
-
37
34
logical , parameter :: dbg = .false.
38
35
39
36
! offset to higher phase than 0.5 to avoid interference
40
37
! between phase separation mixing and latent heat for Skye.
41
38
real (dp), parameter :: eos_phase_boundary = 0.9d0
42
39
43
- contains
40
+ private
41
+ public :: do_phase_separation
44
42
43
+ contains
45
44
46
45
subroutine do_phase_separation (s , dt , ierr )
47
- use chem_def, only: chem_isos, ic12, io16
46
+ type (star_info), pointer :: s
47
+ real (dp), intent (in ) :: dt
48
+ integer , intent (out ) :: ierr
49
+
50
+ if (s% phase_separation_option == ' CO' ) then
51
+ call do_2component_phase_separation(s, dt, ' CO' , ierr)
52
+ else if (s% phase_separation_option == ' ONe' ) then
53
+ call do_2component_phase_separation(s, dt, ' ONe' , ierr)
54
+ else
55
+ write (* ,* ) ' invalid phase_separation_option'
56
+ stop
57
+ end if
58
+ end subroutine do_phase_separation
59
+
60
+ subroutine do_2component_phase_separation (s , dt , components , ierr )
61
+ use chem_def, only: chem_isos, ic12, io16, ine20
48
62
use chem_lib, only: chem_get_iso_id
49
63
type (star_info), pointer :: s
50
64
real (dp), intent (in ) :: dt
65
+ character (len=* ), intent (in ) :: components
51
66
integer , intent (out ) :: ierr
52
67
53
- real (dp) :: dq_crystal , XO, XC, pad
54
- integer :: k, k_bound, kstart, net_ic12, net_io16
68
+ real (dp) :: XNe , XO, XC, pad
69
+ integer :: k, k_bound, kstart, net_ic12, net_io16, net_ine20
55
70
logical :: save_Skye_use_ion_offsets
56
71
72
+ ! Set phase separation mixing mass negative at beginning of phase separation
73
+ s% phase_sep_mixing_mass = - 1d0
57
74
s% eps_phase_separation(1 :s% nz) = 0d0
58
75
59
76
if (s% phase(s% nz) < eos_phase_boundary) then
60
77
s% crystal_core_boundary_mass = 0d0
61
78
return
62
79
end if
63
-
64
- ! Set phase separation mixing mass negative at beginning of phase separation
65
- s% phase_sep_mixing_mass = - 1d0
66
-
80
+
67
81
net_ic12 = s% net_iso(ic12)
68
82
net_io16 = s% net_iso(io16)
83
+ net_ine20 = s% net_iso(ine20)
69
84
70
85
! Find zone of phase transition from liquid to solid
71
86
k_bound = - 1
@@ -75,15 +90,17 @@ subroutine do_phase_separation(s, dt, ierr)
75
90
exit
76
91
end if
77
92
end do
78
-
79
- ! Check that we're still in C/O dominated material, otherwise skip phase separation
80
- XO = s% xa(net_io16,k_bound)
93
+
81
94
XC = s% xa(net_ic12,k_bound)
82
- if (XO + XC < 0.9d0 ) return
95
+ XO = s% xa(net_io16,k_bound)
96
+ XNe = s% xa(net_ine20,k_bound)
97
+ ! Check that we're still in C/O or O/Ne dominated material as appropriate,
98
+ ! otherwise skip phase separation
99
+ if (components == ' CO' .and. XO + XC < 0.9d0 ) return
100
+ if (components == ' ONe' .and. XNe + XO < 0.8d0 ) return ! O/Ne mixtures tend to have more byproducts of burning mixed in
83
101
84
102
! If there is a phase transition, reset the composition at the boundary
85
103
if (k_bound > 0 ) then
86
- dq_crystal = 0d0
87
104
88
105
! core boundary needs to be padded by a minimal amount (less than a zone worth of mass)
89
106
! to account for loss of precision during remeshing.
@@ -112,17 +129,15 @@ subroutine do_phase_separation(s, dt, ierr)
112
129
exit
113
130
end if
114
131
115
- call move_one_zone(s,k,dq_crystal )
132
+ call move_one_zone(s,k,components )
116
133
! crystallized out to k now, liquid starts at k-1.
117
134
! now mix the liquid material outward until stably stratified
118
- if (dq_crystal > 0d0 ) then
119
- call mix_outward(s, k-1 )
120
- end if
135
+ call mix_outward(s, k-1 , 0 )
121
136
122
137
end do
123
138
124
139
call update_model_(s,1 ,s% nz,.false. )
125
-
140
+
126
141
! phase separation heating term for use by energy equation
127
142
do k= 1 ,s% nz
128
143
s% eps_phase_separation(k) = (s% eps_phase_separation(k) - s% energy(k)) / dt
@@ -132,66 +147,86 @@ subroutine do_phase_separation(s, dt, ierr)
132
147
end if
133
148
134
149
ierr = 0
135
- end subroutine do_phase_separation
150
+ end subroutine do_2component_phase_separation
136
151
137
- subroutine move_one_zone (s ,k ,dq_crystal )
138
- use chem_def, only: chem_isos, ic12, io16
152
+ subroutine move_one_zone (s ,k ,components )
153
+ use chem_def, only: chem_isos, ic12, io16, ine20
139
154
use chem_lib, only: chem_get_iso_id
140
155
type (star_info), pointer :: s
141
156
integer , intent (in ) :: k
142
- real (dp ), intent (inout ) :: dq_crystal
157
+ character (len =* ), intent (in ) :: components
143
158
144
- real (dp) :: XC, XO, XC1, XO1, dXO, Xfac, dqsum
145
- integer :: net_ic12, net_io16
146
-
147
- dq_crystal = dq_crystal + s% dq(k)
159
+ real (dp) :: XC, XO, XNe, XC1, XO1, XNe1, dXO, dXNe, Xfac
160
+ integer :: net_ic12, net_io16, net_ine20
148
161
149
162
net_ic12 = s% net_iso(ic12)
150
163
net_io16 = s% net_iso(io16)
164
+ net_ine20 = s% net_iso(ine20)
151
165
152
- XO = s% xa(net_io16,k)
153
- XC = s% xa(net_ic12,k)
166
+ if (components == ' CO' ) then
167
+ XO = s% xa(net_io16,k)
168
+ XC = s% xa(net_ic12,k)
154
169
155
- ! Call Blouin 2021 phase diagram.
156
- ! Need to rescale temporarily because phase diagram assumes XO + XC = 1
157
- Xfac = XO + XC
158
- XO = XO/ Xfac
159
- XC = XC/ Xfac
160
-
161
- dXO = blouin_delta_xo(XO)
162
-
163
- s% xa(net_io16,k) = Xfac* (XO + dXO)
164
- s% xa(net_ic12,k) = Xfac* (XC - dXO)
170
+ ! Call Blouin phase diagram.
171
+ ! Need to rescale temporarily because phase diagram assumes XO + XC = 1
172
+ Xfac = XO + XC
173
+ XO = XO/ Xfac
174
+ XC = XC/ Xfac
175
+
176
+ dXO = blouin_delta_xo(XO)
177
+
178
+ s% xa(net_io16,k) = Xfac* (XO + dXO)
179
+ s% xa(net_ic12,k) = Xfac* (XC - dXO)
180
+
181
+ ! Redistribute change in C,O into zone k-1,
182
+ ! conserving total mass of C,O
183
+ XC1 = s% xa(net_ic12,k-1 )
184
+ XO1 = s% xa(net_io16,k-1 )
185
+ s% xa(net_ic12,k-1 ) = XC1 + Xfac* dXO * s% dq(k) / s% dq(k-1 )
186
+ s% xa(net_io16,k-1 ) = XO1 - Xfac* dXO * s% dq(k) / s% dq(k-1 )
187
+ else if (components == ' ONe' ) then
188
+ XNe = s% xa(net_ine20,k)
189
+ XO = s% xa(net_io16,k)
165
190
166
- ! Redistribute change in X,O into zone k-1,
167
- ! conserving total mass of X,O
168
- XC1 = s% xa(net_ic12,k-1 )
169
- XO1 = s% xa(net_io16,k-1 )
170
- s% xa(net_ic12,k-1 ) = XC1 + Xfac* dXO * s% dq(k) / s% dq(k-1 )
171
- s% xa(net_io16,k-1 ) = XO1 - Xfac* dXO * s% dq(k) / s% dq(k-1 )
191
+ ! Call Blouin phase diagram.
192
+ ! Need to rescale temporarily because phase diagram assumes XO + XNe = 1
193
+ Xfac = XO + XNe
194
+ XO = XO/ Xfac
195
+ XNe = XNe/ Xfac
196
+
197
+ dXNe = blouin_delta_xne(XNe)
198
+
199
+ s% xa(net_ine20,k) = Xfac* (XNe + dXNe)
200
+ s% xa(net_io16,k) = Xfac* (XO - dXNe)
201
+
202
+ ! Redistribute change in Ne,O into zone k-1,
203
+ ! conserving total mass of Ne,O
204
+ XO1 = s% xa(net_io16,k-1 )
205
+ XNe1 = s% xa(net_ine20,k-1 )
206
+ s% xa(net_io16,k-1 ) = XO1 + Xfac* dXNe * s% dq(k) / s% dq(k-1 )
207
+ s% xa(net_ine20,k-1 ) = XNe1 - Xfac* dXNe * s% dq(k) / s% dq(k-1 )
208
+ else
209
+ write (* ,* ) ' invalid components option in phase separation'
210
+ stop
211
+ end if
172
212
173
213
call update_model_(s,k-1 ,s% nz,.true. )
174
214
175
215
end subroutine move_one_zone
176
-
177
- ! mix composition outward until reaching stable composition profile
178
- subroutine mix_outward (s ,kbot )
179
- use chem_def, only: chem_isos, ihe4, ic12, io16
180
216
217
+ ! mix composition outward until reaching stable composition profile
218
+ subroutine mix_outward (s ,kbot ,min_mix_zones )
181
219
type (star_info), pointer :: s
182
- integer , intent (in ) :: kbot
220
+ integer , intent (in ) :: kbot, min_mix_zones
183
221
184
222
real (dp) :: avg_xa(s% species)
185
- real (dp) :: mass, dXC_top, dXC_bot, dXO_top, dXO_bot, B_term, grada, gradr
186
- integer :: k, l, ktop, net_ihe4, net_ic12, net_io16
223
+ real (dp) :: mass, B_term, grada, gradr
224
+ integer :: k, l, ktop
187
225
logical :: use_brunt
188
226
189
227
use_brunt = s% phase_separation_mixing_use_brunt
190
- net_ihe4 = s% net_iso(ihe4)
191
- net_ic12 = s% net_iso(ic12)
192
- net_io16 = s% net_iso(io16)
193
228
194
- do k= kbot,1 ,- 1
229
+ do k= kbot- min_mix_zones ,1 ,- 1
195
230
ktop = k
196
231
197
232
if (s% m(ktop) > s% phase_sep_mixing_mass) then
@@ -234,7 +269,7 @@ subroutine mix_outward(s,kbot)
234
269
end do
235
270
236
271
! Call a final update over all mixed cells now.
237
- call update_model_(s, ktop, kbot, .true. )
272
+ call update_model_(s, ktop, kbot+1 , .true. )
238
273
239
274
end subroutine mix_outward
240
275
@@ -269,7 +304,39 @@ real(dp) function blouin_delta_xo(Xin)
269
304
270
305
blouin_delta_xo = Xnew - Xin
271
306
end function blouin_delta_xo
272
-
307
+
308
+ real(dp) function blouin_delta_xne (Xin )
309
+ real (dp), intent (in ) :: Xin ! mass fraction
310
+ real (dp) :: Xnew ! mass fraction
311
+ real (dp) :: xne, dxne ! number fractions
312
+ real (dp) :: a0, a1, a2, a3, a4, a5
313
+
314
+ ! Convert input mass fraction to number fraction, assuming O/Ne mixture
315
+ xne = (Xin/ 20d0 )/ (Xin/ 20d0 + (1d0 - Xin)/ 16d0 )
316
+
317
+ a0 = 0d0
318
+ a1 = - 0.120299d0
319
+ a2 = 1.304399d0
320
+ a3 = - 1.722625d0
321
+ a4 = 0.393996d0
322
+ a5 = 0.144529d0
323
+
324
+ dxne = &
325
+ a0 + &
326
+ a1* xne + &
327
+ a2* xne* xne + &
328
+ a3* xne* xne* xne + &
329
+ a4* xne* xne* xne* xne + &
330
+ a5* xne* xne* xne* xne* xne
331
+
332
+ xne = xne + dxne
333
+
334
+ ! Convert back to mass fraction
335
+ Xnew = 20d0 * xne/ (20d0 * xne + 16d0 * (1d0 - xne))
336
+
337
+ blouin_delta_xne = Xnew - Xin
338
+ end function blouin_delta_xne
339
+
273
340
subroutine update_model_ (s , kc_t , kc_b , do_brunt )
274
341
275
342
use turb_info, only: set_mlt_vars
@@ -338,8 +405,7 @@ subroutine update_model_ (s, kc_t, kc_b, do_brunt)
338
405
return
339
406
340
407
end subroutine update_model_
341
-
342
-
408
+
343
409
end module phase_separation
344
410
345
411
0 commit comments