155 subroutine read_params(fl)
160 end subroutine read_params
165 double precision,
dimension(:),
allocatable :: t_table
166 double precision,
dimension(:),
allocatable :: L_table
167 double precision,
dimension(:),
allocatable :: f_table
168 double precision :: ratt, fact1, fact2, fact3, dL1, dL2
169 double precision :: tstep, Lstep
170 integer :: ntable, i, j
172 Character(len=65) :: PPL_curves(1:6)
175 fl%coolcurve=
'JCcorona'
179 fl%rc_is_1d_loop = .false.
181 fl%rad_damp_height=0.5d0
182 fl%rad_damp_scale=0.15d0
185 if (fl%fip_ > 0)
then
186 select case (trim(fl%coolcurve))
187 case (
'Dere_photo',
'Dere_photo_DM')
189 call mpistop(
"FIP cooling requires coolcurve='Dere_photo' or 'Dere_photo_DM'")
193 if(fl%rc_split) any_source_split=.true.
196 ppl_curves = [
Character(len=65) ::
'Hildner',
'FM',
'Rosner',
'Klimchuk',
'SPEX_DM_rough',
'SPEX_DM_fine']
197 do i=1,
size(ppl_curves)
198 if (ppl_curves(i)==fl%coolcurve)
then
206 select case(fl%coolcurve)
210 print *,
'Use Hildner (1974) piecewise power law'
212 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
213 allocate(fl%a_PPL(1:fl%n_PPL))
216 fl%l_PPL(1:fl%n_PPL) = 10.d0**
x_hildner(1:
n_hildner) * (10.d0**fl%t_PPL(1:fl%n_PPL))**fl%a_PPL(1:fl%n_PPL)
220 print *,
'Use Forbes and Malherbe (1991)-like piecewise power law'
222 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
223 allocate(fl%a_PPL(1:fl%n_PPL))
224 fl%t_PPL(1:fl%n_PPL+1) =
t_fm(1:
n_fm+1)
226 fl%l_PPL(1:fl%n_PPL) = 10.d0**
x_fm(1:
n_fm) * (10.d0**fl%t_PPL(1:fl%n_PPL))**fl%a_PPL(1:fl%n_PPL)
230 print *,
'Use piecewise power law according to Rosner (1978)'
232 print *,
'and extended by Priest (1982) from Van Der Linden (1991)'
234 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
235 allocate(fl%a_PPL(1:fl%n_PPL))
238 fl%l_PPL(1:fl%n_PPL) = 10.d0**
x_rosner(1:
n_rosner) * (10.d0**fl%t_PPL(1:fl%n_PPL))**fl%a_PPL(1:fl%n_PPL)
242 print *,
'Use Klimchuk (2008) piecewise power law'
244 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
245 allocate(fl%a_PPL(1:fl%n_PPL))
248 fl%l_PPL(1:fl%n_PPL) = 10.d0**
x_klimchuk(1:
n_klimchuk) * (10.d0**fl%t_PPL(1:fl%n_PPL))**fl%a_PPL(1:fl%n_PPL)
250 case(
'SPEX_DM_rough')
252 print *,
'Use the rough piece wise power law fit to the SPEX_DM curve (2009)'
254 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
255 allocate(fl%a_PPL(1:fl%n_PPL))
262 print *,
'Use the fine, detailed piece wise power law fit to the SPEX_DM curve (2009)'
264 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
265 allocate(fl%a_PPL(1:fl%n_PPL))
271 call mpistop(
"This piecewise power law is unknown")
275 fl%t_PPL(1:fl%n_PPL+1) = 10.d0**fl%t_PPL(1:fl%n_PPL+1)
277 if (si_unit) fl%l_PPL(1:fl%n_PPL) = fl%l_PPL(1:fl%n_PPL) * 10.0d0**(-13)
280 fl%t_PPL(1:fl%n_PPL+1) = fl%t_PPL(1:fl%n_PPL+1) / unit_temperature
281 fl%l_PPL(1:fl%n_PPL) = fl%l_PPL(1:fl%n_PPL) * unit_numberdensity**2 * unit_time / unit_pressure * (1.d0+2.d0*he_abundance)
284 fl%l_PPL(fl%n_PPL+1) = fl%l_PPL(fl%n_PPL) * ( fl%t_PPL(fl%n_PPL+1) / fl%t_PPL(fl%n_PPL) )**fl%a_PPL(fl%n_PPL)
285 fl%lref = fl%l_PPL(fl%n_PPL+1)
286 fl%tref = fl%t_PPL(fl%n_PPL+1)
289 fl%tcoolmin = fl%t_PPL(1)
290 fl%tcoolmax = fl%t_PPL(fl%n_PPL+1)
292 if (fl%tlow==bigdouble) fl%tlow=fl%tcoolmin
299 allocate(fl%tcool(1:fl%ncool), fl%Lcool(1:fl%ncool), fl%dLdtcool(1:fl%ncool))
300 allocate(fl%Yc(1:fl%ncool))
301 if(fl%fip_ > 0)
allocate(fl%frac_lowFIP(1:fl%ncool))
303 fl%tcool(1:fl%ncool) = zero
304 fl%Lcool(1:fl%ncool) = zero
305 fl%dLdtcool(1:fl%ncool) = zero
308 select case(fl%coolcurve)
312 print *,
'Use Colgan & Feldman (2008) cooling curve'
314 print *,
'This version only till 10000 K, beware for floor T treatment'
316 allocate(t_table(1:ntable))
317 allocate(l_table(1:ntable))
323 print *,
'Use Dalgarno & McCray (1972) cooling curve'
325 allocate(t_table(1:ntable))
326 allocate(l_table(1:ntable))
332 write(*,
'(3a)')
'Use MacDonald & Bailey (1981) cooling curve '&
333 ,
'as implemented in ZEUS-3D, with the values '&
334 ,
'from Dalgarno & McCRay (1972) for low temperatures.'
336 allocate(t_table(1:ntable))
337 allocate(l_table(1:ntable))
338 t_table(1:ntable) =
t_dm(1:21)
339 l_table(1:ntable) =
l_dm(1:21)
345 print *,
'Use Mellema & Lundqvist (2002) cooling curve '&
346 ,
'for zero metallicity '
348 allocate(t_table(1:ntable))
349 allocate(l_table(1:ntable))
355 print *,
'Use Mellema & Lundqvist (2002) cooling curve '&
356 ,
'for WC-star metallicity '
358 allocate(t_table(1:ntable))
359 allocate(l_table(1:ntable))
365 print *,
'Use Mellema & Lundqvist (2002) cooling curve '&
366 ,
'for solar metallicity '
368 allocate(t_table(1:ntable))
369 allocate(l_table(1:ntable))
375 print *,
'Use Cloudy based cooling curve '&
376 ,
'for ism metallicity '
378 allocate(t_table(1:ntable))
379 allocate(l_table(1:ntable))
385 print *,
'Use Cloudy based cooling curve '&
386 ,
'for solar metallicity '
388 allocate(t_table(1:ntable))
389 allocate(l_table(1:ntable))
395 print *,
'Use SPEX cooling curve (Schure et al. 2009) '&
396 ,
'for solar metallicity '
398 allocate(t_table(1:ntable))
399 allocate(l_table(1:ntable))
405 print *,
'Use SPEX cooling curve for solar metallicity above 10^4 K. '
406 print *,
'At lower temperatures,use Dalgarno & McCray (1972), '
407 print *,
'with a pre-set ionization fraction of 10^-3. '
408 print *,
'as described by Schure et al. (2009). '
411 allocate(t_table(1:ntable))
412 allocate(l_table(1:ntable))
420 print *,
'Use Dere (2009) cooling curve for solar corona'
422 allocate(t_table(1:ntable))
423 allocate(l_table(1:ntable))
427 case(
'Dere_corona_DM')
429 print *,
'Combination of Dere_corona (2009) for high temperatures and'
431 print *,
'Dalgarno & McCray (1972), DM2, for low temperatures'
433 allocate(t_table(1:ntable))
434 allocate(l_table(1:ntable))
442 print *,
'Use Dere (2009) cooling curve for solar photophere'
444 allocate(t_table(1:ntable))
445 allocate(l_table(1:ntable))
446 if (fl%fip_ > 0)
allocate(f_table(1:ntable))
451 case(
'Dere_photo_DM')
453 print *,
'Combination of Dere_photo (2009) for high temperatures and'
455 print *,
'Dalgarno & McCray (1972), DM2, for low temperatures'
457 allocate(t_table(1:ntable))
458 allocate(l_table(1:ntable))
459 if (fl%fip_ > 0)
allocate(f_table(1:ntable))
464 if (fl%fip_ > 0)
then
465 f_table(1:
n_dm_2-1) = zero
471 print *,
'Use Colgan (2008) cooling curve'
473 allocate(t_table(1:ntable))
474 allocate(l_table(1:ntable))
480 print *,
'Combination of Colgan (2008) for high temperatures and'
482 print *,
'Dalgarno & McCray (1972), DM2, for low temperatures'
484 allocate(t_table(1:ntable))
485 allocate(l_table(1:ntable))
492 call mpistop(
"This coolingcurve is unknown")
496 fl%tcoolmax = t_table(ntable)
497 fl%tcoolmin = t_table(1)
498 ratt = (fl%tcoolmax-fl%tcoolmin)/( dble(fl%ncool-1) + smalldouble)
500 fl%tcool(1) = fl%tcoolmin
501 fl%Lcool(1) = l_table(1)
503 fl%tcool(fl%ncool) = fl%tcoolmax
504 fl%Lcool(fl%ncool) = l_table(ntable)
506 if (fl%fip_ > 0)
then
507 fl%frac_lowFIP(1) = f_table(1)
508 fl%frac_lowFIP(fl%ncool) = f_table(ntable)
512 fl%tcool(i) = fl%tcool(i-1)+ratt
516 if(fl%tcool(i) < t_table(j+1))
then
517 if(j.eq. ntable-1 )
then
518 fact1 = (fl%tcool(i)-t_table(j+1)) &
519 /(t_table(j)-t_table(j+1))
520 fact2 = (fl%tcool(i)-t_table(j)) &
521 /(t_table(j+1)-t_table(j))
522 fl%Lcool(i) = l_table(j)*fact1 + l_table(j+1)*fact2
523 if (fl%fip_ > 0)
then
524 fl%frac_lowFIP(i) = f_table(j)*fact1 + f_table(j+1)*fact2
528 dl1 = l_table(j+1)-l_table(j)
529 dl2 = l_table(j+2)-l_table(j+1)
530 jump =(max(dabs(dl1),dabs(dl2)) > 2*min(dabs(dl1),dabs(dl2)))
533 fact1 = (fl%tcool(i)-t_table(j+1)) &
534 /(t_table(j)-t_table(j+1))
535 fact2 = (fl%tcool(i)-t_table(j)) &
536 /(t_table(j+1)-t_table(j))
537 fl%Lcool(i) = l_table(j)*fact1 + l_table(j+1)*fact2
538 if (fl%fip_ > 0)
then
539 fl%frac_lowFIP(i) = f_table(j)*fact1 + f_table(j+1)*fact2
543 fact1 = ((fl%tcool(i)-t_table(j+1)) &
544 * (fl%tcool(i)-t_table(j+2))) &
545 / ((t_table(j)-t_table(j+1)) &
546 * (t_table(j)-t_table(j+2)))
547 fact2 = ((fl%tcool(i)-t_table(j)) &
548 * (fl%tcool(i)-t_table(j+2))) &
549 / ((t_table(j+1)-t_table(j)) &
550 * (t_table(j+1)-t_table(j+2)))
551 fact3 = ((fl%tcool(i)-t_table(j)) &
552 * (fl%tcool(i)-t_table(j+1))) &
553 / ((t_table(j+2)-t_table(j)) &
554 * (t_table(j+2)-t_table(j+1)))
555 fl%Lcool(i) = l_table(j)*fact1 + l_table(j+1)*fact2 &
557 if (fl%fip_ > 0)
then
558 fl%frac_lowFIP(i) = f_table(j)*fact1 + f_table(j+1)*fact2 &
568 fl%tcool(1:fl%ncool) = 10.0d0**fl%tcool(1:fl%ncool)
569 fl%Lcool(1:fl%ncool) = 10.0d0**fl%Lcool(1:fl%ncool)
572 if (si_unit) fl%Lcool(1:fl%ncool) = fl%Lcool(1:fl%ncool) * 10.0d0**(-13)
575 fl%tcool(1:fl%ncool) = fl%tcool(1:fl%ncool) / unit_temperature
576 fl%Lcool(1:fl%ncool) = fl%Lcool(1:fl%ncool) * unit_numberdensity**2 * unit_time / unit_pressure * (1.d0+2.d0*he_abundance)
578 fl%tcoolmin = fl%tcool(1)+smalldouble
580 if (fl%tlow==bigdouble) fl%tlow=fl%tcoolmin
581 fl%tcoolmax = fl%tcool(fl%ncool)
582 fl%lgtcoolmin = dlog10(fl%tcoolmin)
583 fl%lgtcoolmax = dlog10(fl%tcoolmax)
584 fl%lgstep = (fl%lgtcoolmax-fl%lgtcoolmin) * 1.d0 / (fl%ncool-1)
585 fl%dLdtcool(1) = (fl%Lcool(2)-fl%Lcool(1))/(fl%tcool(2)-fl%tcool(1))
586 fl%dLdtcool(fl%ncool) = (fl%Lcool(fl%ncool)-fl%Lcool(fl%ncool-1))/(fl%tcool(fl%ncool)-fl%tcool(fl%ncool-1))
589 fl%dLdtcool(i) = (fl%Lcool(i+1)-fl%Lcool(i-1))/(fl%tcool(i+1)-fl%tcool(i-1))
594 if (
allocated(f_table))
deallocate(f_table)
596 fl%tref = fl%tcoolmax
597 fl%lref = fl%Lcool(fl%ncool)
598 fl%Yc(fl%ncool) = zero
599 do i=fl%ncool-1, 1, -1
600 fl%Yc(i) = fl%Yc(i+1)
602 tstep = 1.0d-2*(fl%tcool(i+1)-fl%tcool(i))
603 call findl(fl%tcool(i+1)-j*tstep, lstep, fl)
604 fl%Yc(i) = fl%Yc(i) + fl%lref/fl%tref*tstep/lstep
609 rc_gamma_1=rc_gamma-1.d0
610 invgam = 1.d0/rc_gamma_1
614 use,
intrinsic :: ieee_arithmetic, only: ieee_is_finite
619 double precision :: frac, Tleft, Tright, Tpoint, dtemp
620 double precision :: Lpoint, eps, deps_dT
622 if (.not.
associated(fl%get_eps_derivative_from_T))
then
623 call mpistop(
"eion cooling table requires an EOS heat-capacity callback")
625 if (rc_gamma_1 <= zero)
then
626 call mpistop(
"invalid gamma for eion cooling table")
628 if (fl%tcoolmin <= zero .or. fl%tcoolmax <= fl%tcoolmin)
then
629 call mpistop(
"invalid temperature range for eion cooling table")
632 if (
allocated(fl%Teion))
deallocate(fl%Teion)
633 if (
allocated(fl%Yeion))
deallocate(fl%Yeion)
634 allocate(fl%Teion(1:fl%ncool), fl%Yeion(1:fl%ncool))
636 fl%eion_lgtmin = dlog10(fl%tcoolmin)
637 fl%eion_lgstep = (dlog10(fl%tcoolmax)-fl%eion_lgtmin) / &
640 frac = dble(i-1)/dble(fl%ncool-1)
641 fl%Teion(i) = 10.d0**(fl%eion_lgtmin + &
642 frac*(dlog10(fl%tcoolmax)-fl%eion_lgtmin))
648 fl%Yeion(fl%ncool) = zero
649 do i = fl%ncool-1, 1, -1
650 fl%Yeion(i) = fl%Yeion(i+1)
652 tright = fl%Teion(i+1)
653 dtemp = (tright-tleft)/100.d0
655 tpoint = tleft+(dble(j)-half)*dtemp
656 call findl(tpoint, lpoint, fl)
657 call fl%get_eps_derivative_from_T( &
658 tpoint, invgam, eps, deps_dt)
659 if (.not. ieee_is_finite(lpoint) .or. lpoint <= zero)
then
660 call mpistop(
"invalid Lambda in eion cooling table")
662 if (.not. ieee_is_finite(deps_dt) .or. deps_dt <= zero)
then
663 call mpistop(
"invalid heat capacity in eion cooling table")
665 fl%Yeion(i) = fl%Yeion(i) + &
666 fl%lref/fl%tref*dtemp*deps_dt/lpoint
668 if (fl%Yeion(i) <= fl%Yeion(i+1))
then
669 call mpistop(
"eion cooling transform is not monotonic")
672 fl%has_eion_table = .true.
707 integer,
intent(in) :: ixI^L,ixO^L
708 double precision,
intent(in) :: x(ixI^S,1:ndim)
709 double precision :: w(ixI^S,1:nw)
710 double precision,
intent(out):: coolrate(ixI^S)
713 double precision :: rho(ixI^S)
714 double precision :: L1, Te(ixI^S)
715 double precision :: rho_safe
716 double precision :: fip_prim, frac_lowFIP, fip_factor
717 double precision :: rad_damp_factor
720 call fl%get_rho(w,x,ixi^l,ixo^l,rho)
721 call fl%get_temperature(w,x,ixi^l,ixo^l,te)
723 {
do ix^db = ixo^lim^db\}
725 if(te(ix^d) <= fl%tcoolmin)
then
727 else if(te(ix^d) >= fl%tcoolmax)
then
731 call findl(te(ix^d),l1,fl)
738 if (fl%fip_ > 0)
then
740 fip_prim = min(
maxfip, max(
minfip, w(ix^d,fl%fip_) / rho_safe))
742 fip_factor = one - frac_lowfip + fip_prim * frac_lowfip
746 rad_damp_factor = one
748 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin1 + fl%rad_damp_height)
then
749 rad_damp_factor = exp(-(x(ix^d,ndim)-xprobmin1-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
751 if (fl%rc_is_1d_loop .and.
slab_uniform .and. fl%rad_damp &
752 .and. x(ix^d,ndim) >= xprobmax1 - fl%rad_damp_height)
then
753 rad_damp_factor = exp(-(x(ix^d,ndim)-xprobmax1+fl%rad_damp_height)**2/fl%rad_damp_scale**2)
757 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin2 + fl%rad_damp_height)
then
758 rad_damp_factor = exp(-(x(ix^d,ndim)-xprobmin2-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
762 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin3 + fl%rad_damp_height)
then
763 rad_damp_factor = exp(-(x(ix^d,ndim)-xprobmin3-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
767 coolrate(ix^d) = l1 * fip_factor * rad_damp_factor
784 integer,
intent(in) :: ixI^L, ixO^L
785 double precision,
intent(in) :: qdt
786 double precision,
intent(in) :: x(ixI^S,1:ndim)
787 double precision,
intent(in) :: wCT(ixI^S,1:nw)
788 double precision,
intent(in) :: w(ixI^S,1:nw)
789 double precision,
intent(out) :: coolrate(ixI^S)
792 double precision :: rho(ixI^S), Te(ixI^S), pthermal(ixI^S)
793 double precision :: eint_old(ixI^S)
794 double precision :: Y1, Y2, L1, Ttarget
795 double precision :: Rguess, Rtarget
796 double precision :: pfloor, ptarget, eint_floor, eint_target
797 double precision :: Lmax, fact
800 if (qdt <= zero)
then
801 call mpistop(
"getvar_cooling_exact requires qdt > 0")
803 if (
associated(fl%get_eps_derivative_from_T) .and. &
804 .not. fl%has_eion_table)
then
805 call mpistop(
"eion exact-cooling table is not initialized")
807 call fl%get_rho(wct, x, ixi^l, ixo^l, rho)
808 call fl%get_temperature(wct, x, ixi^l, ixo^l, te)
809 call fl%get_pthermal(wct, x, ixi^l, ixo^l, pthermal)
811 fl, wct, x, ixi^l, ixo^l, pthermal, eint_old)
812 fact = fl%lref*qdt/fl%tref
813 {
do ix^db = ixo^lim^db\}
814 if (rho(ix^d) <= zero .or. te(ix^d) <= zero .or. &
815 pthermal(ix^d) <= zero)
then
816 coolrate(ix^d) = zero
819 if (te(ix^d) <= fl%tcoolmin)
then
820 coolrate(ix^d) = zero
823 rguess = pthermal(ix^d)/(rho(ix^d)*te(ix^d))
825 fl, rho(ix^d), fl%tlow, rguess, &
826 pfloor, eint_floor, rtarget)
827 lmax = max(zero, (eint_old(ix^d)-eint_floor)/qdt)
828 if (te(ix^d) >= fl%tcoolmax)
then
830 l1 = min(l1*rho(ix^d)**2, lmax)
835 if (fl%has_eion_table)
then
837 y2 = y1 + fact*rho(ix^d)
840 call findy(te(ix^d), y1, fl)
841 y2 = y1 + fact*rho(ix^d)*rc_gamma_1
842 call findt(ttarget, y2, fl)
844 if (ttarget <= fl%tcoolmin)
then
848 fl, rho(ix^d), ttarget, rguess, &
849 ptarget, eint_target, rtarget)
850 l1 = max(zero, (eint_old(ix^d)-eint_target)/qdt)
886 integer,
intent(in) :: ixI^L, ixO^L
887 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim)
888 double precision,
intent(in) :: wCT(ixI^S,1:nw)
889 double precision,
intent(inout) :: w(ixI^S,1:nw)
892 double precision :: pthermal(ixI^S), rho(ixI^S)
893 double precision :: eint_current(ixI^S)
894 double precision :: temperature(ixI^S), Rfactor(ixI^S)
895 double precision :: Rguess, Rfloor, pfloor, eint_floor
898 call fl%get_pthermal(w, x, ixi^l, ixo^l, pthermal)
899 call fl%get_rho(w, x, ixi^l, ixo^l, rho)
901 fl, w, x, ixi^l, ixo^l, pthermal, eint_current)
903 if (
associated(fl%get_pthermal_Rfactor_from_rho_T))
then
905 call fl%get_temperature(w, x, ixi^l, ixo^l, temperature)
907 {
do ix^db = ixo^lim^db\}
908 if (temperature(ix^d) >= fl%tlow) cycle
909 if (rho(ix^d) > zero .and. temperature(ix^d) > zero)
then
910 rguess = pthermal(ix^d) / (rho(ix^d)*temperature(ix^d))
915 fl, rho(ix^d), fl%tlow, rguess, &
916 pfloor, eint_floor, rfloor)
917 if (eint_current(ix^d) < eint_floor)
then
918 w(ix^d,fl%e_) = w(ix^d,fl%e_) + &
919 (eint_floor-eint_current(ix^d))
924 call fl%get_var_Rfactor(wct, x, ixi^l, ixo^l, rfactor)
925 {
do ix^db = ixo^lim^db\}
927 fl, rho(ix^d), fl%tlow, rfactor(ix^d), &
928 pfloor, eint_floor, rfloor)
929 if (eint_current(ix^d) < eint_floor)
then
930 w(ix^d,fl%e_) = w(ix^d,fl%e_) + &
931 (eint_floor-eint_current(ix^d))
940 integer,
intent(in) :: ixI^L, ixO^L
941 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw)
942 double precision,
intent(inout) :: w(ixI^S,1:nw)
944 double precision,
intent(out) :: res(ixI^S)
946 double precision :: pth(ixI^S),rho(ixI^S),Rfactor(ixI^S),L1,Tlocal2
947 double precision :: Te(ixI^S)
948 double precision :: Lmax
949 double precision :: Y1, Y2
950 double precision :: de, emax,fact
951 double precision :: Rfloor, Rnew, Rstate
952 double precision :: pfloor, ptarget, pstate
953 double precision :: eint_old, eint_floor, eint_target
956 call fl%get_pthermal_equi(wct,x,ixi^l,ixo^l,pth)
957 if (
associated(fl%get_eps_derivative_from_T) .and. &
958 .not. fl%has_eion_table)
then
959 call mpistop(
"eion exact-cooling table is not initialized")
961 call fl%get_rho_equi(wct,x,ixi^l,ixo^l,rho)
962 call fl%get_temperature_equi(wct,x,ixi^l,ixo^l,te)
963 rfactor(ixo^s)=pth(ixo^s)/(rho(ixo^s)*te(ixo^s))
965 fact = fl%lref*qdt/fl%tref
967 {
do ix^db = ixo^lim^db\}
969 fl, rho(ix^d), te(ix^d), rfactor(ix^d), &
970 pstate, eint_old, rstate)
972 fl, rho(ix^d), fl%tlow, rfactor(ix^d), &
973 pfloor, eint_floor, rfloor)
974 lmax = max(zero, (eint_old-eint_floor)/qdt)
975 emax = max(zero, eint_old-eint_floor)
976 if( te(ix^d)<=fl%tcoolmin )
then
978 else if( te(ix^d)>=fl%tcoolmax )
then
982 if (te(ix^d) <
block%wextra(ix^d,fl%Tcoff_))
then
983 l1 = l1*sqrt((te(ix^d)/
block%wextra(ix^d,fl%Tcoff_))**5)
989 if (fl%has_eion_table)
then
991 y2 = y1 + fact*rho(ix^d)
994 call findy(te(ix^d),y1,fl)
995 y2 = y1 + fact*rho(ix^d)*rc_gamma_1
996 call findt(tlocal2,y2,fl)
998 if(tlocal2<=fl%tcoolmin)
then
1002 fl, rho(ix^d), tlocal2, rfactor(ix^d), &
1003 ptarget, eint_target, rnew)
1004 de = eint_old-eint_target
1008 if (te(ix^d) <
block%wextra(ix^d,fl%Tcoff_))
then
1009 de = de*sqrt((te(ix^d)/
block%wextra(ix^d,fl%Tcoff_))**5)
1012 de = min(max(zero, de), emax)
1079 integer,
intent(in) :: ixI^L, ixO^L
1080 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw), wCTprim(ixI^S,1:nw)
1081 double precision,
intent(inout) :: w(ixI^S,1:nw)
1083 double precision :: Y1, Y2
1084 double precision :: L1, Tlocal2
1085 double precision :: Rguess, Rfloor, Rnew, R2
1086 double precision :: rho(ixI^S), Te(ixI^S), rhonew(ixI^S)
1087 double precision :: eint_old(ixI^S), eint_work(ixI^S)
1088 double precision :: eint_after(ixI^S)
1089 double precision :: Lmax, fact
1090 double precision :: de_thin, de_thick, emax
1091 double precision :: T1, T2, Tnew(ixI^S), tau, xi
1092 double precision :: xi_arr(ixI^S), emax_rem_arr(ixI^S)
1093 double precision :: cool_fac, fip_prim, frac_lowFIP, fip_factor
1094 double precision :: pold(ixI^S), pwork(ixI^S), pafter(ixI^S)
1095 double precision :: pfloor, ptarget, eint_floor, eint_target
1098 if (
associated(fl%get_eps_derivative_from_T) .and. &
1099 .not. fl%has_eion_table)
then
1100 call mpistop(
"eion exact-cooling table is not initialized")
1102 call fl%get_rho(w,x,ixi^l,ixo^l,rhonew)
1103 call fl%get_rho(wct, x, ixi^l, ixo^l, rho)
1104 call fl%get_pthermal(w, x, ixi^l, ixo^l, pwork)
1105 call fl%get_pthermal(wct, x, ixi^l, ixo^l, pold)
1106 call fl%get_temperature(wct, x, ixi^l, ixo^l, te)
1108 fl, wct, x, ixi^l, ixo^l, pold, eint_old)
1110 fl, w, x, ixi^l, ixo^l, pwork, eint_work)
1111 fact = fl%lref*qdt/fl%tref
1114 {
do ix^db = ixo^lim^db\}
1117 if (te(ix^d) <= fl%tcoolmin) cycle
1118 if (rho(ix^d) > zero .and. te(ix^d) > zero)
then
1119 rguess = pold(ix^d)/(rho(ix^d)*te(ix^d))
1124 fl, rhonew(ix^d), fl%tlow, rguess, &
1125 pfloor, eint_floor, rfloor)
1126 lmax = max(zero, eint_work(ix^d)-eint_floor)/qdt
1127 emax = max(zero, eint_work(ix^d)-eint_floor)
1128 if (fl%rad_newton)
then
1129 xi = exp(-pwork(ix^d) / fl%rad_newton_pthick)
1130 xi = min(max(xi, zero), one)
1135 if (fl%rad_newton) xi_arr(ix^d) = xi
1139 if (fl%fip_ > 0)
then
1140 fip_prim = min(
maxfip, max(
minfip, wctprim(ix^d,fl%fip_)))
1145 fip_factor = one - frac_lowfip + fip_prim * frac_lowfip
1146 cool_fac = cool_fac * fip_factor
1152 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin1 + fl%rad_damp_height)
then
1153 cool_fac = cool_fac * exp(-(x(ix^d,ndim)-xprobmin1-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
1155 if (fl%rc_is_1d_loop .and.
slab_uniform .and. fl%rad_damp &
1156 .and. x(ix^d,ndim) >= xprobmax1 - fl%rad_damp_height)
then
1157 cool_fac = cool_fac * exp(-(x(ix^d,ndim)-xprobmax1+fl%rad_damp_height)**2/fl%rad_damp_scale**2)
1161 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin2 + fl%rad_damp_height)
then
1162 cool_fac = cool_fac * exp(-(x(ix^d,ndim)-xprobmin2-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
1166 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin3 + fl%rad_damp_height)
then
1167 cool_fac = cool_fac * exp(-(x(ix^d,ndim)-xprobmin3-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
1172 if (te(ix^d) >= fl%tcoolmax)
then
1174 l1 = l1 * rho(ix^d)**2
1175 l1 = min(cool_fac * l1, lmax)
1177 w(ix^d,fl%e_) = w(ix^d,fl%e_) - de_thin
1181 if (fl%has_eion_table)
then
1183 y2 = y1 + cool_fac*fact*rho(ix^d)
1189 call findy(te(ix^d), y1, fl)
1190 y2 = y1 + cool_fac*fact*rho(ix^d)*rc_gamma_1
1191 call findt(tlocal2, y2, fl)
1194 if (tlocal2 <= fl%tcoolmin)
then
1198 fl, rho(ix^d), tlocal2, rguess, &
1199 ptarget, eint_target, rnew)
1200 de_thin = eint_old(ix^d)-eint_target
1208 if (te(ix^d) <
block%wextra(ix^d,fl%Tcoff_))
then
1209 de_thin = de_thin * sqrt( (te(ix^d)/
block%wextra(ix^d,fl%Tcoff_))**5 )
1212 de_thin = min(max(zero, de_thin), emax)
1213 w(ix^d,fl%e_) = w(ix^d,fl%e_) - de_thin
1215 if (fl%rad_newton)
then
1216 emax_rem_arr(ix^d) = max(zero, emax - de_thin)
1221 if (fl%rad_newton)
then
1222 call fl%get_temperature(w, x, ixi^l, ixo^l, tnew)
1223 call fl%get_pthermal(w, x, ixi^l, ixo^l, pafter)
1225 fl, w, x, ixi^l, ixo^l, pafter, eint_after)
1226 {
do ix^db = ixo^lim^db\}
1227 if (te(ix^d) <= fl%tcoolmin) cycle
1229 tau = max(0.1d0 * sqrt(fl%rad_newton_rhosurf/rho(ix^d)), 4.d0*qdt)
1230 t2 = fl%rad_newton_trad + (t1-fl%rad_newton_trad)*exp(-qdt/tau)
1231 if (rho(ix^d) > zero .and. tnew(ix^d) > zero)
then
1232 rguess = pafter(ix^d)/(rho(ix^d)*tnew(ix^d))
1237 fl, rho(ix^d), t2, rguess, &
1238 ptarget, eint_target, r2)
1239 de_thick = (one-xi_arr(ix^d)) * &
1240 (eint_after(ix^d)-eint_target)
1242 de_thick = min(de_thick, emax_rem_arr(ix^d))
1243 w(ix^d,fl%e_) = w(ix^d,fl%e_) - de_thick