ttauridisk.f90
Go to the documentation of this file.
1!#############################################################################
2!# #
3!# fosite - 2D hydrodynamical simulation program #
4!# module: ttauridisk.f90 #
5!# #
6!# Copyright (C) 2006-2024 #
7!# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
8!# #
9!# This program is free software; you can redistribute it and/or modify #
10!# it under the terms of the GNU General Public License as published by #
11!# the Free Software Foundation; either version 2 of the License, or (at #
12!# your option) any later version. #
13!# #
14!# This program is distributed in the hope that it will be useful, but #
15!# WITHOUT ANY WARRANTY; without even the implied warranty of #
16!# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
17!# NON INFRINGEMENT. See the GNU General Public License for more #
18!# details. #
19!# #
20!# You should have received a copy of the GNU General Public License #
21!# along with this program; if not, write to the Free Software #
22!# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
23!# #
24!#############################################################################
25
26!----------------------------------------------------------------------------!
28!----------------------------------------------------------------------------!
29PROGRAM ttauri
30 USE fosite_mod
31#ifdef PARALLEL
32#ifdef HAVE_MPI_MOD
33 USE mpi
34#endif
35#endif
36 IMPLICIT NONE
37#ifdef PARALLEL
38#ifdef HAVE_MPIF_H
39 include 'mpif.h'
40#endif
41#endif
42 !--------------------------------------------------------------------------!
43 ! general constants
44 REAL, PARAMETER :: gn = 6.6742d-11 ! Newtons grav. constant !
45 REAL, PARAMETER :: cc = 2.99792458d+8 ! speed of light !
46 REAL, PARAMETER :: msun = 1.989d+30 ! solar mass [kg] !
47 REAL, PARAMETER :: au = 1.49597870691e+11 ! astronomical unit [m] !
48 REAL, PARAMETER :: year = 3.15576e+7 ! Julian year [sec] !
49 REAL, PARAMETER :: parsec = 0.5/pi*1.296e+6 * au ! parsec [m] !
50 ! simulation parameters
51 REAL, PARAMETER :: tsim = 1.0e+4 * year
52 REAL, PARAMETER :: m_bh = 0.5e+0 * msun ! mass of central point mass !
53 REAL, PARAMETER :: m_disk = 1.0e-1 * m_bh ! accretion disk mass !
54 REAL, PARAMETER :: rs = 2 * gn * m_bh / cc**2 ! Schwarzschild radius !
55 REAL, PARAMETER :: lscale = au ! typical length scale !
56 REAL, PARAMETER :: etasgs = 1.0e-6
57 REAL, PARAMETER :: gamma = 1.4
58 ! computational domain
59 REAL, PARAMETER :: rmin = 2.0d+0 * lscale
60 REAL, PARAMETER :: rmax = 3.0d+2 * lscale
61 REAL, PARAMETER :: zmin = -1.3d+2 * lscale
62 REAL, PARAMETER :: zmax = 1.3d+2 * lscale
63 REAL, PARAMETER :: ztan = 1.0e+2 * lscale ! scale for tancyl. coordinates!
64 ! initial condition:
65 ! hydrostatic equilibrium for slightly non-keplerian flow
66 ! deviation from Keplerian: v_phi(s,z) = v_kep(s,z) / lambda(z)
67 ! lambda(z) = 1 + A0/(1+(z/Z0)**2)
68 ! pressure in equatorial plane: Pc(s) = P0 * EXP(-s/S0)
69 REAL, PARAMETER :: z0 = 3.0e+02 * lscale ! vertical scale !
70 REAL, PARAMETER :: a0 = 1.0e-01 ! velocity deviation !
71 REAL, PARAMETER :: s0 = 1.5e+02 * lscale ! radial scale !
72 REAL, PARAMETER :: b0 = -1.0 ! <1 ! ! slope for density power law !
73 REAL, PARAMETER :: rho_inf = 1.0e-15 ! density at infinity !
74 REAL, PARAMETER :: p_inf = 1.4e-10 ! pressure at infinity !
75 INTEGER, PARAMETER :: problem = euler
76 ! resolution
77 INTEGER, PARAMETER :: rres = 100
78 INTEGER, PARAMETER :: phires = 1
79 INTEGER, PARAMETER :: zres = 128
80 ! output file parameter
81 INTEGER, PARAMETER :: onum = 1000 ! number of outputs !
82 CHARACTER(LEN=256), PARAMETER :: odir &! output directory
83 = "./"
84 CHARACTER(LEN=256), PARAMETER & ! output data file name !
85 :: ofname = 'Ttauri'
86 !--------------------------------------------------------------------------!
87 CLASS(fosite), ALLOCATABLE :: sim
88 !--------------------------------------------------------------------------!
89
90 ALLOCATE(sim)
91
92 CALL sim%InitFosite()
93
94 CALL makeconfig(sim%config)
95
96 CALL sim%Setup()
97
98 ! set initial condition
99 CALL initdata(sim%Mesh, sim%Physics, sim%Fluxes, sim%Timedisc, sim%Sources)
100
101 CALL sim%Run()
102
103 CALL sim%Finalize()
104
105CONTAINS
106
107 SUBROUTINE makeconfig(config)
108 IMPLICIT NONE
109 !------------------------------------------------------------------------!
110 TYPE(dict_typ),POINTER :: config
111 !------------------------------------------------------------------------!
112 ! Local variable declaration
113 TYPE(dict_typ), POINTER :: mesh, physics, boundary, datafile, logfile, sources, &
114 timedisc,fluxes,stemp
115 !------------------------------------------------------------------------!
116
117 ! mesh settings
118 mesh => dict(&
119 "meshtype" / midpoint, &
120 "geometry" / cylindrical, &
121 "inum" / rres, & ! resolution in x and !
122 "jnum" / phires, & ! resolution in y and !
123 "knum" / zres, & ! z direction !
124 "xmin" / rmin, &
125 "xmax" / rmax, &
126 "ymin" / (0.0), &
127 "ymax" / (2.*pi), &
128 "zmin" / zmin, &
129 "zmax" / zmax)
130
131 ! physics settings
132 physics => dict(&
133 "problem" / problem, &
134 "gamma" / gamma, & ! ratio of specific heats !
135 "mu" / 6.02e-4, & ! mean molecular weight !
136 "dpmax" / 1.0e+3) ! for advanced time step control !
137
138 ! numerical scheme for flux calculation
139 fluxes => dict(&
140 "fluxtype" / kt, &
141 "order" / linear, &
142 "variables" / primitive, & ! vars. to use for reconstruction!
143 "limiter" / minmod, & ! one of: minmod, monocent,... !
144 "theta" / 1.2) ! optional parameter for limiter !
145
146 ! boundary conditions
147 boundary => dict( &
148!!$ "western" / REFLECTING, &
149!!$ +"eastern" / REFLECTING, &
150!!$ +"western" / CUSTOM, &
151!!$ +"eastern" / CUSTOM, &
152!!$ +"western" / NO_GRADIENTS, &
153!!$ +"eastern" / NO_GRADIENTS, &
154 "western" / custom, &
155 "eastern" / farfield, &
156!!$ +"southern" / AXIS, &
157!!$ +"southern" / REFLECTING, &
158!!$ +"northern" / REFLECTING)
159 "southern" / periodic, &
160!!$ +"northern" / CUSTOM)
161!!$ +"southern" / NO_GRADIENTS, &
162!!$ +"northern" / NO_GRADIENTS)
163!!$ +"southern" / FARFIELD, &
164 "northern" / periodic, &
165 ! "bottomer" / NO_GRADIENTS, &
166 "bottomer" / farfield, &
167 "topper" / farfield)
168!!$ +"northern" / REFLECTING)
169
170 ! source term due to a point mass
171 stemp => dict("stype" / gravity, &
172 "pmass/gtype" / pointmass, & ! grav. accel. of a point mass !
173 "pmass/mass" / m_bh) ! mass of the accreting object[kg] !
174
175 NULLIFY(sources)
176 CALL setattr(sources, "grav", stemp)
177
178
179 ! account for energy losses due to radiative cooling
180!!$ stemp => Dict(, &
181!!$ "stype" / COOLING,, &
182!!$ "cvis" / 0.9) ! CFL number for cooling time !
183!!$ CALL SetAttr(sources, "cooling", stemp)
184
185! ! viscosity source term
186! stemp => Dict("stype" / VISCOSITY, &
187! "cvis" / 0.6, &
188!!!$ +"vismodel" / ALPHA, &
189!!!$ +"dynconst" / 0.1)
190! "vismodel" / BETA, &
191! "dynconst" / 0.001, &
192! "output/stress" / 1, &
193!! "output/kinvis" / 1, &
194! "output/dynvis" / 1)
195
196 ! time discretization settings
197 timedisc => dict(&
198 "method" / modified_euler, &
199 "order" / 3, &
200 "cfl" / 0.4, &
201 "stoptime" / tsim, &
202 "dtlimit" / 1.0e-3, &
203 "maxiter" / 1000000000, &
204 "output/external_sources" / 1, &
205 "output/geometrical_sources" / 1, &
206 "output/fluxes" / 0)
207
208! ! initialize log input/output
209! logfile => Dict(, &
210! "fileformat" / BINARY, &
211! +"filename" / TRIM(lfname), &
212! +"dtwall" / 3600, &
213! +"filecycles" / 1)
214
215 ! initialize data input/output
216 datafile => dict("fileformat" / vtk, &
217 "unit" / 5555, &
218 "filename" / (trim(odir) // trim(ofname)), &
219 "stoptime" / tsim, &
220 "count" / onum, &
221 "filecycles" / (onum+1))
222
223 config => dict("mesh" / mesh, &
224 "physics" / physics, &
225 "boundary" / boundary, &
226 "fluxes" / fluxes, &
227 "sources" / sources, &
228 "timedisc" / timedisc, &
229! "logfile" / logfile, &
230 "datafile" / datafile)
231
232 END SUBROUTINE makeconfig
233
234 SUBROUTINE initdata(Mesh,Physics,Fluxes,Timedisc,Sources)
237 IMPLICIT NONE
238 !------------------------------------------------------------------------!
239 CLASS(mesh_base) ,INTENT(IN) :: Mesh
240 CLASS(physics_base) ,INTENT(INOUT) :: Physics
241 CLASS(fluxes_base) ,INTENT(INOUT) :: Fluxes
242 CLASS(timedisc_base),INTENT(INOUT):: Timedisc
243 CLASS(sources_list),ALLOCATABLE,INTENT(INOUT) :: Sources
244 !------------------------------------------------------------------------!
245 ! Local variable declaration
246 CLASS(sources_base), POINTER :: sp
247 CLASS(sources_gravity), POINTER :: gp => null()
248 REAL, DIMENSION(Mesh%IGMIN:Mesh%IGMAX,Mesh%JGMIN:Mesh%JGMAX,Mesh%KGMIN:Mesh%KGMAX,2) :: dv
249 REAL :: s,z,tau,lambda,tau1,tau2,dPs,dPz,s1,s2,z1,z2,P0,rho0,cs_inf
250 REAL :: mdisk,am
251#ifdef PARALLEL
252 INTEGER :: ierror
253 REAL :: mdisk_local,am_local
254#endif
255 INTEGER :: i,j,k,n
256 CHARACTER(LEN=20) :: mdisk_str,am_str
257 !------------------------------------------------------------------------!
258 ! get gravitational acceleration
259 IF (ALLOCATED(sources)) &
260 sp => sources%GetSourcesPointer(gravity)
261 IF (.NOT.ASSOCIATED(sp)) &
262 CALL physics%Error("ttauridisk::InitData","no gravity term initialized")
263
264 ! initial condition (computational domain)
265 ! the total disk mass is proportional to the central pressure;
266 ! to determine the necessary central pressure for a given
267 ! disk mass, the initial condition is computed twice
268 p0 = 1.0e+10
269 rho0 = 1.0e-09
270 cs_inf = sqrt(gamma*p_inf/rho_inf)
271 DO n=1,2
272 DO k=mesh%KGMIN,mesh%KGMAX
273 DO j=mesh%JGMIN,mesh%JGMAX
274 DO i=mesh%IGMIN,mesh%IGMAX
275 s = abs(mesh%bccart(i,j,k,1))
276 z = mesh%bccart(i,j,k,3)
277if (s .eq. 0.0 .or. z .eq. 0.0) print *,s,z,i,j
278
279 tau = func_tau(s,z)
280 lambda = func_lambda(z)
281 timedisc%pvar%data4d(i,j,k,physics%XVELOCITY) = 0.0
282 timedisc%pvar%data4d(i,j,k,physics%ZVELOCITY) = 0.0
283 timedisc%pvar%data4d(i,j,k,physics%PRESSURE) = pc(tau,rho0,cs_inf)
284 z1 = mesh%cart%faces(i,j,k,5,3) ! western cell faces z coordinate
285 z2 = mesh%cart%faces(i,j,k,6,3) ! eastern cell faces z coordinate
286 tau1 = func_tau(s,z1)
287 tau2 = func_tau(s,z2)
288 dpz = (pc(tau2,rho0,cs_inf)-pc(tau1,rho0,cs_inf))/mesh%dlz%data3d(i,j,k)
289 IF (abs(z).GT.0.0) THEN
290!!$ Timedisc%pvar(i,j,Physics%DENSITY) = rho0 * rho(s,z,tau,lambda)
291 timedisc%pvar%data4d(i,j,k,physics%DENSITY) = dpz / gz(s,z)
292 ELSE
293 timedisc%pvar%data4d(i,j,k,physics%DENSITY) = rho0 * (s/s0)**b0
294 END IF
295 s1 = abs(mesh%cart%faces(i,j,k,1,1)) !vorher (3,1) ! southern cell faces s coordinate
296 s2 = abs(mesh%cart%faces(i,j,k,2,1)) !vorher (4,1) ! northern cell faces s coordinate
297 tau1 = func_tau(s1,z)
298 tau2 = func_tau(s2,z)
299 dps = (pc(tau2,rho0,cs_inf)-pc(tau1,rho0,cs_inf))/mesh%dlx%data3d(i,j,k)
300! Timedisc%pvar%data4d(i,j,k,Physics%YVELOCITY) = SQRT(MAX(0.0, &
301! s*(dPs/Timedisc%pvar%data4d(i,j,k,Physics%DENSITY) - gs(s,z))))
302 timedisc%pvar%data4d(i,j,k,physics%YVELOCITY) = sqrt(max(0.0,-s*gs(s,z) / lambda))
303 END DO
304 END DO
305 END DO
306 ! compute disk mass
307 mdisk = sum(timedisc%pvar%data4d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,physics%DENSITY) &
308 * mesh%volume%data3d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX))
309 ! compute angular momentum
310 am = sum(mesh%hy%bcenter(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX) &
311 * timedisc%pvar%data4d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,physics%YVELOCITY) &
312 * timedisc%pvar%data4d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX,physics%DENSITY) &
313 * mesh%volume%data3d(mesh%IMIN:mesh%IMAX,mesh%JMIN:mesh%JMAX,mesh%KMIN:mesh%KMAX))
314
315#ifdef PARALLEL
316 mdisk_local = mdisk
317 CALL mpi_allreduce(mdisk_local,mdisk,1,default_mpi_real,mpi_sum, &
318 mesh%comm_cart,ierror)
319 am_local = am
320 CALL mpi_allreduce(am_local,am,1,default_mpi_real,mpi_sum, &
321 mesh%comm_cart,ierror)
322#endif
323!!$ ! adjust central pressure
324!!$ P0 = M_DISK / mdisk * P0
325 ! adjust density at (S0,Z=0)
326 rho0 = m_disk / mdisk * rho0
327 END DO
328 ! 2. initialize gravitational acceleration
329! CALL gp%UpdateGravity(Mesh,Physics,Fluxes,Timedisc%pvar,0.0,0.0)
330! Timedisc%pvar%data4d(:,:,:,2:2+Physics%VDIM) = &
331! Timedisc%GetCentrifugalVelocity(Mesh,Physics,Fluxes,Sources,(/0.,0.,1./),gp%accel%data4d)
332
333
334 ! add velocity perturbations
335!!$ CALL RANDOM_SEED
336!!$ CALL RANDOM_NUMBER(dv)
337!!$ Timedisc%pvar(:,:,Physics%XVELOCITY) = Timedisc%pvar(:,:,Physics%XVELOCITY) &
338!!$ + (dv(:,:,1)-0.5)*2.0E+2
339!!$ Timedisc%pvar(:,:,Physics%YVELOCITY) = Timedisc%pvar(:,:,Physics%YVELOCITY) &
340!!$ + (dv(:,:,2)-0.5)*2.0E+2
341
342 SELECT TYPE (bbottom => timedisc%Boundary%Boundary(bottom)%p)
343 CLASS IS (boundary_farfield)
344 DO k=1,mesh%GKNUM
345 DO j=mesh%JMIN,mesh%JMAX
346 DO i=mesh%IMIN,mesh%IMAX
347 bbottom%data(i,j,k,:) = timedisc%pvar%data4d(i,j,mesh%KMIN-k,:)
348 END DO
349 END DO
350 END DO
351 END SELECT
352
353 SELECT TYPE (btop => timedisc%Boundary%Boundary(top)%p)
354 CLASS IS (boundary_farfield)
355 DO k=1,mesh%GKNUM
356 DO j=mesh%JMIN,mesh%JMAX
357 DO i=mesh%IMIN,mesh%IMAX
358 btop%data(i,j,k,:) = timedisc%pvar%data4d(i,j,mesh%KMAX+k,:)
359 END DO
360 END DO
361 END DO
362 END SELECT
363
364 SELECT TYPE (beast => timedisc%Boundary%Boundary(east)%p)
365 CLASS IS (boundary_farfield)
366 DO k=mesh%KMIN,mesh%KMAX
367 DO j=mesh%JMIN,mesh%JMAX
368 DO i=1,mesh%GINUM
369 beast%data(i,j,k,:) = timedisc%pvar%data4d(mesh%IMAX+i,j,k,:)
370 END DO
371 END DO
372 END DO
373 END SELECT
374
375 ! western
376 SELECT TYPE (bwest => timedisc%Boundary%Boundary(west)%p)
377 CLASS IS(boundary_custom)
378 CALL bwest%SetCustomBoundaries(mesh,physics, &
379 (/custom_nograd,custom_outflow,custom_kepler,custom_nograd,custom_nograd/))
380 END SELECT
381
382 CALL physics%Convert2Conservative(timedisc%pvar,timedisc%cvar)
383 CALL timedisc%Boundary%CenterBoundary(mesh,physics,0.0,timedisc%pvar, &
384 timedisc%cvar)
385
386 ! print some information
387 WRITE (mdisk_str, '(ES10.2)') mdisk/msun
388 WRITE (am_str, '(ES10.2)') am
389 CALL mesh%Info(" DATA-----> initial condition: non Keplerian flow")
390 CALL mesh%Info(" disk mass: " // trim(mdisk_str) // " M_sun")
391 CALL mesh%Info(" angular momentum: " // trim(am_str) // " kg/m^2/s")
392
393 END SUBROUTINE initdata
394
395 ELEMENTAL FUNCTION vkepler(sc,zc) RESULT(res)
396 IMPLICIT NONE
397 REAL,INTENT(IN) :: sc,zc
398 REAL :: res
399 res = sqrt(gn*m_bh/sc) * (1.0d0+(zc/sc)**2)**(-0.75)
400 END FUNCTION vkepler
401
402 ELEMENTAL FUNCTION gs(sc,zc) RESULT(res)
403 IMPLICIT NONE
404 REAL,INTENT(IN) :: sc,zc
405 REAL :: res
406 res = -(gn*m_bh/sc**2) / sqrt(1.0d0+(zc/sc)**2)**3
407 END FUNCTION gs
408
409 ELEMENTAL FUNCTION gz(sc,zc) RESULT(res)
410 IMPLICIT NONE
411 REAL,INTENT(IN) :: sc,zc
412 REAL :: res
413 res = -(gn*m_bh/sc**2) * (zc/sc) / sqrt(1.0d0+(zc/sc)**2)**3
414 END FUNCTION gz
415
416 ELEMENTAL FUNCTION func_lambda(zc) RESULT(res)
417 IMPLICIT NONE
418 REAL,INTENT(IN) :: zc
419 REAL :: res
420 res = 1.0d0 + a0/(1.0d0+(zc/z0)**2)
421 END FUNCTION func_lambda
422
423 ELEMENTAL FUNCTION func_tau(sc,zc) RESULT(res)
424 IMPLICIT NONE
425 REAL,INTENT(IN) :: sc,zc
426 REAL :: res
427 res = sc*sqrt(1.0d0 + (zc/sc)**2*(1.0d0 + (1.0d0+0.5d0*(zc/z0)**2)/a0))
428 END FUNCTION func_tau
429
430 ELEMENTAL FUNCTION pc(tau,rho_s0,cs_inf) RESULT(res)
431 IMPLICIT NONE
432 REAL,INTENT(IN) :: tau,rho_s0,cs_inf
433 REAL :: res
434! res = P0 * EXP(-tau/S0)
435 res = p_inf * (1.0 + a0/(1.0+a0) * 1.0/(1.0-b0) * 0.5 * gamma * &
436 (cc/cs_inf)**2 * rho_s0/rho_inf * (rs/s0) * (tau/s0)**(b0-1.0))
437 END FUNCTION pc
438
439!!$ ELEMENTAL FUNCTION dPc(tau) RESULT(res)
440!!$ IMPLICIT NONE
441!!$ REAL,INTENT(IN) :: tau
442!!$ REAL :: res
443!!$ res = -1.0D0/S0 * Pc(tau)
444!!$ END FUNCTION dPc
445
446! ELEMENTAL FUNCTION rho(sc,zc,tau,lambda) RESULT(res)
447! IMPLICIT NONE
448! REAL,INTENT(IN) :: sc,zc,tau,lambda
449! REAL :: res
450! res = A0/(1.0+A0) * lambda/(lambda-1.0) * sqrt(1.0+(zc/sc)**2)**3 &
451! * (tau/S0)**B0 * (s/tau)**3
452! END FUNCTION rho
453
454
455END PROGRAM ttauri
elemental real function func_tau(sc, zc)
Definition: agndisk.f90:508
elemental real function pc(tau, rho_s0, cs_inf, gamma)
Definition: agndisk.f90:515
elemental real function gz(sc, zc)
Definition: agndisk.f90:494
elemental real function func_lambda(zc)
Definition: agndisk.f90:501
elemental real function vkepler(sc, zc)
Definition: agndisk.f90:480
elemental real function gs(sc, zc)
Definition: agndisk.f90:487
subroutine initdata(Mesh, Physics, Fluxes, Timedisc)
Definition: bondi2d.f90:274
subroutine makeconfig(Sim, config)
Definition: bondi2d.f90:165
generic source terms module providing functionaly common to all source terms
generic gravity terms module providing functionaly common to all gravity terms
main fosite class
Definition: fosite.f90:71
program ttauri
Program and data initialization for 3D rotating flow.
Definition: ttauridisk.f90:29