18 double precision,
private :: He_abundance
21 double precision,
private :: rc_gamma
24 double precision,
private :: rc_gamma_1
27 double precision,
private :: invgam
32 integer,
intent(in) :: ixI^L, ixO^L
33 double precision,
intent(in) :: w(ixI^S,nw)
34 double precision,
intent(in) :: x(ixI^S,1:ndim)
35 double precision,
intent(out):: res(ixI^S)
41 double precision :: rad_damp_height
42 double precision :: rad_damp_scale
45 double precision,
allocatable :: tcool(:), lcool(:), dldtcool(:)
46 double precision,
allocatable :: yc(:)
47 double precision :: tref, lref, tcoolmin,tcoolmax
48 double precision :: lgtcoolmin, lgtcoolmax, lgstep
52 double precision,
allocatable :: y_ppl(:), t_ppl(:), l_ppl(:), a_ppl(:)
55 double precision :: tlow
74 logical :: isppl = .false.
79 logical :: has_equi = .false.
81 logical :: subtract_equi = .false.
83 double precision,
allocatable :: frac_lowfip(:)
87 logical :: rad_newton = .false.
88 double precision :: rad_newton_pthick = 25.d0
89 double precision :: rad_newton_trad = 0.006d0
90 double precision :: rad_newton_rhosurf = 1.d4
93 character(len=std_len) :: coolcurve
95 procedure(
get_subr1),
pointer,
nopass :: get_rho => null()
96 procedure(
get_subr1),
pointer,
nopass :: get_rho_equi => null()
97 procedure(
get_subr1),
pointer,
nopass :: get_pthermal => null()
98 procedure(
get_subr1),
pointer,
nopass :: get_pthermal_equi => null()
99 procedure(
get_subr1),
pointer,
nopass :: get_var_rfactor => null()
100 procedure(
get_subr1),
pointer,
nopass :: get_temperature_equi => null()
109 double precision,
intent(in) :: phys_gamma,He_abund
112 he_abundance=he_abund
118 subroutine read_params(fl)
123 end subroutine read_params
128 double precision,
dimension(:),
allocatable :: t_table
129 double precision,
dimension(:),
allocatable :: L_table
130 double precision,
dimension(:),
allocatable :: f_table
131 double precision :: ratt, fact1, fact2, fact3, dL1, dL2
132 double precision :: tstep, Lstep
133 integer :: ntable, i, j
135 Character(len=65) :: PPL_curves(1:6)
138 fl%coolcurve=
'JCcorona'
143 fl%rad_damp_height=0.5d0
144 fl%rad_damp_scale=0.15d0
147 if (fl%fip_ > 0)
then
148 select case (trim(fl%coolcurve))
149 case (
'Dere_photo',
'Dere_photo_DM')
151 call mpistop(
"FIP cooling requires coolcurve='Dere_photo' or 'Dere_photo_DM'")
155 if(fl%rc_split) any_source_split=.true.
158 ppl_curves = [
Character(len=65) ::
'Hildner',
'FM',
'Rosner',
'Klimchuk',
'SPEX_DM_rough',
'SPEX_DM_fine']
159 do i=1,
size(ppl_curves)
160 if (ppl_curves(i)==fl%coolcurve)
then
168 select case(fl%coolcurve)
172 print *,
'Use Hildner (1974) piecewise power law'
174 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
175 allocate(fl%a_PPL(1:fl%n_PPL))
178 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)
182 print *,
'Use Forbes and Malherbe (1991)-like piecewise power law'
184 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
185 allocate(fl%a_PPL(1:fl%n_PPL))
186 fl%t_PPL(1:fl%n_PPL+1) =
t_fm(1:
n_fm+1)
188 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)
192 print *,
'Use piecewise power law according to Rosner (1978)'
194 print *,
'and extended by Priest (1982) from Van Der Linden (1991)'
196 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
197 allocate(fl%a_PPL(1:fl%n_PPL))
200 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)
204 print *,
'Use Klimchuk (2008) piecewise power law'
206 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
207 allocate(fl%a_PPL(1:fl%n_PPL))
210 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)
212 case(
'SPEX_DM_rough')
214 print *,
'Use the rough piece wise power law fit to the SPEX_DM curve (2009)'
216 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
217 allocate(fl%a_PPL(1:fl%n_PPL))
224 print *,
'Use the fine, detailed piece wise power law fit to the SPEX_DM curve (2009)'
226 allocate(fl%t_PPL(1:fl%n_PPL+1), fl%l_PPL(1:fl%n_PPL+1))
227 allocate(fl%a_PPL(1:fl%n_PPL))
233 call mpistop(
"This piecewise power law is unknown")
237 fl%t_PPL(1:fl%n_PPL+1) = 10.d0**fl%t_PPL(1:fl%n_PPL+1)
239 if (si_unit) fl%l_PPL(1:fl%n_PPL) = fl%l_PPL(1:fl%n_PPL) * 10.0d0**(-13)
242 fl%t_PPL(1:fl%n_PPL+1) = fl%t_PPL(1:fl%n_PPL+1) / unit_temperature
243 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)
246 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)
247 fl%lref = fl%l_PPL(fl%n_PPL+1)
248 fl%tref = fl%t_PPL(fl%n_PPL+1)
251 fl%tcoolmin = fl%t_PPL(1)
252 fl%tcoolmax = fl%t_PPL(fl%n_PPL+1)
254 if (fl%tlow==bigdouble) fl%tlow=fl%tcoolmin
261 allocate(fl%tcool(1:fl%ncool), fl%Lcool(1:fl%ncool), fl%dLdtcool(1:fl%ncool))
262 allocate(fl%Yc(1:fl%ncool))
263 if(fl%fip_ > 0)
allocate(fl%frac_lowFIP(1:fl%ncool))
265 fl%tcool(1:fl%ncool) = zero
266 fl%Lcool(1:fl%ncool) = zero
267 fl%dLdtcool(1:fl%ncool) = zero
270 select case(fl%coolcurve)
274 print *,
'Use Colgan & Feldman (2008) cooling curve'
276 print *,
'This version only till 10000 K, beware for floor T treatment'
278 allocate(t_table(1:ntable))
279 allocate(l_table(1:ntable))
285 print *,
'Use Dalgarno & McCray (1972) cooling curve'
287 allocate(t_table(1:ntable))
288 allocate(l_table(1:ntable))
294 write(*,
'(3a)')
'Use MacDonald & Bailey (1981) cooling curve '&
295 ,
'as implemented in ZEUS-3D, with the values '&
296 ,
'from Dalgarno & McCRay (1972) for low temperatures.'
298 allocate(t_table(1:ntable))
299 allocate(l_table(1:ntable))
300 t_table(1:ntable) =
t_dm(1:21)
301 l_table(1:ntable) =
l_dm(1:21)
307 print *,
'Use Mellema & Lundqvist (2002) cooling curve '&
308 ,
'for zero metallicity '
310 allocate(t_table(1:ntable))
311 allocate(l_table(1:ntable))
317 print *,
'Use Mellema & Lundqvist (2002) cooling curve '&
318 ,
'for WC-star metallicity '
320 allocate(t_table(1:ntable))
321 allocate(l_table(1:ntable))
327 print *,
'Use Mellema & Lundqvist (2002) cooling curve '&
328 ,
'for solar metallicity '
330 allocate(t_table(1:ntable))
331 allocate(l_table(1:ntable))
337 print *,
'Use Cloudy based cooling curve '&
338 ,
'for ism metallicity '
340 allocate(t_table(1:ntable))
341 allocate(l_table(1:ntable))
347 print *,
'Use Cloudy based cooling curve '&
348 ,
'for solar metallicity '
350 allocate(t_table(1:ntable))
351 allocate(l_table(1:ntable))
357 print *,
'Use SPEX cooling curve (Schure et al. 2009) '&
358 ,
'for solar metallicity '
360 allocate(t_table(1:ntable))
361 allocate(l_table(1:ntable))
367 print *,
'Use SPEX cooling curve for solar metallicity above 10^4 K. '
368 print *,
'At lower temperatures,use Dalgarno & McCray (1972), '
369 print *,
'with a pre-set ionization fraction of 10^-3. '
370 print *,
'as described by Schure et al. (2009). '
373 allocate(t_table(1:ntable))
374 allocate(l_table(1:ntable))
382 print *,
'Use Dere (2009) cooling curve for solar corona'
384 allocate(t_table(1:ntable))
385 allocate(l_table(1:ntable))
389 case(
'Dere_corona_DM')
391 print *,
'Combination of Dere_corona (2009) for high temperatures and'
393 print *,
'Dalgarno & McCray (1972), DM2, for low temperatures'
395 allocate(t_table(1:ntable))
396 allocate(l_table(1:ntable))
404 print *,
'Use Dere (2009) cooling curve for solar photophere'
406 allocate(t_table(1:ntable))
407 allocate(l_table(1:ntable))
408 if (fl%fip_ > 0)
allocate(f_table(1:ntable))
413 case(
'Dere_photo_DM')
415 print *,
'Combination of Dere_photo (2009) for high temperatures and'
417 print *,
'Dalgarno & McCray (1972), DM2, for low temperatures'
419 allocate(t_table(1:ntable))
420 allocate(l_table(1:ntable))
421 if (fl%fip_ > 0)
allocate(f_table(1:ntable))
426 if (fl%fip_ > 0)
then
427 f_table(1:
n_dm_2-1) = zero
433 print *,
'Use Colgan (2008) cooling curve'
435 allocate(t_table(1:ntable))
436 allocate(l_table(1:ntable))
442 print *,
'Combination of Colgan (2008) for high temperatures and'
444 print *,
'Dalgarno & McCray (1972), DM2, for low temperatures'
446 allocate(t_table(1:ntable))
447 allocate(l_table(1:ntable))
454 call mpistop(
"This coolingcurve is unknown")
458 fl%tcoolmax = t_table(ntable)
459 fl%tcoolmin = t_table(1)
460 ratt = (fl%tcoolmax-fl%tcoolmin)/( dble(fl%ncool-1) + smalldouble)
462 fl%tcool(1) = fl%tcoolmin
463 fl%Lcool(1) = l_table(1)
465 fl%tcool(fl%ncool) = fl%tcoolmax
466 fl%Lcool(fl%ncool) = l_table(ntable)
468 if (fl%fip_ > 0)
then
469 fl%frac_lowFIP(1) = f_table(1)
470 fl%frac_lowFIP(fl%ncool) = f_table(ntable)
474 fl%tcool(i) = fl%tcool(i-1)+ratt
478 if(fl%tcool(i) < t_table(j+1))
then
479 if(j.eq. ntable-1 )
then
480 fact1 = (fl%tcool(i)-t_table(j+1)) &
481 /(t_table(j)-t_table(j+1))
482 fact2 = (fl%tcool(i)-t_table(j)) &
483 /(t_table(j+1)-t_table(j))
484 fl%Lcool(i) = l_table(j)*fact1 + l_table(j+1)*fact2
485 if (fl%fip_ > 0)
then
486 fl%frac_lowFIP(i) = f_table(j)*fact1 + f_table(j+1)*fact2
490 dl1 = l_table(j+1)-l_table(j)
491 dl2 = l_table(j+2)-l_table(j+1)
492 jump =(max(dabs(dl1),dabs(dl2)) > 2*min(dabs(dl1),dabs(dl2)))
495 fact1 = (fl%tcool(i)-t_table(j+1)) &
496 /(t_table(j)-t_table(j+1))
497 fact2 = (fl%tcool(i)-t_table(j)) &
498 /(t_table(j+1)-t_table(j))
499 fl%Lcool(i) = l_table(j)*fact1 + l_table(j+1)*fact2
500 if (fl%fip_ > 0)
then
501 fl%frac_lowFIP(i) = f_table(j)*fact1 + f_table(j+1)*fact2
505 fact1 = ((fl%tcool(i)-t_table(j+1)) &
506 * (fl%tcool(i)-t_table(j+2))) &
507 / ((t_table(j)-t_table(j+1)) &
508 * (t_table(j)-t_table(j+2)))
509 fact2 = ((fl%tcool(i)-t_table(j)) &
510 * (fl%tcool(i)-t_table(j+2))) &
511 / ((t_table(j+1)-t_table(j)) &
512 * (t_table(j+1)-t_table(j+2)))
513 fact3 = ((fl%tcool(i)-t_table(j)) &
514 * (fl%tcool(i)-t_table(j+1))) &
515 / ((t_table(j+2)-t_table(j)) &
516 * (t_table(j+2)-t_table(j+1)))
517 fl%Lcool(i) = l_table(j)*fact1 + l_table(j+1)*fact2 &
519 if (fl%fip_ > 0)
then
520 fl%frac_lowFIP(i) = f_table(j)*fact1 + f_table(j+1)*fact2 &
530 fl%tcool(1:fl%ncool) = 10.0d0**fl%tcool(1:fl%ncool)
531 fl%Lcool(1:fl%ncool) = 10.0d0**fl%Lcool(1:fl%ncool)
534 if (si_unit) fl%Lcool(1:fl%ncool) = fl%Lcool(1:fl%ncool) * 10.0d0**(-13)
537 fl%tcool(1:fl%ncool) = fl%tcool(1:fl%ncool) / unit_temperature
538 fl%Lcool(1:fl%ncool) = fl%Lcool(1:fl%ncool) * unit_numberdensity**2 * unit_time / unit_pressure * (1.d0+2.d0*he_abundance)
540 fl%tcoolmin = fl%tcool(1)+smalldouble
542 if (fl%tlow==bigdouble) fl%tlow=fl%tcoolmin
543 fl%tcoolmax = fl%tcool(fl%ncool)
544 fl%lgtcoolmin = dlog10(fl%tcoolmin)
545 fl%lgtcoolmax = dlog10(fl%tcoolmax)
546 fl%lgstep = (fl%lgtcoolmax-fl%lgtcoolmin) * 1.d0 / (fl%ncool-1)
547 fl%dLdtcool(1) = (fl%Lcool(2)-fl%Lcool(1))/(fl%tcool(2)-fl%tcool(1))
548 fl%dLdtcool(fl%ncool) = (fl%Lcool(fl%ncool)-fl%Lcool(fl%ncool-1))/(fl%tcool(fl%ncool)-fl%tcool(fl%ncool-1))
551 fl%dLdtcool(i) = (fl%Lcool(i+1)-fl%Lcool(i-1))/(fl%tcool(i+1)-fl%tcool(i-1))
556 if (
allocated(f_table))
deallocate(f_table)
558 fl%tref = fl%tcoolmax
559 fl%lref = fl%Lcool(fl%ncool)
560 fl%Yc(fl%ncool) = zero
561 do i=fl%ncool-1, 1, -1
562 fl%Yc(i) = fl%Yc(i+1)
564 tstep = 1.0d-2*(fl%tcool(i+1)-fl%tcool(i))
565 call findl(fl%tcool(i+1)-j*tstep, lstep, fl)
566 fl%Yc(i) = fl%Yc(i) + fl%lref/fl%tref*tstep/lstep
571 rc_gamma_1=rc_gamma-1.d0
572 invgam = 1.d0/rc_gamma_1
582 double precision :: y_extra, factor
585 allocate(fl%y_PPL(1:fl%n_PPL+1))
587 fl%y_PPL(1:fl%n_PPL+1) = zero
590 factor = fl%l_PPL(fl%n_PPL+1) * fl%t_PPL(i) / (fl%l_PPL(i) * fl%t_PPL(fl%n_PPL+1))
591 if (fl%a_PPL(i) == 1.d0)
then
592 y_extra = log( fl%t_PPL(i) / fl%t_PPL(i+1) )
594 y_extra = 1 / (1 - fl%a_PPL(i)) * (1 - ( fl%t_PPL(i) / fl%t_PPL(i+1) )**(fl%a_PPL(i)-1) )
596 fl%y_PPL(i) = fl%y_PPL(i+1) - factor*y_extra
607 integer,
intent(in) :: ixI^L,ixO^L
608 double precision,
intent(in) :: x(ixI^S,1:ndim)
609 double precision :: w(ixI^S,1:nw)
610 double precision,
intent(out):: coolrate(ixI^S)
613 double precision :: pth(ixI^S),rho(ixI^S)
614 double precision :: L1,Te(ixI^S),Rfactor(ixI^S)
617 call fl%get_pthermal(w,x,ixi^l,ixo^l,pth)
618 call fl%get_rho(w,x,ixi^l,ixo^l,rho)
619 call fl%get_var_Rfactor(w,x,ixi^l,ixo^l,rfactor)
620 te(ixo^s) = pth(ixo^s) / (rho(ixo^s)*rfactor(ixo^s))
622 {
do ix^db = ixo^lim^db\}
624 if(te(ix^d) <= fl%tcoolmin)
then
626 else if(te(ix^d) >= fl%tcoolmax)
then
630 call findl(te(ix^d),l1,fl)
633 if(
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) .le. fl%rad_damp_height)
then
634 l1 = l1*exp(-(x(ix^d,ndim)-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
644 integer,
intent(in) :: ixI^L, ixO^L
645 double precision,
intent(in) :: qdt, x(ixI^S, 1:ndim), wCT(ixI^S, 1:nw)
646 double precision :: w(ixI^S, 1:nw)
647 double precision,
intent(out) :: coolrate(ixI^S)
649 double precision :: y1, y2, l1, tlocal2
650 double precision :: Te(ixI^S), pnew(ixI^S), rho(ixI^S), rhonew(ixI^S)
651 double precision :: emin, Lmax, fact, Rfactor(ixI^S), pth(ixI^S)
654 call fl%get_pthermal(wct, x, ixi^l, ixo^l, pth)
655 call fl%get_rho(wct, x, ixi^l, ixo^l, rho)
656 call fl%get_var_Rfactor(wct,x,ixi^l,ixo^l,rfactor)
657 te(ixo^s)=pth(ixo^s)/(rho(ixo^s)*rfactor(ixo^s))
659 call fl%get_pthermal(w, x, ixi^l, ixo^l, pnew)
660 call fl%get_rho(w, x, ixi^l, ixo^l, rhonew)
662 fact=fl%lref*qdt/fl%tref
664 {
do ix^db = ixo^lim^db\}
665 emin = rhonew(ix^d) * fl%tlow * rfactor(ix^d) * invgam
666 lmax = max(zero, ( pnew(ix^d)*invgam - emin ) / qdt)
670 if( te(ix^d)<= fl%tcoolmin)
then
672 else if( te(ix^d)>= fl%tcoolmax )
then
674 l1 = l1 * rho(ix^d)**2
677 call findy(te(ix^d), y1, fl)
678 y2 = y1 + fact * rho(ix^d)*rc_gamma_1
679 call findt(tlocal2, y2, fl)
680 if( tlocal2 <= fl%tcoolmin )
then
683 l1 = (te(ix^d)- tlocal2)*rho(ix^d)*rfactor(ix^d)*invgam/qdt
687 if(
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) .le. fl%rad_damp_height)
then
688 l1 = l1*exp(-(x(ix^d,ndim)-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
695 qsourcesplit,active,fl)
698 integer,
intent(in) :: ixI^L, ixO^L
699 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw), wCTprim(ixI^S,1:nw)
700 double precision,
intent(inout) :: w(ixI^S,1:nw)
701 logical,
intent(in) :: qsourcesplit
702 logical,
intent(inout) :: active
704 double precision,
allocatable,
dimension(:^D&) :: Lequi
706 if(qsourcesplit .eqv.fl%rc_split)
then
708 call cool_exact(qdt,ixi^l,ixo^l,wct,wctprim,w,x,fl)
709 if(fl%subtract_equi)
then
710 allocate(lequi(ixi^s))
712 w(ixo^s,fl%e_) = w(ixo^s,fl%e_)+lequi(ixo^s)
722 integer,
intent(in) :: ixI^L, ixO^L
723 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw)
724 double precision,
intent(inout) :: w(ixI^S,1:nw)
726 double precision :: etherm(ixI^S), rho(ixI^S), Rfactor(ixI^S),emin
729 call fl%get_pthermal(w,x,ixi^l,ixo^l,etherm)
730 call fl%get_rho(w,x,ixi^l,ixo^l,rho)
731 call fl%get_var_Rfactor(wct,x,ixi^l,ixo^l,rfactor)
732 {
do ix^db = ixo^lim^db\}
733 emin = rho(ix^d)*fl%tlow*rfactor(ix^d)
734 if(etherm(ix^d) < emin)
then
735 w(ix^d,fl%e_)=w(ix^d,fl%e_)+(emin-etherm(ix^d))*invgam
743 integer,
intent(in) :: ixI^L, ixO^L
744 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw)
745 double precision,
intent(inout) :: w(ixI^S,1:nw)
747 double precision,
intent(out) :: res(ixI^S)
749 double precision :: pth(ixI^S),rho(ixI^S),Rfactor(ixI^S),L1,Tlocal2
750 double precision :: Te(ixI^S)
751 double precision :: emin, Lmax
752 double precision :: Y1, Y2
753 double precision :: de, emax,fact
756 call fl%get_pthermal_equi(wct,x,ixi^l,ixo^l,pth)
757 call fl%get_rho_equi(wct,x,ixi^l,ixo^l,rho)
758 call fl%get_temperature_equi(wct,x,ixi^l,ixo^l,te)
759 rfactor(ixo^s)=pth(ixo^s)/(rho(ixo^s)*te(ixo^s))
763 fact = fl%lref*qdt/fl%tref
764 {
do ix^db = ixo^lim^db\}
765 emin = rho(ix^d)*fl%tlow*rfactor(ix^d)*invgam
766 lmax = max(zero,(pth(ix^d)*invgam-emin)/qdt)
767 emax = max(zero, pth(ix^d)*invgam-emin)
768 if( te(ix^d)<=fl%tcoolmin )
then
771 else if( te(ix^d)>=fl%tcoolmax )
then
775 if(te(ix^d)<
block%wextra(ix^d,fl%Tcoff_))
then
776 l1=l1*sqrt((te(ix^d)/
block%wextra(ix^d,fl%Tcoff_))**5)
782 call findy(te(ix^d),y1,fl)
783 y2 = y1 + fact * rho(ix^d)*rc_gamma_1
784 call findt(tlocal2,y2,fl)
785 if(tlocal2<=fl%tcoolmin)
then
788 de = (te(ix^d)-tlocal2)*rho(ix^d)*rfactor(ix^d)*invgam
791 if(te(ix^d)<
block%wextra(ix^d,fl%Tcoff_))
then
792 de=de*sqrt((te(ix^d)/
block%wextra(ix^d,fl%Tcoff_))**5)
804 integer,
intent(in) :: ixI^L, ixO^L
805 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw), wCTprim(ixI^S,1:nw)
806 double precision,
intent(inout) :: w(ixI^S,1:nw)
808 double precision :: Y1, Y2
809 double precision :: L1, pth(ixI^S), Tlocal2, pnew(ixI^S)
810 double precision :: rho(ixI^S), Te(ixI^S), rhonew(ixI^S), Rfactor(ixI^S)
811 double precision :: emin, Lmax, fact
812 double precision :: de_thin, de_thick, emax, emax_rem
813 double precision :: T1, T2, p1(ixI^S), tau, xi
814 double precision :: xi_arr(ixI^S), emax_rem_arr(ixI^S)
815 double precision :: cool_fac, fip_prim, frac_lowFIP, fip_factor
818 call fl%get_rho(wct,x,ixi^l,ixo^l,rho)
819 call fl%get_var_Rfactor(wct,x,ixi^l,ixo^l,rfactor)
822 call fl%get_pthermal(wct,x,ixi^l,ixo^l,te)
823 te(ixo^s)=te(ixo^s)/(rho(ixo^s)*rfactor(ixo^s))
825 te(ixo^s)=wctprim(ixo^s,iw_e)/(rho(ixo^s)*rfactor(ixo^s))
827 call fl%get_pthermal(w,x,ixi^l,ixo^l,pnew)
828 call fl%get_rho(w,x,ixi^l,ixo^l,rhonew)
830 fact = fl%lref*qdt/fl%tref
834 {
do ix^db = ixo^lim^db\}
835 emin = rhonew(ix^d)*fl%tlow*rfactor(ix^d)*invgam
836 lmax = max(zero,pnew(ix^d)*invgam-emin)/qdt
837 emax = max(zero,pnew(ix^d)*invgam-emin)
838 if (te(ix^d)<=fl%tcoolmin) cycle
839 if (fl%rad_newton)
then
840 xi = exp(-pnew(ix^d) / fl%rad_newton_pthick)
841 xi = min(max(xi, zero), one)
849 if (fl%fip_ > 0)
then
850 fip_prim = min(
maxfip, max(
minfip, wctprim(ix^d,fl%fip_)))
855 fip_factor = one - frac_lowfip + fip_prim * frac_lowfip
856 cool_fac = cool_fac * fip_factor
861 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) <= xprobmin1 + fl%rad_damp_height)
then
862 cool_fac = cool_fac * exp(-(x(ix^d,ndim)-xprobmin1-fl%rad_damp_height)**2/fl%rad_damp_scale**2)
865 if (
slab_uniform .and. fl%rad_damp .and. x(ix^d,ndim) >= xprobmax1 - fl%rad_damp_height)
then
866 cool_fac = cool_fac * exp(-(x(ix^d,ndim)-xprobmax1+fl%rad_damp_height)**2/fl%rad_damp_scale**2)
872 if (te(ix^d) >= fl%tcoolmax)
then
874 l1 = l1 * rho(ix^d)**2
875 l1 = min(cool_fac * l1, lmax)
877 w(ix^d,fl%e_) = w(ix^d,fl%e_) - de_thin
880 call findy(te(ix^d), y1, fl)
882 y2 = y1 + cool_fac * fact * rho(ix^d) * rc_gamma_1
884 call findt(tlocal2, y2, fl)
886 if (tlocal2 <= fl%tcoolmin)
then
889 de_thin = (te(ix^d) - tlocal2)*rho(ix^d)*rfactor(ix^d)*invgam
897 if (te(ix^d) <
block%wextra(ix^d,fl%Tcoff_))
then
898 de_thin = de_thin * sqrt( (te(ix^d)/
block%wextra(ix^d,fl%Tcoff_))**5 )
901 de_thin = min(de_thin, emax)
902 w(ix^d,fl%e_) = w(ix^d,fl%e_) - de_thin
903 if (fl%rad_newton)
then
905 emax_rem_arr(ix^d) = max(zero, emax - de_thin)
911 if (fl%rad_newton)
then
912 call fl%get_pthermal(w, x, ixi^l, ixo^l, p1)
913 {
do ix^db = ixo^lim^db\}
914 t1 = p1(ix^d) / (rho(ix^d) * rfactor(ix^d))
915 tau = max(0.1d0 * sqrt( fl%rad_newton_rhosurf / rho(ix^d)), 4.d0 * qdt)
916 t2 = fl%rad_newton_trad + (t1 - fl%rad_newton_trad) * exp(-qdt / tau)
917 de_thick = min((one - xi_arr(ix^d)) * (t1 - t2) * rho(ix^d) * rfactor(ix^d) * invgam, emax_rem_arr(ix^d))
918 w(ix^d,fl%e_) = w(ix^d,fl%e_) - de_thick
927 double precision,
intent(IN) :: tpoint
928 double precision,
intent(OUT) :: lpoint
932 lpoint =fl%l_PPL(fl%n_PPL) * ( tpoint / fl%t_PPL(fl%n_PPL) )**fl%a_PPL(fl%n_PPL)
934 lpoint = fl%Lcool(fl%ncool) * sqrt( tpoint / fl%tcoolmax)
941 double precision,
intent(in) :: tpoint
944 double precision :: lgtp
947 if (tpoint <= fl%tcool(1))
then
950 else if (tpoint >= fl%tcool(fl%ncool))
then
955 lgtp = dlog10(tpoint)
956 jl = int((lgtp - fl%lgtcoolmin) / fl%lgstep) + 1
957 jl = max(1, min(fl%ncool-1, jl))
960 + (tpoint - fl%tcool(jl)) &
961 * (fl%frac_lowFIP(jl+1) - fl%frac_lowFIP(jl)) &
962 / (fl%tcool(jl+1) - fl%tcool(jl))
970 double precision,
intent(IN) :: tpoint
971 double precision,
intent(OUT) :: Lpoint
974 double precision :: lgtp
978 i = maxloc(fl%t_PPL, dim=1, mask=fl%t_PPL<tpoint)
979 lpoint = fl%l_PPL(i) * (tpoint / fl%t_PPL(i))**fl%a_PPL(i)
981 lgtp = dlog10(tpoint)
982 jl = int((lgtp - fl%lgtcoolmin) /fl%lgstep) + 1
983 lpoint = fl%Lcool(jl)+ (tpoint-fl%tcool(jl)) &
984 * (fl%Lcool(jl+1)-fl%Lcool(jl)) &
985 / (fl%tcool(jl+1)-fl%tcool(jl))
994 double precision,
intent(IN) :: tpoint
995 double precision,
intent(OUT) :: Ypoint
998 double precision :: lgtp
999 double precision :: y_extra,factor
1003 i = maxloc(fl%t_PPL, dim=1, mask=fl%t_PPL<tpoint)
1004 factor = fl%l_PPL(fl%n_PPL+1) * fl%t_PPL(i) / (fl%l_PPL(i) * fl%t_PPL(fl%n_PPL+1))
1005 if(fl%a_PPL(i)==1.d0)
then
1006 y_extra = log( fl%t_PPL(i) / tpoint )
1008 y_extra = 1 / (1 - fl%a_PPL(i)) * (1 - ( fl%t_PPL(i) / tpoint )**(fl%a_PPL(i)-1) )
1010 ypoint = fl%y_PPL(i) + factor*y_extra
1012 lgtp = dlog10(tpoint)
1013 jl = int((lgtp - fl%lgtcoolmin) / fl%lgstep) + 1
1014 ypoint = fl%Yc(jl)+ (tpoint-fl%tcool(jl)) &
1015 * (fl%Yc(jl+1)-fl%Yc(jl)) &
1016 / (fl%tcool(jl+1)-fl%tcool(jl))
1019 end subroutine findy
1028 double precision,
intent(OUT) :: tpoint
1029 double precision,
intent(IN) :: Ypoint
1032 double precision :: factor
1033 integer :: jl,jc,jh,i
1036 i = minloc(fl%y_PPL, dim=1, mask=fl%y_PPL>ypoint)
1037 factor = fl%l_PPL(i) * fl%t_PPL(fl%n_PPL+1) / (fl%l_PPL(fl%n_PPL+1) * fl%t_PPL(i))
1038 if(fl%a_PPL(i)==1.d0)
then
1039 tpoint = fl%t_PPL(i) * exp( -1.d0 * factor * ( ypoint - fl%y_PPL(i)))
1041 tpoint = fl%t_PPL(i) * (1 - (1 - fl%a_PPL(i)) * factor * (ypoint - fl%y_PPL(i)))**(1 / (1 - fl%a_PPL(i)))
1044 if(ypoint >= fl%Yc(1))
then
1045 tpoint = fl%tcoolmin
1046 else if (ypoint == fl%Yc(fl%ncool))
then
1047 tpoint = fl%tcoolmax
1054 if(ypoint <= fl%Yc(jc))
then
1061 tpoint = fl%tcool(jl)+ (ypoint-fl%Yc(jl)) &
1062 * (fl%tcool(jl+1)-fl%tcool(jl)) &
1063 / (fl%Yc(jl+1)-fl%Yc(jl))
1066 end subroutine findt
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
integer, parameter unitpar
file handle for IO
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
logical phys_trac
Use TRAC for MHD or 1D HD.
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
This module defines the procedures of a physics module. It contains function pointers for the various...
module radiative cooling – add optically thin radiative cooling
subroutine getvar_cooling(ixil, ixol, w, x, coolrate, fl)
subroutine radiative_cooling_init_params(phys_gamma, he_abund)
Radiative cooling initialization.
subroutine findl(tpoint, lpoint, fl)
subroutine get_cool_equi(qdt, ixil, ixol, wct, w, x, fl, res)
subroutine radiative_cooling_init(fl, read_params)
subroutine create_y_ppl(fl)
subroutine radiative_cooling_add_source(qdt, ixil, ixol, wct, wctprim, w, x, qsourcesplit, active, fl)
subroutine calc_l_extended(tpoint, lpoint, fl)
double precision function lowfip_fraction(tpoint, fl)
subroutine cool_exact(qdt, ixil, ixol, wct, wctprim, w, x, fl)
subroutine findt(tpoint, ypoint, fl)
subroutine floortemperature(qdt, ixil, ixol, wct, w, x, fl)
subroutine getvar_cooling_exact(qdt, ixil, ixol, wct, w, x, coolrate, fl)
subroutine findy(tpoint, ypoint, fl)
module containing all optically thin radiative cooling tables
double precision, dimension(1:101) l_dere_corona
double precision, dimension(1:71) t_mlsolar1
double precision, dimension(1:151) l_cl_solar
double precision, dimension(1:5) t_fm
double precision, dimension(1:14) a_spex_dm_fine
double precision, dimension(1:9) a_rosner
double precision, dimension(1:110) l_spex
double precision, dimension(1:51) l_mb
double precision, dimension(1:10) t_rosner
double precision, dimension(1:5) a_hildner
double precision, dimension(1:9) x_rosner
double precision, dimension(1:7) x_klimchuk
double precision, dimension(1:151) l_cl_ism
double precision, dimension(1:8) t_spex_dm_rough
double precision, dimension(1:110) nenh_spex
double precision, dimension(1:110) t_spex
double precision, dimension(1:76) l_dm_2
double precision, dimension(1:15) t_spex_dm_fine
double precision, dimension(1:7) x_spex_dm_rough
double precision, dimension(1:14) x_spex_dm_fine
double precision, dimension(1:71) l_mlsolar1
double precision, dimension(1:45) t_jccorona
double precision, dimension(1:5) x_hildner
double precision, dimension(1:71) t_mlcosmol
double precision, dimension(1:151) t_cl_ism
double precision, dimension(1:151) t_cl_solar
double precision, dimension(1:51) t_mb
double precision, dimension(1:8) t_klimchuk
double precision, dimension(1:55) t_colgan
double precision, dimension(1:55) l_colgan
double precision, dimension(1:4) a_fm
double precision, dimension(1:101) l_dere_photo
double precision, dimension(1:45) l_jccorona
double precision, dimension(1:71) l_mlwc
double precision, dimension(1:71) l_dm
double precision, dimension(1:71) t_mlwc
double precision, dimension(1:7) a_spex_dm_rough
double precision, dimension(1:71) t_dm
double precision, dimension(1:7) a_klimchuk
double precision, dimension(1:71) l_mlcosmol
double precision, dimension(1:76) t_dm_2
double precision, dimension(1:6) t_hildner
double precision, dimension(1:4) x_fm
double precision, dimension(1:101) t_dere
double precision, dimension(1:101) lowfip_frac