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 star_utils
21 :
22 : use star_private_def
23 : use const_def, only: dp, i8, pi, pi4, ln10, clight, crad, msun, rsun, lsun, one_third, four_thirds_pi
24 : use num_lib
25 : use utils_lib
26 : use auto_diff_support
27 :
28 : implicit none
29 :
30 : private
31 : public :: eval_min_cell_collapse_time
32 : public :: min_dr_div_cs
33 : public :: get_XYZ
34 : public :: lookup_nameofvar
35 : public :: start_time
36 : public :: update_time
37 : public :: foreach_cell
38 : public :: write_eos_call_info
39 : public :: eval_csound
40 : public :: eval_current_abundance
41 : public :: eval_current_z
42 : public :: eval_ledd
43 : public :: normalize_dqs
44 : public :: set_qs
45 : public :: set_m_and_dm
46 : public :: set_dm_bar
47 : public :: set_rmid
48 : public :: get_r_from_xh
49 : public :: get_r_and_lnr_from_xh
50 : public :: get_t_and_lnt_from_xh
51 : public :: get_lnt_from_xh
52 : public :: get_lnr_from_xh
53 : public :: get_rho_and_lnd_from_xh
54 : public :: store_t_in_xh
55 : public :: store_r_in_xh
56 : public :: store_rho_in_xh
57 : public :: store_lnd_in_xh
58 : public :: store_lnt_in_xh
59 : public :: cell_specific_ke
60 : public :: cell_specific_pe
61 : public :: get_phot_info
62 : public :: init_random
63 : public :: rand
64 : public :: interp_val_to_pt
65 : public :: get_log_concentration
66 : public :: get_lconv
67 : public :: get_ladv
68 : public :: get_lrad_div_ledd
69 : public :: get_lrad
70 : public :: get_ledd
71 : public :: tau_eff
72 : public :: get_rho_face_val
73 : public :: omega_crit
74 : public :: eval_cell_section_total_energy
75 : public :: conv_time_scale
76 : public :: qhse_time_scale
77 : public :: eps_nuc_time_scale
78 : public :: cooling_time_scale
79 : public :: get_face_values
80 : public :: threshold_smoothing
81 : public :: save_eqn_residual_info
82 : public :: calc_ptrb_ad_tw
83 : public :: set_energy_eqn_scal
84 : public :: get_scale_height_face_val
85 : public :: weighted_smoothing
86 : public :: get_kap_face
87 : public :: get_rho_face
88 : public :: get_rho_start_face
89 : public :: get_chirho_face
90 : public :: get_chit_face
91 : public :: get_t_face
92 : public :: get_Peos_face
93 : public :: get_Peos_face_val
94 : public :: get_cp_face
95 : public :: get_grada_face
96 : public :: get_gradr_face
97 : public :: get_scale_height_face
98 : public :: get_tau
99 : public :: after_c_burn
100 : public :: get_shock_info
101 : public :: reset_starting_vectors
102 : public :: eval_irradiation_heat
103 : public :: set_phot_info
104 : public :: set_m_grav_and_grav
105 : public :: set_scale_height
106 : public :: set_abs_du_div_cs
107 : public :: set_conv_time_scales
108 : public :: set_rv_info
109 : public :: smooth
110 : public :: safe_div_val
111 : public :: center_avg_x
112 : public :: surface_avg_x
113 : public :: get_remnant_mass
114 : public :: get_ejecta_mass
115 : public :: get_phi_joss
116 : public :: center_value
117 : public :: eval_kh_timescale
118 : public :: k_for_q
119 : public :: total_angular_momentum
120 : public :: reset_epsnuc_vectors
121 : public :: yrs_for_init_timestep
122 : public :: set_phase_of_evolution
123 : public :: get_string_for_model_number
124 : public :: e00
125 : public :: em1
126 : public :: ep1
127 : public :: store_partials
128 : public :: save_eqn_dxa_partials
129 : public :: unpack_residual_partials
130 : public :: get_area_info_opt_time_center
131 : public :: calc_ptot_ad_tw
132 : public :: get_face_weights
133 : public :: get_dke_dt_dpe_dt
134 : public :: get_pvsc_ad
135 : public :: show_matrix
136 : public :: no_extra_profile_columns
137 : public :: no_data_for_extra_profile_columns
138 : public :: total_times
139 : public :: current_min_xa_hard_limit
140 : public :: current_sum_xa_hard_limit
141 : public :: lookup_nameofequ
142 : public :: eval_total_energy_integrals
143 : public :: set_luminosity_by_category
144 : public :: eval_deltam_total_energy_integrals
145 : public :: report_xa_bad_nums
146 : public :: eval_current_y
147 : public :: get_name_for_restart_file
148 : public :: eval_integrated_total_energy_profile
149 : public :: use_xh_to_set_rho_to_dm_div_dv
150 : public :: cell_specific_total_energy
151 : public :: store_lnr_in_xh
152 : public :: interp_q
153 : public :: set_zero_alpha_rti
154 : public :: after_he_burn
155 : public :: interp_xa_to_pt
156 : public :: set_xqs
157 : public :: get_tau_at_r
158 : public :: smooth_abundances
159 : public :: do_boxcar_mixing
160 : public :: eval_total_energy_profile
161 : public :: get_delta_pg_traditional
162 : public :: get_delta_pg_bildsten2012
163 : public :: write_to_extra_terminal_output_file
164 :
165 : logical, parameter :: mdb = .false.
166 :
167 : contains
168 :
169 66 : subroutine foreach_cell(s,nzlo,nzhi,use_omp,do1,ierr)
170 : type (star_info), pointer :: s
171 : integer, intent(in) :: nzlo, nzhi
172 : logical, intent(in) :: use_omp
173 : interface
174 : subroutine do1(s,k,ierr)
175 : use star_private_def
176 : implicit none
177 : type (star_info), pointer :: s
178 : integer, intent(in) :: k
179 : integer, intent(out) :: ierr
180 : end subroutine do1
181 : end interface
182 : integer, intent(out) :: ierr
183 :
184 : integer :: k, op_err
185 : logical :: okay
186 66 : ierr = 0
187 :
188 66 : if (nzlo == nzhi) then
189 0 : call do1(s,nzlo,ierr)
190 0 : return
191 : end if
192 :
193 66 : if (use_omp) then
194 66 : okay = .true.
195 66 : !$OMP PARALLEL DO PRIVATE(k,op_err) SCHEDULE(dynamic,2)
196 : do k = nzlo, nzhi
197 : if (.not. okay) cycle
198 : op_err = 0
199 : call do1(s,k,op_err)
200 : if (op_err /= 0) okay = .false. ! cannot just exit from a parallel loop
201 : end do
202 : !$OMP END PARALLEL DO
203 66 : if (.not. okay) ierr = -1
204 : else
205 0 : do k = nzlo, nzhi
206 0 : call do1(s,k,ierr)
207 0 : if (ierr /= 0) exit
208 : end do
209 : end if
210 :
211 : end subroutine foreach_cell
212 :
213 :
214 0 : subroutine get_average_Y_and_Z(s, nzlo, nzhi, y_avg, z_avg, ierr)
215 : use chem_def
216 : type (star_info), pointer :: s
217 : integer, intent(in) :: nzlo, nzhi
218 : real(dp), intent(out) :: y_avg, z_avg
219 : integer, intent(out) :: ierr
220 : integer :: k, nz, h1, h2, he3, he4
221 0 : real(dp) :: total_mass_h, total_mass_he, total_mass_z, cell_mass, total_mass
222 0 : ierr = 0
223 0 : nz = s% nz
224 0 : h1 = s% net_iso(ih1)
225 0 : h2 = s% net_iso(ih2)
226 0 : he3 = s% net_iso(ihe3)
227 0 : he4 = s% net_iso(ihe4)
228 0 : total_mass=0; total_mass_h=0; total_mass_he=0; total_mass_z=0
229 0 : do k=nzlo, nzhi
230 0 : cell_mass = s% dm(k)
231 0 : total_mass = total_mass + cell_mass
232 0 : total_mass_h = total_mass_h + cell_mass*s% xa(h1, k)
233 0 : if (h2 /= 0) total_mass_h = total_mass_h + cell_mass*s% xa(h2, k)
234 0 : total_mass_he = total_mass_he + cell_mass*s% xa(he4, k)
235 0 : if (he3 /= 0) total_mass_he = total_mass_he + cell_mass*s% xa(he3, k)
236 : end do
237 0 : total_mass_z = total_mass - (total_mass_h + total_mass_he)
238 0 : z_avg = total_mass_z / total_mass
239 0 : y_avg = total_mass_he / total_mass
240 0 : end subroutine get_average_Y_and_Z
241 :
242 :
243 0 : real(dp) function eval_current_y(s, nzlo, nzhi, ierr)
244 : type (star_info), pointer :: s
245 : integer, intent(in) :: nzlo, nzhi
246 : integer, intent(out) :: ierr
247 : real(dp) :: y_avg, z_avg
248 0 : call get_average_Y_and_Z(s, nzlo, nzhi, y_avg, z_avg, ierr)
249 0 : eval_current_y = y_avg
250 0 : end function eval_current_y
251 :
252 :
253 0 : real(dp) function eval_current_z(s, nzlo, nzhi, ierr)
254 : type (star_info), pointer :: s
255 : integer, intent(in) :: nzlo, nzhi
256 : integer, intent(out) :: ierr
257 : real(dp) :: y_avg, z_avg
258 0 : call get_average_Y_and_Z(s, nzlo, nzhi, y_avg, z_avg, ierr)
259 0 : eval_current_z = z_avg
260 0 : end function eval_current_z
261 :
262 :
263 11 : real(dp) function eval_current_abundance(s, j, nzlo, nzhi, ierr)
264 : type (star_info), pointer :: s
265 : integer, intent(in) :: j, nzlo, nzhi
266 : integer, intent(out) :: ierr
267 : integer :: k, nz
268 11 : real(dp) :: cell_mass, jmass, total_mass
269 :
270 11 : ierr = 0
271 :
272 11 : if (j == 0) then
273 11 : eval_current_abundance = 0
274 : return
275 : end if
276 :
277 11 : nz = s% nz
278 11 : total_mass=0; jmass=0
279 22 : do k=nzlo, nzhi
280 11 : cell_mass = s% dm(k)
281 11 : total_mass = total_mass + cell_mass
282 22 : jmass = jmass + cell_mass*s% xa(j, k)
283 : end do
284 11 : eval_current_abundance = jmass / total_mass
285 :
286 11 : end function eval_current_abundance
287 :
288 :
289 0 : subroutine smooth_abundances(s, cnt, nzlo, nzhi, ierr)
290 : type (star_info), pointer :: s
291 : integer, intent(in) :: cnt ! make this many passes
292 : integer, intent(in) :: nzlo, nzhi ! only smooth zones nzlo to nzhi inclusive
293 : integer, intent(out) :: ierr
294 : integer :: k, j, nz
295 0 : ierr = 0
296 0 : nz = s% nz
297 0 : do j = 1, cnt
298 0 : do k = max(nzlo,2), min(nzhi, nz)
299 0 : s% xa(:,k) = (s% xa(:,k-1) + s% xa(:,k) + s% xa(:,k+1))/3
300 : end do
301 0 : if (nzhi == nz) s% xa(:,nz) = (s% xa(:,nz-1) + s% xa(:,nz) + s% xa(:,nz))/3
302 0 : if (nzlo == 1) s% xa(:,1) = (s% xa(:,2) + s% xa(:,1) + s% xa(:,1))/3
303 : end do
304 0 : s% need_to_setvars = .true.
305 0 : end subroutine smooth_abundances
306 :
307 :
308 0 : integer function k_for_q(s, q)
309 : ! return k s.t. q(k) >= q > q(k)-dq(k)
310 : type (star_info), pointer :: s
311 : real(dp), intent(in) :: q
312 : integer :: k, nz
313 0 : nz = s% nz
314 0 : if (q >= 1) then
315 0 : k_for_q = 1; return
316 0 : else if (q <= s% q(nz)) then
317 0 : k_for_q = nz; return
318 : end if
319 0 : do k = 1, nz-1
320 0 : if (q > s% q(k+1)) then
321 0 : k_for_q = k; return
322 : end if
323 : end do
324 0 : k_for_q = nz
325 : end function k_for_q
326 :
327 :
328 1 : subroutine get_name_for_restart_file(n, num_digits, num)
329 : integer, intent(in) :: n, num_digits
330 : character (len=*), intent(out) :: num
331 1 : call get_string_for_model_number('x', n, num_digits, num)
332 1 : end subroutine get_name_for_restart_file
333 :
334 :
335 1 : subroutine get_string_for_model_number(prefix, n, num_digits, num)
336 : character (len=*), intent(in) :: prefix
337 : integer, intent(in) :: n, num_digits
338 : character (len=*), intent(out) :: num
339 : integer :: val
340 : character (len=32) :: fstring
341 : include 'formats'
342 1 : val = mod(n, 10**num_digits) ! wrap around
343 1 : if (val == 0) then
344 0 : write(num,*) n
345 0 : num = adjustl(num)
346 0 : return
347 : end if
348 1 : write(fstring,'( "(a,i",i2.2,".",i2.2,")" )') num_digits, num_digits
349 1 : write(num,fstring) trim(prefix), val
350 1 : end subroutine get_string_for_model_number
351 :
352 :
353 0 : subroutine report_xa_bad_nums(s,ierr)
354 : type (star_info), pointer :: s
355 : integer, intent(out) :: ierr
356 : integer :: k, j
357 0 : ierr = 0
358 0 : do k=1,s% nz
359 0 : do j=1,s% species
360 0 : if (is_bad(s% xa(j,k))) then
361 0 : ierr = -1
362 0 : write(*,*) j, k, s% xa(j,k)
363 : end if
364 : end do
365 : end do
366 0 : end subroutine report_xa_bad_nums
367 :
368 :
369 79998 : real(dp) function eval_csound(s,k,ierr) result(cs)
370 : type (star_info), pointer :: s
371 : integer, intent(in) :: k
372 : integer, intent(out) :: ierr
373 79998 : real(dp) :: cs2
374 : include 'formats'
375 79998 : ierr = 0
376 79998 : cs2 = s% gamma1(k)*s% Peos(k)/s% rho(k)
377 79998 : if (cs2 < 0d0) then
378 0 : cs = 0d0
379 0 : ierr = -1
380 0 : return
381 : end if
382 79998 : cs = sqrt(cs2)
383 79998 : end function eval_csound
384 :
385 :
386 55 : subroutine set_m_grav_and_grav(s) ! using mass_corrections
387 : type (star_info), pointer :: s
388 55 : real(dp) :: r, lnR
389 : integer :: k, nz
390 : include 'formats'
391 55 : nz = s% nz
392 55 : if (.not. s% use_mass_corrections) then
393 66962 : do k=1,nz
394 66962 : s% m_grav(k) = s% m(k)
395 : end do
396 : else
397 : s% m_grav(nz) = &
398 0 : s% M_center + s% dm(nz)*s% mass_correction(nz)
399 0 : do k=nz-1,1,-1
400 : s% m_grav(k) = &
401 0 : s% m_grav(k+1) + s% dm(k)*s% mass_correction(k)
402 : end do
403 : end if
404 66962 : do k=1,nz
405 : ! We need to call set_m_grav_and_grav during model loading before we have set all vars
406 66907 : call get_r_and_lnR_from_xh(s, k, r, lnR)
407 66962 : s% grav(k) = s% cgrav(k)*s% m_grav(k)/(r*r)
408 : end do
409 55 : end subroutine set_m_grav_and_grav
410 :
411 :
412 66907 : subroutine get_r_and_lnR_from_xh(s, k, r, lnR, xh_in)
413 : type (star_info), pointer :: s
414 : integer, intent(in) :: k
415 : real(dp), intent(out) :: r, lnR
416 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
417 66907 : real(dp), pointer :: xh(:,:)
418 66907 : if (present(xh_in)) then
419 0 : xh => xh_in
420 : else
421 66907 : xh => s% xh
422 : end if
423 66907 : lnR = xh(s% i_lnR,k)
424 66907 : r = exp(lnR)
425 66907 : end subroutine get_r_and_lnR_from_xh
426 :
427 :
428 14559 : real(dp) function get_r_from_xh(s, k, xh_in) result(r)
429 : type (star_info), pointer :: s
430 : integer, intent(in) :: k
431 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
432 14559 : real(dp), pointer :: xh(:,:)
433 14559 : if (present(xh_in)) then
434 0 : xh => xh_in
435 : else
436 14559 : xh => s% xh
437 : end if
438 14559 : r = exp(xh(s% i_lnR,k))
439 14559 : end function get_r_from_xh
440 :
441 :
442 0 : real(dp) function get_lnR_from_xh(s, k, xh_in) result(lnR)
443 : type (star_info), pointer :: s
444 : integer, intent(in) :: k
445 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
446 0 : real(dp), pointer :: xh(:,:)
447 0 : if (present(xh_in)) then
448 0 : xh => xh_in
449 : else
450 0 : xh => s% xh
451 : end if
452 0 : lnR = xh(s% i_lnR,k)
453 0 : end function get_lnR_from_xh
454 :
455 1428 : subroutine store_r_in_xh(s, k, r, xh_in)
456 : type (star_info), pointer :: s
457 : integer, intent(in) :: k
458 : real(dp), intent(in) :: r
459 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
460 1428 : real(dp), pointer :: xh(:,:)
461 1428 : if (present(xh_in)) then
462 1428 : xh => xh_in
463 : else
464 0 : xh => s% xh
465 : end if
466 1428 : xh(s% i_lnR,k) = log(r)
467 1428 : end subroutine store_r_in_xh
468 :
469 :
470 0 : subroutine store_lnR_in_xh(s, k, lnR, xh_in)
471 : type (star_info), pointer :: s
472 : integer, intent(in) :: k
473 : real(dp), intent(in) :: lnR
474 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
475 0 : real(dp), pointer :: xh(:,:)
476 0 : if (present(xh_in)) then
477 0 : xh => xh_in
478 : else
479 0 : xh => s% xh
480 : end if
481 0 : xh(s% i_lnR,k) = lnR
482 0 : end subroutine store_lnR_in_xh
483 :
484 :
485 0 : subroutine get_T_and_lnT_from_xh(s, k, T, lnT, xh_in)
486 : type (star_info), pointer :: s
487 : integer, intent(in) :: k
488 : real(dp), intent(out) :: T, lnT
489 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
490 0 : real(dp), pointer :: xh(:,:)
491 0 : if (present(xh_in)) then
492 0 : xh => xh_in
493 : else
494 0 : xh => s% xh
495 : end if
496 0 : lnT = xh(s% i_lnT,k)
497 0 : T = exp(lnT)
498 0 : end subroutine get_T_and_lnT_from_xh
499 :
500 :
501 : real(dp) function get_T_from_xh(s, k, xh_in) result(T)
502 : type (star_info), pointer :: s
503 : integer, intent(in) :: k
504 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
505 : real(dp), pointer :: xh(:,:)
506 : if (present(xh_in)) then
507 : xh => xh_in
508 : else
509 : xh => s% xh
510 : end if
511 : T = exp(xh(s% i_lnT,k))
512 : end function get_T_from_xh
513 :
514 :
515 0 : real(dp) function get_lnT_from_xh(s, k, xh_in) result(lnT)
516 : type (star_info), pointer :: s
517 : integer, intent(in) :: k
518 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
519 0 : real(dp), pointer :: xh(:,:)
520 0 : if (present(xh_in)) then
521 0 : xh => xh_in
522 : else
523 0 : xh => s% xh
524 : end if
525 0 : lnT = xh(s% i_lnT,k)
526 0 : end function get_lnT_from_xh
527 :
528 :
529 0 : subroutine store_T_in_xh(s, k, T, xh_in)
530 : type (star_info), pointer :: s
531 : integer, intent(in) :: k
532 : real(dp), intent(in) :: T
533 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
534 0 : real(dp), pointer :: xh(:,:)
535 0 : if (present(xh_in)) then
536 0 : xh => xh_in
537 : else
538 0 : xh => s% xh
539 : end if
540 0 : xh(s% i_lnT,k) = log(T)
541 0 : end subroutine store_T_in_xh
542 :
543 :
544 1472 : subroutine store_lnT_in_xh(s, k, lnT, xh_in)
545 : type (star_info), pointer :: s
546 : integer, intent(in) :: k
547 : real(dp), intent(in) :: lnT
548 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
549 1472 : real(dp), pointer :: xh(:,:)
550 1472 : if (present(xh_in)) then
551 1472 : xh => xh_in
552 : else
553 0 : xh => s% xh
554 : end if
555 1472 : xh(s% i_lnT,k) = lnT
556 1472 : end subroutine store_lnT_in_xh
557 :
558 :
559 0 : subroutine get_rho_and_lnd_from_xh(s, k, rho, lnd, xh_in)
560 : type (star_info), pointer :: s
561 : integer, intent(in) :: k
562 : real(dp), intent(out) :: rho, lnd
563 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
564 0 : real(dp), pointer :: xh(:,:)
565 0 : if (present(xh_in)) then
566 0 : xh => xh_in
567 : else
568 0 : xh => s% xh
569 : end if
570 0 : lnd = xh(s% i_lnd,k)
571 0 : rho = exp(lnd)
572 0 : end subroutine get_rho_and_lnd_from_xh
573 :
574 :
575 17509 : subroutine store_rho_in_xh(s, k, rho, xh_in)
576 : type (star_info), pointer :: s
577 : integer, intent(in) :: k
578 : real(dp), intent(in) :: rho
579 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
580 17509 : real(dp), pointer :: xh(:,:)
581 17509 : if (present(xh_in)) then
582 2950 : xh => xh_in
583 : else
584 14559 : xh => s% xh
585 : end if
586 17509 : xh(s% i_lnd,k) = log(rho)
587 17509 : end subroutine store_rho_in_xh
588 :
589 :
590 493 : subroutine store_lnd_in_xh(s, k, lnd, xh_in)
591 : type (star_info), pointer :: s
592 : integer, intent(in) :: k
593 : real(dp), intent(in) :: lnd
594 : real(dp), intent(in), pointer, optional :: xh_in(:,:)
595 493 : real(dp), pointer :: xh(:,:)
596 493 : if (present(xh_in)) then
597 493 : xh => xh_in
598 : else
599 0 : xh => s% xh
600 : end if
601 493 : xh(s% i_lnd,k) = lnd
602 493 : end subroutine store_lnd_in_xh
603 :
604 :
605 11 : subroutine use_xh_to_set_rho_to_dm_div_dV(s, ierr)
606 : type (star_info), pointer :: s
607 : integer, intent(out) :: ierr
608 : integer :: k, nz, i_lnR, i_lnd
609 11 : real(dp) :: rL, rR, dm, dV, rho
610 : include 'formats'
611 11 : ierr = 0
612 11 : i_lnR = s% i_lnR
613 11 : i_lnd = s% i_lnd
614 11 : if (i_lnd == 0 .or. i_lnR == 0) return
615 11 : nz = s% nz
616 11 : rR = s% R_center
617 14570 : do k = nz, 1, -1
618 14559 : rL = rR
619 14559 : rR = get_r_from_xh(s,k)
620 14559 : dm = s% dm(k)
621 14559 : dV = four_thirds_pi*(rR*rR*rR - rL*rL*rL)
622 14559 : rho = dm/dV
623 14559 : if (rho <= 0d0) then
624 0 : write(*,3) 'set_rho_to_dm_div_dV: rho <= 0', &
625 0 : k, nz, rho, dm, dV, rR, rL
626 0 : ierr = -1
627 0 : return
628 : end if
629 14570 : call store_rho_in_xh(s, k, rho)
630 : end do
631 : end subroutine use_xh_to_set_rho_to_dm_div_dV
632 :
633 :
634 66 : subroutine set_m_and_dm(s)
635 : type (star_info), pointer :: s
636 : integer :: k
637 : include 'formats'
638 81532 : do k = 1, s% nz
639 81466 : s% m(k) = s% M_center + s% q(k)*s% xmstar
640 81466 : s% dm(k) = s% dq(k)*s% xmstar
641 81532 : if (s% dm(k) <= 0d0 .or. is_bad(s% m(k) + s% dm(k))) then
642 0 : write(*,2) 'dm m dq q M_center', k, &
643 0 : s% dm(k), s% m(k), s% dq(k), s% q(k), s% M_center
644 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'set_m_and_dm')
645 : end if
646 : end do
647 66 : end subroutine set_m_and_dm
648 :
649 :
650 66 : subroutine set_dm_bar(s, nz, dm, dm_bar)
651 : type (star_info), pointer :: s
652 : integer, intent(in) :: nz
653 : real(dp), intent(in) :: dm(:) ! (nz)
654 : real(dp), intent(inout) :: dm_bar(:) ! (nz)
655 : integer :: k
656 81400 : do k=2,nz-1
657 81400 : dm_bar(k) = 0.5d0*(dm(k-1) + dm(k))
658 : end do
659 66 : dm_bar(1) = 0.5d0*dm(1)
660 66 : if (s% rsp_flag .or. s% RSP2_flag) then ! rsp and RSP2 use this definition
661 0 : dm_bar(nz) = 0.5d0*(dm(nz-1) + dm(nz))
662 : else
663 66 : dm_bar(nz) = 0.5d0*dm(nz-1) + dm(nz)
664 : end if
665 66 : end subroutine set_dm_bar
666 :
667 :
668 0 : subroutine normalize_dqs(s, nz, dq, ierr)
669 : ! rescale dq's so that add to 1.000
670 : ! work in from boundaries to meet at largest dq
671 : type (star_info), pointer :: s
672 : integer, intent(in) :: nz
673 : real(dp), intent(inout) :: dq(:) ! (nz)
674 : integer, intent(out) :: ierr
675 : integer :: k, midq
676 0 : real(dp) :: dqsum1, dqsum2, dq_min
677 : include 'formats'
678 0 : k = minloc(dq(1:nz),dim=1)
679 0 : dq_min = dq(k)
680 0 : if (dq_min <= 0d0) then
681 0 : write(*,2) 'bad dq', k, dq(k)
682 0 : ierr = -1
683 0 : stop
684 0 : return
685 : end if
686 0 : midq = maxloc(dq(1:nz),dim=1)
687 : ! surface inward
688 0 : dqsum1 = 0
689 0 : do k=1, midq
690 0 : dqsum1 = dqsum1 + dq(k)
691 0 : if (dq(k) <= 0) then
692 0 : ierr = -1
693 0 : return
694 : end if
695 : end do
696 : ! center outward
697 0 : dqsum2 = 0
698 0 : do k=nz, midq+1, -1
699 0 : dqsum2 = dqsum2 + dq(k)
700 0 : if (dq(k) <= 0) then
701 0 : ierr = -1
702 0 : return
703 : end if
704 : end do
705 0 : do k=1,nz
706 0 : dq(k) = dq(k)/(dqsum1 + dqsum2)
707 : end do
708 : end subroutine normalize_dqs
709 :
710 :
711 68 : subroutine set_qs(s, nz, q, dq, ierr) ! set q's using normalized dq's
712 : type (star_info), pointer :: s
713 : integer, intent(in) :: nz
714 : real(dp), intent(inout) :: dq(:) ! (nz)
715 : real(dp), intent(inout) :: q(:) ! (nz)
716 : integer, intent(out) :: ierr
717 : integer :: k, midq
718 68 : real(dp) :: dqsum1, dqsum2
719 : logical :: okay
720 : include 'formats'
721 68 : ierr = 0
722 : ! normalize_dqs destroys bit-for-bit read as inverse of write for models.
723 : ! ok for create pre ms etc., but not for read model
724 68 : if (s% do_normalize_dqs_as_part_of_set_qs) then
725 0 : call normalize_dqs(s, nz, dq, ierr)
726 0 : if (ierr /= 0) return
727 : end if
728 68 : q(1) = 1d0
729 68 : okay = .true.
730 86396 : do k=2,nz
731 86328 : q(k) = q(k-1) - dq(k-1)
732 86396 : if (q(k) < 0d0 .or. q(k) > 1d0) then
733 : okay = .false.
734 : exit
735 : end if
736 : end do
737 68 : if (okay) return
738 0 : midq = maxloc(dq(1:nz),dim=1)
739 : ! surface inward
740 0 : dqsum1 = 0
741 0 : do k=1, midq
742 0 : q(k) = 1d0 - dqsum1
743 0 : dqsum1 = dqsum1 + dq(k)
744 : end do
745 : ! center outward
746 : dqsum2 = 0
747 0 : do k=nz, midq+1, -1
748 0 : dqsum2 = dqsum2 + dq(k)
749 0 : q(k) = dqsum2
750 : end do
751 : end subroutine set_qs
752 :
753 :
754 20 : subroutine set_xqs(nz, xq, dq, ierr) ! set xq's using dq's
755 : integer, intent(in) :: nz
756 : real(dp), intent(inout) :: dq(:) ! (nz)
757 : real(dp), intent(inout) :: xq(:) ! (nz)
758 : integer, intent(out) :: ierr
759 : integer :: k
760 : include 'formats'
761 20 : ierr = 0
762 20 : xq(1) = 0
763 22698 : do k=2,nz-1
764 22698 : xq(k) = xq(k-1) + dq(k-1)
765 : end do
766 20 : xq(nz) = 1 - dq(nz)
767 20 : if (xq(nz) < xq(nz-1)) then
768 0 : xq(nz) = xq(nz-1) + dq(nz-1)
769 0 : dq(nz) = 1 - xq(nz)
770 0 : if (dq(nz) <= 0) then
771 0 : ierr = -1
772 0 : return
773 : end if
774 : end if
775 : end subroutine set_xqs
776 :
777 :
778 0 : real(dp) function interp_val_to_pt(v,k,sz,dq,str)
779 : use interp_1d_lib, only: interp_4_to_1
780 : integer, intent(in) :: k, sz
781 : real(dp), intent(in) :: v(:), dq(:)
782 : character (len=*), intent(in) :: str
783 : integer :: ierr
784 : include 'formats'
785 0 : if (k == 1) then
786 0 : interp_val_to_pt = v(k)
787 0 : return
788 : end if
789 0 : if (k > 2 .and. k < sz) then
790 : ierr = 0
791 : call interp_4_to_1( &
792 : 0.5d0*(dq(k-2)+dq(k-1)), &
793 : 0.5d0*(dq(k-1)+dq(k)), &
794 : 0.5d0*(dq(k)+dq(k+1)), &
795 : 0.5d0*dq(k-2)+dq(k-1), &
796 : v(k-2), v(k-1), v(k), v(k+1), &
797 0 : interp_val_to_pt, str, ierr)
798 0 : if (ierr == 0) return
799 0 : write(*,1) '0.5d0*(dq(k-2)+dq(k-1))', 0.5d0*(dq(k-2)+dq(k-1))
800 0 : write(*,1) '0.5d0*(dq(k-1)+dq(k))', 0.5d0*(dq(k-1)+dq(k))
801 0 : write(*,1) '0.5d0*(dq(k)+dq(k+1))', 0.5d0*(dq(k)+dq(k+1))
802 0 : write(*,2) 'dq(k-2)', k-2, dq(k-2)
803 0 : write(*,2) 'dq(k-1)', k-1, dq(k-1)
804 0 : write(*,2) 'dq(k)', k, dq(k)
805 0 : write(*,2) 'dq(k+1)', k+1, dq(k+1)
806 :
807 0 : call mesa_error(__FILE__,__LINE__,'interp_val_to_pt')
808 : end if
809 0 : interp_val_to_pt = (v(k)*dq(k-1) + v(k-1)*dq(k))/(dq(k-1) + dq(k))
810 0 : end function interp_val_to_pt
811 :
812 :
813 0 : real(dp) function interp_xa_to_pt(xa,j,k,sz,dq,str)
814 0 : use interp_1d_lib, only: interp_4_to_1
815 : real(dp), intent(in) :: xa(:,:), dq(:)
816 : character (len=*), intent(in) :: str
817 : integer, intent(in) :: j, k, sz
818 : integer :: ierr
819 : include 'formats'
820 0 : if (j == 0) then
821 : interp_xa_to_pt = 0
822 : return
823 : end if
824 0 : if (k == 1) then
825 0 : interp_xa_to_pt = xa(j,k)
826 0 : return
827 : end if
828 0 : if (k > 2 .and. k < sz) then
829 : ierr = 0
830 : call interp_4_to_1( &
831 : 0.5d0*(dq(k-2)+dq(k-1)), &
832 : 0.5d0*(dq(k-1)+dq(k)), &
833 : 0.5d0*(dq(k)+dq(k+1)), &
834 : 0.5d0*dq(k-2)+dq(k-1), &
835 : xa(j,k-2), xa(j,k-1), xa(j,k), xa(j,k+1), &
836 0 : interp_xa_to_pt, str, ierr)
837 0 : interp_xa_to_pt = min(1d0,max(0d0,interp_xa_to_pt))
838 0 : if (ierr == 0) return
839 : end if
840 0 : interp_xa_to_pt = (xa(j,k)*dq(k-1) + xa(j,k-1)*dq(k))/(dq(k-1) + dq(k))
841 0 : interp_xa_to_pt = min(1d0,max(0d0,interp_xa_to_pt))
842 0 : end function interp_xa_to_pt
843 :
844 :
845 98 : real(dp) function get_dtau1(s, ierr)
846 : type (star_info), pointer :: s
847 : integer, intent(out) :: ierr
848 : integer :: k
849 98 : real(dp) :: kap
850 : include 'formats'
851 98 : ierr = 0
852 98 : k = 1
853 98 : kap = s% opacity(1)
854 98 : get_dtau1 = s% dm(1)*kap/(pi4*s% rmid(1)*s% rmid(1))
855 98 : if (is_bad(get_dtau1)) then
856 0 : ierr = -1
857 0 : if (.not. s% report_ierr) return
858 : k = 1
859 0 : write(*,2) 'get_dtau1', k, get_dtau1
860 0 : write(*,2) 's% dm(1)', k, s% dm(k)
861 0 : write(*,2) 's% opacity(1)', k, s% opacity(k)
862 0 : write(*,2) 's% rmid(1)', k, s% rmid(k)
863 0 : write(*,2) 's% r(1)', k, s% r(k)
864 0 : write(*,2) 's% r(2)', 2, s% r(2)
865 0 : call mesa_error(__FILE__,__LINE__,'get_dtau1')
866 : end if
867 0 : end function get_dtau1
868 :
869 :
870 77 : subroutine get_tau(s, ierr)
871 : type (star_info), pointer :: s
872 : integer, intent(out) :: ierr
873 : ! tau(k) is optical depth at outer boundary of cell k
874 77 : real(dp) :: dtau, kap, dm_sum, L_sum
875 : integer :: k
876 : logical, parameter :: dbg = .true.
877 : include 'formats'
878 : ierr = 0
879 77 : dtau = get_dtau1(s, ierr)
880 77 : if (ierr /= 0) return
881 77 : s% tau(1) = s% tau_factor*s% tau_base
882 77 : dm_sum = 0
883 77 : L_sum = 0
884 93081 : do k = 2, s% nz
885 93004 : s% tau(k) = s% tau(k-1) + dtau
886 93004 : kap = s% opacity(k)
887 93004 : dtau = s% dm(k)*kap/(pi4*s% rmid(k)*s% rmid(k))
888 93004 : if (is_bad(dtau)) then
889 0 : ierr = -1
890 0 : if (.not. s% report_ierr) return
891 0 : write(*,2) 'dtau', k, dtau
892 0 : write(*,2) 's% dm(k)', k, s% dm(k)
893 0 : write(*,2) 's% opacity(k)', k, s% opacity(k)
894 0 : write(*,2) 's% rmid(k)', k, s% rmid(k)
895 0 : call mesa_error(__FILE__,__LINE__,'get_tau')
896 : end if
897 93081 : if (k == s% nz) s% tau_center = s% tau(k) + dtau
898 : !write(*,*) 'dtau, dlogtau', k, tau(k) - tau(k-1), &
899 : ! log10(tau(k)/tau(k-1))
900 : end do
901 : end subroutine get_tau
902 :
903 :
904 : integer function find_cell_for_mass(s, m)
905 : type (star_info), pointer :: s
906 : real(dp), intent(in) :: m
907 : integer :: k
908 : find_cell_for_mass = s% nz
909 : do k = 1, s% nz-1
910 : if (s% m(k) >= m .and. m > s% m(k+1)) then
911 : find_cell_for_mass = k
912 : return
913 : end if
914 : end do
915 : end function find_cell_for_mass
916 :
917 :
918 33 : subroutine get_delta_Pg_traditional(s, delta_Pg)
919 : type (star_info), pointer :: s
920 : real(dp), intent(out) :: delta_Pg ! seconds
921 : ! g-mode period spacing for l=1
922 33 : real(dp) :: dr, N2, integral, r
923 : integer :: k
924 : logical, parameter :: dbg = .false.
925 : include 'formats'
926 : if (dbg) then
927 : write(*,2) 's% star_mass', s% model_number, s% star_mass
928 : write(*,2) 's% photosphere_r', s% model_number, s% photosphere_r
929 : write(*,2) 's% Teff', s% model_number, s% Teff
930 : end if
931 33 : delta_Pg = 0._dp
932 33 : if (.not. s% calculate_Brunt_N2) return
933 33 : k = 0
934 33 : r = 0._dp
935 33 : N2 = 0._dp
936 33 : dr = 0._dp
937 33 : integral = 0._dp
938 :
939 : ! we integrate at cell edges.
940 40733 : do k = 2, s% nz
941 40700 : N2 = s% brunt_N2(k) ! brunt_N2 at cell_face
942 40700 : r = s% r(k) ! r evaluated at cell_face
943 40700 : dr = s% rmid(k-1) - s% rmid(k) ! dr evaluated at cell face.
944 40733 : if (N2 > 0d0) integral = integral + sqrt(N2)*dr/r
945 : end do
946 :
947 : if (dbg) write(*,2) ' integral ', &
948 : s% model_number,integral
949 :
950 33 : if (integral == 0) return
951 33 : delta_Pg = sqrt(2._dp)*pi*pi/integral
952 33 : if (is_bad(delta_Pg)) delta_Pg = 0._dp
953 :
954 : if (dbg) write(*,2) 'delta_Pg', s% model_number, delta_Pg
955 :
956 : end subroutine get_delta_Pg_traditional
957 :
958 0 : subroutine get_delta_Pg_bildsten2012(s, nu_max, delta_Pg)
959 : type (star_info), pointer :: s
960 : real(dp), intent(in) :: nu_max ! microHz
961 : real(dp), intent(out) :: delta_Pg ! seconds
962 : ! g-mode period spacing for l=1
963 0 : real(dp) :: integral, N2, omega2, kr2, L2, el, &
964 0 : dr, r, r2, cs2, sl2, I_integral, I_integral_limit
965 : integer :: k, k_sl2
966 : logical, parameter :: dbg = .false.
967 : include 'formats'
968 : if (dbg) then
969 : write(*,2) 'nu_max', s% model_number, nu_max
970 : write(*,2) 's% star_mass', s% model_number, s% star_mass
971 : write(*,2) 's% photosphere_r', s% model_number, s% photosphere_r
972 : write(*,2) 's% Teff', s% model_number, s% Teff
973 : end if
974 0 : delta_Pg = 0
975 0 : if (.not. s% calculate_Brunt_N2) return
976 0 : integral = 0
977 0 : I_integral = 0
978 0 : I_integral_limit = 0.5d0
979 0 : omega2 = pow2(2*pi*nu_max/1d6)
980 : if (dbg) write(*,1) 'log omega2', log10(omega2)
981 0 : el = 1
982 0 : L2 = el*(el+1)
983 0 : k_sl2 = 0
984 0 : do k = 2, s% nz
985 0 : N2 = s% brunt_N2(k)
986 0 : r = s% r(k)
987 0 : r2 = r*r
988 0 : cs2 = s% csound_face(k)*s% csound_face(k)
989 0 : sl2 = L2*cs2/r2
990 0 : dr = s% rmid(k-1) - s% rmid(k)
991 0 : if (omega2 >= sl2) then
992 : cycle
993 : end if
994 : if (k_sl2 == 0) then
995 : k_sl2 = k
996 : if (dbg) write(*,2) 'k_sl2', k
997 : end if
998 0 : if (N2 > omega2) then ! in g-cavity
999 : if (dbg .and. integral == 0) write(*,2) 'enter g-cavity', k
1000 0 : integral = integral + sqrt(N2)*dr/r
1001 : else ! in decay region
1002 0 : if (integral == 0) cycle ! ! haven't been in g-cavity yet
1003 : if (dbg .and. I_integral == 0) write(*,2) 'enter decay', k
1004 : ! in decay region below g-cavity; I_integral estimates decay
1005 0 : kr2 = (1 - n2/omega2)*(1 - Sl2/omega2)*omega2/cs2
1006 0 : I_integral = I_integral + sqrt(-kr2)*dr
1007 0 : if (I_integral > I_integral_limit) exit
1008 : end if
1009 : end do
1010 :
1011 : if (dbg) write(*,2) 'omega2 nu_max integral I_integral', &
1012 : s% model_number, omega2, nu_max, integral, I_integral
1013 :
1014 0 : if (integral == 0) return
1015 0 : delta_Pg = sqrt(2d0)*pi*pi/integral
1016 0 : if (is_bad(delta_Pg)) delta_Pg = 0
1017 :
1018 : if (dbg) write(*,2) 'delta_Pg', s% model_number, delta_Pg
1019 :
1020 : end subroutine get_delta_Pg_bildsten2012
1021 :
1022 :
1023 66 : subroutine set_rmid(s, nzlo, nzhi, ierr)
1024 : type (star_info), pointer :: s
1025 : integer, intent(in) :: nzlo, nzhi
1026 : integer, intent(out) :: ierr
1027 : integer :: k, nz
1028 66 : real(dp) :: r003, rp13, rmid, rmid2
1029 : logical :: dbg
1030 : include 'formats'
1031 66 : ierr = 0
1032 66 : nz = s% nz
1033 66 : dbg = .false.
1034 66 : if (s% RSP_flag) then ! mid = avg r
1035 : !dbg = s% model_number >= s% max_model_number - 1
1036 0 : do k=nzlo, nzhi
1037 0 : if (k < nz) then
1038 0 : rmid = 0.5d0*(s% r(k) + s% r(k+1))
1039 : else
1040 0 : rmid = 0.5d0*(s% r(k) + s% R_center)
1041 : end if
1042 0 : s% rmid(k) = rmid
1043 : if (dbg) write(*,3) 'set_rmid s% r(k)', k, s% model_number, s% r(k)
1044 : if (dbg) write(*,3) 'set_rmid s% rmid(k)', k, s% model_number, s% rmid(k)
1045 0 : if (s% rmid_start(k) < 0) s% rmid_start(k) = s% rmid(k)
1046 0 : rmid2 = rmid*rmid
1047 : end do
1048 66 : return
1049 : end if
1050 : ! mid = middle by volume
1051 80060 : do k=nzlo, nzhi
1052 79994 : r003 = s% r(k)*s% r(k)*s% r(k)
1053 79994 : if (k < nz) then
1054 79928 : rp13 = s% r(k+1)*s% r(k+1)*s% r(k+1)
1055 : else
1056 66 : rp13 = s% R_center*s% R_center*s% R_center
1057 : end if
1058 79994 : rmid = pow(0.5d0*(r003 + rp13),one_third)
1059 79994 : s% rmid(k) = rmid
1060 79994 : if (s% rmid_start(k) < 0) s% rmid_start(k) = s% rmid(k)
1061 80060 : rmid2 = rmid*rmid
1062 : end do
1063 : end subroutine set_rmid
1064 :
1065 :
1066 0 : real(dp) function get_tau_at_r(s, r, ierr)
1067 : type (star_info), pointer :: s
1068 : real(dp), intent(in) :: r
1069 : integer, intent(out) :: ierr
1070 0 : real(dp) :: dtau, tau_m1, tau_00
1071 : integer :: k
1072 : logical, parameter :: dbg = .false.
1073 : include 'formats'
1074 : ierr = 0
1075 0 : dtau = get_dtau1(s, ierr)
1076 0 : if (ierr /= 0) return
1077 0 : tau_00 = s% tau_factor*s% tau_base
1078 0 : get_tau_at_r = tau_00
1079 0 : if (r >= s% r(1)) return
1080 0 : do k = 2, s% nz
1081 0 : tau_m1 = tau_00
1082 0 : tau_00 = tau_m1 + dtau
1083 0 : if (r < s% r(k-1) .and. r >= s% r(k)) then
1084 : get_tau_at_r = &
1085 0 : (tau_00*(s% r(k-1)-r) + tau_m1*(r-s% r(k)))/(s% r(k-1)-s% r(k))
1086 0 : return
1087 : end if
1088 0 : dtau = s% dm(k)*s% opacity(k)/(pi4*s% rmid(k)*s% rmid(k))
1089 : end do
1090 : end function get_tau_at_r
1091 :
1092 :
1093 132 : subroutine set_phot_info(s)
1094 : use atm_lib, only: atm_black_body_T
1095 : type (star_info), pointer :: s
1096 : real(dp) :: luminosity
1097 : include 'formats'
1098 : call get_phot_info(s, &
1099 : s% photosphere_r, s% photosphere_m, s% photosphere_v, &
1100 : s% photosphere_L, s% photosphere_T, s% photosphere_csound, &
1101 : s% photosphere_opacity, s% photosphere_logg, &
1102 132 : s% photosphere_column_density, s% photosphere_cell_k)
1103 : s% photosphere_black_body_T = &
1104 132 : atm_black_body_T(s% photosphere_L, s% photosphere_r)
1105 132 : s% Teff = s% photosphere_black_body_T
1106 132 : s% photosphere_r = s% photosphere_r/Rsun
1107 132 : s% photosphere_m = s% photosphere_m/Msun
1108 132 : s% photosphere_L = s% photosphere_L/Lsun
1109 132 : s% L_phot = s% photosphere_L
1110 132 : luminosity = s% L(1)
1111 132 : if (is_bad(luminosity)) then
1112 0 : write(*,2) 's% L(1)', s% model_number, s% L(1)
1113 0 : write(*,2) 's% xh(s% i_lum,1)', s% model_number, s% xh(s% i_lum,1)
1114 0 : call mesa_error(__FILE__,__LINE__,'set_phot_info')
1115 0 : luminosity = 0d0
1116 : end if
1117 132 : s% L_surf = luminosity/Lsun
1118 132 : s% log_surface_luminosity = log10(max(1d-99,luminosity/Lsun))
1119 : ! log10(stellar luminosity in solar units)
1120 132 : if (is_bad(s% L_surf)) then
1121 0 : write(*,2) 's% L_surf', s% model_number, s% L_surf
1122 0 : call mesa_error(__FILE__,__LINE__,'set_phot_info')
1123 : end if
1124 132 : end subroutine set_phot_info
1125 :
1126 :
1127 132 : subroutine get_phot_info(s,r,m,v,L,T_phot,cs,kap,logg,ysum,k_phot)
1128 : type (star_info), pointer :: s
1129 : real(dp), intent(out) :: r, m, v, L, T_phot, cs, kap, logg, ysum
1130 : integer, intent(out) :: k_phot
1131 :
1132 : integer :: k
1133 132 : real(dp) :: tau00, taup1, dtau, r003, rp13, r3, tau_phot, &
1134 132 : Tface_0, Tface_1
1135 :
1136 : include 'formats'
1137 :
1138 : ! set values for surface as defaults in case phot not in model
1139 132 : r = s% r(1)
1140 132 : m = s% m(1)
1141 132 : if (s% u_flag) then
1142 0 : v = s% u(1)
1143 132 : else if (s% v_flag) then
1144 0 : v = s% v(1)
1145 : else
1146 132 : v = 0d0
1147 : end if
1148 132 : L = max(1d0, s% L(1)) ! don't use negative L(1)
1149 132 : T_phot = s% T(1)
1150 132 : cs = s% csound(1)
1151 132 : kap = s% opacity(1)
1152 132 : logg = safe_log10(s% cgrav(1)*m/(r*r))
1153 132 : k_phot = 1
1154 132 : if (s% tau_factor >= 1) then
1155 : ! This is always true for tables, regardless of tau_base.
1156 132 : return ! just use surface values
1157 : end if
1158 0 : tau_phot = s% tau_base ! this holds for case of tau_factor < 1
1159 0 : tau00 = s% tau_factor*s% tau_base ! start at tau_surf < tau_phot and go inward
1160 0 : taup1 = 0
1161 0 : ysum = 0
1162 0 : do k = 1, s% nz-1
1163 0 : dtau = s% dm(k)*s% opacity(k)/(pi4*s% rmid(k)*s% rmid(k))
1164 0 : taup1 = tau00 + dtau
1165 0 : ysum = ysum + s% rho(k)*(s% r(k) - s% r(k+1))
1166 0 : if (taup1 >= tau_phot .and. dtau > 0d0) then
1167 0 : if (k == 1) then
1168 0 : Tface_0 = s% T_surf
1169 : else
1170 0 : Tface_0 = 0.5d0*(s% T(k) + s% T(k-1))
1171 : end if
1172 0 : Tface_1 = 0.5d0*(s% T(k) + s% T(k+1))
1173 0 : T_phot = Tface_0 + (Tface_1 - Tface_0)*(tau_phot - tau00)/dtau
1174 0 : r003 = s% r(k)*s% r(k)*s% r(k)
1175 0 : rp13 = s% r(k+1)*s% r(k+1)*s% r(k+1)
1176 0 : r3 = r003 + (rp13 - r003)*(tau_phot - tau00)/dtau
1177 0 : r = pow(r3,one_third)
1178 0 : m = s% m(k) - s% dm(k)*(tau_phot - tau00)/dtau
1179 0 : if (s% u_flag) then
1180 0 : v = s% v_center
1181 : ! skip it since get_phot_info can be called before u_face has been set
1182 0 : else if (s% v_flag) then
1183 0 : v = s% v(k) + (s% v(k+1) - s% v(k))*(tau_phot - tau00)/dtau
1184 : end if
1185 : L = s% L(k) + (s% L(k+1) - s% L(k))*(tau_phot - tau00)/dtau
1186 0 : L = max(1d0, s% L(1)) ! don't use negative L(1)
1187 0 : logg = safe_log10(s% cgrav(k_phot)*m/(r*r))
1188 0 : k_phot = k
1189 : ! don't bother interpolating these.
1190 0 : cs = s% csound(k_phot)
1191 0 : kap = s% opacity(k_phot)
1192 0 : return
1193 : end if
1194 0 : tau00 = taup1
1195 : end do
1196 : !write(*,*) 'get_phot_info failed to find photosphere'
1197 0 : k_phot = s% nz
1198 0 : r = s% R_center
1199 0 : m = s% m_center
1200 0 : v = s% v_center
1201 0 : T_phot = s% T(k_phot)
1202 0 : L = max(1d0, s% L_center)
1203 0 : cs = s% csound(k_phot)
1204 0 : kap = s% opacity(k_phot)
1205 0 : logg = safe_log10(s% cgrav(k_phot)*m/(r*r))
1206 132 : end subroutine get_phot_info
1207 :
1208 :
1209 440 : real(dp) function center_value(s, p)
1210 : type (star_info), pointer :: s
1211 : real(dp), intent(in) :: p(:)
1212 440 : real(dp) :: sum_x, sum_dq, dx, dq
1213 : integer :: k
1214 440 : sum_x = 0
1215 440 : sum_dq = 0
1216 440 : do k = s% nz, 1, -1
1217 440 : dq = s% dq(k)
1218 440 : dx = p(k)*dq
1219 440 : if (sum_dq+dq >= s% center_avg_value_dq) then
1220 440 : sum_x = sum_x + dx*(s% center_avg_value_dq - sum_dq)/dq
1221 440 : sum_dq = s% center_avg_value_dq
1222 440 : exit
1223 : end if
1224 0 : sum_x = sum_x + dx
1225 0 : sum_dq = sum_dq + dq
1226 : end do
1227 440 : center_value = sum_x/sum_dq
1228 440 : end function center_value
1229 :
1230 :
1231 2464 : subroutine interp_q( &
1232 2464 : nz2, nvar_hydro, species, qval, xh, xa, q, dq, struct, comp, ierr)
1233 : use num_lib, only: binary_search
1234 : integer, intent(in) :: nz2, nvar_hydro, species
1235 : real(dp), intent(in) :: qval
1236 : real(dp), intent(in) :: xh(:,:), xa(:,:), q(:), dq(:)
1237 : real(dp), intent(inout) :: struct(:), comp(:)
1238 : integer, intent(out) :: ierr
1239 : integer :: k
1240 2464 : real(dp) :: alfa
1241 2464 : ierr = 0
1242 2464 : if (qval <= q(nz2)) then
1243 1 : if (nvar_hydro > 0) &
1244 5 : struct(1:nvar_hydro) = xh(1:nvar_hydro,nz2)
1245 1 : if (species > 0) &
1246 9 : comp(1:species) = xa(1:species,nz2)
1247 1 : return
1248 : end if
1249 2463 : k = binary_search(nz2, q, 0, qval)
1250 2463 : if (k < 1 .or. k >= nz2) then
1251 0 : ierr = -1
1252 0 : return
1253 : end if
1254 2463 : if (qval <= q(k) .and. qval > q(k+1)) then
1255 2463 : alfa = (qval - q(k+1)) / dq(k)
1256 2463 : if (nvar_hydro > 0) &
1257 : struct(1:nvar_hydro) = &
1258 12315 : alfa*xh(1:nvar_hydro,k) + (1-alfa)*xh(1:nvar_hydro,k+1)
1259 2463 : if (species > 0) &
1260 22167 : comp(1:species) = alfa*xa(1:species,k) + (1-alfa)*xa(1:species,k+1)
1261 2463 : return
1262 : end if
1263 0 : ierr = -1
1264 2464 : end subroutine interp_q
1265 :
1266 :
1267 33 : subroutine set_abs_du_div_cs(s)
1268 : type (star_info), pointer :: s
1269 :
1270 : integer :: k, nz, j
1271 33 : real(dp) :: abs_du, cs
1272 : include 'formats'
1273 33 : nz = s% nz
1274 :
1275 33 : if (s% v_flag) then
1276 0 : do k=2,nz
1277 0 : abs_du = abs(s% v_start(k) - s% v_start(k-1))
1278 0 : cs = maxval(s% csound(max(1,k-5):min(nz,k+5)))
1279 0 : s% abs_du_plus_cs(k) = abs_du + cs
1280 0 : s% abs_du_div_cs(k) = abs_du/cs
1281 : end do
1282 0 : k = 1
1283 0 : s% abs_du_plus_cs(k) = s% abs_du_plus_cs(k+1)
1284 0 : s% abs_du_div_cs(k) = s% abs_du_div_cs(k+1)
1285 0 : do j = 1,3
1286 0 : do k=2,nz-1
1287 0 : s% abs_du_div_cs(k) = sum(s% abs_du_div_cs(k-1:k+1))/3d0
1288 : end do
1289 : end do
1290 33 : else if (s% u_flag) then
1291 0 : do k=2,nz-1
1292 : abs_du = &
1293 : max(abs(s% u_start(k) - s% u_start(k+1)), &
1294 0 : abs(s% u_start(k) - s% u_start(k-1)))
1295 0 : cs = maxval(s% csound(max(1,k-5):min(nz,k+5)))
1296 0 : s% abs_du_plus_cs(k) = abs_du + cs
1297 0 : s% abs_du_div_cs(k) = abs_du/cs
1298 : end do
1299 0 : k = nz
1300 : s% abs_du_plus_cs(k) = &
1301 0 : abs(s% u_start(k) - s% u_start(k-1)) + s% csound_start(k)
1302 : s% abs_du_div_cs(k) = &
1303 0 : abs(s% u_start(k) - s% u_start(k-1))/s% csound_start(k)
1304 0 : k = 2
1305 : s% abs_du_plus_cs(k) = &
1306 0 : abs(s% u_start(k) - s% u_start(k+1)) + s% csound_start(k)
1307 : s% abs_du_div_cs(k) = &
1308 0 : abs(s% u_start(k) - s% u_start(k+1))/s% csound_start(k)
1309 0 : k = 1
1310 0 : s% abs_du_plus_cs(k) = s% abs_du_plus_cs(k+1)
1311 0 : s% abs_du_div_cs(k) = s% abs_du_div_cs(k+1)
1312 0 : do j = 1,3
1313 0 : do k=2,nz-1
1314 0 : s% abs_du_div_cs(k) = sum(s% abs_du_div_cs(k-1:k+1))/3d0
1315 : end do
1316 : end do
1317 : else
1318 40766 : do k=1,nz
1319 40733 : s% abs_du_plus_cs(k) = 1d99
1320 40766 : s% abs_du_div_cs(k) = 1d99
1321 : end do
1322 : end if
1323 :
1324 2464 : end subroutine set_abs_du_div_cs
1325 :
1326 :
1327 33 : subroutine get_shock_info(s)
1328 : type (star_info), pointer :: s
1329 : integer :: k, nz
1330 33 : real(dp) :: v_div_cs_00, v_div_cs_m1, v_div_cs_min, v_div_cs_max, shock_radius
1331 : real(dp), pointer :: v(:)
1332 :
1333 : include 'formats'
1334 :
1335 33 : s% shock_mass = 0d0
1336 33 : s% shock_q = 0d0
1337 33 : s% shock_radius = 0d0
1338 33 : s% shock_velocity = 0d0
1339 33 : s% shock_csound = 0d0
1340 33 : s% shock_lgT = 0d0
1341 33 : s% shock_lgRho = 0d0
1342 33 : s% shock_lgP = 0d0
1343 33 : s% shock_gamma1 = 0d0
1344 33 : s% shock_entropy = 0d0
1345 33 : s% shock_tau = 0d0
1346 33 : s% shock_k = 0
1347 :
1348 33 : if (s% u_flag) then
1349 0 : v => s% u
1350 33 : else if (s% v_flag) then
1351 0 : v => s% v
1352 : else
1353 33 : return
1354 : end if
1355 :
1356 0 : nz = s% nz
1357 0 : shock_radius = -1
1358 0 : v_div_cs_00 = v(1)/s% csound(1)
1359 0 : do k = 2,nz-1
1360 0 : v_div_cs_m1 = v_div_cs_00
1361 0 : v_div_cs_00 = v(k)/s% csound(k)
1362 0 : v_div_cs_max = max(v_div_cs_00, v_div_cs_m1)
1363 0 : v_div_cs_min = min(v_div_cs_00, v_div_cs_m1)
1364 0 : if (v_div_cs_max >= 1d0 .and. v_div_cs_min < 1d0) then
1365 0 : if (v(k+1) > s% csound(k+1)) then ! skip single point glitches
1366 : shock_radius = &
1367 0 : find0(s% r(k), v_div_cs_00-1d0, s% r(k-1), v_div_cs_m1-1d0)
1368 0 : if (shock_radius <= 0d0) then
1369 0 : call mesa_error(__FILE__,__LINE__,'get_shock_info 1')
1370 : end if
1371 : exit
1372 : end if
1373 : end if
1374 0 : if (v_div_cs_min <= -1d0 .and. v_div_cs_max > -1d0) then
1375 0 : if (v(k+1) < -s% csound(k+1)) then ! skip single point glitches
1376 : shock_radius = &
1377 0 : find0(s% r(k), v_div_cs_00+1d0, s% r(k-1), v_div_cs_m1+1d0)
1378 0 : if (shock_radius <= 0d0) then
1379 0 : call mesa_error(__FILE__,__LINE__,'get_shock_info 2')
1380 : end if
1381 : exit
1382 : end if
1383 : end if
1384 : end do
1385 0 : if (shock_radius < 0d0) return
1386 :
1387 : call get_shock_location_info( &
1388 : s, .false., k-1, v, shock_radius, &
1389 : s% shock_mass, &
1390 : s% shock_q, &
1391 : s% shock_radius, &
1392 : s% shock_velocity, &
1393 : s% shock_csound, &
1394 : s% shock_lgT, &
1395 : s% shock_lgRho, &
1396 : s% shock_lgP, &
1397 : s% shock_gamma1, &
1398 : s% shock_entropy, &
1399 : s% shock_tau, &
1400 0 : s% shock_k)
1401 :
1402 : end subroutine get_shock_info
1403 :
1404 :
1405 0 : subroutine get_shock_location_info( &
1406 : s, dbg, k_shock, v, r, &
1407 : shock_mass, &
1408 : shock_q, &
1409 : shock_radius, &
1410 : shock_velocity, &
1411 : shock_csound, &
1412 : shock_lgT, &
1413 : shock_lgRho, &
1414 : shock_lgP, &
1415 : shock_gamma1, &
1416 : shock_entropy, &
1417 : shock_tau, &
1418 : shock_k)
1419 : type (star_info), pointer :: s
1420 : integer, intent(in) :: k_shock
1421 : logical, intent(in) :: dbg
1422 : real(dp), intent(in), pointer :: v(:)
1423 : real(dp), intent(in) :: r
1424 : real(dp), intent(out) :: &
1425 : shock_mass, &
1426 : shock_q, &
1427 : shock_radius, &
1428 : shock_velocity, &
1429 : shock_csound, &
1430 : shock_lgT, &
1431 : shock_lgRho, &
1432 : shock_lgP, &
1433 : shock_gamma1, &
1434 : shock_entropy, &
1435 : shock_tau
1436 : integer, intent(out) :: shock_k
1437 :
1438 : integer :: k
1439 0 : real(dp) :: alfa, beta
1440 :
1441 : include 'formats'
1442 :
1443 0 : k = k_shock
1444 : if (r < s% R_center .or. r > s% r(1) .or. &
1445 : k < 1 .or. k > s% nz .or. &
1446 0 : .not. associated(v) .or. &
1447 : .not. (s% v_flag .or. s% u_flag)) then
1448 0 : shock_mass = 0
1449 0 : shock_q = 0
1450 0 : shock_radius = 0
1451 0 : shock_velocity = 0
1452 0 : shock_csound = 0
1453 0 : shock_lgT = 0
1454 0 : shock_lgRho = 0
1455 0 : shock_lgP = 0
1456 0 : shock_gamma1 = 0
1457 0 : shock_entropy = 0
1458 0 : shock_tau = 0
1459 0 : shock_k = 0
1460 0 : return
1461 : end if
1462 :
1463 0 : shock_radius = r/Rsun
1464 0 : shock_k = k
1465 0 : if (k < s% nz) then
1466 0 : alfa = (r - s% r(k))/(s% r(k+1) - s% r(k))
1467 0 : beta = 1d0 - alfa
1468 0 : shock_mass = (alfa*s% m(k+1) + beta*s% m(k))/Msun
1469 0 : shock_q = alfa*s% q(k+1) + beta*s% q(k)
1470 0 : shock_velocity = alfa*v(k+1) + beta*v(k)
1471 : else
1472 0 : shock_mass = s% m(k)/Msun
1473 0 : shock_q = s% q(k)
1474 0 : shock_velocity = v(k)
1475 : end if
1476 0 : shock_csound = s% csound(k)
1477 0 : shock_lgT = s% lnT(k)/ln10
1478 0 : shock_lgRho = s% lnd(k)/ln10
1479 0 : shock_lgP = s% lnPeos(k)/ln10
1480 0 : shock_gamma1 = s% gamma1(k)
1481 0 : shock_entropy = s% entropy(k)
1482 0 : shock_tau = s% tau(k)
1483 :
1484 : end subroutine get_shock_location_info
1485 :
1486 :
1487 0 : real(dp) function min_dr_div_cs(s,min_k) ! seconds
1488 : type (star_info), pointer :: s
1489 : integer, intent(out) :: min_k
1490 : integer :: k, nz, k_min
1491 0 : real(dp) :: dr, dt, min_q, max_q, min_abs_u_div_cs, min_abs_du_div_cs, r00, rp1, dr_div_cs, remnant_mass
1492 : include 'formats'
1493 0 : nz = s% nz
1494 0 : min_k = nz
1495 0 : min_dr_div_cs = 1d99
1496 0 : min_q = s% min_q_for_dt_div_min_dr_div_cs_limit
1497 0 : max_q = s% max_q_for_dt_div_min_dr_div_cs_limit
1498 0 : k_min = max(1, s% min_k_for_dt_div_min_dr_div_cs_limit)
1499 0 : if (s% check_remnant_only_for_dt_div_min_dr_div_cs_limit) then
1500 0 : remnant_mass = get_remnant_mass(s)
1501 : else
1502 0 : remnant_mass = s% m(1)
1503 : end if
1504 : min_abs_u_div_cs = &
1505 0 : s% min_abs_u_div_cs_for_dt_div_min_dr_div_cs_limit
1506 : min_abs_du_div_cs = &
1507 0 : s% min_abs_du_div_cs_for_dt_div_min_dr_div_cs_limit
1508 0 : if (s% v_flag) then
1509 0 : do k = k_min, nz-1
1510 0 : if (s% m(k) > remnant_mass) cycle
1511 0 : if (s% q(k) > max_q) cycle
1512 0 : if (s% q(k) < min_q) exit
1513 0 : if (abs(s% v_start(k))/s% csound(k) < min_abs_u_div_cs) cycle
1514 0 : if (s% abs_du_div_cs(k) < min_abs_du_div_cs) cycle
1515 0 : r00 = s% r(k)
1516 0 : rp1 = s% r(k+1)
1517 0 : dr_div_cs = (r00 - rp1)/s% csound(k)
1518 0 : if (dr_div_cs < min_dr_div_cs) then
1519 0 : min_dr_div_cs = dr_div_cs
1520 0 : min_k = k
1521 : end if
1522 : end do
1523 : !write(*,3) 'min_dr_div_cs', min_k, s% model_number, min_dr_div_cs
1524 0 : return
1525 : end if
1526 0 : if (.not. s% u_flag) return
1527 0 : do k = k_min, nz-1
1528 0 : if (s% m(k) > remnant_mass) cycle
1529 0 : if (s% q(k) > max_q) cycle
1530 0 : if (s% q(k) < min_q) exit
1531 0 : if (abs(s% u_start(k))/s% csound(k) < min_abs_u_div_cs) cycle
1532 0 : if (s% abs_du_div_cs(k) < min_abs_du_div_cs) cycle
1533 0 : dr = s% r(k) - s% r(k+1)
1534 0 : dt = dr/s% abs_du_plus_cs(k)
1535 0 : if (dt < min_dr_div_cs) then
1536 0 : min_dr_div_cs = dt
1537 0 : min_k = k
1538 : end if
1539 : end do
1540 : end function min_dr_div_cs
1541 :
1542 :
1543 12 : subroutine reset_epsnuc_vectors(s)
1544 : type (star_info), pointer :: s
1545 : integer :: k, nz
1546 12 : nz = s% nz
1547 15563 : do k=1,s% nz
1548 15551 : s% eps_nuc(k) = 0d0
1549 15551 : s% d_epsnuc_dlnd(k) = 0d0
1550 15551 : s% d_epsnuc_dlnT(k) = 0d0
1551 139959 : s% d_epsnuc_dx(:,k) = 0d0
1552 388775 : s% eps_nuc_categories(:,k) = 0d0
1553 139959 : s% dxdt_nuc(:,k) = 0d0
1554 139959 : s% d_dxdt_nuc_dRho(:,k) = 0d0
1555 139959 : s% d_dxdt_nuc_dT(:,k) = 0d0
1556 1135223 : s% d_dxdt_nuc_dx(:,:,k) = 0d0
1557 15563 : s% eps_nuc_neu_total(k) = 0d0
1558 : end do
1559 12 : end subroutine reset_epsnuc_vectors
1560 :
1561 :
1562 44 : subroutine reset_starting_vectors(s)
1563 : type (star_info), pointer :: s
1564 : integer :: k, nz
1565 44 : nz = s% nz
1566 55336 : do k=1,s% nz
1567 55292 : s% T_start(k) = -1d99
1568 55292 : s% r_start(k) = -1d99
1569 55292 : s% rmid_start(k) = -1d99
1570 55292 : s% v_start(k) = -1d99
1571 55292 : s% u_start(k) = -1d99
1572 55292 : s% lnd_start(k) = -1d99
1573 55292 : s% lnT_start(k) = -1d99
1574 55292 : s% csound_start(k) = -1d99
1575 55292 : s% rho_start(k) = -1d99
1576 55292 : s% erad_start(k) = -1d99
1577 55292 : s% alpha_RTI_start(k) = -1d99
1578 55292 : s% opacity_start(k) = -1d99
1579 55292 : s% w_start(k) = -1d99
1580 55336 : s% dPdr_dRhodr_info(k) = -1d99
1581 : end do
1582 44 : end subroutine reset_starting_vectors
1583 :
1584 :
1585 104652 : subroutine save_eqn_dxa_partials(&
1586 104652 : s, k, nvar, i_eqn, species, dxam1, dxa00, dxap1, str, ierr)
1587 : type (star_info), pointer :: s
1588 : integer, intent(in) :: k, nvar, i_eqn, species
1589 : real(dp), intent(in), dimension(species) :: dxam1, dxa00, dxap1
1590 : character (len=*), intent(in) :: str
1591 : integer, intent(out) :: ierr
1592 : integer :: j
1593 104652 : ierr = 0
1594 941868 : do j=1,species
1595 837216 : call em1(s, i_eqn, j+s% nvar_hydro, k, nvar, dxam1(j))
1596 837216 : call e00(s, i_eqn, j+s% nvar_hydro, k, nvar, dxa00(j))
1597 941868 : call ep1(s, i_eqn, j+s% nvar_hydro, k, nvar, dxap1(j))
1598 : end do
1599 104652 : end subroutine save_eqn_dxa_partials
1600 :
1601 :
1602 104740 : subroutine save_eqn_residual_info(s, k, nvar, i_eqn, resid, str, ierr)
1603 : type (star_info), pointer :: s
1604 : integer, intent(in) :: k, nvar, i_eqn
1605 : type(auto_diff_real_star_order1), intent(in) :: resid
1606 : character (len=*), intent(in) :: str
1607 : integer, intent(out) :: ierr
1608 4084860 : real(dp) :: d_dm1(nvar), d_d00(nvar), d_dp1(nvar)
1609 : call unpack_residual_partials(s, k, nvar, i_eqn, &
1610 104740 : resid, d_dm1, d_d00, d_dp1)
1611 : call store_partials( &
1612 104740 : s, k, i_eqn, nvar, d_dm1, d_d00, d_dp1, str, ierr)
1613 104740 : end subroutine save_eqn_residual_info
1614 :
1615 :
1616 209392 : subroutine unpack_residual_partials(s, k, nvar, i_eqn, &
1617 209392 : residual, d_dm1, d_d00, d_dp1)
1618 : use auto_diff
1619 : use auto_diff_support
1620 : type (star_info), pointer :: s
1621 : integer, intent(in) :: k, nvar, i_eqn
1622 : type(auto_diff_real_star_order1) :: residual
1623 : real(dp) :: d_dm1(nvar), d_d00(nvar), d_dp1(nvar)
1624 :
1625 : real(dp) :: val, dlnd_m1, dlnd_00, dlnd_p1, dlnT_m1, dlnT_00, dlnT_p1, &
1626 : dw_m1, dw_00, dw_p1, &
1627 : dlnR_m1, dlnR_00, dlnR_p1, &
1628 : dv_m1, dv_00, dv_p1, dL_m1, dL_00, dL_p1, &
1629 : dHp_m1, dHp_00, dHp_p1, &
1630 : dw_div_wc_m1, dw_div_wc_00, dw_div_wc_p1, &
1631 : djrot_m1, djrot_00, djrot_p1, &
1632 : dxtra1_m1, dxtra1_00, dxtra1_p1, &
1633 : dxtra2_m1, dxtra2_00, dxtra2_p1
1634 :
1635 : include 'formats'
1636 :
1637 : call unwrap(residual, val, &
1638 : dlnd_m1, dlnd_00, dlnd_p1, dlnT_m1, dlnT_00, dlnT_p1, &
1639 : dw_m1, dw_00, dw_p1, dlnR_m1, dlnR_00, dlnR_p1, &
1640 : dv_m1, dv_00, dv_p1, dL_m1, dL_00, dL_p1, &
1641 : dHp_m1, dHp_00, dHp_p1, &
1642 : dw_div_wc_m1, dw_div_wc_00, dw_div_wc_p1, &
1643 : djrot_m1, djrot_00, djrot_p1, &
1644 : dxtra1_m1, dxtra1_00, dxtra1_p1, &
1645 209392 : dxtra2_m1, dxtra2_00, dxtra2_p1)
1646 :
1647 8166288 : d_dm1 = 0; d_d00 = 0; d_dp1 = 0
1648 209392 : call unpack1(s% i_lnd, dlnd_m1, dlnd_00, dlnd_p1)
1649 209392 : call unpack1(s% i_lnT, dlnT_m1, dlnT_00, dlnT_p1)
1650 209392 : call unpack1(s% i_lnR, dlnR_m1, dlnR_00, dlnR_p1)
1651 209392 : if (s% i_v /= 0) call unpack1(s% i_v, dv_m1, dv_00, dv_p1)
1652 209392 : if (s% i_u /= 0) call unpack1(s% i_u, dv_m1, dv_00, dv_p1)
1653 209392 : if (s% i_lum /= 0) call unpack1(s% i_lum, dL_m1, dL_00, dL_p1)
1654 209392 : if (s% i_w /= 0) call unpack1(s% i_w, dw_m1, dw_00, dw_p1)
1655 209392 : if (s% i_Hp /= 0) call unpack1(s% i_Hp, dHp_m1, dHp_00, dHp_p1)
1656 209392 : if (s% i_w_div_wc /= 0) call unpack1(s% i_w_div_wc, dw_div_wc_m1, dw_div_wc_00, dw_div_wc_p1)
1657 209392 : if (s% i_j_rot /= 0) call unpack1(s% i_j_rot, djrot_m1, djrot_00, djrot_p1)
1658 :
1659 : contains
1660 :
1661 418784 : subroutine unpack1(j, dvar_m1, dvar_00, dvar_p1)
1662 : integer, intent(in) :: j
1663 : real(dp), intent(in) :: dvar_m1, dvar_00, dvar_p1
1664 418784 : d_dm1(j) = dvar_m1
1665 418784 : d_d00(j) = dvar_00
1666 209392 : d_dp1(j) = dvar_p1
1667 418784 : end subroutine unpack1
1668 :
1669 : end subroutine unpack_residual_partials
1670 :
1671 209392 : subroutine store_partials(s, k, i_eqn, nvar, d_dm1, d_d00, d_dp1, str, ierr)
1672 : type (star_info), pointer :: s
1673 : integer, intent(in) :: k, i_eqn, nvar
1674 : real(dp), intent(in) :: d_dm1(nvar), d_d00(nvar), d_dp1(nvar)
1675 : character (len=*), intent(in) :: str
1676 : integer, intent(out) :: ierr
1677 : integer :: nz, j
1678 : logical, parameter :: checking = .true.
1679 209392 : ierr = 0
1680 209392 : nz = s% nz
1681 2722096 : do j=1,nvar
1682 2512704 : if (k > 1) then
1683 2510592 : if (checking) call check_dequ(d_dm1(j),trim(str) // ' d_dm1')
1684 2510592 : call em1(s, i_eqn, j, k, nvar, d_dm1(j))
1685 : end if
1686 2512704 : if (checking) call check_dequ(d_d00(j),trim(str) // ' d_d00')
1687 2512704 : call e00(s, i_eqn, j, k, nvar, d_d00(j))
1688 2722096 : if (k < nz) then
1689 2510592 : if (checking) call check_dequ(d_dp1(j),trim(str) // ' d_dp1')
1690 2510592 : call ep1(s, i_eqn, j, k, nvar, d_dp1(j))
1691 : end if
1692 : end do
1693 :
1694 : contains
1695 :
1696 7533888 : subroutine check_dequ(dequ, str)
1697 : real(dp), intent(in) :: dequ
1698 : character (len=*), intent(in) :: str
1699 : include 'formats'
1700 7533888 : if (is_bad(dequ)) then
1701 0 : !$omp critical (store_partials_crit)
1702 0 : ierr = -1
1703 0 : if (s% report_ierr) then
1704 0 : write(*,2) 'store_partials: bad ' // trim(str), k, dequ
1705 : end if
1706 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'store_partials')
1707 : !$omp end critical (store_partials_crit)
1708 0 : return
1709 : end if
1710 : end subroutine check_dequ
1711 :
1712 : end subroutine store_partials
1713 :
1714 :
1715 77 : subroutine set_scale_height(s)
1716 : type (star_info), pointer :: s
1717 77 : real(dp) :: Hp, alt_Hp, alfa, beta, rho_face, Peos_face
1718 : integer :: k
1719 : include 'formats'
1720 93158 : do k=1,s% nz
1721 93081 : if (s% cgrav(k) == 0) then
1722 0 : s% scale_height(k) = 0
1723 0 : cycle
1724 : end if
1725 93081 : if (k == 1) then
1726 : alfa = 1
1727 : else
1728 93004 : alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
1729 : end if
1730 93081 : beta = 1 - alfa
1731 93004 : if (alfa == 1) then
1732 77 : rho_face = s% rho(k)
1733 77 : Peos_face = s% Peos(k)
1734 : else
1735 93004 : rho_face = alfa*s% rho(k) + beta*s% rho(k-1)
1736 93004 : Peos_face = alfa*s% Peos(k) + beta*s% Peos(k-1)
1737 : end if
1738 93081 : Hp = Peos_face/(rho_face*s% grav(k))
1739 93081 : if (s% cgrav(k) <= 0) then
1740 0 : alt_Hp = s% r(k)
1741 : else
1742 93081 : alt_Hp = sqrt(Peos_face / s% cgrav(k)) / rho_face
1743 : end if
1744 93158 : s% scale_height(k) = min(Hp, alt_Hp)
1745 : end do
1746 77 : end subroutine set_scale_height
1747 :
1748 :
1749 0 : real(dp) function tau_eff(s,k)
1750 : ! tau_eff = tau that gives the local P == P_atm if this location at surface
1751 : type (star_info), pointer :: s
1752 : integer, intent(in) :: k
1753 0 : real(dp) :: Peos, g, Pextra_factor
1754 0 : if (k == 1) then
1755 0 : tau_eff = s% tau(1)
1756 0 : return
1757 : end if
1758 0 : if (s% cgrav(k) <= 0d0) then
1759 0 : tau_eff = 0d0
1760 : return
1761 : end if
1762 0 : Peos = (s% dq(k-1)*s% Peos(k) + s% dq(k)*s% Peos(k-1))/(s% dq(k-1) + s% dq(k))
1763 0 : g = s% cgrav(k)*s% m_grav(k)/(s% r(k)*s% r(k))
1764 0 : Pextra_factor = s% Pextra_factor
1765 : tau_eff = s% opacity(k)*(Peos/g - &
1766 0 : Pextra_factor*(s% L(k)/s% m_grav(k))/(6d0*pi*clight*s% cgrav(k)))
1767 0 : end function tau_eff
1768 :
1769 :
1770 21 : real(dp) function eval_Ledd(s, ierr)
1771 : type (star_info), pointer :: s
1772 : integer, intent(out) :: ierr
1773 21 : real(dp) :: dtau1, dtau, tau, dqsum, Ledd_sum
1774 : integer :: k
1775 : logical, parameter :: dbg = .false.
1776 : include 'formats'
1777 21 : ierr = 0
1778 21 : eval_Ledd = 0d0
1779 21 : if (s% cgrav(1) <= 0d0) return
1780 21 : dtau1 = get_dtau1(s, ierr)
1781 21 : if (ierr /= 0) return
1782 21 : dtau = dtau1
1783 21 : tau = s% tau_factor*s% tau_base
1784 21 : dqsum = s% dq(1)
1785 21 : Ledd_sum = s% dq(1)*pi4*clight*s% cgrav(1)*s% m_grav(1)/s% opacity(1)
1786 2415 : do k = 2, s% nz
1787 2415 : tau = tau + dtau
1788 2415 : if (tau > s% surf_avg_tau) exit
1789 2394 : dtau = s% dm(k)*s% opacity(k)/(pi4*s% rmid(k)*s% rmid(k))
1790 2394 : dqsum = dqsum + s% dq(k)
1791 : Ledd_sum = Ledd_sum + &
1792 2415 : s% dq(k)*pi4*clight*s% cgrav(1)*s% m_grav(1)/s% opacity(k)
1793 : end do
1794 21 : eval_Ledd = Ledd_sum/dqsum
1795 21 : end function eval_Ledd
1796 :
1797 :
1798 10 : real(dp) function eval_min_cell_collapse_time(s,k_lo,k_hi,min_collapse_k,ierr) &
1799 10 : result(min_collapse_time)
1800 : type (star_info), pointer :: s
1801 : integer, intent(in) :: k_lo, k_hi
1802 : integer, intent(out) :: min_collapse_k, ierr
1803 10 : real(dp) :: rp1, vp1, r00, v00, time
1804 : integer :: k
1805 : logical, parameter :: dbg = .false.
1806 : include 'formats'
1807 10 : ierr = 0
1808 10 : rp1 = s% R_center
1809 10 : vp1 = s% v_center
1810 10 : min_collapse_time = 1d99
1811 10 : min_collapse_k = -1
1812 10 : if (.not. s% v_flag) return
1813 0 : do k = k_hi, k_lo, -1
1814 0 : v00 = s% v(k)
1815 0 : r00 = s% r(k)
1816 0 : if (r00 <= rp1) then
1817 : !ierr = -1
1818 0 : min_collapse_time = -1
1819 0 : min_collapse_k = -1
1820 0 : return
1821 : write(*,2) 'bad radii', k, r00, rp1
1822 : call mesa_error(__FILE__,__LINE__,'eval_min_cell_collapse_time')
1823 : end if
1824 0 : if (vp1 > v00) then
1825 0 : time = (r00 - rp1)/(vp1 - v00)
1826 0 : if (time < min_collapse_time) then
1827 0 : min_collapse_time = time
1828 0 : min_collapse_k = k
1829 : end if
1830 : end if
1831 0 : rp1 = r00
1832 0 : vp1 = v00
1833 : end do
1834 : end function eval_min_cell_collapse_time
1835 :
1836 :
1837 42 : real(dp) function total_angular_momentum(s) result(J)
1838 : type (star_info), pointer :: s
1839 : include 'formats'
1840 42 : if (.not. s% rotation_flag) then
1841 : J = 0
1842 : else
1843 0 : J = dot_product(s% dm_bar(1:s% nz), s% j_rot(1:s% nz))
1844 : end if
1845 42 : end function total_angular_momentum
1846 :
1847 :
1848 0 : real(dp) function eval_irradiation_heat(s,k)
1849 : type (star_info), pointer :: s
1850 : integer, intent(in) :: k
1851 0 : real(dp) :: irradiation_dq, xq, eps
1852 0 : eval_irradiation_heat = 0
1853 0 : if (s% irradiation_flux /= 0) then
1854 0 : irradiation_dq = pi4*s% r(1)*s% r(1)*s% column_depth_for_irradiation/s% xmstar
1855 0 : xq = 1 - s% q(k)
1856 0 : if (irradiation_dq > xq) then ! add irradiation heat for cell k
1857 0 : eps = 0.25d0 * s% irradiation_flux / s% column_depth_for_irradiation
1858 0 : if (irradiation_dq < xq + s% dq(k)) then ! only part of cell gets heated
1859 0 : eval_irradiation_heat = eps*(irradiation_dq - xq)/s% dq(k)
1860 : else ! all of cell gets heated
1861 : eval_irradiation_heat = eps
1862 : end if
1863 : end if
1864 : end if
1865 0 : end function eval_irradiation_heat
1866 :
1867 :
1868 0 : subroutine start_time(s, time0, total_all_before)
1869 : type (star_info), pointer :: s
1870 : integer(i8), intent(out) :: time0
1871 : real(dp), intent(out) :: total_all_before
1872 : integer(i8) :: clock_rate
1873 0 : if (.not. s% doing_timing) return
1874 0 : total_all_before = total_times(s)
1875 0 : call system_clock(time0,clock_rate)
1876 : end subroutine start_time
1877 :
1878 :
1879 0 : subroutine update_time(s, time0, total_all_before, total)
1880 : type (star_info), pointer :: s
1881 : integer(i8), intent(in) :: time0
1882 : real(dp), intent(in) :: total_all_before
1883 : real(dp), intent(inout) :: total
1884 0 : real(dp) :: total_all_after, other_stuff
1885 : integer(i8) :: time1, clock_rate
1886 0 : if (.not. s% doing_timing) return
1887 0 : call system_clock(time1,clock_rate)
1888 0 : total_all_after = total_times(s)
1889 0 : other_stuff = total_all_after - total_all_before
1890 : ! don't double count any other stuff
1891 0 : total = total + (dble(time1-time0)/clock_rate - other_stuff)
1892 : end subroutine update_time
1893 :
1894 :
1895 0 : real(dp) function total_times(s)
1896 : type (star_info), pointer :: s
1897 : total_times = &
1898 : s% time_evolve_step + &
1899 : s% time_remesh + &
1900 : s% time_adjust_mass + &
1901 : s% time_conv_premix + &
1902 : s% time_element_diffusion + &
1903 : s% time_struct_burn_mix + &
1904 : s% time_solver_matrix + &
1905 : s% time_solve_mix + &
1906 : s% time_solve_burn + &
1907 : s% time_solve_omega_mix + &
1908 : s% time_eos + &
1909 : s% time_neu_kap + &
1910 : s% time_nonburn_net + &
1911 : s% time_mlt + &
1912 : s% time_set_hydro_vars + &
1913 0 : s% time_set_mixing_info
1914 0 : end function total_times
1915 :
1916 :
1917 11 : real(dp) function get_remnant_mass(s)
1918 : type (star_info), pointer :: s
1919 11 : get_remnant_mass = s% m(1) - get_ejecta_mass(s)
1920 11 : end function get_remnant_mass
1921 :
1922 :
1923 22 : real(dp) function get_ejecta_mass(s)
1924 : use num_lib, only: find0
1925 : type (star_info), pointer :: s
1926 : integer :: k
1927 22 : real(dp) :: v, vesc, v_div_vesc, v_div_vesc_prev, dm
1928 : include 'formats'
1929 22 : get_ejecta_mass = 0d0
1930 22 : if (.not. (s% u_flag .or. s% v_flag)) return
1931 0 : v_div_vesc_prev = 0d0
1932 0 : do k=1,s% nz
1933 0 : if (s% u_flag) then
1934 : !v = s% u_face_ad(k)%val ! CANNOT USE u_face for this
1935 : ! approximate value is good enough for this estimate
1936 0 : if (k == 1) then
1937 0 : v = s% u(k)
1938 : else
1939 0 : v = 0.5d0*(s% u(k-1) + s% u(k))
1940 : end if
1941 : else
1942 0 : v = s% v(k)
1943 : end if
1944 0 : vesc = sqrt(2d0*s% cgrav(k)*s% m(k)/s% r(k))
1945 0 : v_div_vesc = v/vesc
1946 0 : if (v_div_vesc < 1d0) then
1947 0 : if (k == 1) return
1948 0 : dm = find0(0d0, v_div_vesc_prev-1d0, s% dm(k-1), v_div_vesc-1d0)
1949 0 : if (dm < 0d0) then
1950 0 : write(*,2) 'v_div_vesc_prev-1d0', k, v_div_vesc_prev-1d0
1951 0 : write(*,2) 'v_div_vesc-1d0', k, v_div_vesc-1d0
1952 0 : write(*,2) 's% dm(k-1)', k, s% dm(k-1)
1953 0 : write(*,2) 'dm', k, dm
1954 0 : call mesa_error(__FILE__,__LINE__,'get_ejecta_mass')
1955 : end if
1956 0 : if (k == 2) then
1957 : get_ejecta_mass = dm
1958 : else
1959 0 : get_ejecta_mass = sum(s% dm(1:k-2)) + dm
1960 : end if
1961 0 : return
1962 : end if
1963 0 : v_div_vesc_prev = v_div_vesc
1964 : end do
1965 22 : end function get_ejecta_mass
1966 :
1967 :
1968 220 : subroutine smooth(dc, sz)
1969 : real(dp), intent(inout) :: dc(:)
1970 : integer, intent(in) :: sz
1971 : integer :: k
1972 220 : k = 1
1973 220 : dc(k) = (3*dc(k) + dc(k+1))/4
1974 268880 : do k=2,sz-1
1975 268880 : dc(k) = (dc(k-1) + 2*dc(k) + dc(k+1))/4
1976 : end do
1977 220 : k = sz
1978 220 : dc(k) = (dc(k-1) + 3*dc(k))/4
1979 22 : end subroutine smooth
1980 :
1981 :
1982 0 : subroutine do_boxcar_mixing( &
1983 : s, min_mass, max_mass, boxcar_nominal_mass, number_iterations, ierr)
1984 : ! code based on SNEC
1985 : type (star_info), pointer :: s
1986 : real(dp), intent(in) :: min_mass, max_mass, boxcar_nominal_mass
1987 : integer, intent(in) :: number_iterations
1988 : integer, intent(out) :: ierr
1989 : integer :: nz, iter, k_inner, k_outer, j, k
1990 0 : real(dp) :: dm_sum, target_mass, actual_mass, xa, min_m, max_m
1991 : include 'formats'
1992 0 : ierr = 0
1993 0 : nz = s% nz
1994 0 : target_mass = boxcar_nominal_mass*Msun
1995 0 : min_m = min_mass*Msun
1996 0 : max_m = max_mass*Msun
1997 0 : write(*,2) 'iters min max box', number_iterations, min_mass, max_mass, boxcar_nominal_mass
1998 0 : do iter = 1, number_iterations
1999 0 : do k_inner = nz, 1, -1
2000 0 : if (s% m(k_inner) < min_m) cycle
2001 : dm_sum = 0
2002 0 : k_outer = 1
2003 0 : do k = k_inner, 1, -1
2004 0 : dm_sum = dm_sum + s% dm(k)
2005 0 : if (dm_sum > target_mass) then
2006 : k_outer = k
2007 : exit
2008 : end if
2009 : end do
2010 0 : if (s% m(k_outer) > max_m) cycle
2011 0 : actual_mass = dm_sum
2012 0 : do j=1,s% species
2013 : xa = 0d0
2014 0 : do k=k_outer,k_inner
2015 0 : xa = xa + s% xa(j,k)*s% dm(k)
2016 : end do
2017 0 : do k=k_outer,k_inner
2018 0 : s% xa(j,k) = xa/dm_sum
2019 : end do
2020 : end do
2021 0 : if (actual_mass < target_mass) exit
2022 : end do
2023 : end do
2024 0 : s% need_to_setvars = .true.
2025 0 : end subroutine do_boxcar_mixing
2026 :
2027 :
2028 79994 : subroutine get_XYZ(s, xa, X, Y, Z)
2029 : use chem_def, only: ih1, ih2, ihe3, ihe4
2030 : type (star_info), pointer :: s
2031 : real(dp), intent(in) :: xa(:)
2032 : real(dp), intent(out) :: X, Y, Z
2033 79994 : X = 0d0
2034 79994 : if (s% net_iso(ih1) /= 0) X = X + xa(s% net_iso(ih1))
2035 79994 : if (s% net_iso(ih2) /= 0) X = X + xa(s% net_iso(ih2))
2036 79994 : X = min(1d0, max(0d0, X))
2037 79994 : Y = 0d0
2038 79994 : if (s% net_iso(ihe3) /= 0) Y = Y + xa(s% net_iso(ihe3))
2039 79994 : if (s% net_iso(ihe4) /= 0) Y = Y + xa(s% net_iso(ihe4))
2040 79994 : Y = min(1d0, max(0d0, Y))
2041 79994 : Z = min(1d0, max(0d0, 1d0 - (X + Y)))
2042 79994 : end subroutine get_XYZ
2043 :
2044 :
2045 225 : subroutine get_face_values(s, v_mid, v_face, ierr)
2046 : ! simple interpolation by mass
2047 : type (star_info), pointer :: s
2048 : real(dp), intent(in) :: v_mid(:)
2049 : real(dp), intent(inout) :: v_face(:)
2050 : integer, intent(out) :: ierr
2051 : integer :: k
2052 225 : real(dp) :: dq_sum
2053 225 : ierr = 0
2054 225 : v_face(1) = v_mid(1)
2055 281420 : do k=2, s% nz
2056 281195 : dq_sum = s% dq(k-1) + s% dq(k)
2057 281420 : v_face(k) = (v_mid(k)*s% dq(k-1) + v_mid(k-1)*s% dq(k))/dq_sum
2058 : end do
2059 79994 : end subroutine get_face_values
2060 :
2061 :
2062 0 : real(dp) function get_Ledd(s,k) result(Ledd)
2063 : type (star_info), pointer :: s
2064 : integer, intent(in) :: k
2065 0 : real(dp) :: kap_face
2066 : integer :: j
2067 0 : if (k == 1) then
2068 0 : j = 2
2069 : else
2070 0 : j = k
2071 : end if
2072 0 : kap_face = interp_val_to_pt(s% opacity,j,s% nz,s% dq,'get_Ledd')
2073 0 : Ledd = pi4*clight*s% cgrav(j)*s% m_grav(j)/kap_face
2074 0 : end function get_Ledd
2075 :
2076 :
2077 0 : real(dp) function get_Lrad(s,k)
2078 : type (star_info), pointer :: s
2079 : integer, intent(in) :: k
2080 0 : get_Lrad = s% L(k) - get_Lconv(s,k)
2081 0 : end function get_Lrad
2082 :
2083 :
2084 0 : real(dp) function get_Lconv(s,k)
2085 : type (star_info), pointer :: s
2086 : integer, intent(in) :: k
2087 0 : if (k == 1) then
2088 0 : get_Lconv = 0d0
2089 : return
2090 : end if
2091 0 : if (s% RSP2_flag .or. s% RSP_flag) then
2092 0 : get_Lconv = s% Lc(k)
2093 : else
2094 0 : get_Lconv = s% L_conv(k) ! L_conv set by last call on mlt
2095 : end if
2096 : end function get_Lconv
2097 :
2098 :
2099 0 : real(dp) function get_Ladv(s,k)
2100 : type (star_info), pointer :: s
2101 : integer, intent(in) :: k
2102 0 : real(dp) :: T, Erad, v, r
2103 0 : T = s% T(k)
2104 0 : Erad = crad*T*T*T*T
2105 0 : if (s% u_flag) then
2106 0 : v = s% u(k)
2107 0 : else if (s% v_flag) then
2108 0 : v = s% v(k)
2109 : else
2110 : v = 0d0
2111 : end if
2112 0 : r = s% rmid(k)
2113 0 : get_Ladv = pi4*r*r*v*Erad
2114 0 : end function get_Ladv
2115 :
2116 :
2117 0 : real(dp) function get_Lrad_div_Ledd(s,k) result(L_rad_div_Ledd)
2118 : type (star_info), pointer :: s
2119 : integer, intent(in) :: k
2120 : integer :: j
2121 0 : real(dp) :: del_m, del_T4, area
2122 0 : if (s% cgrav(k) <= 0) then
2123 0 : L_rad_div_Ledd = 0d0
2124 : return
2125 : end if
2126 0 : if (k == 1) then
2127 : j = 2
2128 : else
2129 0 : j = k
2130 : end if
2131 0 : del_m = s% dm_bar(j)
2132 0 : del_T4 = pow4(s% T(j-1)) - pow4(s% T(j))
2133 0 : area = pi4*s% r(j)*s% r(j)
2134 : L_rad_div_Ledd = &
2135 0 : -(area*area*crad*(del_T4/del_m)/3)/(pi4*s% cgrav(j)*s% m_grav(j))
2136 0 : end function get_Lrad_div_Ledd
2137 :
2138 :
2139 : real(dp) function cell_start_specific_KE(s,k)
2140 : type (star_info), pointer :: s
2141 : integer, intent(in) :: k
2142 : cell_start_specific_KE = cell_start_specific_KE_qp(s,k)
2143 : end function cell_start_specific_KE
2144 :
2145 :
2146 52348 : real(qp) function cell_start_specific_KE_qp(s,k)
2147 : ! for consistency with dual cells at faces, use <v**2> instead of <v>**2
2148 : type (star_info), pointer :: s
2149 : integer, intent(in) :: k
2150 52348 : real(qp) :: qhalf, v0, v1, v2, Mbar
2151 52348 : qhalf = 0.5d0
2152 52348 : if (s% use_mass_corrections) then
2153 0 : Mbar = s% mass_correction(k)
2154 : else
2155 : Mbar = 1.0_qp
2156 : end if
2157 52348 : if (s% u_flag) then
2158 0 : v0 = s% u_start(k)
2159 0 : cell_start_specific_KE_qp = qhalf*Mbar*v0**2
2160 52348 : else if (s% v_flag) then
2161 0 : v0 = s% v_start(k)
2162 0 : if (k < s% nz) then
2163 0 : v1 = s% v_start(k+1)
2164 : else
2165 0 : v1 = s% v_center
2166 : end if
2167 0 : v2 = qhalf*(v0**2 + v1**2)
2168 0 : cell_start_specific_KE_qp = qhalf*Mbar*v2
2169 : else ! ignore kinetic energy if no velocity variables
2170 : cell_start_specific_KE_qp = 0d0
2171 : end if
2172 52348 : end function cell_start_specific_KE_qp
2173 :
2174 :
2175 13567 : real(dp) function cell_specific_KE(s,k,d_dv00,d_dvp1)
2176 : type (star_info), pointer :: s
2177 : integer, intent(in) :: k
2178 : real(dp), intent(out) :: d_dv00, d_dvp1
2179 13567 : cell_specific_KE = cell_specific_KE_qp(s,k,d_dv00,d_dvp1)
2180 13567 : end function cell_specific_KE
2181 :
2182 :
2183 65915 : real(qp) function cell_specific_KE_qp(s,k,d_dv00,d_dvp1)
2184 : ! for consistency with dual cells at faces, use <v**2> instead of <v>**2
2185 : type (star_info), pointer :: s
2186 : integer, intent(in) :: k
2187 : real(dp), intent(out) :: d_dv00, d_dvp1
2188 65915 : real(dp) :: dv2_dv00, dv2_dvp1
2189 65915 : real(qp) :: qhalf, v0, v1, v2, Mbar
2190 65915 : qhalf = 0.5d0
2191 65915 : if (s% use_mass_corrections) then
2192 0 : Mbar = s% mass_correction(k)
2193 : else
2194 : Mbar = 1.0_qp
2195 : end if
2196 65915 : if (s% u_flag) then
2197 0 : v0 = s% u(k)
2198 0 : cell_specific_KE_qp = qhalf*Mbar*v0**2
2199 0 : d_dv00 = s% u(k)
2200 0 : d_dvp1 = 0d0
2201 65915 : else if (s% v_flag) then
2202 0 : v0 = s% v(k)
2203 0 : if (k < s% nz) then
2204 0 : v1 = s% v(k+1)
2205 0 : dv2_dvp1 = s% v(k+1)
2206 : else
2207 0 : v1 = s% v_center
2208 0 : dv2_dvp1 = 0d0
2209 : end if
2210 0 : v2 = qhalf*(v0**2 + v1**2)
2211 0 : dv2_dv00 = s% v(k)
2212 0 : cell_specific_KE_qp = qhalf*Mbar*v2
2213 0 : d_dv00 = qhalf*Mbar*dv2_dv00
2214 0 : d_dvp1 = qhalf*Mbar*dv2_dvp1
2215 : else ! ignore kinetic energy if no velocity variables
2216 65915 : cell_specific_KE_qp = 0d0
2217 65915 : d_dv00 = 0d0
2218 65915 : d_dvp1 = 0d0
2219 : end if
2220 65915 : end function cell_specific_KE_qp
2221 :
2222 :
2223 68390 : real(dp) function cell_specific_PE(s,k,d_dlnR00,d_dlnRp1)
2224 : type (star_info), pointer :: s
2225 : integer, intent(in) :: k
2226 : real(dp), intent(out) :: d_dlnR00,d_dlnRp1
2227 13567 : cell_specific_PE = cell_specific_PE_qp(s,k,d_dlnR00,d_dlnRp1)
2228 13567 : end function cell_specific_PE
2229 :
2230 :
2231 120738 : real(qp) function cell_specific_PE_qp(s,k,d_dlnR00,d_dlnRp1)
2232 : ! for consistency with dual cells at faces, <m/r>_cntr => (m(k)/r(k) + m(k+1)/r(k+1))/2 /= m_cntr/r_cntr
2233 : ! i.e., use avg of m/r at faces of cell rather than ratio of cell center mass over cell center r.
2234 : type (star_info), pointer :: s
2235 : integer, intent(in) :: k
2236 : real(dp), intent(out) :: d_dlnR00,d_dlnRp1
2237 120738 : real(qp) :: qhalf, rp1, r00, mp1, m00, Gp1, G00, gravp1, grav00, Mbar
2238 120738 : real(dp) :: d_grav00_dlnR00, d_gravp1_dlnRp1
2239 : include 'formats'
2240 120738 : qhalf = 0.5d0
2241 120738 : if (s% use_mass_corrections) then
2242 0 : Mbar = s% mass_correction(k)
2243 : else
2244 : Mbar = 1.0_qp
2245 : end if
2246 120738 : if (k == s% nz) then
2247 99 : rp1 = s% R_center
2248 99 : mp1 = s% m_center
2249 99 : Gp1 = s% cgrav(s% nz)
2250 : else
2251 120639 : rp1 = s% r(k+1)
2252 120639 : mp1 = s% m_grav(k+1)
2253 120639 : Gp1 = s% cgrav(k+1)
2254 : end if
2255 120738 : if (rp1 <= 0d0) then
2256 99 : gravp1 = 0d0
2257 99 : d_gravp1_dlnRp1 = 0d0
2258 : else
2259 120639 : gravp1 = -Gp1*mp1/rp1
2260 120639 : d_gravp1_dlnRp1 = -gravp1
2261 : end if
2262 120738 : r00 = s% r(k)
2263 120738 : m00 = s% m_grav(k)
2264 120738 : G00 = s% cgrav(k)
2265 120738 : grav00 = -G00*m00/r00
2266 120738 : d_grav00_dlnR00 = -grav00
2267 120738 : cell_specific_PE_qp = qhalf*Mbar*(gravp1 + grav00)
2268 120738 : d_dlnR00 = qhalf*Mbar*d_grav00_dlnR00
2269 120738 : d_dlnRp1 = qhalf*Mbar*d_gravp1_dlnRp1
2270 120738 : if (is_bad(cell_specific_PE_qp)) then
2271 0 : write(*,2) 'cell_specific_PE_qp', k, cell_specific_PE_qp
2272 0 : write(*,2) 'gravp1', k, gravp1
2273 0 : write(*,2) 'grav00', k, grav00
2274 0 : call mesa_error(__FILE__,__LINE__,'cell_specific_PE')
2275 : end if
2276 120738 : end function cell_specific_PE_qp
2277 :
2278 :
2279 : real(dp) function cell_start_specific_PE(s,k)
2280 : type (star_info), pointer :: s
2281 : integer, intent(in) :: k
2282 : cell_start_specific_PE = cell_start_specific_PE_qp(s,k)
2283 : end function cell_start_specific_PE
2284 :
2285 :
2286 52348 : real(dp) function cell_start_specific_PE_qp(s,k)
2287 : ! for consistency with dual cells at faces, <m/r>_cntr => (m(k)/r(k) + m(k+1)/r(k+1))/2 /= m_cntr/r_cntr
2288 : ! i.e., use avg of m/r at faces of cell rather than ratio of cell center mass over cell center r.
2289 : type (star_info), pointer :: s
2290 : integer, intent(in) :: k
2291 52348 : real(qp) :: qhalf, rp1, r00, mp1, m00, Gp1, G00, gravp1, grav00, Mbar
2292 : include 'formats'
2293 52348 : qhalf = 0.5d0
2294 52348 : if (s% use_mass_corrections) then
2295 0 : Mbar = s% mass_correction_start(k)
2296 : else
2297 : Mbar = 1.0_qp
2298 : end if
2299 52348 : if (k == s% nz) then
2300 44 : rp1 = s% R_center
2301 44 : mp1 = s% m_center
2302 44 : Gp1 = s% cgrav(s% nz)
2303 : else
2304 52304 : rp1 = s% r_start(k+1)
2305 52304 : mp1 = s% m_grav_start(k+1)
2306 52304 : Gp1 = s% cgrav(k+1)
2307 : end if
2308 52348 : if (rp1 <= 0d0) then
2309 44 : gravp1 = 0d0
2310 : else
2311 52304 : gravp1 = -Gp1*mp1/rp1
2312 : end if
2313 52348 : r00 = s% r_start(k)
2314 52348 : m00 = s% m_grav_start(k)
2315 52348 : G00 = s% cgrav(k)
2316 52348 : grav00 = -G00*m00/r00
2317 52348 : cell_start_specific_PE_qp = qhalf*Mbar*(gravp1 + grav00)
2318 52348 : if (is_bad(cell_start_specific_PE_qp)) then
2319 0 : write(*,2) 'cell_start_specific_PE_qp', k, cell_start_specific_PE_qp
2320 0 : write(*,2) 'gravp1', k, gravp1
2321 0 : write(*,2) 'grav00', k, grav00
2322 0 : call mesa_error(__FILE__,__LINE__,'cell_start_specific_PE_qp')
2323 : end if
2324 52348 : end function cell_start_specific_PE_qp
2325 :
2326 :
2327 0 : real(dp) function cell_specific_rotational_energy(s,k)
2328 : type (star_info), pointer :: s
2329 : integer, intent(in) :: k
2330 0 : real(dp) :: e_00, e_p1
2331 0 : e_00 = s% i_rot(k)% val*s% omega(k)*s% omega(k)
2332 0 : if (k < s% nz) then
2333 0 : e_p1 = s% i_rot(k+1)% val*s% omega(k+1)*s% omega(k+1)
2334 : else
2335 : e_p1 = 0
2336 : end if
2337 0 : cell_specific_rotational_energy = 0.5d0*(e_p1 + e_00)
2338 0 : end function cell_specific_rotational_energy
2339 :
2340 :
2341 52348 : subroutine get_dke_dt_dpe_dt(s, k, dt, &
2342 : dke_dt, d_dkedt_dv00, d_dkedt_dvp1, &
2343 : dpe_dt, d_dpedt_dlnR00, d_dpedt_dlnRp1, ierr)
2344 : type (star_info), pointer :: s
2345 : integer, intent(in) :: k
2346 : real(dp), intent(in) :: dt
2347 : real(dp), intent(out) :: &
2348 : dke_dt, d_dkedt_dv00, d_dkedt_dvp1, &
2349 : dpe_dt, d_dpedt_dlnR00, d_dpedt_dlnRp1
2350 : integer, intent(out) :: ierr
2351 52348 : real(dp) :: PE_start, PE_new, KE_start, KE_new, q1
2352 : real(dp) :: dpe_dlnR00, dpe_dlnRp1, dke_dv00, dke_dvp1
2353 : include 'formats'
2354 52348 : ierr = 0
2355 : ! rate of change in specific PE (erg/g/s)
2356 52348 : PE_start = cell_start_specific_PE_qp(s,k)
2357 52348 : PE_new = cell_specific_PE_qp(s,k,dpe_dlnR00,dpe_dlnRp1)
2358 52348 : q1 = PE_new - PE_start
2359 52348 : dpe_dt = q1/dt ! erg/g/s
2360 52348 : d_dpedt_dlnR00 = dpe_dlnR00/dt
2361 52348 : d_dpedt_dlnRp1 = dpe_dlnRp1/dt
2362 : ! rate of change in specific KE (erg/g/s)
2363 52348 : KE_start = cell_start_specific_KE_qp(s,k)
2364 52348 : KE_new = cell_specific_KE_qp(s,k,dke_dv00,dke_dvp1)
2365 52348 : q1 = KE_new - KE_start
2366 52348 : dke_dt = q1/dt ! erg/g/s
2367 52348 : d_dkedt_dv00 = dke_dv00/dt
2368 52348 : d_dkedt_dvp1 = dke_dvp1/dt
2369 52348 : end subroutine get_dke_dt_dpe_dt
2370 :
2371 :
2372 : real(dp) function eval_deltaM_total_from_profile( &
2373 : deltaM, premesh_dm, profile)
2374 : real(dp), intent(in) :: deltaM
2375 : real(dp), intent(in) :: premesh_dm(:), profile(:)
2376 : real(dp) :: sum_dm, dm, total, f
2377 : integer :: k
2378 : include 'formats'
2379 : total = 0
2380 : sum_dm = 0
2381 : do k=1,size(premesh_dm,dim=1)
2382 : if (sum_dm >= deltaM) exit
2383 : dm = premesh_dm(k)
2384 : if (sum_dm + dm > deltaM) then
2385 : f = (deltaM - sum_dm)/dm
2386 : total = total + f*profile(k)
2387 : exit
2388 : end if
2389 : total = total + profile(k)
2390 : sum_dm = sum_dm + dm
2391 : end do
2392 : eval_deltaM_total_from_profile = total
2393 : end function eval_deltaM_total_from_profile
2394 :
2395 :
2396 11 : real(dp) function cell_specific_total_energy(s, k) result(cell_total)
2397 : type (star_info), pointer :: s
2398 : integer, intent(in) :: k
2399 11 : real(dp) :: d_dv00,d_dvp1,d_dlnR00,d_dlnRp1
2400 : include 'formats'
2401 11 : cell_total = s% energy(k)
2402 11 : if (s% v_flag .or. s% u_flag) &
2403 0 : cell_total = cell_total + cell_specific_KE(s,k,d_dv00,d_dvp1)
2404 11 : cell_total = cell_total + cell_specific_PE(s,k,d_dlnR00,d_dlnRp1)
2405 11 : if (s% rotation_flag .and. s% include_rotation_in_total_energy) &
2406 0 : cell_total = cell_total + cell_specific_rotational_energy(s,k)
2407 11 : if (s% RSP2_flag) cell_total = cell_total + pow2(s% w(k))
2408 11 : if (s% rsp_flag) cell_total = cell_total + s% RSP_Et(k)
2409 11 : end function cell_specific_total_energy
2410 :
2411 :
2412 0 : subroutine eval_integrated_total_energy_profile(s, arr, direction, ierr)
2413 : type (star_info), pointer :: s
2414 : integer, intent(in) :: direction
2415 : integer, intent(out) :: ierr
2416 : real(dp), intent(out) :: arr(:)
2417 : integer :: k, start, finish
2418 :
2419 0 : ierr = 0
2420 0 : if (direction == 1) then
2421 0 : start = 1
2422 0 : finish = s%nz
2423 0 : else if (direction == -1) then
2424 0 : start = s%nz
2425 0 : finish = 1
2426 : else
2427 0 : ierr = 1
2428 0 : call mesa_error(__FILE__,__LINE__)
2429 : end if
2430 :
2431 0 : arr(start) = cell_specific_total_energy(s,start) * s%dm(start)
2432 0 : do k=start+direction, finish, direction
2433 0 : arr(k) = arr(k-direction) + cell_specific_total_energy(s,k) * s%dm(k)
2434 : end do
2435 :
2436 0 : end subroutine eval_integrated_total_energy_profile
2437 :
2438 45 : subroutine eval_deltaM_total_energy_integrals( &
2439 : s, klo, khi, deltaM, save_profiles, &
2440 45 : total_energy_profile, &
2441 : total_internal_energy, total_gravitational_energy, &
2442 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2443 : total_turbulent_energy, sum_total)
2444 : type (star_info), pointer :: s
2445 : integer, intent(in) :: klo, khi ! sum from klo to khi
2446 : real(dp), intent(in) :: deltaM
2447 : logical, intent(in) :: save_profiles
2448 : real(dp), intent(out), dimension(:) :: total_energy_profile
2449 : real(dp), intent(out) :: &
2450 : total_internal_energy, total_gravitational_energy, &
2451 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2452 : total_turbulent_energy, sum_total
2453 : integer :: k
2454 45 : real(dp) :: dm, sum_dm, cell_total, cell1, d_dv00, d_dvp1, d_dlnR00, d_dlnRp1, alfa, beta,TDC_eturb_cell
2455 : include 'formats'
2456 :
2457 45 : total_internal_energy = 0d0
2458 45 : total_gravitational_energy = 0d0
2459 45 : total_radial_kinetic_energy = 0d0
2460 45 : total_rotational_kinetic_energy = 0d0
2461 45 : total_turbulent_energy = 0d0
2462 45 : sum_total = 0d0
2463 :
2464 45 : if (klo < 1 .or. khi > s% nz .or. klo > khi) return
2465 :
2466 45 : sum_dm = 0
2467 54857 : do k=klo,khi
2468 54812 : if (sum_dm >= deltaM) exit
2469 54812 : cell_total = 0
2470 54812 : dm = s% dm(k)
2471 54812 : if (sum_dm + dm > deltaM) dm = deltaM - sum_dm
2472 54812 : cell1 = dm*s% energy(k)
2473 54812 : cell_total = cell_total + cell1
2474 54812 : total_internal_energy = total_internal_energy + cell1
2475 54812 : if (s% v_flag .or. s% u_flag) then
2476 0 : cell1 = dm*cell_specific_KE(s,k,d_dv00,d_dvp1)
2477 0 : cell_total = cell_total + cell1
2478 0 : total_radial_kinetic_energy = total_radial_kinetic_energy + cell1
2479 : end if
2480 54812 : cell1 = dm*cell_specific_PE(s,k,d_dlnR00,d_dlnRp1)
2481 54812 : cell_total = cell_total + cell1
2482 54812 : total_gravitational_energy = total_gravitational_energy + cell1
2483 54812 : if (s% rotation_flag) then
2484 0 : cell1 = dm*cell_specific_rotational_energy(s,k)
2485 0 : total_rotational_kinetic_energy = total_rotational_kinetic_energy + cell1
2486 0 : if (s% include_rotation_in_total_energy) &
2487 0 : cell_total = cell_total + cell1
2488 : end if
2489 54812 : if (s% RSP2_flag) then
2490 0 : cell1 = dm*pow2(s% w(k))
2491 0 : cell_total = cell_total + cell1
2492 0 : total_turbulent_energy = total_turbulent_energy + cell1
2493 54812 : else if (.not. s% RSP2_flag .and. s% mlt_vc(k) > 0d0 .and. s% MLT_option == 'TDC' .and. &
2494 : s% TDC_include_eturb_in_energy_equation) then
2495 : ! write a wrapper for this.
2496 0 : if (k == 1) then
2497 0 : TDC_eturb_cell = pow2(s% mlt_vc(k)/sqrt_2_div_3)
2498 : else
2499 0 : call get_face_weights(s, k, alfa, beta)
2500 : TDC_eturb_cell = alfa*pow2(s% mlt_vc(k)/sqrt_2_div_3) + &
2501 0 : beta*pow2(s% mlt_vc(k-1)/sqrt_2_div_3)
2502 : end if
2503 0 : cell1 = dm*TDC_eturb_cell
2504 0 : cell_total = cell_total + cell1
2505 0 : total_turbulent_energy = total_turbulent_energy + cell1
2506 : end if
2507 54812 : if (s% rsp_flag) then
2508 0 : cell1 = dm*s% RSP_Et(k)
2509 0 : cell_total = cell_total + cell1
2510 0 : total_turbulent_energy = total_turbulent_energy + cell1
2511 : end if
2512 54857 : if (save_profiles) then
2513 13087 : total_energy_profile(k) = cell_total
2514 : end if
2515 : end do
2516 :
2517 : sum_total = total_internal_energy + total_gravitational_energy + &
2518 45 : total_radial_kinetic_energy + total_turbulent_energy
2519 :
2520 45 : if (s% include_rotation_in_total_energy) &
2521 0 : sum_total = sum_total + total_rotational_kinetic_energy
2522 :
2523 : end subroutine eval_deltaM_total_energy_integrals
2524 :
2525 :
2526 0 : subroutine eval_total_energy_profile(s, total_energy_profile)
2527 : type (star_info), pointer :: s
2528 : real(dp), intent(out), dimension(:) :: total_energy_profile
2529 :
2530 : integer :: k
2531 0 : real(dp) :: dm, cell_total, cell1, d_dv00, d_dvp1, d_dlnR00, d_dlnRp1
2532 : include 'formats'
2533 :
2534 0 : do k=1, s%nz
2535 0 : cell_total = 0
2536 0 : dm = s% dm(k)
2537 0 : cell1 = dm*s% energy(k)
2538 0 : cell_total = cell_total + cell1
2539 0 : if (s% v_flag .or. s% u_flag) then
2540 0 : cell1 = dm*cell_specific_KE(s,k,d_dv00,d_dvp1)
2541 0 : cell_total = cell_total + cell1
2542 : end if
2543 0 : cell1 = dm*cell_specific_PE(s,k,d_dlnR00,d_dlnRp1)
2544 0 : cell_total = cell_total + cell1
2545 0 : if (s% rotation_flag) then
2546 0 : cell1 = dm*cell_specific_rotational_energy(s,k)
2547 0 : if (s% include_rotation_in_total_energy) &
2548 0 : cell_total = cell_total + cell1
2549 : end if
2550 0 : if (s% RSP2_flag) then
2551 0 : cell1 = dm*pow2(s% w(k))
2552 0 : cell_total = cell_total + cell1
2553 : end if
2554 0 : if (s% rsp_flag) then
2555 0 : cell1 = dm*s% RSP_Et(k)
2556 0 : cell_total = cell_total + cell1
2557 : end if
2558 0 : total_energy_profile(k) = cell_total
2559 : end do
2560 :
2561 0 : end subroutine eval_total_energy_profile
2562 :
2563 :
2564 0 : real(dp) function eval_cell_section_total_energy( &
2565 : s, klo, khi) result(sum_total)
2566 : type (star_info), pointer :: s
2567 : integer, intent(in) :: klo, khi ! sum from klo to khi
2568 : real(dp) :: &
2569 : total_internal_energy, total_gravitational_energy, &
2570 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2571 : total_turbulent_energy
2572 0 : real(dp), allocatable, dimension(:) :: total_energy_profile
2573 0 : allocate(total_energy_profile(1:s% nz))
2574 : call eval_deltaM_total_energy_integrals( &
2575 : s, klo, khi, s% mstar, .false., &
2576 : total_energy_profile, &
2577 : total_internal_energy, total_gravitational_energy, &
2578 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2579 0 : total_turbulent_energy, sum_total)
2580 0 : end function eval_cell_section_total_energy
2581 :
2582 :
2583 33 : subroutine eval_total_energy_integrals(s, &
2584 : total_internal_energy, total_gravitational_energy, &
2585 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2586 : total_turbulent_energy, sum_total)
2587 : type (star_info), pointer :: s
2588 : real(dp), intent(out) :: &
2589 : total_internal_energy, total_gravitational_energy, &
2590 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2591 : total_turbulent_energy, sum_total
2592 33 : real(dp), allocatable, dimension(:) :: total_energy_profile
2593 33 : allocate(total_energy_profile(1:s% nz))
2594 : call eval_deltaM_total_energy_integrals( &
2595 : s, 1, s% nz, s% mstar, .false., &
2596 : total_energy_profile, &
2597 : total_internal_energy, total_gravitational_energy, &
2598 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2599 33 : total_turbulent_energy, sum_total)
2600 33 : end subroutine eval_total_energy_integrals
2601 :
2602 :
2603 : subroutine eval_total_energy_integrals_and_profile(s, &
2604 : total_energy_profile, &
2605 : total_internal_energy, total_gravitational_energy, &
2606 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2607 : total_turbulent_energy, sum_total)
2608 : type (star_info), pointer :: s
2609 : real(dp), intent(out) :: total_energy_profile(:), &
2610 : total_internal_energy, total_gravitational_energy, &
2611 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2612 : total_turbulent_energy, sum_total
2613 : call eval_deltaM_total_energy_integrals( &
2614 : s, 1, s% nz, s% mstar, .true., &
2615 : total_energy_profile, &
2616 : total_internal_energy, total_gravitational_energy, &
2617 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2618 : total_turbulent_energy, sum_total)
2619 : end subroutine eval_total_energy_integrals_and_profile
2620 :
2621 :
2622 : real(dp) function get_total_energy_integral(s,k) result(sum_total)
2623 : ! from surface down to k
2624 : type (star_info), pointer :: s
2625 : integer, intent(in) :: k
2626 : real(dp) :: &
2627 : total_internal_energy, total_gravitational_energy, &
2628 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2629 : total_turbulent_energy
2630 : real(dp), allocatable, dimension(:) :: total_energy_profile
2631 : allocate(total_energy_profile(1:s% nz))
2632 : call eval_deltaM_total_energy_integrals( &
2633 : s, 1, k, s% mstar, .false., &
2634 : total_energy_profile, &
2635 : total_internal_energy, total_gravitational_energy, &
2636 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2637 : total_turbulent_energy, sum_total)
2638 : end function get_total_energy_integral
2639 :
2640 :
2641 : real(dp) function get_total_energy_integral_outward(s,k) result(sum_total)
2642 : ! from surface down to k
2643 : type (star_info), pointer :: s
2644 : integer, intent(in) :: k
2645 : real(dp) :: &
2646 : total_internal_energy, total_gravitational_energy, &
2647 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2648 : total_turbulent_energy
2649 : real(dp), allocatable, dimension(:) :: total_energy_profile
2650 : allocate(total_energy_profile(1:s% nz))
2651 : call eval_deltaM_total_energy_integrals( &
2652 : s, k, s% nz, s% mstar, .false., &
2653 : total_energy_profile, &
2654 : total_internal_energy, total_gravitational_energy, &
2655 : total_radial_kinetic_energy, total_rotational_kinetic_energy, &
2656 : total_turbulent_energy, sum_total)
2657 : end function get_total_energy_integral_outward
2658 :
2659 :
2660 0 : real(dp) function get_log_concentration(s,j,k) result(log_c)
2661 : use chem_def, only: chem_isos
2662 : type (star_info), pointer :: s
2663 : integer, intent(in) :: j, k
2664 : ! concentration = number density / number density of electrons
2665 : ! Ci = (Xi/Ai) / sum(Zi*Xi/Ai) [see Thoul et al, ApJ 421:828-842, 1994]
2666 : integer :: i, cid, species
2667 0 : real(dp) :: tmp, c
2668 0 : log_c = -1d99
2669 0 : if (s% chem_id(j) == 0) return
2670 0 : species = s% species
2671 0 : tmp = 0d0
2672 0 : do i=1,species
2673 0 : cid = s% chem_id(i)
2674 0 : tmp = tmp + chem_isos% Z(cid)*s% xa(i,k)/chem_isos% Z_plus_N(cid)
2675 : end do
2676 0 : cid = s% chem_id(j)
2677 0 : c = (s% xa(j,k)/chem_isos% Z_plus_N(cid))/tmp
2678 0 : log_c = safe_log10(c)
2679 0 : end function get_log_concentration
2680 :
2681 :
2682 0 : real(dp) function get_phi_Joss(s,k) result(phi)
2683 0 : use eos_def, only: i_lnPgas
2684 : ! Joss, Salpeter, Ostriker, 1973. density inversion when Lrad/Ledd > phi.
2685 : type (star_info), pointer :: s
2686 : integer, intent(in) :: k
2687 0 : phi = 1d0/(1d0 + (s% Pgas(k)/(4* s% Prad(k)))*s% d_eos_dlnT(i_lnPgas,k))
2688 0 : end function get_phi_Joss
2689 :
2690 :
2691 0 : logical function after_He_burn(s, he4_limit)
2692 0 : use chem_def
2693 : type (star_info), pointer :: s
2694 : real(dp), intent(in) :: he4_limit
2695 : integer :: nz, h1, he4
2696 : real(dp), parameter :: small = 1d-4
2697 0 : after_He_burn = .false.
2698 0 : nz = s% nz
2699 0 : h1 = s% net_iso(ih1)
2700 0 : he4 = s% net_iso(ihe4)
2701 0 : if (h1 == 0 .or. he4 == 0) return
2702 0 : if (s% xa(h1,nz) > small .or. s% xa(he4,nz) > he4_limit) return
2703 0 : after_He_burn = .true.
2704 0 : end function after_He_burn
2705 :
2706 :
2707 0 : logical function after_C_burn(s, c12_limit)
2708 0 : use chem_def
2709 : type (star_info), pointer :: s
2710 : real(dp), intent(in) :: c12_limit
2711 : integer :: nz, h1, he4, c12
2712 : real(dp), parameter :: small = 1d-4
2713 0 : after_C_burn = .false.
2714 0 : nz = s% nz
2715 0 : h1 = s% net_iso(ih1)
2716 0 : he4 = s% net_iso(ihe4)
2717 0 : c12 = s% net_iso(ic12)
2718 0 : if (h1 == 0 .or. he4 == 0 .or. c12 == 0) return
2719 0 : if (s% xa(h1,nz) > small .or. s% xa(he4,nz) > small .or. &
2720 0 : s% xa(c12,nz) > c12_limit) return
2721 0 : after_C_burn = .true.
2722 0 : end function after_C_burn
2723 :
2724 :
2725 0 : integer function lookup_nameofvar(s, namestr)
2726 : type (star_info), pointer :: s
2727 : character (len=*), intent(in) :: namestr
2728 : integer :: i
2729 0 : lookup_nameofvar = 0
2730 0 : do i=1,s% nvar_total
2731 0 : if (namestr == s% nameofvar(i)) then
2732 0 : lookup_nameofvar = i
2733 0 : return
2734 : end if
2735 : end do
2736 0 : end function lookup_nameofvar
2737 :
2738 :
2739 0 : integer function lookup_nameofequ(s, namestr)
2740 : type (star_info), pointer :: s
2741 : character (len=*), intent(in) :: namestr
2742 : integer :: i
2743 0 : lookup_nameofequ = 0
2744 0 : do i=1,s% nvar_total
2745 0 : if (namestr == s% nameofequ(i)) then
2746 0 : lookup_nameofequ = i
2747 0 : return
2748 : end if
2749 : end do
2750 : end function lookup_nameofequ
2751 :
2752 :
2753 0 : real(dp) function omega_crit(s, k) ! result always is > 0
2754 : type (star_info), pointer :: s
2755 : integer, intent(in) :: k
2756 0 : real(dp) :: Ledd, gamma_factor, Lrad_div_Ledd, rmid, r003, rp13
2757 : include 'formats'
2758 0 : if (s% rotation_flag) then
2759 : ! Use equatorial radius (at center of cell by volume)
2760 0 : r003 = s% r_equatorial(k)*s% r_equatorial(k)*s% r_equatorial(k)
2761 0 : if (k < s% nz) then
2762 0 : rp13 = s% r_equatorial(k+1)*s% r_equatorial(k+1)*s% r_equatorial(k+1)
2763 : else
2764 0 : rp13 = s% R_center*s% R_center*s% R_center
2765 : end if
2766 0 : rmid = pow(0.5d0*(r003 + rp13),one_third)
2767 : else
2768 0 : rmid = s% rmid(k)
2769 : end if
2770 :
2771 0 : Ledd = pi4*clight*s% cgrav(k)*s% m_grav(k)/s% opacity(k)
2772 0 : Lrad_div_Ledd = get_Lrad_div_Ledd(s,k)
2773 0 : gamma_factor = 1d0 - min(Lrad_div_Ledd, 0.9999d0)
2774 0 : omega_crit = sqrt(gamma_factor*s% cgrav(k)*s% m_grav(k)/pow3(rmid))
2775 0 : end function omega_crit
2776 :
2777 :
2778 89 : subroutine weighted_smoothing(dd, n, ns, preserve_sign, ddold)
2779 : ! based on routine written by S.-C. Yoon, 18 Sept. 2002
2780 : ! for smoothing any variable (dd) with size n over 2*ns+1 cells.
2781 : real(dp), intent(inout) :: dd(:) ! (n)
2782 : integer, intent(in) :: n, ns
2783 : logical, intent(in) :: preserve_sign
2784 : real(dp), intent(inout) :: ddold(:) ! (n) work array
2785 :
2786 : integer :: nweight, mweight, i, j, k
2787 622 : real(dp) :: weight(2*ns+1), sweight, v0
2788 :
2789 : include 'formats'
2790 :
2791 110193 : do i = 1,n
2792 110193 : ddold(i) = dd(i)
2793 : end do
2794 :
2795 : !--preparation for smoothing --------
2796 : nweight = ns
2797 : mweight = 2*nweight+1
2798 622 : do i = 1,mweight
2799 622 : weight(i) = 0d0
2800 : end do
2801 89 : weight(1) = 1d0
2802 533 : do i = 1,mweight-1
2803 1907 : do j = i+1,2,-1
2804 1818 : weight(j) = weight(j) + weight(j-1)
2805 : end do
2806 : end do
2807 :
2808 : !--smoothing ------------------------
2809 110015 : do i=2,n-1
2810 109926 : sweight=0d0
2811 109926 : dd(i)=0d0
2812 109926 : v0 = ddold(i)
2813 493259 : do j = i, max(1,i-nweight), -1
2814 383333 : k=j-i+nweight+1
2815 383333 : if (preserve_sign .and. v0*ddold(j) <= 0) exit
2816 383333 : sweight = sweight+weight(k)
2817 493259 : dd(i) = dd(i)+ddold(j)*weight(k)
2818 : end do
2819 383333 : do j = i+1, min(n,i+nweight)
2820 273407 : k=j-i+nweight+1
2821 273407 : if (preserve_sign .and. v0*ddold(j) <= 0) exit
2822 273407 : sweight = sweight+weight(k)
2823 383333 : dd(i) = dd(i)+ddold(j)*weight(k)
2824 : end do
2825 110015 : if (sweight > 0) then
2826 109926 : sweight = 1d0/sweight
2827 109926 : dd(i) = dd(i)*sweight
2828 : end if
2829 : end do
2830 :
2831 89 : end subroutine weighted_smoothing
2832 :
2833 :
2834 89 : subroutine threshold_smoothing(dd, dd_thresh, n, ns, preserve_sign, ddold)
2835 :
2836 : ! Same as weighted_smoothing, but only smooth contiguous regions where |dd| >= dd_thresh
2837 :
2838 : real(dp), intent(inout) :: dd(:) ! (n)
2839 : real(dp), intent(in) :: dd_thresh
2840 : integer, intent(in) :: n
2841 : integer, intent(in) :: ns
2842 : logical, intent(in) :: preserve_sign
2843 : real(dp), intent(inout) :: ddold(:) ! (n) work array
2844 :
2845 : logical :: in_region
2846 : integer :: i
2847 : integer :: i_a
2848 : integer :: i_b
2849 :
2850 : include 'formats'
2851 :
2852 : ! Process regions
2853 :
2854 89 : in_region = .FALSE.
2855 :
2856 89 : i_a = 1
2857 110193 : do i = 1, n
2858 :
2859 110193 : if (in_region) then
2860 :
2861 110015 : if (ABS(dd(i)) < dd_thresh) then
2862 0 : i_b = i-1
2863 0 : if (i_b > i_a) call weighted_smoothing(dd(i_a:i_b), i_b-i_a+1, ns, preserve_sign, ddold(i_a:i_b))
2864 : in_region = .FALSE.
2865 : end if
2866 :
2867 : else
2868 89 : if (ABS(dd(i)) >= dd_thresh) then
2869 110104 : i_a = i
2870 110104 : in_region = .TRUE.
2871 : end if
2872 :
2873 : end if
2874 :
2875 : end do
2876 :
2877 : ! Handle the final region
2878 :
2879 89 : if (in_region) then
2880 :
2881 89 : i_b = n
2882 89 : if (i_b > i_a) call weighted_smoothing(dd(i_a:i_b), i_b-i_a+1, ns, preserve_sign, ddold(i_a:i_b))
2883 :
2884 : end if
2885 :
2886 89 : return
2887 :
2888 : end subroutine threshold_smoothing
2889 :
2890 :
2891 33 : real(dp) function eval_kh_timescale(G,M,R,L) result(kh)
2892 : real(dp), intent(in) :: G,M,R,L
2893 33 : if (L <= 0) then
2894 : kh = 0d0
2895 : else
2896 33 : kh = 0.75d0*G*M*M/(R*L) ! 0.75 is based on sun. Hansen & Kawaler eqn 1.30
2897 : end if
2898 33 : end function eval_kh_timescale
2899 :
2900 :
2901 1 : real(dp) function yrs_for_init_timestep(s)
2902 : type (star_info), pointer :: s
2903 1 : if (s% initial_mass <= 1) then
2904 : yrs_for_init_timestep = 1d5
2905 : else
2906 1 : yrs_for_init_timestep = 1d5 / pow(s% initial_mass,2.5d0)
2907 : end if
2908 1 : end function yrs_for_init_timestep
2909 :
2910 :
2911 12 : subroutine set_phase_of_evolution(s) ! from evolve after call do_report
2912 : use rates_def, only: i_rate
2913 : use chem_def
2914 : type (star_info), pointer :: s
2915 12 : real(dp) :: center_h1, center_he4
2916 : integer :: nz, j
2917 : include 'formats'
2918 12 : nz = s% nz
2919 :
2920 12 : s% phase_of_evolution = phase_starting
2921 12 : if (s%doing_first_model_of_run) return
2922 :
2923 10 : j = s% net_iso(ih1)
2924 10 : if (j > 0) then
2925 10 : center_h1 = center_avg_x(s,j)
2926 : else
2927 : center_h1 = 1d99
2928 : end if
2929 10 : j = s% net_iso(ihe4)
2930 10 : if (j > 0) then
2931 10 : center_he4 = center_avg_x(s,j)
2932 : else
2933 : center_he4 = 1d99
2934 : end if
2935 :
2936 10 : if (s% doing_relax) then
2937 0 : s% phase_of_evolution = phase_relax
2938 10 : else if (s% photosphere_logg > 6d0) then
2939 0 : s% phase_of_evolution = phase_WDCS
2940 10 : else if (s% L_by_category(i_burn_si) > 1d2) then
2941 0 : s% phase_of_evolution = phase_Si_Burn
2942 10 : else if ( (s% L_by_category(ioo) + s% L_by_category(ico)) > 1d2 .and. center_he4 < 1d-4) then
2943 0 : s% phase_of_evolution = phase_O_Burn
2944 10 : else if (s% L_by_category(i_burn_ne) > 1d2 .and. center_he4 < 1d-4) then
2945 0 : s% phase_of_evolution = phase_Ne_Burn
2946 10 : else if (s% L_by_category(icc) > 1d2 .and. center_he4 < 1d-4) then
2947 0 : s% phase_of_evolution = phase_C_Burn
2948 : else if (center_he4 < 1d-4 .and. &
2949 40 : s% he_core_mass - s% co_core_mass <= 0.1d0 .and. &
2950 : any(s% burn_he_conv_region(1:s% num_conv_boundaries))) then
2951 0 : s% phase_of_evolution = phase_TP_AGB
2952 10 : else if (center_he4 <= 1d-4) then
2953 0 : s% phase_of_evolution = phase_TACHeB
2954 10 : else if (s% center_eps_burn(i3alf) > 1d2) then
2955 0 : s% phase_of_evolution = phase_ZACHeB
2956 10 : else if (s% L_by_category(i3alf) > 1d2) then
2957 0 : s% phase_of_evolution = phase_He_Burn
2958 10 : else if (center_h1 <= 1d-6) then
2959 0 : s% phase_of_evolution = phase_TAMS
2960 10 : else if (center_h1 <= 0.3d0) then
2961 0 : s% phase_of_evolution = phase_IAMS
2962 10 : else if (s% L_nuc_burn_total >= s% L_phot*s% Lnuc_div_L_zams_limit) then
2963 10 : s% phase_of_evolution = phase_ZAMS
2964 0 : else if (s% log_center_temperature > 5d0) then
2965 0 : s% phase_of_evolution = phase_PreMS
2966 : else
2967 : s% phase_of_evolution = phase_starting
2968 : end if
2969 :
2970 12 : end subroutine set_phase_of_evolution
2971 :
2972 :
2973 79994 : subroutine set_rv_info(s,k)
2974 : type (star_info), pointer :: s
2975 : integer, intent(in) :: k
2976 : include 'formats'
2977 79994 : if (s% v_flag) then
2978 0 : if (s% using_velocity_time_centering) then
2979 0 : s% vc(k) = 0.5d0*(s% v_start(k) + s% v(k))
2980 : else
2981 0 : s% vc(k) = s% v(k)
2982 : end if
2983 : else
2984 79994 : s% vc(k) = 0d0
2985 : end if
2986 12 : end subroutine set_rv_info
2987 :
2988 :
2989 0 : subroutine show_matrix(s, dmat, nvar)
2990 : type (star_info), pointer :: s
2991 : integer, intent(in) :: nvar
2992 : real(dp) :: dmat(nvar,nvar)
2993 : integer :: i, j
2994 0 : write(*,'(A)')
2995 0 : write(*,'(18x)', advance = 'no')
2996 0 : do j = 1, nvar
2997 0 : write(*,'(a15)', advance = 'no') s% nameofvar(j)
2998 : end do
2999 0 : write(*,'(A)')
3000 0 : do i = 1, nvar
3001 0 : write(*,'(a15)', advance = 'no') s% nameofequ(i)
3002 0 : do j = 1, nvar
3003 0 : write(*,'(e13.4,2x)', advance = 'no') dmat(i,j)
3004 : end do
3005 0 : write(*,'(A)')
3006 : end do
3007 0 : write(*,'(A)')
3008 0 : end subroutine show_matrix
3009 :
3010 :
3011 : ! e00(i,j,k) is partial of equ(i,k) wrt var(j,k)
3012 8375328 : subroutine e00(s,i,j,k,nvar,v)
3013 : type (star_info), pointer :: s
3014 : integer, intent(in) :: i, j, k, nvar
3015 : real(dp), intent(in) :: v
3016 : logical, parameter :: dbg = .false.
3017 : include 'formats'
3018 :
3019 : if (mdb .and. k==397 .and. v /= 0d0) &
3020 : write(*,4) 'e00(i,j,k) ' // &
3021 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3022 :
3023 : !if (j == s% i_lnd .and. k /= s% nz) return ! this variable is being held constant
3024 :
3025 8375328 : if (v == 0d0) return
3026 :
3027 : if (.false. .and. j == s% i_lnT .and. k == 30) then
3028 : write(*,4) 'e00(i,j,k) ' // &
3029 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v, s% x_scale(j,k)
3030 : end if
3031 :
3032 3641728 : if (is_bad(v)) then
3033 0 : !$omp critical (star_utils_e00_crit1)
3034 : write(*,4) 'e00(i,j,k) ' // &
3035 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3036 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'1 e00')
3037 : !$omp end critical (star_utils_e00_crit1)
3038 : end if
3039 :
3040 3641728 : if (i <= 0 .or. j <= 0 .or. k <= 0 .or. k > s% nz) then
3041 : write(*,4) 'bad i,j,k e00(i,j,k) ' // &
3042 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3043 0 : call mesa_error(__FILE__,__LINE__,'2 e00')
3044 : end if
3045 :
3046 3641728 : if (j > nvar) return ! hybrid
3047 :
3048 3641728 : if (i > nvar) then
3049 0 : !$omp critical (star_utils_e00_crit2)
3050 : write(*,5) 'bad i e00(i,j,k) ' // &
3051 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), &
3052 0 : s% solver_iter, i, j, k, v
3053 0 : call mesa_error(__FILE__,__LINE__,'3 e00')
3054 : !$omp end critical (star_utils_e00_crit2)
3055 : end if
3056 :
3057 3641728 : if (abs(v) < 1d-250) return
3058 :
3059 3641728 : s% dblk(i,j,k) = s% dblk(i,j,k) + v*s% x_scale(j,k)
3060 :
3061 : end subroutine e00
3062 :
3063 :
3064 : ! em1(i,j,k) is partial of equ(i,k) wrt var(j,k-1)
3065 3766240 : subroutine em1(s,i,j,k,nvar,v)
3066 : type (star_info), pointer :: s
3067 : integer, intent(in) :: i, j, k, nvar
3068 : real(dp), intent(in) :: v
3069 : logical, parameter :: dbg = .false.
3070 3766240 : if (k == 1) return
3071 : include 'formats'
3072 :
3073 : if (mdb .and. k==397 .and. v /= 0d0) &
3074 : write(*,4) 'em1(i,j,k) ' // &
3075 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3076 :
3077 3765888 : if (v == 0d0) return
3078 :
3079 : if (.false. .and. j == s% i_lnT .and. k == 31) then
3080 : write(*,4) 'em1(i,j,k) ' // &
3081 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v, s% x_scale(j,k-1)
3082 : end if
3083 :
3084 887140 : if (is_bad(v)) then
3085 0 : !$omp critical (star_utils_em1_crit1)
3086 : write(*,4) 'em1(i,j,k) ' // &
3087 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3088 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'em1')
3089 : !$omp end critical (star_utils_em1_crit1)
3090 : end if
3091 :
3092 887140 : if (i <= 0 .or. j <= 0 .or. k <= 0 .or. k > s% nz) then
3093 : write(*,4) 'bad i,j,k em1(i,j,k) ' // &
3094 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3095 0 : call mesa_error(__FILE__,__LINE__,'em1')
3096 : end if
3097 :
3098 887140 : if (j > nvar) return ! hybrid
3099 :
3100 887140 : if (i > nvar) then
3101 : write(*,5) 'bad i em1(i,j,k) ' // &
3102 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), &
3103 0 : s% solver_iter, i, j, k, v
3104 0 : call mesa_error(__FILE__,__LINE__,'em1')
3105 : end if
3106 :
3107 887140 : if (abs(v) < 1d-250) return
3108 :
3109 887140 : s% lblk(i,j,k) = s% lblk(i,j,k) + v*s% x_scale(j,k-1)
3110 :
3111 : end subroutine em1
3112 :
3113 :
3114 : ! ep1(i,j,k) is partial of equ(i,k) wrt var(j,k+1)
3115 3766240 : subroutine ep1(s,i,j,k,nvar,v)
3116 : type (star_info), pointer :: s
3117 : integer, intent(in) :: i, j, k, nvar
3118 : real(dp), intent(in) :: v
3119 : logical, parameter :: dbg = .false.
3120 : include 'formats'
3121 :
3122 : if (mdb .and. k==397 .and. v /= 0d0) &
3123 : write(*,4) 'ep1(i,j,k) ' // &
3124 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3125 :
3126 3766240 : if (v == 0d0) return
3127 :
3128 : if (.false. .and. j == s% i_lnT .and. k == 29) then
3129 : write(*,4) 'ep1(i,j,k) ' // &
3130 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v, s% x_scale(j,k+1)
3131 : end if
3132 :
3133 526718 : if (is_bad(v)) then
3134 0 : !$omp critical (star_utils_ep1_crit1)
3135 : write(*,4) 'ep1(i,j,k) ' // &
3136 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3137 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'ep1')
3138 : !$omp end critical (star_utils_ep1_crit1)
3139 : end if
3140 :
3141 526718 : if (i <= 0 .or. j <= 0 .or. k <= 0 .or. k > s% nz) then
3142 : write(*,4) 'bad i,j,k ep1(i,j,k) ' // &
3143 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), i, j, k, v
3144 0 : call mesa_error(__FILE__,__LINE__,'ep1')
3145 : end if
3146 :
3147 526718 : if (j > nvar) return
3148 :
3149 526718 : if (i > nvar) then
3150 : write(*,5) 'bad i ep1(i,j,k) ' // &
3151 0 : trim(s% nameofequ(i)) // ' ' // trim(s% nameofvar(j)), &
3152 0 : s% solver_iter, i, j, k, v
3153 0 : call mesa_error(__FILE__,__LINE__,'ep1')
3154 : end if
3155 :
3156 526718 : if (abs(v) < 1d-250) return
3157 :
3158 526718 : s% ublk(i,j,k) = s% ublk(i,j,k) + v*s% x_scale(j,k+1)
3159 :
3160 : end subroutine ep1
3161 :
3162 :
3163 66 : real(dp) function current_min_xa_hard_limit(s) result(min_xa_hard_limit)
3164 : type (star_info), pointer :: s
3165 66 : real(dp) :: logTc, alfa
3166 66 : logTc = s% lnT(s% nz)/ln10
3167 66 : if (logTc <= s% logT_max_for_min_xa_hard_limit) then
3168 66 : min_xa_hard_limit = s% min_xa_hard_limit
3169 0 : else if (logTc >= s% logT_min_for_min_xa_hard_limit_for_highT) then
3170 0 : min_xa_hard_limit = s% min_xa_hard_limit_for_highT
3171 : else
3172 : alfa = (logTc - s% logT_max_for_min_xa_hard_limit) / &
3173 0 : (s% logT_min_for_min_xa_hard_limit_for_highT - s% logT_max_for_min_xa_hard_limit)
3174 : min_xa_hard_limit = &
3175 0 : alfa*s% min_xa_hard_limit_for_highT + (1d0 - alfa)*s% min_xa_hard_limit
3176 : end if
3177 66 : end function current_min_xa_hard_limit
3178 :
3179 :
3180 33 : real(dp) function current_sum_xa_hard_limit(s) result(sum_xa_hard_limit)
3181 : type (star_info), pointer :: s
3182 33 : real(dp) :: logTc, alfa
3183 : include 'formats'
3184 33 : logTc = s% lnT(s% nz)/ln10
3185 33 : if (logTc <= s% logT_max_for_sum_xa_hard_limit) then
3186 33 : sum_xa_hard_limit = s% sum_xa_hard_limit
3187 0 : else if (logTc >= s% logT_min_for_sum_xa_hard_limit_for_highT) then
3188 0 : sum_xa_hard_limit = s% sum_xa_hard_limit_for_highT
3189 : else
3190 : alfa = (logTc - s% logT_max_for_sum_xa_hard_limit) / &
3191 0 : (s% logT_min_for_sum_xa_hard_limit_for_highT - s% logT_max_for_sum_xa_hard_limit)
3192 : sum_xa_hard_limit = &
3193 0 : alfa*s% sum_xa_hard_limit_for_highT + (1d0 - alfa)*s% sum_xa_hard_limit
3194 : end if
3195 : !write(*,1) 'logTc hard_limit', logTc, sum_xa_hard_limit
3196 33 : end function current_sum_xa_hard_limit
3197 :
3198 :
3199 0 : integer function no_extra_profile_columns(id)
3200 : use star_def, only: star_info
3201 : integer, intent(in) :: id
3202 0 : no_extra_profile_columns = 0
3203 0 : end function no_extra_profile_columns
3204 :
3205 :
3206 0 : subroutine no_data_for_extra_profile_columns(id, n, nz, names, vals, ierr)
3207 0 : use star_def, only: maxlen_profile_column_name, star_info
3208 : integer, intent(in) :: id, n, nz
3209 : character (len=maxlen_profile_column_name) :: names(n)
3210 : real(dp) :: vals(nz,n)
3211 : integer, intent(out) :: ierr
3212 0 : ierr = 0
3213 0 : end subroutine no_data_for_extra_profile_columns
3214 :
3215 :
3216 : ! Stiriba, Youssef, Appl, Numer. Math. 45, 499-511. 2003.
3217 :
3218 : ! LPP-HARMOD -- local piecewise parabolic reconstruction
3219 :
3220 : ! interpolant is derived to conserve integral of v in cell k
3221 : ! interpolant slope at cell midpoint is harmonic mean of slopes between adjacent cells
3222 : ! where these slopes between cells are defined as the difference between cell averages
3223 : ! divided by the distance between cell midpoints.
3224 : ! interpolant curvature based on difference between the midpoint slope
3225 : ! and the smaller in magnitude of the slopes between adjacent cells.
3226 :
3227 : ! interpolant f(dq) = a + b*dq + (c/2)*dq^2, with dq = q - q_midpoint
3228 : ! c0 holds a's, c1 holds b's, and c2 holds c's.
3229 :
3230 :
3231 : subroutine get1_lpp(k, nz, &
3232 : dm1, d00, dp1, vm1, v00, vp1, quadratic, monotonic, dbg, c0, c1, c2)
3233 : integer, intent(in) :: k, nz
3234 : real(dp), intent(in) :: dm1, d00, dp1, vm1, v00, vp1
3235 : logical, intent(in) :: quadratic, monotonic
3236 : logical, intent(in) :: dbg
3237 : real(dp), intent(out) :: c0, c1, c2
3238 : real(dp) :: vbdy1, vbdy2, dhalf, sm1, s00, sp1, sprod, dv1, dv2
3239 : logical :: okay
3240 : include 'formats'
3241 :
3242 : c0 = v00
3243 : c2 = 0d0
3244 : if (k == 1) then
3245 : sm1 = 0d0
3246 : sp1 = (v00 - vp1) / (0.5d0*(d00 + dp1))
3247 : c1 = sp1
3248 : else if (k == nz) then
3249 : sp1 = 0d0
3250 : sm1 = (vm1 - v00) / (0.5d0*(dm1 + d00))
3251 : c1 = sm1
3252 : if (dbg) then
3253 : write(*,2) 'get1_lpp c1', k, c1
3254 : end if
3255 : else
3256 : sm1 = (vm1 - v00) / (0.5d0*(dm1 + d00))
3257 : sp1 = (v00 - vp1) / (0.5d0*(d00 + dp1))
3258 : sprod = sm1*sp1
3259 : if (sprod <= 0d0) then
3260 : ! at local min or max, so set slope and curvature to 0.
3261 : c1 = 0d0
3262 : return
3263 : end if
3264 : if (.not. quadratic) then ! minmod
3265 : s00 = (vm1 - vp1)/(d00 + (dm1 + dp1)/2)
3266 : c1 = sm1
3267 : if (sm1*s00 < 0d0) c1 = 0d0
3268 : if (abs(s00) < abs(c1)) c1 = s00
3269 : if (s00*sp1 < 0d0) c1 = 0d0
3270 : if (abs(sp1) < abs(c1)) c1 = sp1
3271 : else
3272 : c1 = sprod*2/(sp1 + sm1) ! harmonic mean slope
3273 : if (abs(sm1) <= abs(sp1)) then
3274 : c2 = (sm1 - c1)/(2d0*d00)
3275 : else
3276 : c2 = (c1 - sp1)/(2d0*d00)
3277 : end if
3278 : c0 = v00 - c2*d00*d00/24d0
3279 : end if
3280 : end if
3281 :
3282 : if (.not. monotonic) return
3283 :
3284 : dhalf = 0.5d0*d00
3285 : dv1 = c1*dhalf
3286 : dv2 = 0.5d0*c2*dhalf*dhalf
3287 : vbdy1 = c0 + dv1 + dv2 ! value at face(k)
3288 : vbdy2 = c0 - dv1 + dv2 ! value at face(k+1)
3289 :
3290 : okay = .true.
3291 :
3292 : if (k > 1) then ! check v00 <= vbdy1 <= vm1 or v00 >= vbdy1 >= vm1
3293 : if ((vm1 - vbdy1)*(vbdy1 - v00) < 0d0) okay = .false.
3294 : end if
3295 :
3296 : if (k < nz) then ! check vp1 <= vdby2 <= v00 or vp1 >= vdby2 >= v00
3297 : if ((v00 - vbdy2)*(vbdy2 - vp1) < 0d0) okay = .false.
3298 : end if
3299 :
3300 : if (okay) return
3301 :
3302 : c0 = v00
3303 : c2 = 0d0
3304 :
3305 : if (k == 1) then
3306 : c1 = (v00 - vp1) / (0.5d0*(d00 + dp1))
3307 : else if (k == nz) then
3308 : c1 = (vm1 - v00) / (0.5d0*(dm1 + d00))
3309 : else if (abs(sm1) <= abs(sp1)) then
3310 : c1 = sm1
3311 : else
3312 : c1 = sp1
3313 : end if
3314 :
3315 0 : end subroutine get1_lpp
3316 :
3317 :
3318 0 : subroutine calc_Ptrb_ad_tw(s, k, Ptrb, Ptrb_div_etrb, ierr)
3319 : ! note: Ptrb_div_etrb is not time weighted
3320 : ! erg cm^-3 = g cm^2 s^-2 cm^-3 = g cm^-1 s^-2
3321 : use auto_diff
3322 : use auto_diff_support
3323 : type (star_info), pointer :: s
3324 : integer, intent(in) :: k
3325 : type(auto_diff_real_star_order1), intent(out) :: Ptrb, Ptrb_div_etrb
3326 : integer, intent(out) :: ierr
3327 : type(auto_diff_real_star_order1) :: etrb, rho
3328 0 : real(dp) :: Ptrb_start
3329 : real(dp), parameter :: x_ALFAP = 2.d0/3.d0
3330 : logical :: time_center, test_partials
3331 : include 'formats'
3332 0 : ierr = 0
3333 : if (s% RSP2_alfap == 0 .or. s% mixing_length_alpha == 0 .or. &
3334 0 : k <= s% RSP2_num_outermost_cells_forced_nonturbulent .or. &
3335 : k > s% nz - int(s% nz/s% RSP_nz_div_IBOTOM)) then
3336 0 : Ptrb_div_etrb = 0d0
3337 0 : Ptrb = 0d0
3338 : return
3339 : end if
3340 0 : rho = wrap_d_00(s,k)
3341 0 : etrb = wrap_etrb_00(s,k)
3342 0 : Ptrb_div_etrb = s% RSP2_alfap*x_ALFAP*etrb*rho
3343 0 : Ptrb = Ptrb_div_etrb*etrb ! cm^2 s^-2 g cm^-3 = erg cm^-3
3344 : time_center = (s% using_velocity_time_centering .and. &
3345 0 : s% include_P_in_velocity_time_centering)
3346 : if (time_center) then
3347 0 : Ptrb_start = s% RSP2_alfap*get_etrb_start(s,k)*s% rho_start(k)
3348 : Ptrb = s% P_theta_for_velocity_time_centering*Ptrb + &
3349 0 : (1d0 - s% P_theta_for_velocity_time_centering)*Ptrb_start
3350 : end if
3351 :
3352 0 : if (is_bad(Ptrb%val)) then
3353 0 : !$omp critical (calc_Ptrb_ad_tw_crit)
3354 0 : write(*,2) 'Ptrb', k, Ptrb%val
3355 0 : call mesa_error(__FILE__,__LINE__,'calc_Ptrb_tw')
3356 : !$omp end critical (calc_Ptrb_ad_tw_crit)
3357 : end if
3358 :
3359 : !test_partials = (k == s% solver_test_partials_k)
3360 0 : test_partials = .false.
3361 : if (test_partials) then
3362 : s% solver_test_partials_val = Ptrb%val
3363 : !s% solver_test_partials_var = i_var_R
3364 : !s% solver_test_partials_dval_dx = 0 ! d_residual_dr_00
3365 : write(*,*) 'calc_Ptrb_ad_tw', s% solver_test_partials_var
3366 : end if
3367 :
3368 0 : end subroutine calc_Ptrb_ad_tw
3369 :
3370 :
3371 : ! Ptot_ad = Peos_ad + Pvsc_ad + Ptrb_ad + mlt_Pturb_ad with time weighting
3372 104608 : subroutine calc_Ptot_ad_tw( &
3373 104608 : s, k, skip_Peos, skip_mlt_Pturb, Ptot_ad, d_Ptot_dxa, ierr)
3374 0 : use auto_diff_support
3375 : type (star_info), pointer :: s
3376 : integer, intent(in) :: k
3377 : logical, intent(in) :: skip_Peos, skip_mlt_Pturb
3378 : type(auto_diff_real_star_order1), intent(out) :: Ptot_ad
3379 : real(dp), dimension(s% species), intent(out) :: d_Ptot_dxa
3380 : integer, intent(out) :: ierr
3381 : integer :: j
3382 104608 : real(dp) :: mlt_Pturb_start, alfa, beta
3383 : type(auto_diff_real_star_order1) :: &
3384 : Peos_ad, Pvsc_ad, Ptrb_ad, mlt_Pturb_ad, Ptrb_ad_div_etrb
3385 : logical :: time_center
3386 : include 'formats'
3387 :
3388 104608 : ierr = 0
3389 941472 : d_Ptot_dxa = 0d0
3390 :
3391 : time_center = (s% using_velocity_time_centering .and. &
3392 : s% include_P_in_velocity_time_centering .and. &
3393 104608 : s% lnT(k)/ln10 <= s% max_logT_for_include_P_and_L_in_velocity_time_centering)
3394 : if (time_center) then
3395 0 : alfa = s% P_theta_for_velocity_time_centering
3396 : else
3397 104608 : alfa = 1d0
3398 : end if
3399 104608 : beta = 1d0 - alfa
3400 :
3401 104608 : Peos_ad = 0d0
3402 104608 : if (.not. skip_Peos) then
3403 104608 : Peos_ad = wrap_peos_00(s, k)
3404 104608 : Peos_ad = alfa*Peos_ad + beta*s% Peos_start(k)
3405 941472 : do j=1,s% species
3406 836864 : d_Ptot_dxa(j) = s% Peos(k)*s% dlnPeos_dxa_for_partials(j,k)
3407 941472 : d_Ptot_dxa(j) = alfa*d_Ptot_dxa(j)
3408 : end do
3409 : end if
3410 :
3411 104608 : Pvsc_ad = 0d0
3412 104608 : if (s% use_Pvsc_art_visc) then
3413 0 : call get_Pvsc_ad(s, k, Pvsc_ad, ierr) ! no time centering for Pvsc
3414 0 : if (ierr /= 0) return
3415 : ! NO TIME CENTERING FOR Pvsc: Pvsc_ad = alfa*Pvsc_ad + beta*s% Pvsc_start(k)
3416 : end if
3417 :
3418 104608 : Ptrb_ad = 0d0
3419 104608 : if (s% RSP2_flag) then
3420 0 : call calc_Ptrb_ad_tw(s, k, Ptrb_ad, Ptrb_ad_div_etrb, ierr)
3421 0 : if (ierr /= 0) return
3422 : ! note that Ptrb_ad is already time weighted
3423 : end if
3424 :
3425 104608 : mlt_Pturb_ad = 0d0
3426 104608 : if ((.not. skip_mlt_Pturb) .and. s% mlt_Pturb_factor > 0d0 .and. k > 1) then
3427 0 : mlt_Pturb_ad = s% mlt_Pturb_factor*pow2(s% mlt_vc_old(k))*get_rho_face(s,k)/3d0
3428 0 : if (time_center) then
3429 : mlt_Pturb_start = &
3430 0 : s% mlt_Pturb_factor*pow2(s% mlt_vc_old(k))*(s% rho_start(k-1) + s% rho_start(k))/6d0
3431 0 : mlt_Pturb_ad = alfa*mlt_Pturb_ad + beta*mlt_Pturb_start
3432 : end if
3433 : end if
3434 :
3435 104608 : Ptot_ad = Peos_ad + Pvsc_ad + Ptrb_ad + mlt_Pturb_ad
3436 :
3437 104608 : if (s% use_other_pressure) Ptot_ad = Ptot_ad + s% extra_pressure(k)
3438 :
3439 104608 : end subroutine calc_Ptot_ad_tw
3440 :
3441 :
3442 0 : subroutine get_Pvsc_ad(s, k, Pvsc, ierr)
3443 104608 : use auto_diff
3444 : use auto_diff_support
3445 : type (star_info), pointer :: s
3446 : integer, intent(in) :: k
3447 : type(auto_diff_real_star_order1), intent(out) :: Pvsc
3448 : integer, intent(out) :: ierr
3449 : type(auto_diff_real_star_order1) :: v00, vp1, Peos, rho, &
3450 : Peos_div_rho, dv
3451 0 : real(dp) :: Pvsc_start, cq, zsh
3452 0 : Pvsc = 0
3453 0 : s% Pvsc(k) = 0d0
3454 0 : Pvsc_start = s% Pvsc_start(k)
3455 0 : if (Pvsc_start < 0d0) s% Pvsc_start(k) = 0d0
3456 0 : if (.not. (s% v_flag .and. s% use_Pvsc_art_visc)) return
3457 0 : cq = s% Pvsc_cq
3458 0 : if (cq == 0d0) return
3459 0 : zsh = s% Pvsc_zsh
3460 0 : v00 = wrap_v_00(s,k)
3461 0 : vp1 = wrap_v_p1(s,k)
3462 0 : Peos = wrap_Peos_00(s,k)
3463 0 : rho = wrap_d_00(s,k)
3464 0 : Peos_div_rho = Peos/rho
3465 0 : dv = (vp1 - v00) - zsh*sqrt(Peos_div_rho)
3466 0 : if (dv%val <= 0d0) return
3467 0 : Pvsc = cq*rho*pow2(dv)
3468 0 : s% Pvsc(k) = Pvsc%val
3469 0 : if (Pvsc_start < 0d0) s% Pvsc_start(k) = s% Pvsc(k)
3470 0 : end subroutine get_Pvsc_ad
3471 :
3472 :
3473 : ! marsaglia and zaman random number generator. period is 2**43 with
3474 : ! 900 million different sequences. the state of the generator (for restarts)
3475 2 : subroutine init_random(s)
3476 : type (star_info), pointer :: s
3477 : integer :: ijkl,ij,kl,i,j,k,l,ii,jj,m
3478 2 : real(dp) :: x,t
3479 2 : ijkl = 54217137
3480 2 : ij = ijkl/30082
3481 2 : kl = ijkl - 30082 * ij
3482 2 : i = mod(ij/177,177) + 2
3483 2 : j = mod(ij,177) + 2
3484 2 : k = mod(kl/169,178) + 1
3485 2 : l = mod(kl,169)
3486 196 : do ii=1,97
3487 : x = 0.0d0
3488 : t = 0.5d0
3489 4850 : do jj =1,24
3490 4656 : m = mod(mod(i*j,179)*k,179)
3491 4656 : i = j
3492 4656 : j = k
3493 4656 : k = m
3494 4656 : l = mod(53*l + 1, 169)
3495 4656 : if (mod(l*m,64) >= 32) x = x + t
3496 4850 : t = 0.5d0 * t
3497 : end do
3498 196 : s% rand_u(ii) = x
3499 : end do
3500 2 : s% rand_c = 362436.0d0/16777216.0d0
3501 2 : s% rand_cd = 7654321.0d0/16777216.0d0
3502 2 : s% rand_cm = 16777213.0d0/16777216.0d0
3503 2 : s% rand_i97 = 97
3504 2 : s% rand_j97 = 33
3505 0 : end subroutine init_random
3506 :
3507 :
3508 0 : real(dp) function rand(s)
3509 : type (star_info), pointer :: s
3510 0 : real(dp) :: uni
3511 0 : uni = s% rand_u(s% rand_i97) - s% rand_u(s% rand_j97)
3512 0 : if (uni < 0.0d0) uni = uni + 1.0d0
3513 0 : s% rand_u(s% rand_i97) = uni
3514 0 : s% rand_i97 = s% rand_i97 - 1
3515 0 : if (s% rand_i97 == 0) s% rand_i97 = 97
3516 0 : s% rand_j97 = s% rand_j97 - 1
3517 0 : if (s% rand_j97 == 0) s% rand_j97 = 97
3518 0 : s% rand_c = s% rand_c - s% rand_cd
3519 0 : if (s% rand_c < 0.0d0) s% rand_c = s% rand_c + s% rand_cm
3520 0 : uni = uni - s% rand_c
3521 0 : if (uni < 0.0d0) uni = uni + 1.0d0
3522 0 : rand = uni
3523 0 : end function rand
3524 :
3525 :
3526 4 : subroutine write_to_extra_terminal_output_file(s, str, advance)
3527 : type (star_info), pointer :: s
3528 : character(len=*), intent(in) :: str
3529 : logical, intent(in) :: advance
3530 : integer :: ierr, io
3531 4 : if (len_trim(s% extra_terminal_output_file) > 0) then
3532 0 : ierr = 0
3533 : open(newunit=io, file=trim(s% extra_terminal_output_file), &
3534 0 : action='write', position='append', iostat=ierr)
3535 0 : if (ierr == 0) then
3536 0 : if (advance) then
3537 0 : write(io,'(a)') trim(str)
3538 : else
3539 0 : write(io,'(a)',advance='no') trim(str)
3540 : end if
3541 0 : close(io)
3542 : else
3543 : write(*,*) 'failed to open extra_terminal_output_file ' // &
3544 0 : trim(s% extra_terminal_output_file)
3545 : end if
3546 : end if
3547 4 : end subroutine write_to_extra_terminal_output_file
3548 :
3549 :
3550 0 : subroutine write_eos_call_info(s,k)
3551 : use chem_def
3552 : type (star_info), pointer :: s
3553 : integer, intent(in) :: k ! 0 means not being called for a particular cell
3554 : integer :: j
3555 : include 'formats'
3556 0 : !$OMP critical (omp_write_eos_call_info)
3557 0 : write(*,'(A)')
3558 0 : do j=1,s% species
3559 0 : write(*,4) 'xa(j,k) ' // trim(chem_isos% name(s% chem_id(j))), j, j+s% nvar_hydro, k, s% xa(j,k)
3560 : end do
3561 0 : write(*,1) 'sum(xa) =', sum(s% xa(:,k))
3562 0 : write(*,1) 'Pgas = ', s% Pgas(k)
3563 0 : write(*,1) 'logPgas = ', s% lnPgas(k)/ln10
3564 0 : write(*,1) 'rho = ', s% rho(k)
3565 0 : write(*,1) 'T = ', s% T(k)
3566 0 : write(*,1) 'logQ = ', s% lnd(k)/ln10 - 2*s% lnT(k)/ln10 + 12
3567 0 : write(*,'(A)')
3568 0 : write(*,1) 'eos_frac_OPAL_SCVH', s% eos_frac_OPAL_SCVH(k)
3569 0 : write(*,1) 'eos_frac_HELM', s% eos_frac_HELM(k)
3570 0 : write(*,1) 'eos_frac_Skye', s% eos_frac_Skye(k)
3571 0 : write(*,1) 'eos_frac_PC', s% eos_frac_PC(k)
3572 0 : write(*,1) 'eos_frac_FreeEOS', s% eos_frac_FreeEOS(k)
3573 0 : write(*,1) 'eos_frac_CMS', s% eos_frac_CMS(k)
3574 0 : write(*,1) 'eos_frac_ideal', s% eos_frac_ideal(k)
3575 0 : write(*,'(A)')
3576 0 : write(*,1) 'Peos = ', s% Peos(k)
3577 0 : write(*,1) 'Prad = ', s% Prad(k)
3578 0 : write(*,1) 'logPeos = ', s% lnPeos(k)/ln10
3579 0 : write(*,1) 'logS = ', s% lnS(k)/ln10
3580 0 : write(*,1) 'logE = ', s% lnE(k)/ln10
3581 0 : write(*,1) 'energy = ', s% energy(k)
3582 0 : write(*,1) 'grada = ', s% grada(k)
3583 0 : write(*,1) 'Cv = ', s% Cv(k)
3584 0 : write(*,1) 'dE_dRho = ', s% dE_dRho(k)
3585 0 : write(*,1) 'cp = ', s% cp(k)
3586 0 : write(*,1) 'gamma1 = ', s% gamma1(k)
3587 0 : write(*,1) 'gamma3 = ', s% gamma3(k)
3588 0 : write(*,1) 'eta = ', s% eta(k)
3589 0 : write(*,1) 'gam = ', s% gam(k)
3590 0 : write(*,1) 'mu = ', s% mu(k)
3591 0 : write(*,1) 'log_free_e = ', s% lnfree_e(k)/ln10
3592 0 : write(*,1) 'chiRho = ', s% chiRho(k)
3593 0 : write(*,1) 'chiT = ', s% chiT(k)
3594 0 : write(*,'(A)')
3595 0 : write(*,*) 'do_eos_for_cell k, nz', k, s% nz
3596 0 : write(*,1) 'logRho = ', s% lnd(k)/ln10
3597 0 : write(*,1) 'logT = ', s% lnT(k)/ln10
3598 0 : write(*,1) 'z = ', s% Z(k)
3599 0 : write(*,1) 'x = ', s% X(k)
3600 0 : write(*,1) 'abar = ', s% abar(k)
3601 0 : write(*,1) 'zbar = ', s% zbar(k)
3602 0 : write(*,'(A)')
3603 0 : write(*,1) 'tau = ', s% tau(k)
3604 0 : write(*,'(A)')
3605 0 : write(*,*) 's% eos_rq% tiny_fuzz', s% eos_rq% tiny_fuzz
3606 0 : write(*,'(A)')
3607 : !call mesa_error(__FILE__,__LINE__,'write_eos_call_info')
3608 : !$OMP end critical (omp_write_eos_call_info)
3609 0 : end subroutine write_eos_call_info
3610 :
3611 :
3612 239 : real(dp) function surface_avg_x(s,j)
3613 : type (star_info), pointer :: s
3614 : integer, intent(in) :: j
3615 239 : real(dp) :: sum_x, sum_dq
3616 : integer :: k
3617 : include 'formats'
3618 239 : if (j == 0) then
3619 239 : surface_avg_x = 0d0
3620 : return
3621 : end if
3622 239 : sum_x = 0
3623 239 : sum_dq = 0
3624 50668 : do k = 1, s% nz
3625 50668 : sum_x = sum_x + s% xa(j,k)*s% dq(k)
3626 50668 : sum_dq = sum_dq + s% dq(k)
3627 50668 : if (sum_dq >= s% surface_avg_abundance_dq) exit
3628 : end do
3629 239 : surface_avg_x = sum_x/sum_dq
3630 239 : end function surface_avg_x
3631 :
3632 :
3633 300 : real(dp) function center_avg_x(s,j)
3634 : type (star_info), pointer :: s
3635 : integer, intent(in) :: j
3636 300 : real(dp) :: sum_x, sum_dq, dx, dq
3637 : integer :: k
3638 300 : if (j == 0) then
3639 300 : center_avg_x = 0d0
3640 : return
3641 : end if
3642 267 : sum_x = 0
3643 267 : sum_dq = 0
3644 267 : do k = s% nz, 1, -1
3645 267 : dq = s% dq(k)
3646 267 : dx = s% xa(j,k)*dq
3647 267 : if (sum_dq+dq >= s% center_avg_value_dq) then
3648 267 : sum_x = sum_x+ dx*(s% center_avg_value_dq - sum_dq)/dq
3649 267 : sum_dq = s% center_avg_value_dq
3650 267 : exit
3651 : end if
3652 0 : sum_x = sum_x + dx
3653 0 : sum_dq = sum_dq + dq
3654 : end do
3655 267 : center_avg_x = sum_x/sum_dq
3656 267 : end function center_avg_x
3657 :
3658 :
3659 209260 : subroutine get_area_info_opt_time_center(s, k, area, inv_R2, ierr)
3660 : use auto_diff_support
3661 : type (star_info), pointer :: s
3662 : integer, intent(in) :: k
3663 : type(auto_diff_real_star_order1), intent(out) :: area, inv_R2
3664 : integer, intent(out) :: ierr
3665 : type(auto_diff_real_star_order1) :: r_00, r2_00
3666 209260 : ierr = 0
3667 209260 : r_00 = wrap_r_00(s,k)
3668 209260 : r2_00 = pow2(r_00)
3669 209260 : if (s% using_velocity_time_centering) then
3670 0 : area = 4d0*pi*(r2_00 + r_00*s% r_start(k) + s% r_start(k)**2)/3d0
3671 0 : inv_R2 = 1d0/(r_00*s% r_start(k))
3672 : else
3673 209260 : area = 4d0*pi*r2_00
3674 209260 : inv_R2 = 1d0/r2_00
3675 : end if
3676 209260 : end subroutine get_area_info_opt_time_center
3677 :
3678 :
3679 52348 : subroutine set_energy_eqn_scal(s, k, scal, ierr) ! 1/(erg g^-1 s^-1)
3680 : type (star_info), pointer :: s
3681 : integer, intent(in) :: k
3682 : real(dp), intent(out) :: scal
3683 : integer, intent(out) :: ierr
3684 52348 : real(dp) :: cell_energy_fraction_start
3685 : include 'formats'
3686 52348 : ierr = 0
3687 52348 : if (k > 1) then
3688 52304 : scal = 1d0
3689 : else
3690 44 : scal = 1d-6
3691 : end if
3692 52348 : if (s% dedt_eqn_r_scale > 0d0) then
3693 : cell_energy_fraction_start = &
3694 52348 : s% energy_start(k)*s% dm(k)/s% total_internal_energy_old
3695 52348 : scal = min(scal, cell_energy_fraction_start*s% dedt_eqn_r_scale)
3696 : end if
3697 52348 : scal = scal*s% dt/s% energy_start(k)
3698 209260 : end subroutine set_energy_eqn_scal
3699 :
3700 :
3701 107640 : real(dp) function conv_time_scale(s,k_in) result(tau_conv)
3702 : type (star_info), pointer :: s
3703 : integer, intent(in) :: k_in
3704 : integer :: k
3705 53820 : real(dp) :: brunt_B, alfa, beta, rho_face, Peos_face, chiT_face, chiRho_face, &
3706 53820 : f, dlnP, dlnT, grada_face, gradT_actual, brunt_N2
3707 53820 : if (.not. s% calculate_Brunt_B) then
3708 19743 : tau_conv = 0d0
3709 : return
3710 : end if
3711 53820 : k = max(2,k_in)
3712 53820 : brunt_B = s% brunt_B(k)
3713 53820 : call get_face_weights(s, k, alfa, beta)
3714 53820 : rho_face = alfa*s% rho(k) + beta*s% rho(k-1)
3715 53820 : Peos_face = alfa*s% Peos(k) + beta*s% Peos(k-1)
3716 53820 : chiT_face = alfa*s% chiT(k) + beta*s% chiT(k-1)
3717 53820 : chiRho_face = alfa*s% chiRho(k) + beta*s% chiRho(k-1)
3718 53820 : f = pow2(s% grav(k))*rho_face/Peos_face*chiT_face/chiRho_face
3719 53820 : dlnP = s% lnPeos(k-1) - s% lnPeos(k)
3720 53820 : dlnT = s% lnT(k-1) - s% lnT(k)
3721 53820 : grada_face = alfa*s% grada(k) + beta*s% grada(k-1)
3722 53820 : gradT_actual = safe_div_val(s, dlnT, dlnP) ! mlt has not been called yet when doing this
3723 53820 : brunt_N2 = f*(brunt_B - (gradT_actual - grada_face))
3724 53820 : if(abs(brunt_B) > 0d0) then
3725 34077 : tau_conv = 1d0/sqrt(abs(brunt_N2))
3726 : else
3727 : tau_conv = 0d0
3728 : end if
3729 : end function conv_time_scale
3730 :
3731 :
3732 44 : subroutine set_conv_time_scales(s)
3733 : type (star_info), pointer :: s
3734 : integer :: k
3735 44 : real(dp) :: tau_conv
3736 : include 'formats'
3737 44 : s% min_conv_time_scale = 1d99
3738 44 : s% max_conv_time_scale = 0d0
3739 53864 : do k=1,s%nz
3740 53820 : if (s% X(k) > s% max_X_for_conv_timescale) cycle
3741 53820 : if (s% X(k) < s% min_X_for_conv_timescale) cycle
3742 53820 : if (s% q(k) > s% max_q_for_conv_timescale) cycle
3743 53820 : if (s% q(k) < s% min_q_for_conv_timescale) exit
3744 53820 : tau_conv = conv_time_scale(s,k)
3745 53820 : if (tau_conv < s% min_conv_time_scale) &
3746 44 : s% min_conv_time_scale = tau_conv
3747 53820 : if (tau_conv > s% max_conv_time_scale) &
3748 1702 : s% max_conv_time_scale = tau_conv
3749 : end do
3750 44 : if (s% max_conv_time_scale == 0d0) s% max_conv_time_scale = 1d99
3751 44 : if (s% min_conv_time_scale == 1d99) s% min_conv_time_scale = 0d0
3752 44 : end subroutine set_conv_time_scales
3753 :
3754 :
3755 0 : real(dp) function QHSE_time_scale(s,k) result(tau_qhse)
3756 : type (star_info), pointer :: s
3757 : integer, intent(in) :: k
3758 0 : real(dp) :: abs_dv
3759 0 : if (s% v_flag) then
3760 0 : abs_dv = abs(s% v(k) - s% v_start(k))
3761 0 : else if (s% u_flag) then
3762 0 : abs_dv = abs(s% u_face_ad(k)%val - s% u_face_start(k))
3763 : else
3764 : abs_dv = 0d0
3765 : end if
3766 0 : tau_qhse = abs_dv/(s% cgrav(k)*s% m_grav(k)/pow2(s% r(k)))
3767 0 : end function QHSE_time_scale
3768 :
3769 :
3770 0 : real(dp) function eps_nuc_time_scale(s,k) result(tau_epsnuc)
3771 : type (star_info), pointer :: s
3772 : integer, intent(in) :: k
3773 0 : tau_epsnuc = s% Cp(k)*s% T(k)/max(1d-10,abs(s% eps_nuc(k)))
3774 0 : end function eps_nuc_time_scale
3775 :
3776 :
3777 0 : real(dp) function cooling_time_scale(s,k) result(tau_cool)
3778 : type (star_info), pointer :: s
3779 : integer, intent(in) :: k
3780 0 : real(dp) :: thermal_conductivity
3781 0 : thermal_conductivity = (4d0*crad*clight*pow3(s% T(k)))/(3d0*s% opacity(k)*s% rho(k)*s% Cp(k))
3782 0 : tau_cool = pow2(s% scale_height(k)) / thermal_conductivity
3783 0 : end function cooling_time_scale
3784 :
3785 :
3786 479766 : function get_rho_face(s,k) result(rho_face)
3787 : type (star_info), pointer :: s
3788 : integer, intent(in) :: k
3789 : type(auto_diff_real_star_order1) :: rho_face
3790 239982 : real(dp) :: alfa, beta
3791 239982 : if (k == 1) then
3792 198 : rho_face = wrap_d_00(s,k)
3793 198 : return
3794 : end if
3795 239784 : call get_face_weights(s, k, alfa, beta)
3796 239784 : rho_face = alfa*wrap_d_00(s,k) + beta*wrap_d_m1(s,k)
3797 239784 : end function get_rho_face
3798 :
3799 :
3800 0 : real(dp) function get_rho_face_val(s,k) result(rho_face)
3801 : type (star_info), pointer :: s
3802 : integer, intent(in) :: k
3803 0 : real(dp) :: alfa, beta
3804 0 : if (k == 1) then
3805 0 : rho_face = s% rho(1)
3806 0 : return
3807 : end if
3808 0 : call get_face_weights(s, k, alfa, beta)
3809 0 : rho_face = alfa*s% rho(k) + beta*s% rho(k-1)
3810 0 : end function get_rho_face_val
3811 :
3812 159922 : function get_rho_start_face(s,k) result(rho_face)
3813 : type (star_info), pointer :: s
3814 : integer, intent(in) :: k
3815 : type(auto_diff_real_star_order1) :: rho_face
3816 79994 : real(dp) :: alfa, beta
3817 79994 : if (k == 1) then
3818 66 : rho_face = wrap_d_00_start(s,k)
3819 66 : return
3820 : end if
3821 79928 : call get_face_weights(s, k, alfa, beta)
3822 79928 : rho_face = alfa*wrap_d_00_start(s,k) + beta*wrap_d_m1_start(s,k)
3823 79928 : end function get_rho_start_face
3824 :
3825 319844 : function get_T_face(s,k) result(T_face)
3826 : type (star_info), pointer :: s
3827 : integer, intent(in) :: k
3828 : type(auto_diff_real_star_order1) :: T_face
3829 159988 : real(dp) :: alfa, beta
3830 159988 : if (k == 1) then
3831 132 : T_face = wrap_T_00(s,k)
3832 132 : return
3833 : end if
3834 159856 : call get_face_weights(s, k, alfa, beta)
3835 159856 : T_face = alfa*wrap_T_00(s,k) + beta*wrap_T_m1(s,k)
3836 159856 : end function get_T_face
3837 :
3838 :
3839 79994 : function get_Prad_face(s,k) result(Prad_face)
3840 : type (star_info), pointer :: s
3841 : integer, intent(in) :: k
3842 : type(auto_diff_real_star_order1) :: Prad_face
3843 79994 : Prad_face = crad*pow4(get_T_face(s,k))/3d0
3844 79994 : end function get_Prad_face
3845 :
3846 :
3847 639688 : function get_Peos_face(s,k) result(Peos_face)
3848 : type (star_info), pointer :: s
3849 : integer, intent(in) :: k
3850 : type(auto_diff_real_star_order1) :: Peos_face
3851 319976 : real(dp) :: alfa, beta
3852 319976 : if (k == 1) then
3853 264 : Peos_face = wrap_Peos_00(s,k)
3854 264 : return
3855 : end if
3856 319712 : call get_face_weights(s, k, alfa, beta)
3857 319712 : Peos_face = alfa*wrap_Peos_00(s,k) + beta*wrap_Peos_m1(s,k)
3858 319712 : end function get_Peos_face
3859 :
3860 26163 : function get_Peos_face_val(s,k) result(Peos_face)
3861 : type (star_info), pointer :: s
3862 : integer, intent(in) :: k
3863 : real(dp) :: Peos_face
3864 13087 : real(dp) :: alfa, beta
3865 13087 : if (k == 1) then
3866 11 : Peos_face = s% Peos(k)
3867 11 : return
3868 : end if
3869 13076 : call get_face_weights(s, k, alfa, beta)
3870 13076 : Peos_face = alfa*s% Peos(k) + beta*s% Peos(k-1)
3871 13076 : end function get_Peos_face_val
3872 :
3873 :
3874 159922 : function get_Cp_face(s,k) result(Cp_face)
3875 : type (star_info), pointer :: s
3876 : integer, intent(in) :: k
3877 : type(auto_diff_real_star_order1) :: Cp_face
3878 79994 : real(dp) :: alfa, beta
3879 79994 : if (k == 1) then
3880 66 : Cp_face = wrap_Cp_00(s,k)
3881 66 : return
3882 : end if
3883 79928 : call get_face_weights(s, k, alfa, beta)
3884 79928 : Cp_face = alfa*wrap_Cp_00(s,k) + beta*wrap_Cp_m1(s,k)
3885 79928 : end function get_Cp_face
3886 :
3887 :
3888 159922 : function get_ChiRho_face(s,k) result(ChiRho_face)
3889 : type (star_info), pointer :: s
3890 : integer, intent(in) :: k
3891 : type(auto_diff_real_star_order1) :: ChiRho_face
3892 79994 : real(dp) :: alfa, beta
3893 79994 : if (k == 1) then
3894 66 : ChiRho_face = wrap_ChiRho_00(s,k)
3895 66 : return
3896 : end if
3897 79928 : call get_face_weights(s, k, alfa, beta)
3898 79928 : ChiRho_face = alfa*wrap_ChiRho_00(s,k) + beta*wrap_ChiRho_m1(s,k)
3899 79928 : end function get_ChiRho_face
3900 :
3901 :
3902 159922 : function get_ChiT_face(s,k) result(ChiT_face)
3903 : type (star_info), pointer :: s
3904 : integer, intent(in) :: k
3905 : type(auto_diff_real_star_order1) :: ChiT_face
3906 79994 : real(dp) :: alfa, beta
3907 79994 : if (k == 1) then
3908 66 : ChiT_face = wrap_ChiT_00(s,k)
3909 66 : return
3910 : end if
3911 79928 : call get_face_weights(s, k, alfa, beta)
3912 79928 : ChiT_face = alfa*wrap_ChiT_00(s,k) + beta*wrap_ChiT_m1(s,k)
3913 79928 : end function get_ChiT_face
3914 :
3915 :
3916 319844 : function get_kap_face(s,k) result(kap_face)
3917 : type (star_info), pointer :: s
3918 : integer, intent(in) :: k
3919 : type(auto_diff_real_star_order1) :: kap_face
3920 159988 : real(dp) :: alfa, beta
3921 159988 : if (k == 1) then
3922 132 : kap_face = wrap_kap_00(s,k)
3923 132 : return
3924 : end if
3925 159856 : call get_face_weights(s, k, alfa, beta)
3926 159856 : kap_face = alfa*wrap_kap_00(s,k) + beta*wrap_kap_m1(s,k)
3927 159856 : end function get_kap_face
3928 :
3929 :
3930 159922 : function get_grada_face(s,k) result(grada_face)
3931 : type (star_info), pointer :: s
3932 : integer, intent(in) :: k
3933 : type(auto_diff_real_star_order1) :: grada_face, mlt_Pturb_ad, P, gamma1_face, alpha
3934 79994 : real(dp) :: alfa, beta
3935 79994 : P = get_Peos_face(s,k)
3936 79994 : if (k == 1) then
3937 66 : grada_face = wrap_grad_ad_00(s,k)
3938 66 : return
3939 : end if
3940 79928 : call get_face_weights(s, k, alfa, beta)
3941 79928 : grada_face = alfa*wrap_grad_ad_00(s,k) + beta*wrap_grad_ad_m1(s,k)
3942 : if (s% have_mlt_vc .and. s% okay_to_set_mlt_vc .and. s% include_mlt_Pturb_in_thermodynamic_gradients &
3943 79928 : .and. s% mlt_Pturb_factor > 0d0 .and. k > 1) then
3944 0 : gamma1_face = alfa*wrap_gamma1_00(s,k) + beta*wrap_gamma1_m1(s,k)
3945 0 : mlt_Pturb_ad = s% mlt_Pturb_factor*pow2(s% mlt_vc_old(k))*get_rho_face(s,k)/3d0
3946 0 : alpha = mlt_Pturb_ad/ (P*gamma1_face)
3947 0 : grada_face = grada_face*(P+mlt_Pturb_ad) / (P * (1d0 + alpha))
3948 : end if
3949 79928 : end function get_grada_face
3950 :
3951 :
3952 79994 : function get_gradr_face(s,k) result(gradr)
3953 : type (star_info), pointer :: s
3954 : integer, intent(in) :: k
3955 : type(auto_diff_real_star_order1) :: gradr
3956 : type(auto_diff_real_star_order1) :: P, opacity, L, Pr, r
3957 : real(dp) :: L_theta
3958 : !include 'formats'
3959 79994 : P = get_Peos_face(s,k)
3960 79994 : opacity = get_kap_face(s,k)
3961 :
3962 79994 : if (s% include_mlt_in_velocity_time_centering) then
3963 : ! consider building a wrapper : wrap_opt_time_center_L_00(s,k)
3964 : if (s% using_velocity_time_centering .and. &
3965 0 : s% include_L_in_velocity_time_centering .and. &
3966 : s% lnT(k)/ln10 <= s% max_logT_for_include_P_and_L_in_velocity_time_centering) then
3967 0 : L_theta = s% L_theta_for_velocity_time_centering
3968 : else
3969 0 : L_theta = 1d0
3970 : end if
3971 0 : L = L_theta*wrap_L_00(s, k) + (1d0 - L_theta)*s% L_start(k)
3972 0 : r = wrap_opt_time_center_r_00(s,k)
3973 : else
3974 79994 : L = wrap_L_00(s,k)
3975 79994 : r = wrap_r_00(s,k)
3976 : end if
3977 79994 : Pr = get_Prad_face(s,k)
3978 79994 : gradr = P*opacity*L/(16d0*pi*clight*s% m_grav(k)*s% cgrav(k)*Pr)
3979 79994 : end function get_gradr_face
3980 :
3981 :
3982 79994 : function get_scale_height_face(s,k) result(scale_height)
3983 : type (star_info), pointer :: s
3984 : integer, intent(in) :: k
3985 : type(auto_diff_real_star_order1) :: scale_height
3986 : type(auto_diff_real_star_order1) :: grav, scale_height2, P, rho
3987 79994 : real(dp) :: G, alfa, beta
3988 : include 'formats'
3989 79994 : G = s% cgrav(k)
3990 79994 : grav = G*s% m_grav(k)/pow2(wrap_r_00(s,k)) ! try geff later.
3991 79994 : if (s% use_rsp_form_of_scale_height .and. k >1) then ! use rsp form of Hp, assumes HSE, wraps P/rho together.
3992 0 : call get_face_weights(s, k, alfa, beta)
3993 0 : scale_height = (alfa*(wrap_Peos_00(s,k))/wrap_d_00(s,k) + beta*(wrap_Peos_m1(s,k))/wrap_d_m1(s,k))/grav
3994 : else
3995 79994 : P = get_Peos_face(s,k)
3996 79994 : rho = get_rho_face(s,k)
3997 79994 : scale_height = P/(grav*rho) ! this assumes HSE
3998 : end if
3999 79994 : if (s% alt_scale_height_flag) then
4000 : ! consider sound speed*hydro time scale as an alternative scale height
4001 : ! (this comes from Eggleton's code.)
4002 79994 : scale_height2 = sqrt(P/G)/rho
4003 79994 : if (scale_height2 < scale_height) then
4004 1905 : scale_height = scale_height2
4005 : end if
4006 : end if
4007 79994 : end function get_scale_height_face
4008 :
4009 :
4010 0 : real(dp) function get_scale_height_face_val(s,k) result(scale_height)
4011 : type (star_info), pointer :: s
4012 : integer, intent(in) :: k
4013 0 : real(dp) :: G, scale_height2, P, rho, alfa, beta
4014 : type(auto_diff_real_star_order1) :: P_face, rho_face, grav
4015 0 : G = s% cgrav(k)
4016 0 : grav = G*s% m_grav(k)/pow2(wrap_r_00(s,k))! try geff later
4017 0 : if (s% use_rsp_form_of_scale_height .and. k >1) then ! use rsp form of Hp, assumes HSE, wraps P/rho together.
4018 0 : call get_face_weights(s, k, alfa, beta)
4019 0 : scale_height = (alfa*(s% Peos(k)/s% rho(k)) + beta*(s% Peos(k-1)/s% rho(k-1)))/grav%val
4020 : else
4021 0 : P_face = get_Peos_face(s,k)
4022 0 : P = P_face%val
4023 0 : rho_face = get_rho_face(s,k)
4024 0 : rho = rho_face%val
4025 0 : scale_height = P/(grav%val*rho) ! this assumes HSE
4026 : end if
4027 0 : if (s% alt_scale_height_flag) then
4028 : ! consider sound speed*hydro time scale as an alternative scale height
4029 : ! (this comes from Eggleton's code.)
4030 0 : scale_height2 = sqrt(P/G)/rho
4031 0 : if (scale_height2 < scale_height) then
4032 0 : scale_height = scale_height2
4033 : end if
4034 : end if
4035 0 : end function get_scale_height_face_val
4036 :
4037 :
4038 : function get_QQ_cell(s,k) result(QQ_cell)
4039 : type (star_info), pointer :: s
4040 : integer, intent(in) :: k
4041 : type(auto_diff_real_star_order1) :: QQ_cell
4042 : type(auto_diff_real_star_order1) :: &
4043 : T_00, d_00, chiT_00, chiRho_00
4044 : T_00 = wrap_T_00(s,k)
4045 : d_00 = wrap_d_00(s,k)
4046 : chiT_00 = wrap_chiT_00(s,k)
4047 : chiRho_00 = wrap_chiRho_00(s,k)
4048 : QQ_cell = chiT_00/(d_00*T_00*chiRho_00)
4049 : end function get_QQ_cell
4050 :
4051 :
4052 1345744 : subroutine get_face_weights(s, k, alfa, beta)
4053 : type (star_info), pointer :: s
4054 : integer, intent(in) :: k
4055 : real(dp), intent(out) :: alfa, beta
4056 : ! face_value(k) = alfa*cell_value(k) + beta*cell_value(k-1)
4057 1345744 : if (k == 1) call mesa_error(__FILE__,__LINE__,'bad k==1 for get_face_weights')
4058 1345744 : alfa = s% dq(k-1)/(s% dq(k-1) + s% dq(k))
4059 1345744 : beta = 1d0 - alfa
4060 1345744 : end subroutine get_face_weights
4061 :
4062 :
4063 161368 : real(dp) function safe_div_val(s, x, y, lim) result(x_div_y)
4064 : type (star_info), pointer :: s
4065 : real(dp), intent(in) :: x, y, lim
4066 : optional :: lim
4067 107548 : real(dp) :: limit
4068 107548 : if (present(lim)) then
4069 0 : limit = lim
4070 : else
4071 : limit = 1d-20
4072 : end if
4073 161368 : if (abs(y) < limit) then
4074 : x_div_y = 0d0
4075 : else
4076 161368 : x_div_y = x/y
4077 : end if
4078 107548 : end function safe_div_val
4079 :
4080 :
4081 : function safe_div(s, x, y, lim) result(x_div_y)
4082 : type (star_info), pointer :: s
4083 : type(auto_diff_real_star_order1), intent(in) :: x, y
4084 : type(auto_diff_real_star_order1) :: x_div_y
4085 : real(dp), intent(in) :: lim
4086 : optional :: lim
4087 : real(dp) :: limit
4088 : if (present(lim)) then
4089 : limit = lim
4090 : else
4091 : limit = 1d-20
4092 : end if
4093 : if (abs(y) < limit) then
4094 : x_div_y = 0d0
4095 : else
4096 : x_div_y = x/y
4097 : end if
4098 : end function safe_div
4099 :
4100 :
4101 43 : subroutine set_luminosity_by_category(s) ! integral by mass from center out
4102 : use chem_def, only: category_name
4103 : use rates_def, only: i_rate
4104 : use utils_lib, only: is_bad
4105 : type (star_info), pointer :: s
4106 : integer :: k, j
4107 1075 : real(dp) :: L_burn_by_category(num_categories)
4108 : include 'formats'
4109 43 : L_burn_by_category(:) = 0
4110 51399 : do k = s% nz, 1, -1
4111 1283943 : do j = 1, num_categories
4112 : L_burn_by_category(j) = &
4113 1232544 : L_burn_by_category(j) + s% dm(k)*s% eps_nuc_categories(j, k)
4114 1232544 : if (is_bad(L_burn_by_category(j))) then
4115 0 : write(*,2) trim(category_name(j)) // ' eps_nuc logT', k, s% eps_nuc_categories(j,k), s% lnT(k)/ln10
4116 0 : if (s% stop_for_bad_nums) call mesa_error(__FILE__,__LINE__,'set_luminosity_by_category')
4117 : end if
4118 1283900 : s% luminosity_by_category(j,k) = L_burn_by_category(j)
4119 : end do
4120 : end do
4121 43 : end subroutine set_luminosity_by_category
4122 :
4123 :
4124 0 : subroutine set_zero_alpha_RTI(id, ierr)
4125 : integer, intent(in) :: id
4126 : integer, intent(out) :: ierr
4127 : type (star_info), pointer :: s
4128 : include 'formats'
4129 : ierr = 0
4130 0 : call get_star_ptr(id, s, ierr)
4131 0 : if (ierr /= 0) return
4132 0 : if (.not. s% u_flag) return
4133 0 : s% xh(s% i_alpha_RTI,1:s% nz) = 0d0
4134 0 : s% alpha_RTI(1:s% nz) = 0d0
4135 0 : s% need_to_setvars = .true.
4136 43 : end subroutine set_zero_alpha_RTI
4137 :
4138 : end module star_utils
|