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-2021 #
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!----------------------------------------------------------------------------!
70 USE common_dict
71 IMPLICIT NONE
72 !--------------------------------------------------------------------------!
73 PRIVATE
74 CHARACTER(LEN=32), PARAMETER :: source_name = "thin accretion disk cooling"
75 INTEGER, PARAMETER :: gray = 1
76 INTEGER, PARAMETER :: gammie = 2
77 INTEGER, PARAMETER :: gammie_sb = 3
78 CHARACTER(LEN=28), PARAMETER, DIMENSION(3) :: &
79 cooling_name = (/ "Gray disk cooling ", &
80 "Gammie disk cooling ", &
81 "Gammie shearing box cooling" /)
82 !--------------------------------------------------------------------------!
83 REAL, PARAMETER :: sqrt_three = 1.73205080757
84 REAL, PARAMETER :: sqrt_twopi = 2.50662827463
85
86! Rosseland mean opacity constants in SI units;
87! taken from Bell & Lin, ApJ, 427, 1994
88! kappa_i= kappa_0i * rho**rexp(i) * T**Texp(i)
89
90!!$ DOUBLE PRECISION, PARAMETER :: kappa0(8) = (/ &
91!!$ 2.00D-05, & ! ice grains [m^2/kg/K^2]
92!!$ 2.00D+15, & ! evaporation of ice grains [m^2/kg*K^7]
93!!$ 1.00D-02, & ! metal grains [m^2/kg/K^0.5]
94!!$ 2.00D+77, & ! evaporation of metal grains [m^5/kg^2*K^24]
95!!$ 1.00D-11, & ! molecules [m^4/kg^(5/3)/K^3]
96!!$ 1.00D-38, & ! H-scattering [m^3/kg^(4/3)/K^10]
97!!$ 1.50D+16, & ! bound-free and free-free [m^5/kg^2*K^(5/2)]
98!!$ KE /) ! electron scattering [m^2/kg]
99 REAL, PARAMETER :: logkappa0(8) = (/ &
100 -10.8197782844, & ! ice grains [m^2/kg/K^2]
101 35.2319235755, & ! evaporation of ice grains [m^2/kg*K^7]
102 -4.60517018599, & ! metal grains [m^2/kg/K^0.5]
103 177.992199341, & ! evaporation of metal grains [m^5/kg^2*K^24]
104 -25.3284360229, & ! molecules [m^4/kg^(5/3)/K^3]
105 -87.4982335338, & ! H-scattering [m^3/kg^(4/3)/K^10]
106 37.246826596, & ! bound-free and free-free [m^5/kg^2*K^(5/2)]
107 -3.3581378922 /) ! electron scattering [m^2/kg]
108 REAL, PARAMETER :: texp(8) = (/ 2.0, -7.0, 0.5, -24.0, 3.0, 10.0, -2.5, 0.0 /)
109 REAL, PARAMETER :: rexp(8) = (/ 0.0, 0.0, 0.0, 1.0, 2./3., 1./3., 1.0, 0.0 /)
110 REAL, PARAMETER :: t0 = 3000 ! temperature constant (opacity interpolation)
111
112 !--------------------------------------------------------------------------!
114 CLASS(logging_base), ALLOCATABLE :: cooling
115 TYPE(marray_base), ALLOCATABLE :: ephir
116 TYPE(sources_gravity), POINTER :: grav
117 REAL :: b_cool
118 REAL :: b_start
119 REAL :: b_final
120 REAL :: t_start
121 REAL :: dt_bdec
122 REAL :: t_0
123 REAL :: rho_0
124 CONTAINS
125 PROCEDURE :: initsources
126 PROCEDURE :: infosources
127 PROCEDURE :: updatecooling
128 final :: finalize
129 END TYPE
130 !--------------------------------------------------------------------------!
131 PUBLIC :: &
132 ! types
134 ! constants
136 !--------------------------------------------------------------------------!
137
138CONTAINS
139
141 SUBROUTINE initsources(this,Mesh,Physics,Fluxes,config,IO)
145 IMPLICIT NONE
146 !------------------------------------------------------------------------!
147 CLASS(sources_diskcooling), INTENT(INOUT) :: this
148 CLASS(mesh_base), INTENT(IN) :: Mesh
149 CLASS(physics_base), INTENT(IN) :: Physics
150 CLASS(fluxes_base), INTENT(IN) :: Fluxes
151 TYPE(dict_typ), POINTER :: config,IO
152 !------------------------------------------------------------------------!
153 INTEGER :: stype,err
154 INTEGER :: cooling_func
155 !------------------------------------------------------------------------!
156 CALL getattr(config, "stype", stype)
157 CALL this%InitSources_base(stype,source_name)
158
159 ! some sanity checks
160 ! isothermal modules are excluded
161 SELECT TYPE (phys => physics)
162 CLASS IS(physics_euler)
163 ! do nothing
164 CLASS DEFAULT
165 ! abort
166 CALL this%Error("sources_diskcooling::InitSources","physics not supported")
167 END SELECT
168
169 ! check for dimensions
170 IF (physics%VDIM.GT.2) THEN
171 CALL this%Error("sources_diskcooling::InitSources","only 2D simulations supported")
172 END IF
173
174 ! get cooling method
175 CALL getattr(config,"method",cooling_func)
176 IF (cooling_func.LE.1.OR.cooling_func.GT.3) &
177 CALL this%Error("sources_diskcooling::InitSources","unknown cooling method")
178
179 ALLOCATE(logging_base::this%cooling,stat=err)
180 IF (err.EQ.0) ALLOCATE(this%Q,stat=err)
181 IF (err.NE.0) CALL this%Error("sources_diskcooling::InitSources","memory allocation failed")
182 CALL this%cooling%InitLogging(cooling_func,cooling_name(cooling_func))
183 this%Q = marray_base()
184
185 SELECT CASE(this%cooling%GetType())
186 CASE(gray)
187 ! check units, currently only SI units are supported
188 IF (physics%constants%GetType().NE.si) &
189 CALL this%Error("sources_diskcooling::InitSources","only SI units supported for gray cooling")
190 CASE(gammie)
191 ! check for geometry
192 SELECT TYPE (mgeo => mesh%Geometry)
193 CLASS IS(geometry_cylindrical)
194 ALLOCATE(this%ephir)
195 this%ephir = marray_base(2)
196 this%ephir%data4d(:,:,:,1) = -mesh%posvec%bcenter(:,:,:,2)/mesh%radius%bcenter(:,:,:)**2
197 this%ephir%data4d(:,:,:,2) = mesh%posvec%bcenter(:,:,:,1)/mesh%radius%bcenter(:,:,:)**2
198 CLASS DEFAULT
199 CALL this%Error("sources_diskcooling::InitSources","geometry not supported")
200 END SELECT
201 CASE(gammie_sb)
202 SELECT TYPE (mgeo => mesh%Geometry)
203 TYPE IS(geometry_cartesian)
204 ! do nothing
205 CLASS DEFAULT
206 CALL this%Error("sources_diskcooling::InitSources","geometry not supported")
207 END SELECT
208 CASE DEFAULT
209 ! this should not happen (see above)
210 CALL this%Error("sources_diskcooling::InitSources","unknown cooling method")
211 END SELECT
212
213 ! Courant number, i.e. safety factor for numerical stability
214 CALL getattr(config, "cvis", this%cvis, 0.1)
215
216 ! minimum temperature
217 CALL getattr(config, "Tmin", this%T_0, 1.0e-30)
218
219 ! minimum density
220 CALL getattr(config, "Rhomin", this%rho_0, 1.0e-30)
221
222 ! cooling time
223 CALL getattr(config, "b_cool", this%b_cool, 1.0e+00)
224
225 ! initial and final cooling time
226 CALL getattr(config, "b_start", this%b_start, 0.0)
227 CALL getattr(config, "b_final", this%b_final, this%b_cool)
228
229 ! starting point for beta
230 CALL getattr(config, "t_start", this%t_start, 0.0)
231
232 ! timescale for changing beta
233 CALL getattr(config, "dt_bdec", this%dt_bdec, -1.0)
234
235 ! set initial time < 0
236 this%time = -1.0
237
238 ! initialize cooling function
239 this%Q%data1d(:) = 0.0
240
241 !initialise output
242 CALL this%SetOutput(mesh,config,io)
243 CALL this%InfoSources(mesh)
244 END SUBROUTINE initsources
245
246 SUBROUTINE infosources(this,Mesh)
247 IMPLICIT NONE
248 !------------------------------------------------------------------------!
249 CLASS(sources_diskcooling), INTENT(IN) :: this
250 CLASS(mesh_base), INTENT(IN) :: Mesh
251 !------------------------------------------------------------------------!
252 CHARACTER(LEN=32) :: param_str
253 !------------------------------------------------------------------------!
254 CALL this%Info(" cooling function: " // trim(this%cooling%GetName()))
255 SELECT CASE(this%cooling%GetType())
256 CASE(gray)
257 WRITE (param_str,'(ES10.2)') this%T_0
258 CALL this%Info(" min. temperature: " // trim(param_str))
259 WRITE (param_str,'(ES10.2)') this%rho_0
260 CALL this%Info(" minimum density: " // trim(param_str))
261 CASE(gammie)
262 WRITE (param_str,'(ES10.2)') this%b_cool
263 CALL this%Info(" cooling parameter: " // trim(param_str))
264 CASE(gammie_sb)
265 WRITE (param_str,'(ES10.2)') this%b_cool
266 CALL this%Info(" cooling parameter: " // trim(param_str))
267 IF(this%dt_bdec.GE.0.0) THEN
268 WRITE (param_str,'(ES10.2)') this%b_start
269 CALL this%Info(" initial cooling parameter: " // trim(param_str))
270 WRITE (param_str,'(ES10.2)') this%b_final
271 CALL this%Info(" final cooling parameter: " // trim(param_str))
272 WRITE (param_str,'(ES10.2)') this%t_start
273 CALL this%Info(" starting b_dec time: " // trim(param_str))
274 WRITE (param_str,'(ES10.2)') this%dt_bdec
275 CALL this%Info(" operating time: " // trim(param_str))
276 END IF
277 END SELECT
278 END SUBROUTINE infosources
279
280
282 SUBROUTINE updatecooling(this,Mesh,Physics,time,pvar)
284 IMPLICIT NONE
285 !------------------------------------------------------------------------!
286 CLASS(sources_diskcooling), INTENT(INOUT) :: this
287 CLASS(mesh_base), INTENT(IN) :: Mesh
288 CLASS(physics_euler), INTENT(IN) :: Physics
289 REAL, INTENT(IN) :: time
290 CLASS(statevector_euler), INTENT(IN) :: pvar
291 !------------------------------------------------------------------------!
292 REAL :: muRgamma,Qfactor
293 !------------------------------------------------------------------------!
294
295 ! energy loss due to radiation processes
296 SELECT CASE(this%cooling%GetType())
297 CASE(gray)
298 ! make sure the
299 IF (ASSOCIATED(this%grav)) THEN
300 IF (ALLOCATED(this%grav%height)) THEN
301 IF (ASSOCIATED(this%grav%height%data1d)) THEN
302 ! some constants
303 murgamma = physics%mu/(physics%Constants%RG*physics%gamma)
304 qfactor = 8./3.*physics%Constants%SB
305 ! compute gray cooling term
306 this%Q%data1d(:) = lambda_gray(pvar%density%data1d(:),this%grav%height%data1d(:), &
307 murgamma*physics%bccsound%data1d(:)*physics%bccsound%data1d(:), &
308 this%rho_0,this%T_0,qfactor)
309 ELSE
310 CALL this%Error("sources_diskcooling::UpdateCooling","disk height seems not properly assigned in gray cooling")
311 END IF
312 END IF
313 END IF
314 CASE(gammie)
315 ! compute Gammie cooling term based on cooling time scale
316 ! t_cool = b_cool / Omega with Omega = ephi*v / r and
317 ! dimensionless scaling parameter beta which is usually
318 ! held constant except for the initial phase
319 IF (this%dt_bdec.GE.0.0) THEN
320 IF (time .LT. this%t_start) THEN
321 this%b_cool = this%b_start
322 ELSE IF ((time .GE. this%t_start) .AND. ((time-this%t_start) .LT. &
323 this%dt_bdec)) THEN
324 this%b_cool = this%b_start + &
325 (this%b_final-this%b_start)/this%dt_bdec*(time - this%t_start)
326 ELSE IF ((time-this%t_start) .GE. this%dt_bdec) THEN
327 this%b_cool = this%b_final
328 END IF
329 END IF
330 ! set cooling function
331 this%Q%data3d(:,:,:) = lambda_gammie(pvar%pressure%data3d(:,:,:) / (physics%gamma-1.), &
332 abs((this%ephir%data4d(:,:,:,1)*pvar%velocity%data4d(:,:,:,1) &
333 +this%ephir%data4d(:,:,:,2)*(pvar%velocity%data4d(:,:,:,2)&
334 +mesh%OMEGA*mesh%radius%bcenter(:,:,:)))) / this%b_cool)
335 CASE(gammie_sb)
336 ! in sb t_cool = b_cool
337 this%Q%data1d(:) = lambda_gammie(pvar%pressure%data1d(:) / (physics%gamma-1.), &
338 mesh%OMEGA/this%b_cool)
339 END SELECT
340
341 END SUBROUTINE updatecooling
342
343 ELEMENTAL FUNCTION rosselandmeanopacity_new(logrho,logT) RESULT(kappa_R)
344 IMPLICIT NONE
345 !------------------------------------------------------------------------!
346 REAL, INTENT(IN) :: logrho,logt
347 REAL :: kappa_r
348 !------------------------------------------------------------------------!
349 REAL :: kappa4(8)
350 REAL :: tfactor
351 !------------------------------------------------------------------------!
352 ! compute kappa_i^4 for all cooling mechanisms
353!NEC$ unroll(8)
354 kappa4(:) = exp(max(-40.0,min(40.0, &
355 4.*(logkappa0(:)+rexp(:)*logrho+texp(:)*logt))))
356 ! compute (T/T0)**10
357 tfactor = exp(max(-40.0,min(40.0,10.*(logt-log(t0)))))
358 ! compute Rosseland mean using Gails interpolation formula
359 kappa_r = 1. /(tiny(kappa_r) + &
360 (1./kappa4(1) + 1./(1.+tfactor)/(kappa4(2)+kappa4(3)))**0.25 &
361 + (1./(kappa4(4)+kappa4(5)+kappa4(6)) + 1./(kappa4(7)+kappa4(8)))**0.25)
362 END FUNCTION rosselandmeanopacity_new
363
380 ELEMENTAL FUNCTION lambda_gray(Sigma,h,Tc,rho0,T0,Qf) RESULT(Qcool)
381 IMPLICIT NONE
382 !---------------------------------------------------------------------!
383 REAL, INTENT(IN) :: sigma,h,tc,rho0,t0,qf
384 REAL :: qcool
385 REAL :: logrho,logt,kappa,tau,tau_eff,t0tc
386 !---------------------------------------------------------------------!
387 ! logarithm of midplane density
388 ! log(SQRT(2*Pi)^-1 * Sigma / H ) = -log(SQRT(2*Pi) * H / Sigma)
389 logrho = -log(max(rho0,sqrt_twopi * h / sigma))
390 ! logarithm of midplane temperature
391 logt = log(max(t0,tc))
392 ! compute Rosseland mean absorption coefficient using Gails formula
393!CDIR IEXPAND
394 kappa = rosselandmeanopacity_new(logrho,logt)
395 ! optical depth
396 tau = 0.5*kappa*sigma
397 ! effective optical depth
398 tau_eff = 0.5*tau + 1./(3.*tau) + 1./sqrt_three
399 ! temperature ratio
400 t0tc = t0/tc
401 ! cooling term
402 qcool = qf/tau_eff * exp(4.0*logt) * (1.0-t0tc*t0tc*t0tc*t0tc) ! = Tc**4-T0**4
403 END FUNCTION lambda_gray
404
412 ELEMENTAL FUNCTION lambda_gammie(Eint,t_cool_inv) RESULT(Qcool)
413 IMPLICIT NONE
414 !---------------------------------------------------------------------!
415 REAL, INTENT(IN) :: eint,t_cool_inv
416 REAL :: qcool
417 !---------------------------------------------------------------------!
418 qcool = eint * t_cool_inv
419 END FUNCTION lambda_gammie
420
421 SUBROUTINE finalize(this)
422 IMPLICIT NONE
423 !------------------------------------------------------------------------!
424 TYPE(sources_diskcooling), INTENT(INOUT) :: this
425 !------------------------------------------------------------------------!
426 IF (ALLOCATED(this%ephir)) DEALLOCATE(this%ephir)
427 END SUBROUTINE finalize
428
Dictionary for generic data types.
Definition: common_dict.f90:61
base module for numerical flux functions
Definition: fluxes_base.f90:39
defines properties of a 3D cartesian mesh
defines properties of a 3D cylindrical mesh
Basic fosite module.
subroutine finalize(this)
Destructor of logging_base class.
base class for mesh arrays
Definition: marray_base.f90:36
derived class for compound of mesh arrays
basic mesh module
Definition: mesh_base.f90:72
Basic physics module.
physics module for 1D,2D and 3D non-isothermal Euler equations
generic source terms module providing functionaly common to all source terms
source terms module for simple optically thin cooling
subroutine initsources(this, Mesh, Physics, Fluxes, config, IO)
subroutine updatecooling(this, Mesh, Physics, time, pvar)
Updates the cooling function at each time step.
character(len=32), parameter source_name
source terms module for cooling of geometrically thin accretion disks
elemental real function lambda_gray(Sigma, h, Tc, rho0, T0, Qf)
Gray cooling.
integer, parameter, public gray
elemental real function rosselandmeanopacity_new(logrho, logT)
character(len=28), dimension(3), parameter cooling_name
real, dimension(8), parameter texp
subroutine infosources(this, Mesh)
integer, parameter, public gammie_sb
real, dimension(8), parameter logkappa0
elemental real function lambda_gammie(Eint, t_cool_inv)
Gammie cooling.
integer, parameter, public gammie
real, dimension(8), parameter rexp
generic gravity terms module providing functionaly common to all gravity terms
common data structure
basic mesh array class
Definition: marray_base.f90:69
mesh data structure
Definition: mesh_base.f90:122