Line data Source code
1 : ! ***********************************************************************
2 : !
3 : ! Copyright (C) 2010-2019 The MESA Team
4 : !
5 : ! This program is free software: you can redistribute it and/or modify
6 : ! it under the terms of the GNU Lesser General Public License
7 : ! as published by the Free Software Foundation,
8 : ! either version 3 of the License, or (at your option) any later version.
9 : !
10 : ! This program is distributed in the hope that it will be useful,
11 : ! but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 : ! See the GNU Lesser General Public License for more details.
14 : !
15 : ! You should have received a copy of the GNU Lesser General Public License
16 : ! along with this program. If not, see <https://www.gnu.org/licenses/>.
17 : !
18 : ! ***********************************************************************
19 :
20 : module rotation_mix_info
21 :
22 : use const_def, only: dp, pi, pi4, qe, clight, crad, boltz_sigma, lsun, msun, rsun, one_third, &
23 : convective_mixing, overshoot_mixing
24 : use num_lib
25 : use utils_lib
26 : use star_private_def
27 : use magnetic_diffusion
28 :
29 : implicit none
30 :
31 : private
32 : public :: set_rotation_mixing_info, smooth_for_rotation
33 :
34 : real(dp), parameter :: Ri_crit = 0.25d0 ! critical Richardson number
35 : real(dp), parameter :: R_crit = 2500d0 ! critical Reynolds number
36 :
37 : integer, parameter :: i_DSI = 1
38 : integer, parameter :: i_SH = i_DSI + 1
39 : integer, parameter :: i_SSI = i_SH + 1
40 : integer, parameter :: i_ES = i_SSI + 1
41 : integer, parameter :: i_GSF = i_ES + 1
42 : integer, parameter :: i_ST = i_GSF + 1
43 : integer, parameter :: num_instabilities = i_ST
44 :
45 : contains
46 :
47 0 : subroutine set_rotation_mixing_info(s, ierr)
48 : use star_utils, only: weighed_smoothing
49 :
50 : type (star_info), pointer :: s
51 : integer, intent(out) :: ierr
52 :
53 0 : real(dp) :: f_mu, q, D_ST_old, nu_ST_old
54 : ! the following are all defined at cell boundaries
55 : real(dp), dimension(:), pointer :: & ! just copies of pointers
56 0 : r, m, L, j_rot, gradT, grada, grav, visc, Ri
57 : real(dp), dimension(:), allocatable :: & ! allocated temporary storage
58 0 : csound, rho, T, P, cp, cv, chiRho, abar, zbar, gradT_sub_grada, &
59 0 : opacity, kap_cond, gamma1, mu_alt, eps_nuc, enu, L_neu, delta, &
60 0 : scale_height, omega, cell_dr, &
61 0 : dRho, dr, dPressure, domega, d_mu, d_j_rot, &
62 0 : dRho_dr, dRho_dr_ad, dr2omega, H_T, &
63 0 : domega_dlnR, Hj, dlnR_domega, &
64 0 : t_dyn, t_kh, &
65 0 : Ri_mu, Ri_T, &
66 0 : ve0, ve_mu, &
67 0 : v_ssi, h_ssi, Ris_1, Ris_2, &
68 0 : v_es, H_es, &
69 0 : v_gsf, H_gsf, &
70 0 : N2, N2_mu
71 0 : real(dp), allocatable :: smooth_work(:,:), saved(:,:)
72 0 : logical, allocatable :: unstable(:,:) ! (num_instabilities, nz)
73 :
74 : integer :: nz, k, k0, which, op_err
75 0 : real(dp) :: alfa, growth_limit, age_fraction, &
76 0 : D_omega_source, dgtau, angsml, angsmt, prev_out_q, prev_out_q_m1, prev_q, prev_q_m1
77 :
78 : include 'formats'
79 :
80 0 : ierr = 0
81 0 : nz = s% nz
82 :
83 0 : s% D_visc(1:nz) = 0
84 0 : s% D_DSI(1:nz) = 0
85 0 : s% D_SH(1:nz) = 0
86 0 : s% D_SSI(1:nz) = 0
87 0 : s% D_ES(1:nz) = 0
88 0 : s% D_GSF(1:nz) = 0
89 0 : s% D_ST(1:nz) = 0
90 0 : s% nu_ST(1:nz) = 0
91 0 : s% dynamo_B_r(1:nz) = 0
92 0 : s% dynamo_B_phi(1:nz) = 0
93 0 : s% omega_shear(1:nz) = 0
94 0 : s% D_omega(1:nz) = 0
95 :
96 0 : if (all(s% omega(1:nz) == 0d0)) return
97 :
98 0 : call setup(ierr)
99 0 : if (failed('setup for set_rotation_mixing_info', ierr)) return
100 :
101 0 : unstable(:,1:nz) = .false.
102 0 : growth_limit = 1d-10
103 :
104 0 : !$OMP PARALLEL DO PRIVATE(which, k, q, age_fraction, op_err) SCHEDULE(dynamic,2)
105 : do which = 1, num_instabilities
106 :
107 : if (ierr /= 0) cycle
108 : op_err = 0
109 :
110 : select case (which)
111 :
112 : case (i_DSI)
113 :
114 : if (s% D_DSI_factor > 0 .or. s% am_nu_DSI_factor > 0) then
115 : call set_D_DSI(op_err)
116 : if (failed('set_D_DSI', op_err)) then
117 : ierr = -1; cycle
118 : end if
119 : call smooth_for_rotation(s, s% D_DSI, s% smooth_D_DSI, smooth_work(1:nz,which))
120 : if (s% skip_rotation_in_convection_zones) &
121 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% D_DSI)
122 : call zero_if_tiny(s,s% D_DSI)
123 : end if
124 :
125 : case (i_SH)
126 :
127 : if (s% D_SH_factor > 0 .or. s% am_nu_SH_factor > 0) then
128 : call set_D_SH(op_err)
129 : if (failed('set_D_SH', op_err)) then
130 : ierr = -1; cycle
131 : end if
132 : call smooth_for_rotation(s, s% D_SH, s% smooth_D_SH, smooth_work(1:nz,which))
133 : if (s% skip_rotation_in_convection_zones) &
134 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% D_SH)
135 : call zero_if_tiny(s,s% D_SH)
136 : end if
137 :
138 : case (i_SSI)
139 :
140 : if (s% D_SSI_factor > 0 .or. s% am_nu_SSI_factor > 0) then
141 : call set_D_SSI(op_err)
142 : if (failed('set_D_SSI', op_err)) then
143 : ierr = -1; cycle
144 : end if
145 : call smooth_for_rotation(s, s% D_SSI, s% smooth_D_SSI, smooth_work(1:nz,which))
146 : if (s% skip_rotation_in_convection_zones) &
147 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% D_SSI)
148 : call zero_if_tiny(s,s% D_SSI)
149 : end if
150 :
151 : case (i_ES)
152 :
153 : if (s% D_ES_factor > 0 .or. s% am_nu_ES_factor > 0) then
154 : call set_D_ES(op_err)
155 : if (failed('set_D_ES', op_err)) then
156 : ierr = -1; cycle
157 : end if
158 : call smooth_for_rotation(s, s% D_ES, s% smooth_D_ES, smooth_work(1:nz,which))
159 : if (s% skip_rotation_in_convection_zones) &
160 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% D_ES)
161 : call zero_if_tiny(s,s% D_ES)
162 : end if
163 :
164 : case (i_GSF)
165 :
166 : if (s% D_GSF_factor > 0 .or. s% am_nu_GSF_factor > 0) then
167 : call set_D_GSF(op_err)
168 : if (failed('set_D_GSF', op_err)) then
169 : ierr = -1; cycle
170 : end if
171 : call smooth_for_rotation(s, s% D_GSF, s% smooth_D_GSF, smooth_work(1:nz,which))
172 : if (s% skip_rotation_in_convection_zones) &
173 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% D_GSF)
174 : call zero_if_tiny(s,s% D_GSF)
175 : end if
176 :
177 : case (i_ST)
178 :
179 : if (s% D_ST_factor > 0 .or. s% am_nu_ST_factor > 0) then
180 :
181 : call set_ST(s, &
182 : rho, T, r, L, omega, Cp, abar, zbar, delta, grav, &
183 : N2, N2_mu, opacity, kap_cond, scale_height, op_err)
184 : if (failed('set_ST', op_err)) then
185 : ierr = -1; cycle
186 : end if
187 :
188 : call smooth_for_rotation(s, s% D_ST, s% smooth_D_ST, smooth_work(1:nz,which))
189 : call smooth_for_rotation(s, s% nu_ST, s% smooth_nu_ST, smooth_work(1:nz,which))
190 :
191 : ! time smooth for ST only
192 : if (s% prev_mesh_have_ST_start_info .and. .not. s% doing_relax &
193 : .and. .not. s% doing_first_model_of_run .and. s% ST_angsmt>0d0) then
194 :
195 : k0 = 1
196 : angsml = s% ST_angsml
197 : angsmt = s% ST_angsmt
198 : prev_out_q = 0d0
199 : prev_q = 1d0
200 : do k=2, nz-1 ! ignore k=1 or nz edge case
201 : if (s% m(k) > s% mstar_old) cycle
202 : do while (k0 < s% prev_mesh_nz)
203 : if (s% m(k)/s% mstar_old > prev_q) exit
204 : prev_out_q = prev_out_q + s% prev_mesh_dq(k0)
205 : prev_q = 1d0 - prev_out_q
206 : k0 = k0+1
207 : end do
208 : if (s% m(k)/s% mstar_old < prev_q) exit
209 : prev_out_q_m1 = prev_out_q - s% prev_mesh_dq(k0-1)
210 : prev_q_m1 = 1 - prev_out_q_m1
211 :
212 : ! linear interpolation
213 : alfa = (s% m(k)/s% mstar_old - prev_q)/(prev_q_m1-prev_q)
214 : D_ST_old = (1d0-alfa)*s% prev_mesh_D_ST_start(k0) + alfa*s% prev_mesh_D_ST_start(k0-1)
215 : nu_ST_old = (1d0-alfa)*s% prev_mesh_nu_ST_start(k0) + alfa*s% prev_mesh_nu_ST_start(k0-1)
216 : dgtau = angsml*(s% r(k)-s% r(k+1))*(s% r(k-1)*s% r(k))/s% dt
217 : s% D_ST(k) = max(D_ST_old/(1d0 + angsmt), &
218 : min(s% D_ST(k), max(D_ST_old*(1d0 + angsmt), D_ST_old + dgtau)))
219 : s% nu_ST(k) = max(nu_ST_old/(1d0 + angsmt), &
220 : min(s% nu_ST(k), max(nu_ST_old*(1d0 + angsmt), nu_ST_old + dgtau)))
221 : end do
222 : end if
223 :
224 : ! calculate B_r and B_phi
225 : do k = 1, nz
226 : q = s% omega_shear(k)
227 : s% dynamo_B_r(k) = & ! eqn 11, Heger et al. 2005
228 : pow(pow2(pi4*rho(k)*s% nu_ST(k)*q/r(k))*abs(omega(k))*s% nu_ST(k),0.25D0)
229 : s% dynamo_B_phi(k) = & ! eqn 12, Heger et al. 2005
230 : pow(pow2(pi4*rho(k)*omega(k)*q*r(k))*abs(omega(k))*s% nu_ST(k),0.25d0)
231 : end do
232 :
233 : if (s% skip_rotation_in_convection_zones) &
234 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% D_ST)
235 : if (s% skip_rotation_in_convection_zones) &
236 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% nu_ST)
237 : if (s% skip_rotation_in_convection_zones) &
238 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% dynamo_B_r)
239 : if (s% skip_rotation_in_convection_zones) &
240 : call zero_if_convective(nz, s% mixing_type, s% D_mix, s% dynamo_B_phi)
241 : call zero_if_tiny(s,s% D_ST)
242 : call zero_if_tiny(s,s% nu_ST)
243 :
244 : end if
245 :
246 : case default
247 : call mesa_error(__FILE__,__LINE__,'bad case for rotation_mix_info')
248 :
249 : end select
250 :
251 : end do
252 : !$OMP END PARALLEL DO
253 0 : if (failed('set_rotation_mixing_info instabilities', ierr)) return
254 :
255 0 : if (s% D_omega_flag .and. s% doing_finish_load_model) then
256 0 : do k=1,nz
257 0 : s% D_omega(k) = 0d0
258 : end do
259 0 : else if (s% D_omega_flag) then
260 :
261 0 : do k=1,nz
262 0 : if (s% q(k) <= s% max_q_for_D_omega_zero_in_convection_region .and. &
263 : s% mixing_type(k) == convective_mixing) then
264 0 : s% D_omega(k) = 0d0
265 0 : cycle
266 : end if
267 : D_omega_source = &
268 : s% D_DSI_factor * s% D_DSI(k) + &
269 : s% D_SH_factor * s% D_SH(k) + &
270 : s% D_SSI_factor * s% D_SSI(k) + &
271 : s% D_ES_factor * s% D_ES(k) + &
272 : s% D_GSF_factor * s% D_GSF(k) + &
273 0 : s% D_ST_factor * s% D_ST(k)
274 0 : if (is_bad(D_omega_source)) then
275 0 : write(*,2) 'D_omega_source', k, D_omega_source
276 0 : write(*,2) 's% D_DSI_factor * s% D_DSI(k)', k, s% D_DSI_factor * s% D_DSI(k), &
277 0 : s% D_DSI_factor, s% D_DSI(k)
278 0 : write(*,2) 's% D_SH_factor * s% D_SH(k)', k, s% D_SH_factor * s% D_SH(k), &
279 0 : s% D_SH_factor, s% D_SH(k)
280 0 : write(*,2) 's% D_SSI_factor * s% D_SSI(k)', k, s% D_SSI_factor * s% D_SSI(k), &
281 0 : s% D_SSI_factor, s% D_SSI(k)
282 0 : write(*,2) 's% D_ES_factor * s% D_ES(k)', k, s% D_ES_factor * s% D_ES(k), &
283 0 : s% D_ES_factor, s% D_ES(k)
284 0 : write(*,2) 's% D_GSF_factor * s% D_GSF(k)', k, s% D_GSF_factor * s% D_GSF(k), &
285 0 : s% D_GSF_factor, s% D_GSF(k)
286 0 : write(*,2) 's% D_ST_factor * s% D_ST(k)', k, s% D_ST_factor * s% D_ST(k), &
287 0 : s% D_ST_factor, s% D_ST(k)
288 0 : call mesa_error(__FILE__,__LINE__,'rotation mix')
289 : end if
290 0 : s% D_omega(k) = D_omega_source
291 0 : if (is_bad(s% D_omega(k))) then
292 0 : write(*,2) 's% D_omega(k)', k, s% D_omega(k)
293 0 : write(*,2) 'D_omega_source', k, D_omega_source
294 0 : call mesa_error(__FILE__,__LINE__,'rotation mix')
295 : end if
296 : end do
297 :
298 0 : if (s% smooth_D_omega > 0) then
299 0 : call smooth_for_rotation(s, s% D_omega, s% smooth_D_omega, smooth_work(1:nz,1))
300 0 : do k=1,nz
301 0 : if (is_bad(s% D_omega(k))) then
302 0 : write(*,2) 'after smooth_for_rotation s% D_omega(k)', k, s% D_omega(k)
303 0 : call mesa_error(__FILE__,__LINE__,'rotation mix')
304 : end if
305 : end do
306 : end if
307 :
308 0 : if (s% D_omega_mixing_rate > 0d0 .and. s% dt > 0) then
309 0 : call mix_D_omega
310 0 : do k=1,nz
311 0 : if (is_bad(s% D_omega(k))) then
312 0 : write(*,2) 'after mix_D_omega s% D_omega(k)', k, s% D_omega(k)
313 0 : call mesa_error(__FILE__,__LINE__,'rotation mix')
314 : end if
315 : end do
316 : end if
317 :
318 : end if
319 :
320 0 : if (s% D_omega_flag) then
321 0 : do k=1,nz
322 0 : if (is_bad(s% D_omega(k))) then
323 0 : write(*,2) 'before return s% D_omega(k)', k, s% D_omega(k)
324 0 : call mesa_error(__FILE__,__LINE__,'rotation mix')
325 : end if
326 0 : if (s% D_omega(k) < 0d0) s% D_omega(k) = 0d0
327 : end do
328 : end if
329 :
330 :
331 : contains
332 :
333 :
334 0 : subroutine mix_D_omega
335 : integer :: i, k, nz
336 : real(dp), dimension(:), allocatable :: & ! work vectors
337 0 : sig, rhs, d, du, dl, bp, vp, xp, x
338 : real(dp) :: &
339 0 : dt, rate, d_ddt_dm1, d_ddt_d00, d_ddt_dp1, m, &
340 0 : d_dt, d_dt_in, d_dt_out
341 : include 'formats'
342 :
343 0 : nz = s% nz
344 0 : dt = s% dt
345 0 : if (dt == 0) return
346 :
347 0 : allocate(sig(nz), rhs(nz), d(nz), du(nz), dl(nz), bp(nz), vp(nz), xp(nz), x(nz))
348 :
349 0 : rate = min(s% D_omega_mixing_rate, 1d0/dt)
350 0 : do k=2,nz-1
351 0 : if (s% D_omega(k) == 0 .or. s% D_omega(k+1) == 0) then
352 0 : sig(k) = 0
353 : else if ((.not. s% D_omega_mixing_across_convection_boundary) .and. &
354 0 : s% mixing_type(k) /= convective_mixing .and. &
355 : (s% mixing_type(k-1) == convective_mixing .or. &
356 : s% mixing_type(k+1) == convective_mixing)) then
357 0 : sig(k) = 0
358 : else
359 0 : sig(k) = rate*dt
360 : end if
361 : end do
362 0 : sig(1) = 0
363 0 : sig(nz) = 0
364 :
365 0 : do k=1,nz
366 0 : if (k < nz) then
367 0 : d_dt_in = sig(k)*(s% D_omega(k+1) - s% D_omega(k))
368 : else
369 0 : d_dt_in = -sig(k)*s% D_omega(k)
370 : end if
371 0 : if (k > 1) then
372 0 : d_dt_out = sig(k-1)*(s% D_omega(k) - s% D_omega(k-1))
373 0 : d_ddt_dm1 = sig(k-1)
374 0 : d_ddt_d00 = -(sig(k-1) + sig(k))
375 : else
376 0 : d_dt_out = 0
377 0 : d_ddt_dm1 = 0
378 0 : d_ddt_d00 = -sig(k)
379 : end if
380 0 : d_dt = d_dt_in - d_dt_out
381 0 : d_ddt_dp1 = sig(k)
382 0 : rhs(k) = d_dt
383 0 : d(k) = 1d0 - d_ddt_d00
384 0 : if (k < nz) then
385 0 : du(k) = -d_ddt_dp1
386 : else
387 0 : du(k) = 0
388 : end if
389 0 : if (k > 1) dl(k-1) = -d_ddt_dm1
390 : end do
391 0 : dl(nz) = 0
392 :
393 : ! solve tridiagonal
394 0 : bp(1) = d(1)
395 0 : vp(1) = rhs(1)
396 0 : do i = 2,nz
397 0 : m = dl(i-1)/bp(i-1)
398 0 : bp(i) = d(i) - m*du(i-1)
399 0 : vp(i) = rhs(i) - m*vp(i-1)
400 : end do
401 0 : xp(nz) = vp(nz)/bp(nz)
402 0 : x(nz) = xp(nz)
403 0 : do i = nz-1, 1, -1
404 0 : xp(i) = (vp(i) - du(i)*xp(i+1))/bp(i)
405 0 : x(i) = xp(i)
406 : end do
407 :
408 0 : do k=2,nz
409 0 : if (is_bad(x(k))) then
410 : return
411 : write(*,3) 's% D_omega(k) prev, x', k, s% model_number, s% D_omega(k), x(k), bp(i)
412 : call mesa_error(__FILE__,__LINE__,'mix_D_omega')
413 : end if
414 : end do
415 :
416 : ! update D_omega
417 :
418 0 : do k=2,nz
419 0 : s% D_omega(k) = s% D_omega(k) + x(k)
420 0 : if (is_bad(s% D_omega(k))) then
421 0 : write(*,3) 's% D_omega(k)', k, s% model_number, s% D_omega(k)
422 0 : call mesa_error(__FILE__,__LINE__,'mix_D_omega')
423 : end if
424 0 : if (s% D_omega(k) < 0d0) s% D_omega(k) = 0d0
425 : end do
426 0 : s% D_omega(1) = 0d0
427 :
428 0 : end subroutine mix_D_omega
429 :
430 :
431 0 : subroutine setup(ierr)
432 : use kap_lib, only: kap_get_elect_cond_opacity
433 : integer, intent(out) :: ierr
434 :
435 : real(dp) :: &
436 0 : bracket_term, ri0, alfa, beta, enum1, enu00, &
437 0 : rho6, gamma, mu_e, rm23, ctmp, xi2, dynvisc, denom, &
438 0 : eps_nucm1, eps_nuc00, scale_height2, dlnRho_dlnP, dlnT_dlnP, &
439 0 : kap, dlnkap_dlnRho, dlnkap_dlnT
440 :
441 : integer :: i, k
442 :
443 : include 'formats'
444 :
445 0 : ierr = 0
446 0 : nz = s% nz
447 :
448 0 : f_mu = s% am_gradmu_factor
449 :
450 : ! copy some pointers
451 0 : r => s% r
452 0 : m => s% m
453 0 : L => s% L
454 0 : j_rot => s% j_rot
455 0 : gradT => s% gradT
456 0 : grada => s% grada_face
457 0 : grav => s% grav
458 0 : visc => s% D_visc
459 0 : Ri => s% richardson_number
460 :
461 : allocate( &
462 0 : csound(nz), rho(nz), T(nz), P(nz), cp(nz), cv(nz), chiRho(nz), abar(nz), zbar(nz), &
463 0 : opacity(nz), kap_cond(nz), gamma1(nz), mu_alt(nz), omega(nz), cell_dr(nz), eps_nuc(nz), enu(nz), L_neu(nz), &
464 0 : gradT_sub_grada(nz), delta(nz), scale_height(nz), &
465 0 : dRho(nz), dr(nz), dPressure(nz), domega(nz), d_mu(nz), d_j_rot(nz), &
466 0 : dRho_dr(nz), dRho_dr_ad(nz), dr2omega(nz), H_T(nz), &
467 0 : domega_dlnR(nz), Hj(nz), dlnR_domega(nz), t_dyn(nz), t_kh(nz), &
468 0 : Ri_mu(nz), Ri_T(nz), ve0(nz), ve_mu(nz), &
469 0 : v_ssi(nz), h_ssi(nz), Ris_1(nz), Ris_2(nz), &
470 0 : v_es(nz), H_es(nz), v_gsf(nz), H_gsf(nz), N2(nz), N2_mu(nz), &
471 0 : smooth_work(nz,num_instabilities), saved(nz,num_instabilities), &
472 0 : unstable(num_instabilities,nz))
473 :
474 : ! interpolate by mass to get values at cell boundaries
475 0 : enu00 = s% eps_nuc_neu_total(1) + s% non_nuc_neu(1)
476 0 : enu(1) = enu00
477 0 : eps_nuc00 = s% eps_nuc(1)
478 0 : eps_nuc(1) = eps_nuc00
479 0 : csound(1) = s% csound(1)
480 0 : rho(1) = s% rho(1)
481 0 : T(1) = s% T(1)
482 0 : P(1) = s% Peos(1)
483 0 : cp(1) = s% cp(1)
484 0 : cv(1) = s% Cv(1)
485 0 : chiRho(1) = s% chiRho(1)
486 0 : abar(1) = s% abar(1)
487 0 : zbar(1) = s% zbar(1)
488 0 : opacity(1) = s% opacity(1)
489 0 : gamma1(1) = s% gamma1(1)
490 0 : mu_alt(1) = s% abar(1)/(1 + s% zbar(1))
491 0 : delta(1) = s% chiT(1)/s% chiRho(1)
492 0 : L_neu(1) = enu00*s% dm(1)
493 0 : do k = 2, nz
494 0 : alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
495 0 : beta = 1 - alfa
496 0 : enum1 = enu00
497 0 : enu00 = s% eps_nuc_neu_total(k) + s% non_nuc_neu(k)
498 0 : enu(k) = alfa*enu00 + beta*enum1
499 0 : eps_nucm1 = eps_nuc00
500 0 : eps_nuc00 = s% eps_nuc(k)
501 0 : eps_nuc(k) = alfa*eps_nuc00 + beta*eps_nucm1
502 0 : csound(k) = alfa*s% csound(k) + beta*s% csound(k-1)
503 0 : rho(k) = alfa*s% rho(k) + beta*s% rho(k-1)
504 0 : T(k) = alfa*s% T(k) + beta*s% T(k-1)
505 0 : P(k) = alfa*s% Peos(k) + beta*s% Peos(k-1)
506 0 : cp(k) = alfa*s% cp(k) + beta*s% cp(k-1)
507 0 : cv(k) = alfa*s% Cv(k) + beta*s% Cv(k-1)
508 0 : chiRho(k) = alfa*s% chiRho(k) + beta*s% chiRho(k-1)
509 0 : abar(k) = alfa*s% abar(k) + beta*s% abar(k-1)
510 0 : zbar(k) = alfa*s% zbar(k) + beta*s% zbar(k-1)
511 0 : opacity(k) = alfa*s% opacity(k) + beta*s% opacity(k-1)
512 0 : gamma1(k) = alfa*s% gamma1(k) + beta*s% gamma1(k-1)
513 0 : mu_alt(k) = alfa*s% abar(k)/(1 + s% zbar(k)) + beta*s% abar(k-1)/(1 + s% zbar(k-1))
514 0 : delta(k) = alfa*s% chiT(k)/s% chiRho(k) + beta*s% chiT(k-1)/s% chiRho(k-1)
515 0 : L_neu(k) = enu00*s% dm(k) + L_neu(k-1)
516 0 : cell_dr(k-1) = s% rmid(k-1) - s% rmid(k)
517 : end do
518 0 : cell_dr(nz) = s% rmid(nz) - s% R_center
519 :
520 0 : do i = 1, nz
521 0 : gradT_sub_grada(i) = s% gradT(i) - s% grada_face(i)
522 : gradT_sub_grada(i) = & ! make sure it isn't too close to 0
523 0 : sign(max(abs(gradT_sub_grada(i)),1d-99),gradT_sub_grada(i))
524 0 : scale_height(i) = P(i)*r(i)*r(i)/(s% cgrav(i)*m(i)*rho(i))
525 0 : scale_height2 = sqrt(P(i)/s% cgrav(i))/rho(i)
526 0 : if (scale_height2 < scale_height(i)) scale_height(i) = scale_height2
527 0 : omega(i) = s% omega(i)
528 : end do
529 :
530 : ! differences (at cell boundaries)
531 0 : do i = 2, nz-1
532 0 : dRho(i) = rho(i-1) - rho(i)
533 0 : dr(i) = max(1d0, 0.5D0*(r(i-1) - r(i+1)))
534 0 : dPressure(i) = min(-1d-10, P(i-1) - P(i))
535 0 : d_mu(i) = mu_alt(i-1) - mu_alt(i)
536 0 : d_j_rot(i) = j_rot(i-1) - j_rot(i)
537 0 : domega(i) = 0.5D0*(omega(i-1) - omega(i+1))
538 : end do
539 :
540 0 : dRho(1) = 0
541 0 : dRho(nz) = 0
542 :
543 0 : dr(1) = max(1d0,r(1)-r(2))
544 0 : dr(nz) = r(nz) - s% R_center
545 :
546 0 : dPressure(1) = 0
547 0 : dPressure(nz) = 0
548 :
549 0 : d_mu(1) = 0
550 0 : d_mu(nz) = 0
551 :
552 0 : d_j_rot(1) = 0
553 0 : d_j_rot(nz) = 0
554 :
555 0 : domega(1) = 0
556 0 : domega(nz) = 0
557 :
558 0 : do i = 2, nz-1
559 0 : dRho_dr(i) = dRho(i)/dr(i)
560 0 : dRho_dr_ad(i) = rho(i)*dPressure(i)/(P(i)*gamma1(i)*dr(i))
561 0 : dr2omega(i) = 4.5d0*j_rot(i)*d_j_rot(i)/dr(i) ! d(r^2 omega)^2/dr using i = (2/3)*r^2
562 0 : domega_dlnR(i) = domega(i)*r(i)/dr(i)
563 0 : if (gradT(i) > 1d-20) then
564 0 : H_T(i) = scale_height(i)/gradT(i) ! -dr/dlnT, scale height of temperature
565 : else
566 0 : H_T(i) = scale_height(i)
567 : end if
568 0 : if(abs(d_j_rot(i))>0.d0)then
569 0 : Hj(i) = j_rot(i)*dr(i)/d_j_rot(i)
570 : else
571 0 : Hj(i) =0d0
572 : end if
573 : ! dr/dlnj, scale height of angular momentum
574 : end do
575 :
576 0 : dRho_dr(1) = 0; dRho_dr(nz) = 0
577 0 : dRho_dr_ad(1) = 0; dRho_dr_ad(nz) = 0
578 0 : dr2omega(1) = 0; dr2omega(nz) = 0
579 0 : domega_dlnR(1) = 0; domega_dlnR(nz) = 0
580 0 : H_T(1) = H_T(2); H_T(nz) = H_T(nz-1)
581 0 : Hj(1) = Hj(2); Hj(nz) = Hj(nz-1)
582 :
583 0 : do i = 1, nz
584 0 : dlnRho_dlnP = s% grad_density(i)
585 0 : dlnT_dlnP = s% grad_temperature(i)
586 0 : N2(i) = -grav(i)*(1/gamma1(i) - dlnRho_dlnP)/scale_height(i)
587 0 : N2_mu(i) = -grav(i)/scale_height(i)*(1/chiRho(i) - delta(i)*dlnT_dlnP - dlnRho_dlnP)
588 : end do
589 :
590 0 : do k=1,nz
591 0 : s% domega_dlnR(k) = domega_dlnR(k)
592 : end do
593 :
594 : ! safe inverse of domega/dlnR
595 0 : do i = 2, nz-1
596 0 : dlnR_domega(i) = sign(1d0/max(abs(domega_dlnR(i)),1d-30),domega_dlnR(i))
597 : end do
598 0 : dlnR_domega(1) = 0; dlnR_domega(nz) = 0
599 :
600 0 : do k = 2, nz - 1 ! shear
601 : s% omega_shear(k) = &
602 0 : (omega(k-1) - omega(k+1))/(r(k-1) - r(k+1))*(r(k)/omega(k))
603 0 : s% omega_shear(k) = max(1d-30,min(1d30,abs(s% omega_shear(k))))
604 : end do
605 0 : s% omega_shear(1) = 0
606 0 : s% omega_shear(nz) = 0
607 :
608 : ! timescales
609 0 : do i = 1, nz
610 0 : t_dyn(i) = sqrt(r(i)*r(i)*r(i)/(s% cgrav(i)*m(i)))
611 0 : t_kh(i) = s% cgrav(i)*m(i)*m(i)/(r(i)*max(1d0,L(i)+L_neu(i)))
612 : end do
613 :
614 : ! Richardson numbers (Heger 2000, eqn 20)
615 0 : do i = 2, nz-1
616 0 : ri0 = (rho(i)*delta(i)/P(i))*pow2(dlnR_domega(i)*grav(i))
617 0 : Ri_T(i) = ri0*max(0d0,-gradT_sub_grada(i)) ! turn off Ri_T in convection zones
618 0 : Ri_mu(i) = ri0*f_mu*s% smoothed_brunt_B(i)
619 : end do
620 0 : Ri_T(1) = 0; Ri_T(nz) = 0
621 0 : Ri_mu(1) = 0; Ri_mu(nz) = 0
622 0 : do i=1,nz
623 0 : if (N2(i) < 0d0) then
624 0 : Ri(i) = 1d0 ! disable in convective region
625 : else
626 0 : Ri(i) = Ri_T(i) + Ri_mu(i)
627 : end if
628 : end do
629 :
630 : ! dynamic viscosity
631 0 : do i=1,nz
632 0 : rho6 = rho(i)*1d-6
633 0 : gamma = 0.2275d0*zbar(i)*zbar(i)*pow(rho6/abar(i),one_third)*1.d8/T(i)
634 : ! gamma => eq (5) of Itoh et al 1987 ApJ 317,733
635 : ! electron viscosity according to Nandkumar & Pethick 1984 MNRAS
636 0 : mu_e = abar(i)/zbar(i)
637 0 : rm23 = pow(rho6/mu_e,2d0/3d0)
638 0 : ctmp = 1d0 + 1.018d0*rm23
639 : xi2 = sqrt(pi/3d0)*log(zbar(i))/3d0 + 2d0*log(1.32d0+2.33d0/sqrt(gamma)) - &
640 0 : 0.475d0*(1d0+2.036d0*rm23)/ctmp + 0.276d0*rm23/ctmp
641 : ! dynamic shear viscosity according to Wallenborn and Bauss (1978)
642 : ! and also Itoh et al 1987 ApJ 317,733
643 : ! fitting formula for eta* in Eq (12) of Itoh et al. 1987
644 : ctmp = -0.016321227d0+1.0198850d0*pow(gamma,-1.9217970d0) + &
645 0 : 0.024113535d0*pow(gamma,0.49999098d0)
646 : ! dynamic shear viscosity
647 0 : dynvisc = 5.53d3*zbar(i)*pow(rho6,5d0/6d0)*ctmp/pow(abar(i),one_third)
648 : ! add contribution of radiation
649 0 : dynvisc = dynvisc + 4.D0*crad*pow4(T(i))/(15.D0*clight*opacity(i)*rho(i))
650 : ! add contribution of electrons
651 0 : dynvisc = dynvisc + 1.893d6*pow(rm23,2.5d0)/(zbar(i)*ctmp*xi2)
652 : ! kinematic shear viscosity
653 0 : visc(i) = dynvisc/rho(i)
654 : end do
655 :
656 : ! velocities for ES and GSF
657 0 : if (s% D_ES_factor > 0 .or. s% D_GSF_factor > 0) then
658 0 : do i = 1, nz ! Heger 2000, eqns 35 and 36
659 : ! the bracket_term blows up at center since r^2/L and r^2/m can both -> Inf
660 : ! so bullet proof by including lower bounds
661 : bracket_term = &
662 : 2*r(i)*r(i)*(eps_nuc(i)/max(1d-3*Lsun,abs(L(i))) - 1/max(1d-3*Msun,m(i))) - &
663 0 : 3/(pi4*rho(i)*max(1d-3*Rsun,r(i)))
664 0 : if (abs(gradT_sub_grada(i)) < 1d-50) then
665 0 : ve0(i) = 1d99
666 0 : ve_mu(i) = 1d99
667 : else
668 0 : denom = (-gradT_sub_grada(i)*delta(i)*pow2(s% cgrav(i)*m(i)))
669 0 : if (abs(denom) < 1d-50 .or. is_bad(denom)) then
670 0 : if (s% stop_for_bad_nums) then
671 0 : write(*,2) 'denom', i, denom
672 0 : call mesa_error(__FILE__,__LINE__,'rotation mix info: velocities for ES and GSF')
673 : end if
674 0 : ve0(i) = 1d99
675 : else
676 0 : ve0(i) = grada(i)*omega(i)*omega(i)*r(i)*r(i)*r(i)*L(i)*bracket_term/denom
677 : end if
678 : ve_mu(i) = (scale_height(i)/t_kh(i))* &
679 0 : (f_mu*s% smoothed_brunt_B(i))/(gradT_sub_grada(i))
680 : end if
681 0 : if (is_bad(ve0(i))) then
682 0 : if (s% stop_for_bad_nums) then
683 0 : write(*,2) 've0(i)', i, ve0(i)
684 0 : call mesa_error(__FILE__,__LINE__,'rotation mix info')
685 : end if
686 0 : ve0(i) = 1d99
687 : end if
688 0 : if (is_bad(ve_mu(i))) then
689 0 : if (s% stop_for_bad_nums) then
690 0 : write(*,2) 've_mu(i)', i, ve_mu(i)
691 0 : call mesa_error(__FILE__,__LINE__,'rotation mix info')
692 : end if
693 0 : ve_mu(i) = 1d99
694 : end if
695 :
696 0 : if (s% model_number == -1 .and. i == 316) then
697 0 : write(*,2) 'grada(i)', i, grada(i)
698 0 : write(*,2) 'gradT(i)', i, gradT(i)
699 0 : write(*,2) 'gradT_sub_grada(i)', i, gradT_sub_grada(i)
700 0 : write(*,2) 's% smoothed_brunt_B(i)', i, s% smoothed_brunt_B(i)
701 0 : write(*,2) 'omega(i)', i, omega(i)
702 0 : write(*,2) 's% omega(i)', i, s% omega(i)
703 0 : write(*,2) '2*r**2*eps_nuc/L', i, 2*r(i)*r(i)*eps_nuc(i)/max(1d0,L(i))
704 0 : write(*,2) '2*r**2/m', i, 2*r(i)*r(i)/m(i)
705 0 : write(*,2) '3/(4*pi*rho*r)', i, 3/(4*pi*rho(i)*r(i))
706 0 : write(*,2) 've0(i)', i, ve0(i)
707 : end if
708 :
709 : end do
710 :
711 : ! conductive opacities for ST
712 0 : if (s% D_ST_factor > 0d0 .or. s% am_nu_factor > 0d0) then
713 0 : do i = 1, nz
714 : call kap_get_elect_cond_opacity( &
715 : s% kap_handle, zbar(i), log10(rho(i)), log10(T(i)), &
716 0 : kap, dlnkap_dlnRho, dlnkap_dlnT, ierr)
717 0 : if (ierr /= 0) return
718 0 : kap_cond(i) = kap
719 : end do
720 : end if
721 :
722 : end if
723 :
724 0 : end subroutine setup
725 :
726 :
727 0 : subroutine set_D_DSI(ierr)
728 : integer, intent(out) :: ierr
729 : integer :: i, k, kbot, ktop
730 0 : real(dp) :: instability_height, height, D
731 : logical, parameter :: dbg = .false.
732 : include 'formats'
733 :
734 0 : ierr = 0
735 0 : do i = 1, nz
736 0 : unstable(i_DSI,i) = (Ri(i) < Ri_crit) .and. (gradT_sub_grada(i) < 0)
737 : ! stable in convective regions where gradT >= grada
738 : end do
739 :
740 0 : kbot = nz
741 0 : do i = nz-1, 1, -1
742 :
743 0 : if (unstable(i_DSI,i) .and. .not. unstable(i_DSI,i+1)) kbot = i
744 :
745 : if (unstable(i_DSI,i+1) .and. &
746 0 : (i == 1 .or. .not. unstable(i_DSI,i)) .and. kbot > 1) then
747 :
748 0 : if (unstable(i_DSI,i)) then
749 : ktop = i
750 : else
751 0 : ktop = i+1
752 : end if
753 :
754 0 : if (ktop >= kbot) cycle
755 :
756 0 : instability_height = r(ktop) - r(kbot)
757 : if (dbg) write(*,3) 'DSI: ktop, kbot', ktop, kbot
758 0 : do k = ktop, kbot
759 0 : if (.not. unstable(i_DSI,k)) then
760 0 : write(*,2) 'D_DSI where stable?', k, s% q(k), &
761 0 : s% D_DSI(k), D, scale_height(k)*csound(k), &
762 0 : Ri(k), Ri_crit, height, t_dyn(k), &
763 0 : instability_height, scale_height(k), csound(k)
764 0 : call mesa_error(__FILE__,__LINE__,'set_D_DSI')
765 : end if
766 0 : height = min(instability_height, scale_height(k))
767 0 : D = height*height/t_dyn(k)
768 0 : s% D_DSI(k) = min(D, scale_height(k)*csound(k))
769 : if (dbg) write(*,2) 'D_DSI', k, s% q(k), &
770 : s% D_DSI(k), D, scale_height(k)*csound(k), &
771 : Ri(k), Ri_crit, height, t_dyn(k), &
772 0 : instability_height, scale_height(k), csound(k)
773 : end do
774 :
775 : if (dbg) write(*,*)
776 :
777 : end if
778 :
779 : end do
780 : if (dbg) call mesa_error(__FILE__,__LINE__,'set_D_DSI')
781 0 : end subroutine set_D_DSI
782 :
783 :
784 0 : subroutine set_D_SH(ierr) ! comment in Langer code says "DO NOT USE"
785 : integer, intent(out) :: ierr
786 : integer :: i, k, kbot, ktop
787 0 : real(dp) :: instability_height, height, D
788 0 : ierr = 0
789 :
790 0 : do i = 1, nz
791 0 : D = grav(i)/rho(i)*(dRho_dr_ad(i)-dRho_dr(i))+dr2omega(i)/(r(i)*r(i)*r(i))
792 0 : if (D < 0) then
793 0 : unstable(i_SH,i) = .true.
794 0 : s% D_SH(i) = D ! save for later
795 : else
796 0 : s% D_SH(i) = 0
797 : end if
798 : end do
799 :
800 0 : kbot = nz
801 0 : do i = nz-1, 1, -1
802 :
803 0 : if (unstable(i_SH,i) .and. .not. unstable(i_SH,i+1)) kbot = i
804 :
805 : if (unstable(i_SH,i+1) .and. &
806 0 : (i == 1 .or. .not. unstable(i_SH,i)) .and. kbot > 1) then
807 0 : if (unstable(i_SH,i)) then
808 : ktop = i
809 : else
810 0 : ktop = i+1
811 : end if
812 0 : if (ktop >= kbot) cycle
813 0 : instability_height = r(ktop) - r(kbot)
814 0 : do k = ktop, kbot
815 0 : height = min(instability_height, scale_height(k))
816 : ! use the previously calculated value saved in D_SH
817 0 : D = pow2(height*s% D_SH(k)*r(k)/grav(k))/t_dyn(k)
818 0 : s% D_SH(k) = min(D, scale_height(k)*csound(k))
819 : end do
820 : end if
821 :
822 : end do
823 0 : end subroutine set_D_SH
824 :
825 :
826 0 : subroutine set_D_SSI(ierr)
827 : use chem_def
828 : integer, intent(out) :: ierr
829 : integer :: i, k, kbot, ktop
830 0 : real(dp) :: qe3, qe4, dynvisc, Prandtl, radcon, D
831 : include 'formats'
832 :
833 0 : ierr = 0
834 0 : qe3 = qe*qe*qe
835 0 : qe4 = qe3*qe
836 :
837 0 : do i=1,nz
838 0 : unstable(i_SSI,i) = .false.
839 : ! thermal conductivity
840 0 : radcon = 4.D0*crad*clight*T(i)*T(i)*T(i)/(3.D0*opacity(i)*rho(i)) ! erg / (K cm sec)
841 : ! Prandtl-number according to Tassoul
842 0 : dynvisc = visc(i)*rho(i)
843 0 : Prandtl = dynvisc*Cv(i)/radcon
844 0 : Ris_1(i) = 0.125D0*R_crit*Prandtl*Ri_T(i)
845 0 : if (Ris_1(i) <= Ri_crit) then
846 0 : Ris_2(i) = Ri_mu(i)
847 0 : if (Ris_2(i) <= Ri_crit) unstable(i_SSI,i) = .true.
848 : else
849 0 : Ris_2(i) = 0
850 : end if
851 : end do
852 :
853 0 : kbot = nz
854 0 : do i = nz-1, 1, -1
855 :
856 0 : if (unstable(i_SSI,i) .and. .not. unstable(i_SSI,i+1)) kbot = i
857 :
858 : if (unstable(i_SSI,i+1) .and. &
859 0 : (i == 1 .or. .not. unstable(i_SSI,i)) .and. kbot > 1) then
860 0 : if (unstable(i_SSI,i)) then
861 : ktop = i
862 : else
863 0 : ktop = i+1
864 : end if
865 :
866 0 : if (ktop >= kbot) cycle
867 :
868 0 : do k = ktop, kbot ! Heger 2000, eqn 31
869 0 : v_ssi(k)=sqrt(visc(k)/R_crit*abs(domega_dlnR(k)))
870 : end do
871 :
872 : H_ssi(kbot) = v_ssi(kbot)*(r(kbot-1) - r(kbot))/ &
873 0 : max(1d-99,abs(v_ssi(kbot-1) - v_ssi(kbot)))
874 0 : do k = kbot-1, ktop+1, -1
875 : H_ssi(k) = v_ssi(k)*dr(k)/ &
876 0 : max(1d-99,0.5d0*abs(v_ssi(k+1) - v_ssi(k-1)))
877 : end do
878 : H_ssi(ktop) = v_ssi(ktop)*(r(ktop) - r(ktop+1))/ &
879 0 : max(1d-99,abs(v_ssi(ktop) - v_ssi(ktop+1)))
880 :
881 0 : do k = ktop, kbot ! Heger 2000, eqn 34
882 0 : H_ssi(k) = min(H_ssi(k),scale_height(k))
883 0 : v_ssi(k) = min(v_ssi(k),csound(k))
884 : D = H_ssi(k)*v_ssi(k)* &
885 0 : pow2(1d0-max(0d0,max(Ris_1(k),Ris_2(k))/Ri_crit))
886 0 : s% D_SSI(k) = min(D, scale_height(k)*csound(k))
887 :
888 0 : if (s% D_SSI(k) > 1d100) then ! bug
889 0 : write(*,2) 's% D_SSI(k)', k, s% D_SSI(k)
890 0 : write(*,2) 'D', k, D
891 0 : write(*,2) 'scale_height(k)', k, scale_height(k)
892 0 : write(*,2) 'csound(k)', k, csound(k)
893 0 : write(*,2) 'H_ssi(k)', k, H_ssi(k)
894 0 : write(*,2) 'v_ssi(k)', k, v_ssi(k)
895 0 : write(*,2) 'Ris_1(k)', k, Ris_1(k)
896 0 : write(*,2) 'Ris_2(k)', k, Ris_2(k)
897 0 : write(*,2) 'dr(k)', k, dr(k)
898 0 : write(*,2) 'visc(k)', k, visc(k)
899 0 : write(*,2) 'domega_dlnR(k)', k, domega_dlnR(k)
900 0 : call mesa_error(__FILE__,__LINE__,'set_D_SSI')
901 : end if
902 :
903 : end do
904 :
905 : end if
906 :
907 : end do
908 :
909 0 : end subroutine set_D_SSI
910 :
911 :
912 0 : subroutine set_D_ES(ierr)
913 : integer, intent(out) :: ierr
914 : integer :: i, k, kbot, ktop
915 0 : real(dp) :: instability_height, D, v
916 : include 'formats'
917 0 : ierr = 0
918 :
919 0 : do i = 1, nz
920 0 : v = abs(ve0(i)) - abs(ve_mu(i)) ! heger 2000, eqn 38
921 0 : if (v > 0) then
922 0 : unstable(i_ES,i) = .true.
923 0 : v_es(i) = v
924 : else
925 0 : v_es(i) = 0
926 : end if
927 : end do
928 :
929 0 : kbot = nz
930 0 : do i = nz-1, 1, -1
931 :
932 0 : if (unstable(i_ES,i) .and. .not. unstable(i_ES,i+1)) kbot = i
933 :
934 : if (unstable(i_ES,i+1) .and. &
935 0 : (i == 1 .or. .not. unstable(i_ES,i)).and. kbot > 1) then
936 0 : if (unstable(i_ES,i)) then
937 : ktop = i
938 : else
939 0 : ktop = i+1
940 : end if
941 :
942 0 : if (ktop >= kbot) cycle
943 :
944 0 : instability_height = r(ktop) - r(kbot)
945 :
946 : ! heger 2000, eqn 39
947 : H_es(kbot) = v_es(kbot)*(r(kbot-1) - r(kbot))/ &
948 0 : max(1d-99,abs(v_es(kbot-1) - v_es(kbot)))
949 0 : do k = kbot-1, ktop+1, -1
950 : H_es(k) = v_es(k)*dr(k)/ &
951 0 : max(1d-99,0.5d0*abs(v_es(k+1) - v_es(k-1)))
952 : end do
953 : H_es(ktop) = v_es(ktop)*(r(ktop) - r(ktop+1))/ &
954 0 : max(1d-99,abs(v_es(ktop) - v_es(ktop+1)))
955 :
956 0 : do k = ktop, kbot
957 0 : H_es(k) = min(instability_height, H_es(k), scale_height(k))
958 0 : v_es(k) = min(v_es(k), csound(k))
959 0 : D = H_es(k)*v_es(k)
960 0 : s% D_ES(k) = min(D, scale_height(k)*csound(k))
961 : end do
962 :
963 : end if
964 :
965 : end do
966 :
967 0 : end subroutine set_D_ES
968 :
969 :
970 0 : subroutine set_D_GSF(ierr)
971 : integer, intent(out) :: ierr
972 : integer :: i, k, kbot, ktop
973 0 : real(dp) :: instability_height, D, v, v_diff
974 : include 'formats'
975 0 : ierr = 0
976 :
977 0 : do i = 1, nz
978 :
979 : ! heger 2000, eqn 42
980 0 : if(abs(Hj(i))>0d0) then
981 0 : v = ve0(i)*2*H_T(i)*r(i)/(Hj(i)*Hj(i))/(1 + 2*omega(i)*dlnR_domega(i))
982 : else
983 0 : v = 0d0
984 : end if
985 0 : if (is_bad(v)) then
986 0 : write(*,2) 'bad v for GSF', i, v
987 0 : write(*,2) 've0(i)', i, ve0(i)
988 0 : write(*,2) 'H_T(i)', i, H_T(i)
989 0 : write(*,2) 'r(i)', i, r(i)
990 0 : write(*,2) 'Hj(i)', i, Hj(i)
991 0 : write(*,2) 'omega(i)', i, omega(i)
992 0 : write(*,2) 'dlnR_domega(i)', i, dlnR_domega(i)
993 0 : call mesa_error(__FILE__,__LINE__,'set_D_GSF')
994 0 : v = 0
995 : end if
996 0 : v_diff = abs(v) - abs(ve_mu(i)) ! heger 2000, eqn 43
997 0 : if (v_diff > 0) then
998 0 : unstable(i_GSF,i) = .true.
999 0 : v_gsf(i) = v_diff
1000 : else
1001 0 : v_gsf(i) = 0
1002 : end if
1003 :
1004 0 : if (s% model_number == -3 .and. i == -1) then
1005 0 : write(*,2) 've0(i)', i, ve0(i)
1006 0 : write(*,2) 'H_T(i)', i, H_T(i)
1007 0 : write(*,2) 'r(i)', i, r(i)
1008 0 : write(*,2) 'Hj(i)', i, Hj(i)
1009 0 : write(*,2) 'omega(i)', i, omega(i)
1010 0 : write(*,2) 'dlnR_domega(i)', i, dlnR_domega(i)
1011 0 : write(*,2) 'v', i, v
1012 0 : write(*,2) 've_mu(i)', i, ve_mu(i)
1013 0 : write(*,2) 'v_gsf(i)', i, v_gsf(i)
1014 : end if
1015 :
1016 : end do
1017 :
1018 0 : kbot = nz
1019 0 : do i = nz-1, 1, -1
1020 :
1021 0 : if (unstable(i_GSF,i) .and. .not. unstable(i_GSF,i+1)) kbot = i
1022 :
1023 : if (unstable(i_GSF,i+1) .and. &
1024 0 : (i == 1 .or. .not. unstable(i_GSF,i)) .and. kbot > 1) then
1025 0 : if (unstable(i_GSF,i)) then
1026 0 : ktop = i
1027 : else
1028 0 : ktop = i+1
1029 : end if
1030 :
1031 0 : if (ktop >= kbot) cycle
1032 :
1033 0 : instability_height = r(ktop) - r(kbot)
1034 :
1035 : ! heger 2000, eqn 45
1036 : if (kbot == 1) then
1037 : H_gsf(kbot) = v_gsf(kbot)*(s% R_center - r(kbot))/ &
1038 : max(1d-99,abs(v_gsf(kbot)))
1039 : else
1040 : H_gsf(kbot) = v_gsf(kbot)*(r(kbot-1) - r(kbot))/ &
1041 0 : max(1d-99,abs(v_gsf(kbot-1) - v_gsf(kbot)))
1042 : end if
1043 :
1044 : if (kbot == -1) then
1045 : write(*,2) 'r(kbot)', kbot, r(kbot)
1046 : write(*,2) 'r(kbot-1)', kbot-1, r(kbot-1)
1047 : write(*,2) 'v_gsf(kbot)', kbot, v_gsf(kbot)
1048 : write(*,2) 'v_gsf(kbot-1)', kbot-1, v_gsf(kbot-1)
1049 : write(*,2) 'H_gsf(kbot)', kbot, H_gsf(kbot)
1050 : end if
1051 :
1052 0 : do k = max(2,kbot-1), min(nz-1,ktop+1), -1
1053 : H_gsf(k) = v_gsf(k)*dr(k)/ &
1054 0 : max(1d-99,0.5d0*abs(v_gsf(k+1) - v_gsf(k-1)))
1055 0 : if (k == -1) then
1056 0 : write(*,2) 'dr(k)', k, dr(k)
1057 0 : write(*,2) 'v_gsf(k-1)', k-1, v_gsf(k-1)
1058 0 : write(*,2) 'v_gsf(k)', k, v_gsf(k)
1059 0 : write(*,2) 'v_gsf(k+1)', k+1, v_gsf(k+1)
1060 0 : write(*,2) 'H_gsf(k)', k, H_gsf(k)
1061 : end if
1062 : end do
1063 :
1064 0 : if (ktop == nz) then
1065 : H_gsf(ktop) = v_gsf(ktop)*(r(ktop) - s% R_center)/ &
1066 0 : max(1d-99,abs(v_gsf(ktop)))
1067 : else
1068 : H_gsf(ktop) = v_gsf(ktop)*(r(ktop) - r(ktop+1))/ &
1069 0 : max(1d-99,abs(v_gsf(ktop) - v_gsf(ktop+1)))
1070 : end if
1071 :
1072 0 : if (ktop == -1) then
1073 0 : write(*,2) 'r(ktop)', ktop, r(ktop)
1074 0 : write(*,2) 'r(ktop+1)', ktop+1, r(ktop+1)
1075 0 : write(*,2) 'v_gsf(ktop)', ktop, v_gsf(ktop)
1076 0 : write(*,2) 'v_gsf(ktop+1)', ktop+1, v_gsf(ktop+1)
1077 0 : write(*,2) 'H_gsf(ktop)', ktop, H_gsf(ktop)
1078 : end if
1079 :
1080 0 : do k = ktop, kbot
1081 0 : H_gsf(k) = min(instability_height, H_gsf(k), scale_height(k))
1082 0 : v_gsf(k) = min(v_gsf(k), csound(k))
1083 0 : D = H_gsf(k)*v_gsf(k)
1084 0 : s% D_GSF(k) = min(D, scale_height(k)*csound(k))
1085 : end do
1086 :
1087 : end if
1088 :
1089 : end do
1090 :
1091 0 : if (s% model_number == -1) then
1092 0 : k = -1
1093 0 : write(*,2) 've0(k)', k, ve0(k)
1094 0 : write(*,2) 'H_T(k)', k, H_T(k)
1095 0 : write(*,2) 'r(k)', k, r(k)
1096 0 : write(*,2) 'Hj(k)', k, Hj(k)
1097 0 : write(*,2) 'omega(k)', k, omega(k)
1098 0 : write(*,2) 'dlnR_domega(k)', k, dlnR_domega(k)
1099 0 : write(*,2) 'dr(k)', k, dr(k)
1100 0 : write(*,2) 'H_gsf(k)', k, H_gsf(k)
1101 0 : write(*,2) 'v_gsf(k)', k, v_gsf(k)
1102 0 : write(*,2) 'csound(k)', k, csound(k)
1103 0 : write(*,2) 'scale_height(k)', k, scale_height(k)
1104 0 : write(*,2) 's% D_GSF(k)', k, s% D_GSF(k)
1105 : end if
1106 :
1107 0 : end subroutine set_D_GSF
1108 :
1109 :
1110 0 : logical function failed(str, ierr)
1111 : character (len=*), intent(in) :: str
1112 : integer, intent(in) :: ierr
1113 0 : if (ierr == 0) then
1114 : failed = .false.
1115 : return
1116 : end if
1117 0 : write(s% retry_message,*) 'set_rotation_mixing_info failed in call to ' // trim(str)
1118 0 : if (s% report_ierr) write(*, *) s% retry_message
1119 : failed = .true.
1120 : end function failed
1121 :
1122 :
1123 : end subroutine set_rotation_mixing_info
1124 :
1125 :
1126 0 : subroutine smooth_for_rotation(s, v, width, work)
1127 : use star_utils, only: weighed_smoothing
1128 : type (star_info), pointer :: s
1129 : real(dp), dimension(:) :: v, work
1130 : integer :: width
1131 : logical, parameter :: preserve_sign = .false.
1132 0 : if (width <= 0) return
1133 0 : call weighed_smoothing(v, s% nz, width, preserve_sign, work)
1134 0 : end subroutine smooth_for_rotation
1135 :
1136 :
1137 0 : subroutine set_ST(s, &
1138 0 : rho, T, r, L, omega, Cp, abar, zbar, delta, grav, &
1139 0 : N2, N2_mu, opacity, kap_cond, scale_height, &
1140 : ierr)
1141 : ! with modifications by S.-C. Yoon, July 2003
1142 : type (star_info), pointer :: s
1143 : real(dp), dimension(:) :: & ! allocated temporary storage
1144 : rho, T, r, L, omega, Cp, abar, zbar, delta, grav, &
1145 : N2, N2_mu, opacity, kap_cond, scale_height
1146 : integer, intent(out) :: ierr
1147 :
1148 : integer :: nz, k, kk
1149 0 : real(dp) :: xmagfmu, xmagft, xmagfdif, xmagfnu, &
1150 0 : xkap, xgamma, xsig, &
1151 0 : xeta, xmagn, xmagnmu, xmagnt, xmagw, xmagdn, xmagtn, xmagrn, xmag4pd, &
1152 0 : dlnomega_dlnr, xmagq, xmager2w, &
1153 0 : xmagnn, xmagwn, xmagq0, xmagwa0, xmags0, xmagbphi0, xmagbr0, xmageta0, &
1154 0 : xmagkr2n, xmagq1, xmagwa1, xmags1a, xmags1b, xmags1, &
1155 0 : xmagbphi1, xmagbr1, xmageta1a, xmageta1b, xmageta1, &
1156 0 : xmagsm, xmagqm, xmagetam, xmagsf, xmags, xmagnu, xmagdif
1157 :
1158 : include 'formats'
1159 :
1160 0 : ierr = 0
1161 0 : nz = s% nz
1162 :
1163 0 : s% D_ST(1:nz) = 0
1164 0 : s% nu_ST(1:nz) = 0
1165 0 : s% dynamo_B_r(1:nz) = 0
1166 0 : s% dynamo_B_phi(1:nz) = 0
1167 :
1168 0 : xmagfmu = 1
1169 0 : xmagft = 1
1170 0 : xmagfdif = 1
1171 0 : xmagfnu = 1
1172 :
1173 0 : xmageta0 = 0; xmageta1 = 0; xmagetam = 0
1174 0 : xmagq0 = 0; xmagq1 = 0; xmagqm = 0
1175 0 : xmags0 = 0; xmags1 = 0; xmagsm = 0;
1176 :
1177 0 : do k = 2, nz-1
1178 :
1179 : xkap = 16d0*boltz_sigma*T(k)*T(k)*T(k)/ &
1180 0 : (3d0*opacity(k)*rho(k)*rho(k)*Cp(k)) ! thermal diffusivity
1181 :
1182 0 : xsig = calc_sige(abar(k), zbar(k), rho(k), T(k), Cp(k), kap_cond(k), opacity(k))
1183 0 : xeta = calc_eta(xsig) ! magnetic diffusivity
1184 :
1185 0 : xmagn = N2(k)
1186 0 : xmagnmu = N2_mu(k)
1187 0 : xmagnt = xmagn - xmagnmu ! N2_T
1188 0 : xmagw = abs(omega(k))
1189 0 : xmagdn = rho(k)
1190 0 : xmagtn = T(k)
1191 0 : xmagrn = r(k)
1192 0 : xmag4pd = sqrt(pi4*xmagdn)
1193 :
1194 : dlnomega_dlnr = &
1195 0 : (omega(k-1) - omega(k+1))/(r(k-1) - r(k+1))*(r(k)/omega(k))
1196 0 : xmagq = max(1d-30,min(1d30,abs(dlnomega_dlnr))) ! shear
1197 0 : xmager2w = xeta/(r(k)*r(k)*abs(omega(k)))
1198 :
1199 : ! magnetic quantities
1200 0 : if (xmagnmu > 0.0D0) then
1201 0 : xmagnn = xmagnmu*xmagfmu ! N^2
1202 0 : xmagwn = xmagw/sqrt(xmagnn) ! omega/N
1203 0 : xmagq0 = pow(xmagwn,-1.5D0)*pow(xmager2w,0.25D0) ! q0
1204 0 : xmagwa0 = xmagq*xmagwn*xmagw ! omega_A
1205 0 : xmags0 = xmagdn*xmagw*xmagw*xmagrn*xmagrn*pow3(xmagq)*pow4(xmagwn) ! S_0
1206 0 : if (is_bad(xmags0)) then
1207 0 : do kk=1,s% nz
1208 0 : write(*,2) 'omega(kk)', kk, omega(kk)
1209 : end do
1210 0 : write(*,2) 'dlnomega_dlnr', k, dlnomega_dlnr
1211 0 : write(*,2) 'xmagfmu', k, xmagfmu
1212 0 : write(*,2) 'xmagnmu', k, xmagnmu
1213 0 : write(*,2) 'xmagnn', k, xmagnn
1214 0 : write(*,2) 'xmagwn', k, xmagwn
1215 0 : write(*,2) 'xmagq', k, xmagq
1216 0 : write(*,2) 'xmagrn', k, xmagrn
1217 0 : write(*,2) 'xmagw', k, xmagw
1218 0 : write(*,2) 'xmagdn', k, xmagdn
1219 0 : write(*,2) 'xmags0', k, xmags0
1220 0 : call mesa_error(__FILE__,__LINE__,'set_ST')
1221 : end if
1222 0 : xmagbphi0 = xmagwa0*xmag4pd*xmagrn ! B_\phi
1223 0 : xmagbr0 = xmagbphi0*xmagq*xmagwn*xmagwn ! B_r
1224 0 : xmageta0 = pow4(xmagq)*pow6(xmagwn)*xmagrn*xmagrn*xmagw ! eta_e
1225 : end if
1226 :
1227 0 : if (xmagnt > 0.0D0) then
1228 0 : xmagnn = xmagnt*xmagft ! N^2
1229 0 : xmagwn = xmagw/sqrt(xmagnn) ! omega/N
1230 0 : xmagkr2n = xkap/(xmagrn*xmagrn*sqrt(xmagnn)) ! kappa/(r^2 N)
1231 :
1232 : !xmagq1 = pow(xmager2w*xmagwn*pow3(xeta/xkap)/pow7(xmagwn),0.25D0) ! q_1
1233 0 : if(xmagwn > 1d-42) then ! fix from rob
1234 0 : xmagq1 = pow(xmager2w*xmagwn*pow3(xeta/xkap)/pow7(xmagwn),0.25D0) ! q_1
1235 : else
1236 : xmagq1 = 0d0
1237 : end if
1238 :
1239 0 : xmagwa1 = sqrt(xmagq)*xmagw*pow(xmagwn*xmagkr2n,0.125D0) ! \omega_A
1240 0 : xmags1a = xmagdn*pow2(xmagw*xmagrn)*xmagq*sqrt(xmagwn*xmagkr2n) ! S_1a
1241 0 : xmags1b = xmagdn*pow2(xmagw)*pow2(xmagrn)*pow3(xmagq)*pow4(xmagwn) ! S_1b
1242 0 : xmags1 = max(xmags1a,xmags1b) ! S_1
1243 0 : xmagbphi1 = xmagwa1*xmag4pd*xmagrn ! B_\phi
1244 0 : xmagbr1 = xmagbphi1*pow(xmagwn*xmagkr2n,0.25D0) ! B_r
1245 0 : xmageta1a = xmagrn*xmagrn*xmagw*xmagq*pow(xmagwn*xmagkr2n,0.75D0) ! eta_e1a
1246 0 : xmageta1b = pow4(xmagq)*pow6(xmagwn)*pow2(xmagrn)*xmagw ! eta_e1b
1247 0 : xmageta1 = max(xmageta1a,xmageta1b) ! eta_e
1248 : end if
1249 :
1250 0 : if ((xmagnt > 0.D0) .and. (xmagnmu > 0.D0) .and. xmags0+xmags1 /= 0d0) then
1251 0 : xmagsm=xmags0*xmags1/(xmags0+xmags1) ! S_m
1252 0 : if (is_bad(xmagsm)) then
1253 0 : write(*,2) 'xmags0', k, xmags0
1254 0 : write(*,2) 'xmags1', k, xmags1
1255 0 : write(*,2) 'xmags0+xmags1', k, xmags0+xmags1
1256 0 : write(*,2) 'xmags1', k, xmags1
1257 0 : write(*,2) 'xmags0', k, xmags0
1258 0 : write(*,2) 'xmagsm', k, xmagsm
1259 0 : call mesa_error(__FILE__,__LINE__,'set_ST')
1260 : end if
1261 0 : xmagqm=xmagq0+xmagq1 ! q_m
1262 0 : xmagetam=xmageta0*xmageta1/(xmageta0+xmageta1) ! eta_m
1263 0 : else if ((xmagnt <= 0.D0) .and. (xmagnmu > 0.D0)) then
1264 0 : xmagsm=xmags0
1265 0 : xmagqm=xmagq0
1266 0 : xmagetam=xmageta0
1267 0 : else if ((xmagnt > 0.D0) .and. (xmagnmu <= 0.D0)) then
1268 0 : xmagsm=xmags1
1269 0 : xmagqm=xmagq1
1270 0 : xmagetam=xmageta1
1271 0 : else if ((xmagnt <= 0.D0) .and. (xmagnmu <= 0.D0)) then
1272 0 : xmagsm=0.0D0
1273 0 : xmagqm=0.0D0
1274 0 : xmagetam=0.0D0
1275 : end if
1276 :
1277 0 : if (xmagn < 0.0D0) then
1278 0 : xmagsm=0.0D0
1279 0 : xmagqm=0.0D0
1280 0 : xmagetam=0.0D0
1281 : end if
1282 :
1283 0 : if (s% mixing_type(k) == convective_mixing .and. (xmagn > 0.D0)) then
1284 0 : xmagsm=0.0D0
1285 0 : xmagqm=0.0D0
1286 0 : xmagetam=0.0D0
1287 : end if
1288 :
1289 0 : if (s% mixing_type(k) == overshoot_mixing) then
1290 0 : xmagsm=0.0D0
1291 0 : xmagqm=0.0D0
1292 0 : xmagetam=0.0D0
1293 : end if
1294 :
1295 0 : xmagsf=1.D0-MIN(1.D0,xmagqm/xmagq)
1296 0 : xmags=xmagsf*xmagsm ! S
1297 0 : xmagnu=xmags/(xmagw*xmagq*xmagdn) ! \nu_e
1298 0 : xmagdif=xmagsf*xmagetam ! \kappa_c (molecular diffusion)
1299 : ! (set equal to eta_e and compute "mean")
1300 :
1301 : !..... Special treatment for semiconvective regions:
1302 : !..... Geometric mean between semiconvective "effective viscosity"
1303 : !..... and \nu_e as resulting from \mu-dominated case
1304 : !..... (the T-dominated case is indefined in these regions).
1305 : !..... Assume flux is dominated by convective flux and given by
1306 : !..... the luminosity of the star at this point.
1307 : !..... From Kippenhahn&Weigert, Eqs. (7.6) and (7.7), the convective
1308 : !..... velocity can be computed. Now assume \nu=1/3 l_mix v and assume
1309 : !..... that l_mix = H_p.
1310 0 : if ((xmagnt <= 0.D0) .AND. (xmagnmu > 0.D0) .AND. (xmagn > 0.D0)) &
1311 : xmagnu = &
1312 : sqrt(xmagnu*scale_height(k)*(one_third)* &
1313 : pow(grav(k)*delta(k)*scale_height(k)*MAX(0.D0,L(k))/ &
1314 0 : (64.D0*pi*xmagdn*Cp(k)*xmagtn*xmagrn*xmagrn),one_third))
1315 :
1316 0 : s% D_ST(k) = min(xmagdif,xmagnu)*xmagfdif
1317 0 : s% nu_ST(k) = xmagnu*xmagfnu
1318 :
1319 0 : if (is_bad(s% D_ST(k))) then
1320 0 : write(*,4) 'set_ST mixing_type', k, s% model_number, s% mixing_type(k)
1321 0 : write(*,3) 'set_ST xeta', k, s% model_number, xeta
1322 0 : write(*,3) 'set_ST xsig', k, s% model_number, xsig
1323 0 : write(*,3) 'set_ST dlnomega_dlnr', k, s% model_number, dlnomega_dlnr
1324 0 : write(*,3) 'set_ST xmager2w', k, s% model_number, xmager2w
1325 0 : write(*,3) 'set_ST xkap', k, s% model_number, xkap
1326 0 : write(*,3) 'set_ST xgamma', k, s% model_number, xgamma
1327 0 : write(*,3) 'set_ST xmagq', k, s% model_number, xmagq
1328 0 : write(*,3) 'set_ST xmagqm', k, s% model_number, xmagqm
1329 0 : write(*,3) 'set_ST xmagsf', k, s% model_number, xmagsf
1330 0 : write(*,3) 'set_ST xmagsm', k, s% model_number, xmagsm
1331 0 : write(*,3) 'set_ST xmags', k, s% model_number, xmags
1332 0 : write(*,3) 'set_ST xmagnu', k, s% model_number, xmagnu
1333 0 : write(*,3) 'set_ST xmagfdif', k, s% model_number, xmagfdif
1334 0 : write(*,3) 'set_ST D_ST(k)', k, s% model_number, s% D_ST(k)
1335 0 : call mesa_error(__FILE__,__LINE__,'set_ST')
1336 : end if
1337 :
1338 : end do
1339 :
1340 0 : s% D_ST(1) = s% D_ST(2)
1341 0 : s% D_ST(nz) = s% D_ST(nz-1)
1342 :
1343 0 : s% nu_ST(1) = s% nu_ST(2)
1344 0 : s% nu_ST(nz) = s% nu_ST(nz-1)
1345 :
1346 0 : end subroutine set_ST
1347 :
1348 :
1349 0 : subroutine zero_if_convective(nz, mixing_type, D_mix, dc)
1350 : integer, intent(in) :: nz
1351 : integer, dimension(:) :: mixing_type
1352 : real(dp), dimension(:) :: D_mix, dc
1353 : integer :: k
1354 0 : do k=1,nz
1355 0 : if (mixing_type(k) == convective_mixing) dc(k) = 0
1356 : end do
1357 0 : end subroutine zero_if_convective
1358 :
1359 :
1360 0 : subroutine zero_if_tiny(s, dc)
1361 : type (star_info), pointer :: s
1362 : real(dp), dimension(:) :: dc
1363 : integer :: k
1364 0 : real(dp) :: tiny
1365 0 : tiny = s% clip_D_limit
1366 0 : do k=1,s% nz
1367 0 : if (dc(k) < tiny) dc(k) = 0
1368 : end do
1369 0 : end subroutine zero_if_tiny
1370 :
1371 : end module rotation_mix_info
|