sources_diskcooling.f90
Go to the documentation of this file.
1 !#############################################################################
2 !# #
3 !# fosite - 3D hydrodynamical simulation program #
4 !# module: sources_diskcooling.f90 #
5 !# #
6 !# Copyright (C) 2011-2019 #
7 !# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
8 !# Jannes Klee <jklee@astrophysik.uni-kiel.de> #
9 !# #
10 !# This program is free software; you can redistribute it and/or modify #
11 !# it under the terms of the GNU General Public License as published by #
12 !# the Free Software Foundation; either version 2 of the License, or (at #
13 !# your option) any later version. #
14 !# #
15 !# This program is distributed in the hope that it will be useful, but #
16 !# WITHOUT ANY WARRANTY; without even the implied warranty of #
17 !# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
18 !# NON INFRINGEMENT. See the GNU General Public License for more #
19 !# details. #
20 !# #
21 !# You should have received a copy of the GNU General Public License #
22 !# along with this program; if not, write to the Free Software #
23 !# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
24 !# #
25 !#############################################################################
26 !----------------------------------------------------------------------------!
40 !----------------------------------------------------------------------------!
59 !----------------------------------------------------------------------------!
63  USE fluxes_base_mod
64  USE mesh_base_mod
66  USE marray_base_mod
68  USE common_dict
69  IMPLICIT NONE
70  !--------------------------------------------------------------------------!
71  PRIVATE
72  INTEGER, PARAMETER :: gray = 1
73  INTEGER, PARAMETER :: gammie = 2
74  INTEGER, PARAMETER :: gammie_sb = 3
75  !--------------------------------------------------------------------------!
76  REAL, PARAMETER :: sqrt_three = 1.73205080757
77  REAL, PARAMETER :: sqrt_twopi = 2.50662827463
78 
79 ! Rosseland mean opacity constants in SI units;
80 ! taken from Bell & Lin, ApJ, 427, 1994
81 ! kappa_i= kappa_0i * rho**rexp(i) * T**Texp(i)
82 
83 !!$ DOUBLE PRECISION, PARAMETER :: kappa0(8) = (/ &
84 !!$ 2.00D-05, & ! ice grains [m^2/kg/K^2]
85 !!$ 2.00D+15, & ! evaporation of ice grains [m^2/kg*K^7]
86 !!$ 1.00D-02, & ! metal grains [m^2/kg/K^0.5]
87 !!$ 2.00D+77, & ! evaporation of metal grains [m^5/kg^2*K^24]
88 !!$ 1.00D-11, & ! molecules [m^4/kg^(5/3)/K^3]
89 !!$ 1.00D-38, & ! H-scattering [m^3/kg^(4/3)/K^10]
90 !!$ 1.50D+16, & ! bound-free and free-free [m^5/kg^2*K^(5/2)]
91 !!$ KE /) ! electron scattering [m^2/kg]
92  REAL, PARAMETER :: logkappa0(8) = (/ &
93  -10.8197782844, & ! ice grains [m^2/kg/K^2]
94  35.2319235755, & ! evaporation of ice grains [m^2/kg*K^7]
95  -4.60517018599, & ! metal grains [m^2/kg/K^0.5]
96  177.992199341, & ! evaporation of metal grains [m^5/kg^2*K^24]
97  -25.3284360229, & ! molecules [m^4/kg^(5/3)/K^3]
98  -87.4982335338, & ! H-scattering [m^3/kg^(4/3)/K^10]
99  37.246826596, & ! bound-free and free-free [m^5/kg^2*K^(5/2)]
100  -3.3581378922 /) ! electron scattering [m^2/kg]
101  REAL, PARAMETER :: texp(8) = (/ 2.0, -7.0, 0.5, -24.0, 3.0, 10.0, -2.5, 0.0 /)
102  REAL, PARAMETER :: rexp(8) = (/ 0.0, 0.0, 0.0, 1.0, 2./3., 1./3., 1.0, 0.0 /)
103  REAL, PARAMETER :: t0 = 3000 ! temperature constant (opacity interpolation)
104 
105  !--------------------------------------------------------------------------!
107  CHARACTER(LEN=32) :: source_name = "thin accretion disk cooling"
108  CLASS(logging_base), ALLOCATABLE :: cooling
109  REAL :: b_cool
110  REAL :: b_start
111  REAL :: b_final
112  REAL :: t_start
113  REAL :: dt_bdec
114  TYPE(marray_base) :: qcool
115  TYPE(marray_base) :: ephir
116  REAL :: t_0
117  REAL :: rho_0
118  CONTAINS
120  PROCEDURE :: infosources
121  PROCEDURE :: setoutput
123  PROCEDURE :: calctimestep_single
124  PROCEDURE :: updatecooling
125  PROCEDURE :: finalize
126  END TYPE
127  !--------------------------------------------------------------------------!
128  PUBLIC :: &
129  ! types
131  ! constants
133  !--------------------------------------------------------------------------!
134 
135 CONTAINS
136 
138  SUBROUTINE initsources_diskcooling(this,Mesh,Physics,Fluxes,config,IO)
142  IMPLICIT NONE
143  !------------------------------------------------------------------------!
144  CLASS(sources_diskcooling) :: this
145  CLASS(mesh_base), INTENT(IN) :: Mesh
146  CLASS(physics_base), INTENT(IN) :: Physics
147  CLASS(fluxes_base), INTENT(IN) :: Fluxes
148  TYPE(Dict_TYP), POINTER :: config,IO
149  !------------------------------------------------------------------------!
150  INTEGER :: stype
151  INTEGER :: cooling_func
152  !------------------------------------------------------------------------!
153  CALL getattr(config, "stype", stype)
154  CALL this%InitLogging(stype,this%source_name)
155 
156  ! some sanity checks
157  ! isothermal modules are excluded
158  SELECT TYPE (phys => physics)
159  CLASS IS(physics_euler)
160  ! do nothing
161  CLASS DEFAULT
162  ! abort
163  CALL this%Error("InitSources_diskcooling","physics not supported")
164  END SELECT
165 
166  SELECT CASE(cooling_func)
167  CASE(gammie)
168  ! check for geometry
169  SELECT TYPE (mgeo => mesh%Geometry)
170  CLASS IS(geometry_cylindrical)
171  ! do nothing
172  CLASS DEFAULT
173  CALL this%Error("InitSources_diskcooling","geometry not supported")
174  END SELECT
175  CASE(gammie_sb)
176  SELECT TYPE (mgeo => mesh%Geometry)
177  TYPE IS(geometry_cartesian)
178  ! do nothing
179  CLASS DEFAULT
180  CALL this%Error("InitSources_diskcooling","geometry not supported")
181  END SELECT
182  END SELECT
183 
184  ! check for dimensions
185  IF (physics%VDIM.GT.2) THEN
186  CALL this%Error("InitSources_diskcooling","only 2D simulations supported")
187  END IF
188 
189  ! get cooling method
190  CALL getattr(config,"method",cooling_func)
191  ALLOCATE(logging_base::this%cooling)
192  SELECT CASE(cooling_func)
193  CASE(gray)
194  IF (physics%constants%GetType().NE.si) &
195  CALL this%Error("InitSources_diskcooling","only SI units supported for gray cooling")
196  CALL this%cooling%InitLogging(gray,"gray cooling")
197 
198  this%Qcool = marray_base()
199 
200  CASE(gammie)
201  CALL this%cooling%InitLogging(gammie,"Gammie cooling")
202 
203  this%Qcool = marray_base()
204  this%ephir = marray_base(2)
205 
206  CASE(gammie_sb)
207  CALL this%cooling%InitLogging(gammie_sb,"Gammie cooling (SB)")
208 
209  this%Qcool = marray_base()
210 
211  CASE DEFAULT
212  CALL this%Error("UpdateCooling","Cooling function not supported!")
213  END SELECT
214 
215  ! Courant number, i.e. safety factor for numerical stability
216  CALL getattr(config, "cvis", this%cvis, 0.1)
217 
218  ! minimum temperature
219  CALL getattr(config, "Tmin", this%T_0, 1.0e-30)
220 
221  ! minimum density
222  CALL getattr(config, "Rhomin", this%rho_0, 1.0e-30)
223 
224  ! cooling time
225  CALL getattr(config, "b_cool", this%b_cool, 1.0e+00)
226 
227  ! initial and final cooling time
228  CALL getattr(config, "b_start", this%b_start, 0.0)
229  CALL getattr(config, "b_final", this%b_final, this%b_cool)
230 
231  ! starting point for beta
232  CALL getattr(config, "t_start", this%t_start, 0.0)
233 
234  ! timescale for changing beta
235  CALL getattr(config, "dt_bdec", this%dt_bdec, -1.0)
236 
237  ! set initial time < 0
238  this%time = -1.0
239 
240  ! initialize arrays
241  this%Qcool%data1d(:) = 0.0
242  SELECT CASE(cooling_func)
243  CASE(gray)
244  ! do nothing
245  CASE(gammie)
246  this%ephir%data4d(:,:,:,1) = -mesh%posvec%bcenter(:,:,:,2)/mesh%radius%bcenter(:,:,:)**2
247  this%ephir%data4d(:,:,:,2) = mesh%posvec%bcenter(:,:,:,1)/mesh%radius%bcenter(:,:,:)**2
248  CASE(gammie_sb)
249  ! do nothing
250  END SELECT
251 
252  !initialise output
253  CALL this%SetOutput(mesh,config,io)
254  CALL this%InitSources(mesh,fluxes,physics,config,io)
255 
256  END SUBROUTINE initsources_diskcooling
257 
258 
259  SUBROUTINE infosources(this,Mesh)
260  IMPLICIT NONE
261  !------------------------------------------------------------------------!
262  CLASS(sources_diskcooling), INTENT(IN) :: this
263  CLASS(mesh_base), INTENT(IN) :: Mesh
264  !------------------------------------------------------------------------!
265  CHARACTER(LEN=32) :: param_str
266  !------------------------------------------------------------------------!
267  CALL this%Info(" cooling function: " // trim(this%cooling%GetName()))
268  SELECT CASE(this%cooling%GetType())
269  CASE(gray)
270  WRITE (param_str,'(ES8.2)') this%T_0
271  CALL this%Info(" min. temperature: " // trim(param_str))
272  WRITE (param_str,'(ES8.2)') this%rho_0
273  CALL this%Info(" minimum density: " // trim(param_str))
274  CASE(gammie)
275  WRITE (param_str,'(ES8.2)') this%b_cool
276  CALL this%Info(" cooling parameter: " // trim(param_str))
277  CASE(gammie_sb)
278  WRITE (param_str,'(ES8.2)') this%b_cool
279  CALL this%Info(" cooling parameter: " // trim(param_str))
280  IF(this%dt_bdec.GE.0.0) THEN
281  WRITE (param_str,'(ES8.2)') this%b_start
282  CALL this%Info(" initial cooling parameter: " // trim(param_str))
283  WRITE (param_str,'(ES8.2)') this%b_final
284  CALL this%Info(" final cooling parameter: " // trim(param_str))
285  WRITE (param_str,'(ES8.2)') this%t_start
286  CALL this%Info(" starting b_dec time: " // trim(param_str))
287  WRITE (param_str,'(ES8.2)') this%dt_bdec
288  CALL this%Info(" operating time: " // trim(param_str))
289  END IF
290  END SELECT
291  END SUBROUTINE infosources
292 
293 
294  SUBROUTINE setoutput(this,Mesh,config,IO)
295  IMPLICIT NONE
296  !------------------------------------------------------------------------!
297  CLASS(sources_diskcooling) :: this
298  CLASS(mesh_base), INTENT(IN) :: Mesh
299  TYPE(Dict_TYP), POINTER :: config,IO
300  !------------------------------------------------------------------------!
301  INTEGER :: valwrite
302  !------------------------------------------------------------------------!
303 
304  !cooling energy source term
305  CALL getattr(config, "output/Qcool", valwrite, 0)
306  IF (valwrite .EQ. 1) &
307  CALL setattr(io, "Qcool", &
308  this%Qcool%data3d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX))
309 
310  END SUBROUTINE setoutput
311 
312 
313  SUBROUTINE externalsources_single(this,Mesh,Physics,Fluxes,Sources,time,dt,pvar,cvar,sterm)
315  IMPLICIT NONE
316  !------------------------------------------------------------------------!
317  CLASS(sources_diskcooling), INTENT(INOUT) :: this
318  CLASS(mesh_base),INTENT(IN) :: Mesh
319  CLASS(physics_base),INTENT(INOUT) :: Physics
320  CLASS(sources_base),INTENT(INOUT) :: Sources
321  CLASS(fluxes_base),INTENT(IN) :: Fluxes
322  REAL,INTENT(IN) :: time, dt
323  CLASS(marray_compound),INTENT(INOUT):: pvar,cvar,sterm
324  !------------------------------------------------------------------------!
325  SELECT TYPE(s => sterm)
326  TYPE IS (statevector_euler)
327  s%density%data1d(:) = 0.0
328  s%momentum%data1d(:) = 0.0
329 
330  SELECT TYPE(phys => physics)
331  TYPE IS (physics_euler)
332  SELECT TYPE(p => pvar)
333  TYPE IS (statevector_euler)
334  CALL this%UpdateCooling(mesh,phys,sources,time,p)
335  END SELECT
336  END SELECT
337 
338  ! energy loss due to radiation processes
339  s%energy%data1d(:) = -this%Qcool%data1d(:)
340 
341  END SELECT
342  END SUBROUTINE externalsources_single
343 
344 
345  SUBROUTINE calctimestep_single(this,Mesh,Physics,Fluxes,pvar,cvar,time,dt)
347  IMPLICIT NONE
348  !------------------------------------------------------------------------!
349  CLASS(sources_diskcooling), INTENT(INOUT) :: this
350  CLASS(mesh_base), INTENT(IN) :: Mesh
351  CLASS(physics_base), INTENT(INOUT) :: Physics
352  CLASS(fluxes_base), INTENT(IN) :: Fluxes
353  CLASS(marray_compound), INTENT(INOUT) :: pvar,cvar
354  REAL, INTENT(IN) :: time
355  REAL, INTENT(OUT) :: dt
356  !------------------------------------------------------------------------!
357  REAL :: invdt
358  !------------------------------------------------------------------------!
359  ! maximum of inverse cooling timescale t_cool ~ P/Q_cool
360  dt = huge(invdt)
361  SELECT TYPE(p => pvar)
362  CLASS IS(statevector_euler)
363  invdt = maxval(abs(this%Qcool%data1d(:) / p%pressure%data1d(:)), &
364  mask=mesh%without_ghost_zones%mask1d(:))
365  IF (invdt.GT.tiny(invdt)) dt = this%cvis / invdt
366  END SELECT
367  END SUBROUTINE calctimestep_single
368 
370  SUBROUTINE updatecooling(this,Mesh,Physics,Sources,time,pvar)
372  IMPLICIT NONE
373  !------------------------------------------------------------------------!
374  CLASS(sources_diskcooling) :: this
375  CLASS(mesh_base), INTENT(IN) :: Mesh
376  CLASS(physics_euler),INTENT(INOUT) :: Physics
377  CLASS(sources_base), INTENT(INOUT) :: Sources
378  CLASS(statevector_euler),INTENT(INOUT):: pvar
379  REAL, INTENT(IN) :: time
380  !------------------------------------------------------------------------!
381  REAL :: muRgamma,Qfactor
382  !------------------------------------------------------------------------!
383  ! calculate value for beta
384  IF (this%dt_bdec.GE.0.0) THEN
385  IF (time .LT. this%t_start) THEN
386  this%b_cool = this%b_start
387  ELSE IF ((time .GE. this%t_start) .AND. ((time-this%t_start) .LT. &
388  this%dt_bdec)) THEN
389  this%b_cool = this%b_start + &
390  (this%b_final-this%b_start)/this%dt_bdec*(time - this%t_start)
391  ELSE IF ((time-this%t_start) .GE. this%dt_bdec) THEN
392  this%b_cool = this%b_final
393  END IF
394  END IF
395 
396  ! energy loss due to radiation processes
397  SELECT CASE(this%cooling%GetType())
398  CASE(gray)
399  ! some constants
400  murgamma = physics%mu/(physics%Constants%RG*physics%gamma)
401  qfactor = 8./3.*physics%Constants%SB
402  ! compute gray cooling term
403  this%Qcool%data1d(:) = lambda_gray(pvar%data2d(:,physics%DENSITY),sources%height%data1d(:), &
404  murgamma*physics%bccsound%data1d(:)*physics%bccsound%data1d(:), &
405  this%rho_0,this%T_0,qfactor)
406  CASE(gammie)
407  ! compute Gammie cooling term with
408  ! t_cool = b_cool / Omega
409  ! and Omega = ephi*v / r
410  this%Qcool%data3d(:,:,:) = lambda_gammie(pvar%data4d(:,:,:,physics%PRESSURE) / (physics%gamma-1.), &
411  abs((this%ephir%data4d(:,:,:,1)*pvar%data4d(:,:,:,physics%XVELOCITY) &
412  +this%ephir%data4d(:,:,:,2)*(pvar%data4d(:,:,:,physics%YVELOCITY)&
413  +mesh%OMEGA*mesh%radius%bcenter(:,:,:)))) / this%b_cool)
414  CASE(gammie_sb)
415  ! in sb t_cool = b_cool
416  this%Qcool%data1d(:) = lambda_gammie(pvar%pressure%data1d(:) / (physics%gamma-1.), &
417  mesh%OMEGA/this%b_cool)
418  END SELECT
419 
420  END SUBROUTINE updatecooling
421 
422  ELEMENTAL FUNCTION rosselandmeanopacity_new(logrho,logT) RESULT(kappa_R)
423  IMPLICIT NONE
424  !------------------------------------------------------------------------!
425  REAL, INTENT(IN) :: logrho,logt
426  REAL :: kappa_r
427  !------------------------------------------------------------------------!
428  REAL :: kappa4(8)
429  REAL :: tfactor
430  !------------------------------------------------------------------------!
431  ! compute kappa_i^4 for all cooling mechanisms
432 !NEC$ unroll(8)
433  kappa4(:) = exp(max(-40.0,min(40.0, &
434  4.*(logkappa0(:)+rexp(:)*logrho+texp(:)*logt))))
435  ! compute (T/T0)**10
436  tfactor = exp(max(-40.0,min(40.0,10.*(logt-log(t0)))))
437  ! compute Rosseland mean using Gails interpolation formula
438  kappa_r = 1. /(tiny(kappa_r) + &
439  (1./kappa4(1) + 1./(1.+tfactor)/(kappa4(2)+kappa4(3)))**0.25 &
440  + (1./(kappa4(4)+kappa4(5)+kappa4(6)) + 1./(kappa4(7)+kappa4(8)))**0.25)
441  END FUNCTION rosselandmeanopacity_new
442 
459  ELEMENTAL FUNCTION lambda_gray(Sigma,h,Tc,rho0,T0,Qf) RESULT(Qcool)
460  IMPLICIT NONE
461  !---------------------------------------------------------------------!
462  REAL, INTENT(IN) :: sigma,h,tc,rho0,t0,qf
463  REAL :: qcool
464  REAL :: logrho,logt,kappa,tau,tau_eff,t0tc
465  !---------------------------------------------------------------------!
466  ! logarithm of midplane density
467  ! log(SQRT(2*Pi)^-1 * Sigma / H ) = -log(SQRT(2*Pi) * H / Sigma)
468  logrho = -log(max(rho0,sqrt_twopi * h / sigma))
469  ! logarithm of midplane temperature
470  logt = log(max(t0,tc))
471  ! compute Rosseland mean absorption coefficient using Gails formula
472 !CDIR IEXPAND
473  kappa = rosselandmeanopacity_new(logrho,logt)
474  ! optical depth
475  tau = 0.5*kappa*sigma
476  ! effective optical depth
477  tau_eff = 0.5*tau + 1./(3.*tau) + 1./sqrt_three
478  ! temperature ratio
479  t0tc = t0/tc
480  ! cooling term
481  qcool = qf/tau_eff * exp(4.0*logt) * (1.0-t0tc*t0tc*t0tc*t0tc) ! = Tc**4-T0**4
482  END FUNCTION lambda_gray
483 
491  ELEMENTAL FUNCTION lambda_gammie(Eint,t_cool_inv) RESULT(Qcool)
492  IMPLICIT NONE
493  !---------------------------------------------------------------------!
494  REAL, INTENT(IN) :: eint,t_cool_inv
495  REAL :: qcool
496  !---------------------------------------------------------------------!
497  qcool = eint * t_cool_inv
498  END FUNCTION lambda_gammie
499 
500  SUBROUTINE finalize(this)
501  IMPLICIT NONE
502  !------------------------------------------------------------------------!
503  CLASS(sources_diskcooling), INTENT(INOUT) :: this
504  !------------------------------------------------------------------------!
505  SELECT CASE(this%cooling%GetType())
506  CASE(gray)
507  CALL this%Qcool%Destroy()
508  CASE(gammie)
509  CALL this%Qcool%Destroy()
510  CALL this%ephir%Destroy()
511  CASE(gammie_sb)
512  CALL this%Qcool%Destroy()
513  END SELECT
514  END SUBROUTINE finalize
515 
516 END MODULE sources_diskcooling_mod
subroutine finalize(this)
Destructor of common class.
real, dimension(8), parameter rexp
integer, parameter, public gray
generic source terms module providing functionaly common to all source terms
subroutine infosources(this, Mesh)
derived class for compound of mesh arrays
base class for mesh arrays
Definition: marray_base.f90:36
Basic fosite module.
common data structure
defines properties of a 3D cylindrical mesh
integer, parameter, public gammie_sb
subroutine initsources_diskcooling(this, Mesh, Physics, Fluxes, config, IO)
Constructor of disk cooling module.
basic mesh array class
Definition: marray_base.f90:64
subroutine setoutput(this, Mesh, config, IO)
defines properties of a 3D cartesian mesh
Basic physics module.
Dictionary for generic data types.
Definition: common_dict.f90:61
integer, parameter, public gammie
physics module for 1D,2D and 3D non-isothermal Euler equations
elemental real function lambda_gammie(Eint, t_cool_inv)
Gammie cooling.
subroutine updatecooling(this, Mesh, Physics, Sources, time, pvar)
Updates the cooling function at each time step.
real, dimension(8), parameter texp
real, dimension(8), parameter logkappa0
base module for numerical flux functions
Definition: fluxes_base.f90:39
subroutine externalsources_single(this, Mesh, Physics, Fluxes, Sources, time, dt, pvar, cvar, sterm)
subroutine calctimestep_single(this, Mesh, Physics, Fluxes, pvar, cvar, time, dt)
source terms module for cooling of geometrically thin accretion disks
elemental real function rosselandmeanopacity_new(logrho, logT)
elemental real function lambda_gray(Sigma, h, Tc, rho0, T0, Qf)
Gray cooling.