mestel.f90
Go to the documentation of this file.
1!#############################################################################
2!# #
3!# fosite - 3D hydrodynamical simulation program #
4!# module: mestel.f90 #
5!# #
6!# Copyright (C) 2012-2024 #
7!# Manuel Jung <mjung@astrophysik.uni-kiel.de> #
8!# Björn Sperling <sperling@astrophysik.uni-kiel.de> #
9!# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
10!# #
11!# This program is free software; you can redistribute it and/or modify #
12!# it under the terms of the GNU General Public License as published by #
13!# the Free Software Foundation; either version 2 of the License, or (at #
14!# your option) any later version. #
15!# #
16!# This program is distributed in the hope that it will be useful, but #
17!# WITHOUT ANY WARRANTY; without even the implied warranty of #
18!# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
19!# NON INFRINGEMENT. See the GNU General Public License for more #
20!# details. #
21!# #
22!# You should have received a copy of the GNU General Public License #
23!# along with this program; if not, write to the Free Software #
24!# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
25!# #
26!#############################################################################
27
28!----------------------------------------------------------------------------!
71!----------------------------------------------------------------------------!
72PROGRAM mestel
73 USE fosite_mod
74#ifdef NECSXAURORA
75 USE asl_unified
76#endif
77 IMPLICIT NONE
78 !--------------------------------------------------------------------------!
79 ! general constants
80 REAL, PARAMETER :: gn = 6.67384e-11 ! Newtons grav. constant [m^3/kg/s^2]
81 REAL, PARAMETER :: year = 3.15576e+7 ! year [s]
82 REAL, PARAMETER :: parsec = 3.0857e+16 ! parsec [m]
83 REAL, PARAMETER :: au = 1.49598e+11 ! astronomical unit [m]
84 REAL, PARAMETER :: msun = 1.989e+30 ! solar mass [kg]
85 REAL, PARAMETER :: rg = 8.31 ! gas constant
86 ! simulation parameters
87 REAL, PARAMETER :: simtime = 1.0e+4*year ! simulation time [s]
88 REAL, PARAMETER :: mbh = 1.0e+7*msun ! initial black hole mass [kg]
89 REAL, PARAMETER :: mratio = 0.1 ! initial mdisk/mbh mass ratio
90 REAL, PARAMETER :: mdisk = mratio*mbh ! initial disk mass [kg]
91 REAL, PARAMETER :: temp = 100.0 ! initial temperature [K]
92 REAL, PARAMETER :: noise = 0.3 ! initial noise level
93 ! physics settings
94 INTEGER, PARAMETER :: phys = euler ! transport model
95 REAL, PARAMETER :: mu = 6.02e-4 ! mean molecular weight [kg/mol]
96 REAL, PARAMETER :: gamma = 1.4 ! ratio of specific heats
97 REAL, PARAMETER :: beta_vis = 1.0e-3 ! beta viscosity parameter
98 ! mesh settings
99 REAL, PARAMETER :: rmin = 5.0e-2 * parsec ! inner radius [m]
100 REAL, PARAMETER :: rmax = 1.e+0 * parsec ! outer radius [m]
101 REAL, PARAMETER :: rgeo = 1.0 * parsec ! geometry scaling constant
102 INTEGER, PARAMETER :: mgeo = logcylindrical ! mesh geometry
103 INTEGER, PARAMETER :: xres = 64 ! mesh resolution (radial)
104 INTEGER, PARAMETER :: yres = 128 ! mesh resolution (azimuthal)
105 INTEGER, PARAMETER :: zres = 1 ! mesh resolution (z)
106 ! output settings
107 INTEGER, PARAMETER :: onum = 100 ! number of output time steps
108 CHARACTER(LEN=256), PARAMETER :: &
109 ofname = 'markward', & ! data file name
110 odir = "./" ! output directory
111 !--------------------------------------------------------------------------!
112 CLASS(fosite), ALLOCATABLE :: sim
113 !--------------------------------------------------------------------------!
114
115ALLOCATE(sim)
116
117#ifdef NECSXAURORA
118CALL asl_library_initialize()
119#endif
120
121CALL sim%InitFosite()
122CALL makeconfig(sim%config)
123CALL sim%Setup()
124CALL initdata(sim%Timedisc,sim%Mesh,sim%Physics,sim%Fluxes,sim%Sources)
125CALL sim%Run()
126CALL sim%Finalize()
127
128#ifdef NECSXAURORA
129CALL asl_library_finalize()
130#endif
131
132DEALLOCATE(sim)
133
134CONTAINS
135 SUBROUTINE makeconfig(config)
136 IMPLICIT NONE
137 !------------------------------------------------------------------------!
138 TYPE(dict_typ),POINTER :: config
139 !------------------------------------------------------------------------!
140 ! Local variable declaration
141 TYPE(dict_typ),POINTER :: mesh,boundary,timedisc,datafile,&
142 sources,fluxes,grav,physics,&
143 vis,cooling
144 !------------------------------------------------------------------------!
145 physics => dict( &
146 "problem" / phys, &
147 "output/bccsound" / 1, &
148 "mu" / mu, &
149 "gamma" / gamma, &
150 "units" / si)
151
152 fluxes => dict( &
153 "fluxtype" / kt, &
154 "order" / linear, &
155 "variables" / primitive, &
156 "limiter" / vanleer, &
157 "theta" / 1.2)
158
159 mesh => dict( &
160 "meshtype" / midpoint, &
161 "geometry" / mgeo, &
162 "inum" / xres, &
163 "jnum" / yres, &
164 "knum" / zres, &
165 "xmin" / log(rmin/parsec), &
166 "xmax" / log(rmax/parsec), &
167 "ymin" / (-pi), &
168 "ymax" / ( pi), &
169 "zmin" / 0.0, &
170 "zmax" / 0.0, &
171 "gparam" / rgeo, &
172 "use_fargo" / 1, &
173 "fargo" / 1, &
174 "decomposition" / (/-1,1,1/), &
175 "output/volume" / 1 )
176
177 boundary => dict( &
178 "western" / custom, &
179 "eastern" / custom, &
180 "southern" / periodic, &
181 "northern" / periodic, &
182 "bottomer" / reflecting, &
183 "topper" / reflecting)
184
185 grav => dict( &
186 "stype" / gravity, &
187 "cvis" / 0.9, &
188 "energy" / 0, &
189 "output/height" / 1, &
190 "self/gtype" / spectral, &
191 "self/green" / 1, &
192 "pmass/gtype" / pointmass, &
193 "pmass/potential" / newton, &
194 "pmass/mass" / mbh, &
195 "pmass/outbound" / 1)
196
197 ! cooling model
198 cooling => dict( &
199 "stype" / disk_cooling, &
200! "method" / GRAY, &
201 "method" / gammie, &
202 "b_cool" / 10.0, &
203 "Tmin" / 3.0, &
204 "rhomin" / 1.0e-30, &
205 "cvis" / 0.1)
206
207 ! viscosity model
208 vis => dict( &
209 "stype" / viscosity, &
210 "vismodel" / beta, &
211 "dynconst" / beta_vis, &
212 "output/stress" / 1, &
213 "output/dynvis" / 1, &
214 "output/kinvis" / 1, &
215 "cvis" / 0.5)
216
217 ! collect source terms
218 sources => dict( &
219 "diskcooling" / cooling, &
220! "viscosity" / vis, &
221 "grav" / grav)
222
223 ! time discretization settings
224 timedisc => dict( &
225 "method" / ssprk, &
226 "tol_rel" / 1.0e-3, &
227 "cfl" / 0.3, &
228 "stoptime" / simtime, &
229 "dtlimit" / 1.0e-4, &
230 "tmin" / 3.0, &
231 "rhstype" / 1, &
232 "maxiter" / 2000000000)
233
234 ! add absolute error bounds and output fields depending on physics
235 SELECT CASE(phys)
236 CASE(euler)
237 CALL setattr(timedisc, "tol_abs", (/1.0e-3, 1.0e-1, 1.0e-01, 1.0e+10/))
238 CALL setattr(timedisc, "output/xmomentum", 0)
239 CALL setattr(timedisc, "output/ymomentum", 0)
240 CALL setattr(timedisc, "output/energy", 0)
241 CALL setattr(timedisc, "output/rhs", 0)
242 CALL setattr(timedisc, "output/external_sources", 0)
243 CASE DEFAULT
244 CALL sim%Error("MakeConfig","Physics model not supported.")
245 END SELECT
246
247 ! data file settings
248 datafile => dict( &
249 "fileformat" / vtk, &
250 "filename" / "mestel", &
251 "count" / onum)
252
253 ! create configuration
254 config => dict( &
255 "physics" / physics, &
256 "fluxes" / fluxes, &
257 "mesh" / mesh, &
258 "boundary" / boundary, &
259 "sources" / sources, &
260 "timedisc" / timedisc, &
261 "datafile" / datafile)
262
263 END SUBROUTINE makeconfig
264
265
266 SUBROUTINE initdata(Timedisc,Mesh,Physics,Fluxes,Sources)
270 IMPLICIT NONE
271 !------------------------------------------------------------------------!
272 CLASS(timedisc_base), INTENT(INOUT) :: Timedisc
273 CLASS(mesh_base), INTENT(IN) :: Mesh
274 CLASS(physics_base), INTENT(INOUT) :: Physics
275 CLASS(fluxes_base), INTENT(INOUT) :: Fluxes
276 CLASS(sources_list), ALLOCATABLE, INTENT(INOUT) :: Sources
277 !------------------------------------------------------------------------!
278 ! Local variable declaration
279 CLASS(sources_base), POINTER :: sp => null()
280 CLASS(sources_gravity), POINTER :: gp => null()
281 CLASS(marray_base), ALLOCATABLE :: rands,Sigma
282#ifdef PARALLEL
283 INTEGER :: ierror
284#endif
285 REAL :: mass
286 CHARACTER(LEN=20) :: mdisk_str
287#ifdef NECSXAURORA
288 INTEGER :: rng, n
289#endif
290 !------------------------------------------------------------------------!
291 ! get gravitational acceleration
292 IF (ALLOCATED(sources)) &
293 sp => sources%GetSourcesPointer(gravity)
294 IF (.NOT.ASSOCIATED(sp)) &
295 CALL physics%Error("mestel::InitData","no gravity term initialized")
296
297 ! get random numbers for density noise
298 ALLOCATE(rands,sigma)
299 rands = marray_base()
300#ifndef NECSXAURORA
301 CALL initrandseed(physics)
302 CALL random_number(rands%data1d)
303#else
304 CALL asl_random_create(rng, asl_randommethod_mt19937_64)
305 CALL asl_random_distribute_uniform(rng)
306 n = (mesh%IGMAX-mesh%IGMIN+1)*(mesh%JGMAX-mesh%JGMIN+1)*(mesh%KGMAX-mesh%KGMIN+1)
307 CALL asl_random_generate_d(rng, n, rands%data1d)
308 CALL asl_random_destroy(rng)
309#endif
310 rands%data1d(:) = rands%data1d(:) * noise * 2.0 + (1.0 - noise)
311
312 ! set surface density using radial power law (1/r) with a little noise
313 sigma = marray_base()
314 sigma%data1d(:) = rands%data1d(:) * rmin/mesh%radius%data2d(:,2)
315
316 ! determine disk mass
317 mass = sum(mesh%volume%data1d(:)*sigma%data1d(:),mask=mesh%without_ghost_zones%mask1d(:))
318#ifdef PARALLEL
319 CALL mpi_allreduce(mpi_in_place,mass,1,default_mpi_real,mpi_sum, &
320 mesh%comm_cart,ierror)
321#endif
322
323 ! setting for custom boundary conditions (western boundary)
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
330 ! setting for custom boundary conditions (eastern boundary)
331 SELECT TYPE(beast => timedisc%Boundary%boundary(east)%p)
332 CLASS IS (boundary_custom)
333 CALL beast%SetCustomBoundaries(mesh,physics, &
334 (/custom_reflect,custom_reflect,custom_logexpol,custom_reflect/))
335 END SELECT
336
337 SELECT TYPE (pvar => timedisc%pvar)
338 CLASS IS(statevector_euler)
339 ! 1. set surface density by rescaling Sigma
340 pvar%density%data1d(:) = sigma%data1d(:) * mdisk / mass
341 ! 2. initialize gravitational acceleration
342 CALL gp%UpdateGravity(mesh,physics,fluxes,pvar,0.0,0.0)
343 ! 3. set azimuthal velocity: balance initial radial gravitational
344 ! acceleration with centrifugal acceleration
345 pvar%velocity%data4d(:,:,:,1:physics%VDIM) = &
346 timedisc%GetCentrifugalVelocity(mesh,physics,fluxes,sources,(/0.,0.,1./),gp%accel%data4d)
347 ! 4. transform velocities to rotating frame
348 ! ATTENTION: this works only if the second velocity is the azimuthal velocity
349 IF (mesh%OMEGA.GT.0.0) &
350 pvar%velocity%data2d(:,2) = pvar%velocity%data2d(:,2) - mesh%OMEGA*mesh%radius%data2d(:,2)
351 ! 5. set pressure using surface density and initial temperature
352 pvar%pressure%data1d(:) = physics%constants%RG/physics%MU * temp * pvar%density%data1d(:)
353 CLASS DEFAULT
354 CALL physics%Error("mestel::InitData","unsupported state vector")
355 END SELECT
356
357 IF (mesh%fargo%GetType().EQ.2) &
358 timedisc%w(:,:) = sqrt(physics%constants%GN*(mbh/mesh%radius%bcenter(:,mesh%JMIN,:)))
359
360 CALL physics%Convert2Conservative(timedisc%pvar,timedisc%cvar)
361
362 ! print some information
363 WRITE (mdisk_str, '(ES10.2)') mdisk/msun
364 CALL mesh%Info(" DATA-----> initial condition: Mestel's disk")
365 CALL mesh%Info(" disk mass: " // trim(mdisk_str) // " M_sun")
366
367 DEALLOCATE(rands,sigma)
368 END SUBROUTINE initdata
369
370 SUBROUTINE initrandseed(Physics)
371 IMPLICIT NONE
372 !------------------------------------------------------------------------!
373 CLASS(physics_base), INTENT(IN) :: Physics
374 INTEGER :: i, n, clock
375 INTEGER, DIMENSION(:), ALLOCATABLE :: seed
376 !------------------------------------------------------------------------!
377 ! Initialize random number generator with a seed based on the systems time
378 ! source: http://gcc.gnu.org/onlinedocs/gfortran/RANDOM_005fSEED.html
379 CALL random_seed(size = n)
380 ALLOCATE(seed(n))
381 CALL system_clock(count=clock)
382 seed = clock + 37 * (/ (i - 1, i = 1, n) /)
383#ifdef PARALLEL
384 seed = seed + physics%GetRank()
385#endif
386 CALL random_seed(put = seed)
387 DEALLOCATE(seed)
388 END SUBROUTINE initrandseed
389END PROGRAM mestel
subroutine initdata(Mesh, Physics, Fluxes, Timedisc)
Definition: bondi2d.f90:274
subroutine makeconfig(Sim, config)
Definition: bondi2d.f90:165
program mestel
Definition: mestel.f90:72
subroutine initrandseed(Physics)
Definition: mestel.f90:371
physics module for 1D,2D and 3D non-isothermal Euler equations
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