pringle3d.f90
Jim Pringles famous viscous spreading ring solution in 3D.
Jim Pringles famous viscous spreading ring solution in 3D
This variant simulates the ring with vertical extent with and without rotational symmetry. The equations are solved in non-dimensional units, using the Keplerian velocity at the location of the initial ring at R=1 as the velocity scale.
- Remarks
- (1) This test is very sensitive to mesh settings. If there are not enough mesh points at small radii instabilities grow starting at the inner boundary.
- (2) There is an unsolved stability issue with the viscous source term. The stability condition doesn't seem to be sufficient. Thus in case of high Reynolds numbers one has to adjust the viscous CFL number cvis to enforce smaller time steps and preserve stability.
References:
- [32] Lynden-Bell, D. & Pringle, J. E. Evolution of Viscous Disks and Origin of Nebular Variables, M.N.R.A.S vol. 168(3) (1974) pp. 603-637 http://adsabs.harvard.edu/abs/1974MNRAS.168..603L
- [42] Pringle, J. E. Accretion discs in astrophysics Annual review of astronomy and astrophysics. vol. 19 (1981) pp. 137-162 DOI: 10.1146/annurev.aa.19.090181.001033
- [50] Speith, R. and Kley, W. Stability of the viscously spreading ring Astron. Astrophys. vol. 399 (2003), pp. 395-407 DOI: 10.1051/0004-6361:20021783
1!#############################################################################
2!# #
3!# fosite - 3D hydrodynamical simulation program #
4!# module: pringle3d.f90 #
5!# #
6!# Copyright (C) 2008-2019 #
7!# Bjoern Sperling <sperling@astrophysik.uni-kiel.de> #
8!# Tobias Illenseer <tillense@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
27!----------------------------------------------------------------------------!
60!----------------------------------------------------------------------------!
64 IMPLICIT NONE
65 !--------------------------------------------------------------------------!
66 ! simulation parameters
67 REAL, PARAMETER :: TSIM = 5.0e-3 ! simulation time [TVIS] see below
68 ! should be < 1 ~ viscous time scale
69 ! these are the basic parameters; for stable solutions one requires
70 ! MA >> 1 and RE > MA
71 REAL, PARAMETER :: RE = 1.0e+4 ! Reynolds number (at R=1)
72 REAL, PARAMETER :: MA = 1.0e+2 ! Mach number (at R=1)
73 REAL, PARAMETER :: MDISK = 1.0e-2 ! disk mass << 1 = central mass
74 ! lower limit for nitial density
75 REAL, PARAMETER :: RHOMIN = 1.0e-8 ! minimal initial density
76 ! viscosity prescription
77 INTEGER, PARAMETER :: VISTYPE = beta
78! INTEGER, PARAMETER :: VISTYPE = POWERLAW
79 REAL, PARAMETER :: PL_EXP = 0.0 ! exponent for power law viscosity
80 REAL, PARAMETER :: TVIS = 4./3.*re ! viscous time scale
81 REAL, PARAMETER :: TINIT = 1.0e-3 ! time for initial condition [TVIS]
82 ! mesh settings
83! INTEGER, PARAMETER :: MGEO = CYLINDRICAL
84! INTEGER, PARAMETER :: MGEO = LOGCYLINDRICAL
85 INTEGER, PARAMETER :: MGEO = spherical !!! ATTENTION: not applicable in 1D
86 INTEGER, PARAMETER :: XRES = 200 ! x-resolution
87 INTEGER, PARAMETER :: YRES = 16 ! y-resolution
88 INTEGER, PARAMETER :: ZRES = 6 ! z-resolution
89 REAL, PARAMETER :: RMIN = 0.1 ! min radius of comp. domain
90 REAL, PARAMETER :: RMAX = 2.0 ! max radius of comp. domain
91 REAL, PARAMETER :: GPAR = 1.0 ! geometry scaling parameter
92 ! output parameters
93 INTEGER, PARAMETER :: ONUM = 100 ! number of output data sets
94 CHARACTER(LEN=256), PARAMETER & ! output data dir
95 :: ODIR = './'
96 CHARACTER(LEN=256), PARAMETER & ! output data file name
97 :: OFNAME = 'pringle3d'
98 ! derived parameters
99 REAL, PARAMETER :: CSISO = 1./ma ! isothermal speed of sound
100 !--------------------------------------------------------------------------!
101 CLASS(fosite), ALLOCATABLE :: Sim
102 !--------------------------------------------------------------------------!
103
104 ALLOCATE(sim)
105 CALL sim%InitFosite()
107 CALL sim%Setup()
109 CALL sim%Run()
110 CALL sim%Finalize()
111 DEALLOCATE(sim)
112
113CONTAINS
114
117 IMPLICIT NONE
118 !------------------------------------------------------------------------!
119 CLASS(fosite) :: Sim
120 TYPE(Dict_TYP),POINTER :: config
121 !------------------------------------------------------------------------!
122 ! Local variable declaration
123 INTEGER :: bc(6)
124 TYPE(Dict_TYP), POINTER :: mesh, physics, boundary, datafile, &
125 grav, vis, timedisc, fluxes, sources
126 REAL :: x1,x2,y1,y2,z1,z2,cvis
127 !------------------------------------------------------------------------!
128 INTENT(INOUT) :: sim
129 !------------------------------------------------------------------------!
130 ! mesh settings and boundary conditions
131 SELECT CASE(mgeo)
132 CASE(cylindrical)
133 x1 = rmin
134 x2 = rmax
135 y1 = -pi
136 y2 = pi
137! z1 = 0.0
138! z2 = 0.0
139 z1 = -0.1
140 z2 = 0.1
141! bc(WEST) = AXIS
142 bc(west) = no_gradients
143 bc(east) = no_gradients
144! bc(WEST) = ABSORBING
145! bc(EAST) = ABSORBING
146! bc(WEST) = CUSTOM
147! bc(EAST) = CUSTOM
148 bc(south) = periodic
149 bc(north) = periodic
150! bc(BOTTOM) = ABSORBING
151! bc(TOP) = ABSORBING
152 bc(bottom) = reflecting
153 bc(top) = reflecting
154 !!! ATTENTION: empirical formula found for standard parameters
155 !!! seems to work for RMIN=0.05 and XRES <= 1000
156 cvis = (xres/1207.0)**1.9
157 CASE(logcylindrical)
158 x1 = log(rmin/gpar)
159 x2 = log(rmax/gpar)
160 y1 = -pi
161 y2 = pi
162 z1 = 0.0
163 z2 = 0.0
164 bc(west) = no_gradients
165 bc(east) = no_gradients
166 bc(south) = periodic
167 bc(north) = periodic
168 bc(bottom) = no_gradients
169 bc(top) = no_gradients
170 cvis = 0.1
171 CASE(spherical)
172 x1 = rmin
173 x2 = rmax
176 z1 = -pi
177 z2 = pi
178! bc(WEST) = ABSORBING
179 bc(east) = absorbing
180! bc(WEST) = NO_GRADIENTS
181! bc(EAST) = NO_GRADIENTS
182 bc(west) = custom
183! bc(EAST) = CUSTOM
184! bc(SOUTH) = NO_GRADIENTS
185! bc(NORTH) = NO_GRADIENTS
186 bc(south) = absorbing
187 bc(north) = absorbing
188 bc(bottom) = periodic
189 bc(top) = periodic
190 !!! ATTENTION: empirical formula found for standard parameters
191 !!! seems to work for RMIN=0.05 and XRES <= 1000
192 cvis = (xres/1207.0)**1.9
193 CASE DEFAULT
194 CALL sim%Error("pringle::MakeConfig","mesh geometry not supported for Pringle disk")
195 END SELECT
196
197 ! mesh settings
198 mesh => dict( &
199 "meshtype" / midpoint, &
200 "geometry" / mgeo, &
201 "inum" / xres, &
202 "jnum" / yres, &
203 "knum" / zres, &
204 "xmin" / x1, &
205 "xmax" / x2, &
206 "ymin" / y1, &
207 "ymax" / y2, &
208 "zmin" / z1, &
209 "zmax" / z2, &
210! "use_fargo" / 1, &
211! "fargo" / 2, &
212 "gparam" / gpar)
213
214 ! boundary conditions
215 boundary => dict( &
216 "western" / bc(west), &
217 "eastern" / bc(east), &
218 "southern" / bc(south), &
219 "northern" / bc(north), &
220 "bottomer" / bc(bottom), &
221 "topper" / bc(top))
222
223
224 ! physics settings
225 physics => dict( &
226 "problem" / euler_isotherm, &
227 "units" / geometrical, &
228 "cs" / csiso)
229
230 ! flux calculation and reconstruction method
231 fluxes => dict( &
232 "order" / linear, &
233 "fluxtype" / kt, &
234 "variables" / primitive, &
235 "limiter" / vanleer, &
236 "theta" / 1.2)
237
238 ! source term due to viscosity
239 vis => dict( &
240 "stype" / viscosity, &
241 "vismodel" / vistype, &
242 "dynconst" / (1./re), &
243 "exponent" / pl_exp, &
244 "cvis" / cvis)
245
246 ! source term due to a point mass
247 grav => dict( &
248 "stype" / gravity, &
249 "pmass/gtype"/ pointmass, & ! grav. accel. of a point mass
250 "pmass/mass" / 1.0, & ! non-dim. mass of the accreting object
251 "pmass/outbound" / 0) ! disable accretion
252
253 ! combine all source terms
254 sources => dict( &
255 "viscosity" / vis, &
256 "grav" / grav)
257
258 ! time discretization settings
259 timedisc => dict( &
260 "method" / ssprk, &
261 "stoptime" / (tsim * tvis), &
262 "cfl" / 0.4, &
263 "dtlimit" / (1e-10 * tvis), &
264! "rhstype" / 1, &
265 "maxiter" / 100000000, &
266 "tol_rel" / 0.01, &
267 "tol_abs" / (/1e-40,1e-5,1e-8,1e-5/))
268
269! ! enable output of analytical solution
270! #ifdef HAVE_FGSL
271! IF (MGEO.EQ.CYLINDRICAL) &
272! CALL SetAttr(timedisc,"output/solution",1)
273! #endif
274
275 ! initialize data input/output
276 datafile => dict( &
277 "fileformat"/ vtk, &
278 "filename" / (trim(odir) // trim(ofname)), &
279 "count" / onum)
280
281 config => dict( &
282 "mesh" / mesh, &
283 "physics" / physics, &
284 "boundary" / boundary, &
285 "fluxes" / fluxes, &
286 "sources" / sources, &
287 "timedisc" / timedisc, &
288 "datafile" / datafile)
290
295 IMPLICIT NONE
296 !------------------------------------------------------------------------!
297 CLASS(fosite), INTENT(INOUT) :: Sim
298 CLASS(physics_base), INTENT(IN) :: Physics
299 CLASS(mesh_base), INTENT(IN) :: Mesh
300 CLASS(timedisc_base), INTENT(INOUT) :: Timedisc
301 !------------------------------------------------------------------------!
302 ! Local variable declaration
303 CLASS(sources_base), POINTER :: sp
304 CLASS(sources_gravity), POINTER :: gp => null()
305 CLASS(geometry_base), ALLOCATABLE :: geo_cyl
306 TYPE(Dict_TYP), POINTER :: geo_config
307 INTEGER :: i,j,k
308#ifdef PARALLEL
309 INTEGER :: ierror
310#endif
311 REAL, DIMENSION(Mesh%IGMIN:Mesh%IGMAX,Mesh%JGMIN:Mesh%JGMAX,Mesh%KGMIN:Mesh%KGMAX,3) &
312 :: bccyl
313 REAL :: r,z,vr,vphi,sden,mu,height,mass
314 CHARACTER(LEN=64) :: value
315 !------------------------------------------------------------------------!
319
320 ! compute cylindrical coordinates for each cell bary center
321 CALL geo_cyl%Convert2Curvilinear(mesh%bccart,bccyl)
322
323 ! custom boundary conditions if requested
324 SELECT TYPE(bwest => timedisc%Boundary%boundary(west)%p)
325 CLASS IS (boundary_custom)
326 CALL bwest%SetCustomBoundaries(mesh,physics, &
327 (/custom_nograd,custom_outflow,custom_kepler,custom_nograd/))
328 END SELECT
329 SELECT TYPE(beast => timedisc%Boundary%boundary(east)%p)
330 CLASS IS (boundary_custom)
331 CALL beast%SetCustomBoundaries(mesh,physics, &
332 (/custom_nograd,custom_outflow,custom_kepler,custom_nograd/))
333 END SELECT
334
335 ! get gravitational acceleration
336 sp => sim%Sources%GetSourcesPointer(gravity)
337 IF (.NOT.ASSOCIATED(sp)) CALL physics%Error("pringle::InitData","no gravity term initialized")
338
339 SELECT CASE(vistype)
340 CASE(beta)
341 mu=1.0
342 CASE(powerlaw)
343 mu=pl_exp
344 CASE DEFAULT
345 CALL timedisc%Error("pringle::InitData","only pringle and beta viscosity possible")
346 END SELECT
347
348 ! initial condition
349 SELECT TYPE(pvar => timedisc%pvar)
350 TYPE IS(statevector_eulerisotherm)
351 DO k=mesh%KGMIN,mesh%KGMAX
352 DO j=mesh%JGMIN,mesh%JGMAX
353 DO i=mesh%IMIN,mesh%IGMAX
354 ! distance to axis (r-coordinate in cylindrical coordinates)
355 r = bccyl(i,j,k,1)
356 ! z-coordinate
357 z = bccyl(i,j,k,3)
358 ! Keplerian velocity
359 vphi = r/(r**2+z**2)**0.75
360 ! compute pressure scale height
361 height = csiso * sqrt(r**3) ! h = cs / Omega = cs / SQRT(GM/r**3), with GM=1
362#ifdef HAVE_FGSL
363 ! use exact solution at time TINIT
365#else
366 ! use approximation for TINIT << 1
367 ! no need for modified Bessel functions
369#endif
370 pvar%density%data3d(i,j,k) = rhomin + sden / (sqrt(2*pi) * height) &
371 * exp(-0.5*(z/height)**2)
372! pvar%velocity%data4d(i,j,k,1) = vr
373! pvar%velocity%data4d(i,j,k,2) = vphi
374! pvar%velocity%data4d(i,j,k,3) = 0.0
375 END DO
376 END DO
377 END DO
378 ! determine disk mass
379 mass = sum(mesh%volume%data1d(:)*pvar%density%data1d(:),mask=mesh%without_ghost_zones%mask1d)
380#ifdef PARALLEL
381 CALL mpi_allreduce(mpi_in_place,mass,1,default_mpi_real,mpi_sum, &
382 mesh%comm_cart,ierror)
383#endif
384 ! rescale disk mass
385 pvar%density%data1d(:) = pvar%density%data1d(:) * mdisk / mass
386 pvar%velocity%data1d(:) = 0.0 ! initialize all velocities with zero
387 CALL gp%UpdateGravity(mesh,sim%Physics,sim%Fluxes,pvar,0.0,0.0)
388 pvar%velocity%data4d(:,:,:,1:physics%VDIM) = &
389 timedisc%GetCentrifugalVelocity(mesh,sim%Physics,sim%Fluxes,sim%Sources,(/0.,0.,1./), &
390 gp%accel%data4d)
391 CLASS DEFAULT
392 CALL timedisc%Error("pringle::InitData","only isothermal physics possible")
393 END SELECT
394
395 IF (ASSOCIATED(timedisc%solution)) THEN
396 ! store initial condition in exact solution array
397 timedisc%solution = timedisc%pvar
398 END IF
399
400 ! transform to conservative variables
401 CALL physics%Convert2Conservative(timedisc%pvar,timedisc%cvar)
402
403 CALL mesh%Info(" DATA-----> initial condition: " // "pringle disk")
404 WRITE(value,"(ES11.3)") tvis
405 CALL mesh%Info(" " // "viscous timescale: " //trim(value))
406 WRITE(value,"(ES11.3)") re
407 CALL mesh%Info(" " // "Reynolds number: " //trim(value))
408 WRITE(value,"(ES11.3)") ma
409 CALL mesh%Info(" " // "Mach number: " //trim(value))
410 WRITE(value,"(ES11.3)") mdisk
411 CALL mesh%Info(" " // "Disk mass: " //trim(value))
412
413 CALL geo_cyl%Finalize()
414 DEALLOCATE(geo_cyl)
416
417
419 IMPLICIT NONE
420 !--------------------------------------------------------------------!
421 REAL, INTENT(IN) :: mu,tau,r
422 REAL, INTENT(OUT) :: Sigma,vr
423 !--------------------------------------------------------------------!
424 REAL :: lambda,x,r4l,invr4l
425 !--------------------------------------------------------------------!
426 lambda = 1./(4.0-mu)
427 r4l = r**(0.25/lambda)
428 x = 2*lambda**2 / tau * r**(0.25/lambda)
429 invr4l = 1./r4l
430 sigma = mdisk/sqrt((4*pi)**3 * tau) * r4l**(1.5-9*lambda) &
431 * exp(-lambda**2/tau*(1.0-r4l)**2)
432 vr = -1.5/re * ((x*tau)/(2*lambda*lambda))**(4*lambda-2.) &
433 * (1.0 - 0.5*x/lambda * (x*tau/(2*lambda*lambda) - 1.0))
435
436#ifdef HAVE_FGSL
438 IMPLICIT NONE
439 !--------------------------------------------------------------------!
440 REAL, INTENT(IN) :: mu,tau,r
441 REAL, INTENT(OUT) :: Sigma,vr
442 !--------------------------------------------------------------------!
443 REAL :: lambda,r4l,x
444 !--------------------------------------------------------------------!
445 lambda = 1./(4.0-mu)
446 r4l = r**(0.25/lambda)
447 x = 2*lambda**2 / tau * r4l
448 sigma = mdisk/(4*pi) * (lambda/tau) * r4l**2 * r**(-2.25) &
449 * exp(-lambda**2/tau*(1.0+r4l**2)) &
450 * modified_bessel_inu(lambda,x)
451 vr = -1.5/re * ((x*tau)/(2*lambda*lambda))**(4*lambda-2.) &
452 * (1.0 - 0.5*x/lambda * (x*tau/(2*lambda*lambda) &
455
457 USE fgsl
458 IMPLICIT NONE
459 !--------------------------------------------------------------------!
460 REAL, INTENT(IN) :: nu,x
461 REAL :: Inu
462 !--------------------------------------------------------------------!
463 INTEGER :: n
464 !--------------------------------------------------------------------!
465 IF (aint(nu).EQ.nu) THEN
466 ! nu is an integer -> use modified bessel functions of integer order
467 n = int(nu)
468 inu = fgsl_sf_bessel_icn(n,x)
469 ELSE
470 ! nu is not an integer -> use representation of modified bessel functions
471 ! through hypergeometric functions 0F1
472 inu = (0.5*x)**nu / fgsl_sf_gamma(1.0+nu) * fgsl_sf_hyperg_0f1(1.0+nu,(0.5*x)**2)
473 END IF
475#endif
476
recursive subroutine, public deletedict(root)
Delete the dictionary 'root' and all subnodes.
Definition: common_dict.f90:1142
type(dict_typ) function, pointer, public dict(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20)
Construct a new dictionary from several key/value pairs. Together with the Assign subroutine and over...
Definition: common_dict.f90:561
Definition: fosite.f90:41
elemental real function, public asinh(x)
inverse hyperbolic sine function
Definition: functions.f90:100
subroutine new_geometry(Geometry, config)
Definition: geometry_generic.f90:53
generic source terms module providing functionaly common to all source terms
Definition: sources_base.f90:42
generic gravity terms module providing functionaly common to all gravity terms
Definition: sources_gravity.f90:41
subroutine viscousring_analytic(mu, tau, r, Sigma, vr)
Definition: pringle.f90:554