Skip to content
Snippets Groups Projects
Commit 80b0dbf5 authored by Bert Vandenbroucke's avatar Bert Vandenbroucke
Browse files

Merged master into shadowswift_new. Made code compile again.

parents f5804e06 66c5a34a
No related branches found
No related tags found
1 merge request!3211D and 2D moving mesh algorithm
Showing
with 1029 additions and 8 deletions
......@@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Init the project.
AC_INIT([SWIFT],[0.3.0])
AC_INIT([SWIFT],[0.4.0])
AC_CONFIG_SRCDIR([src/space.c])
AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE
......@@ -466,7 +466,7 @@ if test "$enable_warn" != "no"; then
# We will do this by hand instead and only default to the macro for unknown compilers
case "$ax_cv_c_compiler_vendor" in
gnu | clang)
CFLAGS="$CFLAGS -Wall"
CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-parameter"
;;
intel)
CFLAGS="$CFLAGS -w2 -Wunused-variable"
......
......@@ -133,6 +133,7 @@ grp.attrs["Time"] = 0.0
grp.attrs["NumFilesPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = 0
grp.attrs["Dimension"] = 3
#Runtime parameters
grp = file.create_group("/RuntimePars")
......
Setup for a potential of a patch disk, see Creasey, Theuns &
Bower, 2013, MNRAS, Volume 429, Issue 3, p.1922-1948
The density is given by
rho(z) = (Sigma/2b) / cosh^2(z/b)
where Sigma is the surface density, and b the scale height.
The corresponding force is
dphi/dz = 2 pi G Sigma tanh(z/b),
which satifies d^2phi/dz^2 = 4 pi G rho.
# Define the system of units to use internally.
InternalUnitSystem:
UnitMass_in_cgs: 1.9885e33 # Grams
UnitLength_in_cgs: 3.0856776e18 # Centimeters
UnitVelocity_in_cgs: 1e5 # Centimeters per second
UnitCurrent_in_cgs: 1 # Amperes
UnitTemp_in_cgs: 1 # Kelvin
# Parameters governing the time integration
TimeIntegration:
time_begin: 0. # The starting time of the simulation (in internal units).
time_end: 480. # The end time of the simulation (in internal units).
dt_min: 1e-3 # The minimal time-step size of the simulation (in internal units).
dt_max: 1 # The maximal time-step size of the simulation (in internal units).
# Parameters governing the conserved quantities statistics
Statistics:
delta_time: 1.0 # Time between statistics output
# Parameters governing the snapshots
Snapshots:
basename: Disk-Patch # Common part of the name of output files
time_first: 0. # Time of the first output (in internal units)
delta_time: 8. # Time difference between consecutive outputs (in internal units)
# Parameters for the hydrodynamics scheme
SPH:
resolution_eta: 1.2349 # Target smoothing length in units of the mean inter-particle separation (1.2349 == 48Ngbs with the cubic spline kernel).
delta_neighbours: 1. # The tolerance for the targetted number of neighbours.
CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration.
max_ghost_iterations: 30 # Maximal number of iterations allowed to converge towards the smoothing length.
max_smoothing_length: 40. # Maximal smoothing length allowed (in internal units).
# Parameters related to the initial conditions
InitialConditions:
file_name: Disk-Patch.hdf5 # The file to read
# External potential parameters
Disk-PatchPotential:
surface_density: 10.
scale_height: 100.
z_disk: 300.
timestep_mult: 0.03
###############################################################################
# This file is part of SWIFT.
# Copyright (c) 2016 John A. Regan (john.a.regan@durham.ac.uk)
# Tom Theuns (tom.theuns@durham.ac.uk)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import h5py
import sys
import numpy
import math
import random
# Generates N particles in a box of [0:BoxSize,0:BoxSize,-2scale_height:2scale_height]
# see Creasey, Theuns & Bower, 2013, for the equations:
# disk parameters are: surface density sigma
# scale height b
# density: rho(z) = (sigma/2b) sech^2(z/b)
# isothermal velocity dispersion = <v_z^2? = b pi G sigma
# grad potential = 2 pi G sigma tanh(z/b)
# potential = ln(cosh(z/b)) + const
# Dynamical time = sqrt(b / (G sigma))
# to obtain the 1/ch^2(z/b) profile from a uniform profile (a glass, say, or a uniform random variable), note that, when integrating in z
# \int 0^z dz/ch^2(z) = tanh(z)-tanh(0) = \int_0^x dx = x (where the last integral refers to a uniform density distribution), so that z = atanh(x)
# usage: python makeIC.py 1000
# physical constants in cgs
NEWTON_GRAVITY_CGS = 6.672e-8
SOLAR_MASS_IN_CGS = 1.9885e33
PARSEC_IN_CGS = 3.0856776e18
PROTON_MASS_IN_CGS = 1.6726231e24
YEAR_IN_CGS = 3.154e+7
# choice of units
const_unit_length_in_cgs = (PARSEC_IN_CGS)
const_unit_mass_in_cgs = (SOLAR_MASS_IN_CGS)
const_unit_velocity_in_cgs = (1e5)
print "UnitMass_in_cgs: ", const_unit_mass_in_cgs
print "UnitLength_in_cgs: ", const_unit_length_in_cgs
print "UnitVelocity_in_cgs: ", const_unit_velocity_in_cgs
# parameters of potential
surface_density = 10.
scale_height = 100.
# derived units
const_unit_time_in_cgs = (const_unit_length_in_cgs / const_unit_velocity_in_cgs)
const_G = ((NEWTON_GRAVITY_CGS*const_unit_mass_in_cgs*const_unit_time_in_cgs*const_unit_time_in_cgs/(const_unit_length_in_cgs*const_unit_length_in_cgs*const_unit_length_in_cgs)))
print 'G=', const_G
v_disp = numpy.sqrt(scale_height * math.pi * const_G * surface_density)
t_dyn = numpy.sqrt(scale_height / (const_G * surface_density))
print 'dynamical time = ',t_dyn
print ' velocity dispersion = ',v_disp
# Parameters
periodic= 1 # 1 For periodic box
boxSize = 600. #
Radius = 100. # maximum radius of particles [kpc]
G = const_G
N = int(sys.argv[1]) # Number of particles
# these are not used but necessary for I/O
rho = 2. # Density
P = 1. # Pressure
gamma = 5./3. # Gas adiabatic index
fileName = "Disk-Patch.hdf5"
#---------------------------------------------------
numPart = N
mass = 1
internalEnergy = P / ((gamma - 1.)*rho)
#--------------------------------------------------
#File
file = h5py.File(fileName, 'w')
#Units
grp = file.create_group("/Units")
grp.attrs["Unit length in cgs (U_L)"] = const_unit_length_in_cgs
grp.attrs["Unit mass in cgs (U_M)"] = const_unit_mass_in_cgs
grp.attrs["Unit time in cgs (U_t)"] = const_unit_length_in_cgs / const_unit_velocity_in_cgs
grp.attrs["Unit current in cgs (U_I)"] = 1.
grp.attrs["Unit temperature in cgs (U_T)"] = 1.
# Header
grp = file.create_group("/Header")
grp.attrs["BoxSize"] = boxSize
grp.attrs["NumPart_Total"] = [0, numPart, 0, 0, 0, 0]
grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
grp.attrs["NumPart_ThisFile"] = [0, numPart, 0, 0, 0, 0]
grp.attrs["Time"] = 0.0
grp.attrs["NumFilesPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = [0, 0, 0, 0, 0, 0]
grp.attrs["Dimension"] = 3
#Runtime parameters
grp = file.create_group("/RuntimePars")
grp.attrs["PeriodicBoundariesOn"] = periodic
# set seed for random number
numpy.random.seed(1234)
#Particle group
#grp0 = file.create_group("/PartType0")
grp1 = file.create_group("/PartType1")
#generate particle positions
r = numpy.zeros((numPart, 3))
r[:,0] = numpy.random.rand(N) * boxSize
r[:,1] = numpy.random.rand(N) * boxSize
z = scale_height * numpy.arctanh(numpy.random.rand(2*N))
gd = z < boxSize / 2
r[:,2] = z[gd][0:N]
random = numpy.random.rand(N) > 0.5
r[random,2] *= -1
r[:,2] += 0.5 * boxSize
#generate particle velocities
v = numpy.zeros((numPart, 3))
v = numpy.zeros(1)
#v[:,2] =
ds = grp1.create_dataset('Velocities', (numPart, 3), 'f')
ds[()] = v
m = numpy.ones((numPart, ), dtype=numpy.float32) * mass
ds = grp1.create_dataset('Masses', (numPart,), 'f')
ds[()] = m
m = numpy.zeros(1)
ids = 1 + numpy.linspace(0, numPart, numPart, endpoint=False, dtype='L')
ds = grp1.create_dataset('ParticleIDs', (numPart, ), 'L')
ds[()] = ids
ds = grp1.create_dataset('Coordinates', (numPart, 3), 'd')
ds[()] = r
file.close()
#!/bin/bash
# Generate the initial conditions if they are not present.
if [ ! -e Isothermal.hdf5 ]
then
echo "Generating initial conditions for the disk-patch example..."
python makeIC.py 1000
fi
../../swift -g -t 2 disk-patch.yml
;
; test energy / angular momentum conservation of test problem
;
iplot = 1 ; if iplot = 1, make plot of E/Lz conservation, else, simply compare final and initial energy
; set physical constants
@physunits
indir = './'
basefile = 'Disk-Patch_'
; set properties of potential
uL = phys.pc ; unit of length
uM = phys.msun ; unit of mass
uV = 1d5 ; unit of velocity
; properties of patch
surface_density = 10.
scale_height = 100.
; derived units
constG = 10.^(alog10(phys.g)+alog10(uM)-2d0*alog10(uV)-alog10(uL)) ;
pcentre = [0.,0.,300.] * pc / uL
;
infile = indir + basefile + '*'
spawn,'ls -1 '+infile,res
nfiles = n_elements(res)
; choose: calculate change of energy and Lz, comparing first and last
; snapshots for all particles, or do so for a subset
; compare all
ifile = 0
inf = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
id = h5rd(inf,'PartType1/ParticleIDs')
nfollow = n_elements(id)
; follow a subset
nfollow = 500 ; number of particles to follow
;
if (iplot eq 1) then begin
nskip = 1
nsave = nfiles
endif else begin
nskip = nfiles - 2
nsave = 2
endelse
;
lout = fltarr(nfollow, nsave) ; Lz
xout = fltarr(nfollow, nsave) ; x
yout = fltarr(nfollow, nsave) ; y
zout = fltarr(nfollow, nsave) ; z
eout = fltarr(nfollow, nsave) ; energies
ekin = fltarr(nfollow, nsave)
epot = fltarr(nfollow, nsave) ; 2 pi G Sigma b ln(cosh(z/b)) + const
tout = fltarr(nsave)
ifile = 0
isave = 0
for ifile=0,nfiles-1,nskip do begin
inf = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
time = h5ra(inf, 'Header','Time')
p = h5rd(inf,'PartType1/Coordinates')
v = h5rd(inf,'PartType1/Velocities')
id = h5rd(inf,'PartType1/ParticleIDs')
indx = sort(id)
;; ; if you want to sort particles by ID
;; id = id[indx]
;; for ic=0,2 do begin
;; tmp = reform(p[ic,*]) & p[ic,*] = tmp[indx]
;; tmp = reform(v[ic,*]) & v[ic,*] = tmp[indx]
;; endfor
; calculate energy
dd = size(p,/dimen) & npart = dd[1]
ener = fltarr(npart)
dr = fltarr(npart) & dv = dr
for ic=0,2 do dr[*] = dr[*] + (p[ic,*]-pcentre[ic])^2
for ic=0,2 do dv[*] = dv[*] + v[ic,*]^2
xout[*,isave] = p[0,0:nfollow-1]-pcentre[0]
yout[*,isave] = p[1,0:nfollow-1]-pcentre[1]
zout[*,isave] = p[2,0:nfollow-1]-pcentre[2]
Lz = (p[0,*]-pcentre[0]) * v[1,*] - (p[1,*]-pcentre[1]) * v[0,*]
dz = reform(p[2,0:nfollow-1]-pcentre[2])
; print,'time = ',time,p[0,0],v[0,0],id[0]
ek = 0.5 * dv
ep = fltarr(nfollow)
ep = 2 * !pi * constG * surface_density * scale_height * alog(cosh(abs(dz)/scale_height))
ener = ek + ep
tout(isave) = time
lout[*,isave] = lz[0:nfollow-1]
eout(*,isave) = ener[0:nfollow-1]
ekin(*,isave) = ek[0:nfollow-1]
epot(*,isave) = ep[0:nfollow-1]
print,format='('' time= '',f7.1,'' E= '',f9.2,'' Lz= '',e9.2)', time,eout[0],lz[0]
isave = isave + 1
endfor
x0 = reform(xout[0,*])
y0 = reform(xout[1,*])
z0 = reform(xout[2,*])
; calculate relative energy change
de = 0.0 * eout
dl = 0.0 * lout
nsave = isave
for ifile=1, nsave-1 do de[*,ifile] = (eout[*,ifile]-eout[*,0])/eout[*,0]
for ifile=1, nsave-1 do dl[*,ifile] = (lout[*,ifile] - lout[*,0])/lout[*,0]
; calculate statistics of energy changes
print,' relatve energy change: (per cent) ',minmax(de) * 100.
print,' relative Lz change: (per cent) ',minmax(dl) * 100.
; plot enery and Lz conservation for some particles
if(iplot eq 1) then begin
; plot results on energy conservation for some particles
nplot = min(10, nfollow)
win,0
xr = [min(tout), max(tout)]
yr = [-2,2]*1d-2 ; in percent
plot,[0],[0],xr=xr,yr=yr,/xs,/ys,/nodata,xtitle='time',ytitle='dE/E, dL/L (%)'
for i=0,nplot-1 do oplot,tout,de[i,*]
for i=0,nplot-1 do oplot,tout,dl[i,*],color=red
legend,['dE/E','dL/L'],linestyle=[0,0],color=[black,red],box=0,/bottom,/left
screen_to_png,'e-time.png'
; plot vertical oscillation
win,2
xr = [min(tout), max(tout)]
yr = [-3,3]*scale_height
plot,[0],[0],xr=xr,yr=yr,/xs,/ys,/iso,/nodata,xtitle='x',ytitle='y'
color = floor(findgen(nplot)*255/float(nplot))
for i=0,nplot-1 do oplot,tout,zout[i,*],color=color(i)
screen_to_png,'orbit.png'
; make histogram of energy changes at end
win,6
ohist,de,x,y,-0.05,0.05,0.001
plot,x,y,psym=10,xtitle='de (%)'
screen_to_png,'de-hist.png'
endif
end
Generates and evolves a disk-patch, where gas is in hydrostatic
equilibrium with an imposed external gravitational force, using the
equations from Creasey, Theuns & Bower, 2013, MNRAS, Volume 429,
Issue 3, p.1922-1948.
To generate ICs ready for a scientific run:
1) Recover a uniform glass file by running 'getGlass.sh'.
2) Generate pre-ICs by running the 'makeIC.py' script.
3) Run SWIFT with an isothermal EoS, no cooling nor feedback, and the
disk-patch potential switched on and using the parameters from
'disk-patch-icc.yml'
4) The ICs are then ready to be run for a science problem. Rename the last
output to 'Disk-Patch-dynamic.hdf5'. These are now the ICs for the actual test.
When running SWIFT with the parameters from 'disk-patch.yml' and an
ideal gas EoS on these ICs the disk should stay in equilibrium.
# Define the system of units to use internally.
InternalUnitSystem:
UnitMass_in_cgs: 1.9885e33 # Grams
UnitLength_in_cgs: 3.0856776e18 # Centimeters
UnitVelocity_in_cgs: 1e5 # Centimeters per second
UnitCurrent_in_cgs: 1 # Amperes
UnitTemp_in_cgs: 1 # Kelvin
# Parameters governing the time integration
TimeIntegration:
time_begin: 0 # The starting time of the simulation (in internal units).
time_end: 968. # The end time of the simulation (in internal units).
dt_min: 1e-4 # The minimal time-step size of the simulation (in internal units).
dt_max: 1. # The maximal time-step size of the simulation (in internal units).
# Parameters governing the conserved quantities statistics
Statistics:
delta_time: 1 # Time between statistics output
# Parameters governing the snapshots
Snapshots:
basename: Disk-Patch # Common part of the name of output files
time_first: 0. # Time of the first output (in internal units)
delta_time: 12. # Time difference between consecutive outputs (in internal units)
# Parameters for the hydrodynamics scheme
SPH:
resolution_eta: 1.2349 # Target smoothing length in units of the mean inter-particle separation (1.2349 == 48Ngbs with the cubic spline kernel).
delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours.
CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration.
max_ghost_iterations: 30 # Maximal number of iterations allowed to converge towards the smoothing length.
max_smoothing_length: 70. # Maximal smoothing length allowed (in internal units).
# Parameters related to the initial conditions
InitialConditions:
file_name: Disk-Patch.hdf5 # The file to read
# External potential parameters
Disk-PatchPotential:
surface_density: 10.
scale_height: 100.
z_disk: 200.
timestep_mult: 0.03
growth_time: 5.
# Define the system of units to use internally.
InternalUnitSystem:
UnitMass_in_cgs: 1.9885e33 # Grams
UnitLength_in_cgs: 3.0856776e18 # Centimeters
UnitVelocity_in_cgs: 1e5 # Centimeters per second
UnitCurrent_in_cgs: 1 # Amperes
UnitTemp_in_cgs: 1 # Kelvin
# Parameters governing the time integration
TimeIntegration:
time_begin: 968 # The starting time of the simulation (in internal units).
time_end: 12000. # The end time of the simulation (in internal units).
dt_min: 1e-4 # The minimal time-step size of the simulation (in internal units).
dt_max: 1. # The maximal time-step size of the simulation (in internal units).
# Parameters governing the conserved quantities statistics
Statistics:
delta_time: 1 # Time between statistics output
# Parameters governing the snapshots
Snapshots:
basename: Disk-Patch-dynamic # Common part of the name of output files
time_first: 968. # Time of the first output (in internal units)
delta_time: 24. # Time difference between consecutive outputs (in internal units)
# Parameters for the hydrodynamics scheme
SPH:
resolution_eta: 1.2349 # Target smoothing length in units of the mean inter-particle separation (1.2349 == 48Ngbs with the cubic spline kernel).
delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours.
CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration.
max_ghost_iterations: 30 # Maximal number of iterations allowed to converge towards the smoothing length.
max_smoothing_length: 70. # Maximal smoothing length allowed (in internal units).
# Parameters related to the initial conditions
InitialConditions:
file_name: Disk-Patch-dynamic.hdf5 # The file to read
# External potential parameters
Disk-PatchPotential:
surface_density: 10.
scale_height: 100.
z_disk: 200.
timestep_mult: 0.03
;
; test energy / angular momentum conservation of test problem
;
iplot = 1 ; if iplot = 1, make plot of E/Lz conservation, else, simply compare final and initial energy
; set physical constants
@physunits
indir = './'
basefile = 'Disk-Patch-dynamic_'
; set properties of potential
uL = phys.pc ; unit of length
uM = phys.msun ; unit of mass
uV = 1d5 ; unit of velocity
; properties of patch
surface_density = 10.
scale_height = 100.
z_disk = 200.;
gamma = 5./3.
; derived units
constG = 10.^(alog10(phys.g)+alog10(uM)-2d0*alog10(uV)-alog10(uL)) ;
pcentre = [0.,0.,z_disk] * pc / uL
utherm = !pi * constG * surface_density * scale_height / (gamma-1.)
soundspeed = sqrt(gamma * (gamma-1.) * utherm)
t_dyn = sqrt(scale_height / (constG * surface_density))
;
infile = indir + basefile + '*'
spawn,'ls -1 '+infile,res
nfiles = n_elements(res)
; choose: calculate change of energy and Lz, comparing first and last
; snapshots for all particles, or do so for a subset
; compare all
ifile = 0
inf = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
id = h5rd(inf,'PartType0/ParticleIDs')
nfollow = n_elements(id)
; compute anlytic profile
nbins = 100
zbins = findgen(nbins)/float(nbins-1) * 2 * scale_height
rbins = (surface_density/(2.*scale_height)) / cosh(abs(zbins)/scale_height)^2
; plot analytic profile
wset,0
plot,[0],[0],xr=[0,2*scale_height],yr=[0,max(rbins)],/nodata,xtitle='|z|',ytitle=textoidl('\rho')
oplot,zbins,rbins,color=blue
ifile = 0
nskip = nfiles - 1
isave = 0
nplot = 8192 ; randomly plot particles
color = floor(findgen(nfiles)/float(nfiles-1)*255)
;for ifile=0,nfiles-1,nskip do begin
tsave = [0.]
toplot = [1,nfiles-1]
for iplot=0,1 do begin
ifile = toplot[iplot]
inf = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
time = h5ra(inf, 'Header','Time')
tsave = [tsave, time]
print,' time= ',time
p = h5rd(inf,'PartType0/Coordinates')
v = h5rd(inf,'PartType0/Velocities')
id = h5rd(inf,'PartType0/ParticleIDs')
rho = h5rd(inf,'PartType0/Density')
h = h5rd(inf,'PartType0/SmoothingLength')
utherm = h5rd(inf,'PartType0/InternalEnergy')
indx = sort(id)
; substract disk centre
for ic=0,2 do p[ic,*]=p[ic,*] - pcentre[ic]
;; ; if you want to sort particles by ID
;; id = id[indx]
;; rho = rho[indx]
;; utherm = utherm[indx]
;; h = h[indx]
;; for ic=0,2 do begin
;; tmp = reform(p[ic,*]) & p[ic,*] = tmp[indx]
;; tmp = reform(v[ic,*]) & v[ic,*] = tmp[indx]
;; endfor
ip = floor(randomu(ifile+1,nplot)*n_elements(rho))
color = red
if(ifile eq 1) then begin
color=black
endif else begin
color=red
endelse
oplot,abs(p[2,ip]), rho[ip], psym=3, color=color
isave = isave + 1
endfor
; time in units of dynamical time
tsave = tsave[1:*] / t_dyn
label = ['']
for i=0,n_elements(tsave)-1 do label=[label,'time/t_dynamic='+string(tsave[i],format='(f8.0)')]
label = label[1:*]
legend,['analytic',label[0],label[1]],linestyle=[0,0,0],color=[blue,black,red],box=0,/top,/right
; make histograms of particle velocities
xr = 1d-3 * [-1,1]
bsize = 1.d-5
ohist,v[0,*]/soundspeed,x,vx,xr[0],xr[1],bsize
ohist,v[1,*]/soundspeed,y,vy,xr[0],xr[1],bsize
ohist,v[2,*]/soundspeed,z,vz,xr[0],xr[1],bsize
wset,2
plot,x,vx,psym=10,xtitle='velocity/soundspeed',ytitle='pdf',/nodata,xr=xr,/xs
oplot,x,vx,psym=10,color=black
oplot,y,vy,psym=10,color=blue
oplot,z,vz,psym=10,color=red
legend,['vx/c','vy/c','vz/c'],linestyle=[0,0,0],color=[black,blue,red],box=0,/top,/right
end
#!/bin/bash
wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassCube_32.hdf5
###############################################################################
# This file is part of SWIFT.
# Copyright (c) 2016 John A. Regan (john.a.regan@durham.ac.uk)
# Tom Theuns (tom.theuns@durham.ac.uk)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import h5py
import sys
import numpy
import math
import random
import matplotlib.pyplot as plt
# Generates a disk-patch in hydrostatic equilibrium
# see Creasey, Theuns & Bower, 2013, for the equations:
# disk parameters are: surface density sigma
# scale height b
# density: rho(z) = (sigma/2b) sech^2(z/b)
# isothermal velocity dispersion = <v_z^2? = b pi G sigma
# grad potential = 2 pi G sigma tanh(z/b)
# potential = ln(cosh(z/b)) + const
# Dynamical time = sqrt(b / (G sigma))
# to obtain the 1/ch^2(z/b) profile from a uniform profile (a glass, say, or a uniform random variable), note that, when integrating in z
# \int 0^z dz/ch^2(z) = tanh(z)-tanh(0) = \int_0^x dx = x (where the last integral refers to a uniform density distribution), so that z = atanh(x)
# usage: python makeIC.py 1000
# physical constants in cgs
NEWTON_GRAVITY_CGS = 6.672e-8
SOLAR_MASS_IN_CGS = 1.9885e33
PARSEC_IN_CGS = 3.0856776e18
PROTON_MASS_IN_CGS = 1.6726231e24
YEAR_IN_CGS = 3.154e+7
# choice of units
const_unit_length_in_cgs = (PARSEC_IN_CGS)
const_unit_mass_in_cgs = (SOLAR_MASS_IN_CGS)
const_unit_velocity_in_cgs = (1e5)
print "UnitMass_in_cgs: ", const_unit_mass_in_cgs
print "UnitLength_in_cgs: ", const_unit_length_in_cgs
print "UnitVelocity_in_cgs: ", const_unit_velocity_in_cgs
# parameters of potential
surface_density = 10.
scale_height = 100.
gamma = 5./3.
# derived units
const_unit_time_in_cgs = (const_unit_length_in_cgs / const_unit_velocity_in_cgs)
const_G = ((NEWTON_GRAVITY_CGS*const_unit_mass_in_cgs*const_unit_time_in_cgs*const_unit_time_in_cgs/(const_unit_length_in_cgs*const_unit_length_in_cgs*const_unit_length_in_cgs)))
print 'G=', const_G
utherm = math.pi * const_G * surface_density * scale_height / (gamma-1)
v_disp = numpy.sqrt(2 * utherm)
soundspeed = numpy.sqrt(utherm / (gamma * (gamma-1.)))
t_dyn = numpy.sqrt(scale_height / (const_G * surface_density))
t_cross = scale_height / soundspeed
print 'dynamical time = ',t_dyn,' sound crossing time = ',t_cross,' sound speed= ',soundspeed,' 3D velocity dispersion = ',v_disp,' thermal_energy= ',utherm
# Parameters
periodic= 1 # 1 For periodic box
boxSize = 400. # [kpc]
Radius = 100. # maximum radius of particles [kpc]
G = const_G
# File
fileName = "Disk-Patch.hdf5"
#---------------------------------------------------
mass = 1
#--------------------------------------------------
# using glass ICs
# read glass file and generate gas positions and tile it ntile times in each dimension
ntile = 1
inglass = 'glassCube_32.hdf5'
infile = h5py.File(inglass, "r")
one_glass_p = infile["/PartType0/Coordinates"][:,:]
one_glass_h = infile["/PartType0/SmoothingLength"][:]
# scale in [-0.5,0.5]*BoxSize / ntile
one_glass_p[:,:] -= 0.5
one_glass_p *= boxSize / ntile
one_glass_h *= boxSize / ntile
ndens_glass = (one_glass_h.shape[0]) / (boxSize/ntile)**3
h_glass = numpy.amin(one_glass_h) * (boxSize/ntile)
glass_p = []
glass_h = []
for ix in range(0,ntile):
for iy in range(0,ntile):
for iz in range(0,ntile):
shift = one_glass_p.copy()
shift[:,0] += (ix-(ntile-1)/2.) * boxSize / ntile
shift[:,1] += (iy-(ntile-1)/2.) * boxSize / ntile
shift[:,2] += (iz-(ntile-1)/2.) * boxSize / ntile
glass_p.append(shift)
glass_h.append(one_glass_h.copy())
glass_p = numpy.concatenate(glass_p, axis=0)
glass_h = numpy.concatenate(glass_h, axis=0)
# random shuffle of glas ICs
numpy.random.seed(12345)
indx = numpy.random.rand(numpy.shape(glass_h)[0])
indx = numpy.argsort(indx)
glass_p = glass_p[indx, :]
glass_h = glass_h[indx]
# select numGas of them
numGas = 8192
pos = glass_p[0:numGas,:]
h = glass_h[0:numGas]
numGas = numpy.shape(pos)[0]
# compute furthe properties of ICs
column_density = surface_density * numpy.tanh(boxSize/2./scale_height)
enclosed_mass = column_density * boxSize * boxSize
pmass = enclosed_mass / numGas
meanrho = enclosed_mass / boxSize**3
print 'pmass= ',pmass,' mean(rho) = ', meanrho,' entropy= ', (gamma-1) * utherm / meanrho**(gamma-1)
# desired density
rho = surface_density / (2. * scale_height) / numpy.cosh(abs(pos[:,2])/scale_height)**2
u = (1. + 0 * h) * utherm
entropy = (gamma-1) * u / rho**(gamma-1)
mass = 0.*h + pmass
entropy_flag = 0
vel = 0 + 0 * pos
# move centre of disk to middle of box
pos[:,:] += boxSize/2
# create numPart dm particles
numPart = 0
# Create and write output file
#File
file = h5py.File(fileName, 'w')
#Units
grp = file.create_group("/Units")
grp.attrs["Unit length in cgs (U_L)"] = const_unit_length_in_cgs
grp.attrs["Unit mass in cgs (U_M)"] = const_unit_mass_in_cgs
grp.attrs["Unit time in cgs (U_t)"] = const_unit_length_in_cgs / const_unit_velocity_in_cgs
grp.attrs["Unit current in cgs (U_I)"] = 1.
grp.attrs["Unit temperature in cgs (U_T)"] = 1.
# Header
grp = file.create_group("/Header")
grp.attrs["BoxSize"] = boxSize
grp.attrs["NumPart_Total"] = [numGas, numPart, 0, 0, 0, 0]
grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
grp.attrs["NumPart_ThisFile"] = [numGas, numPart, 0, 0, 0, 0]
grp.attrs["Time"] = 0.0
grp.attrs["NumFilesPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = [entropy_flag]
grp.attrs["Dimension"] = 3
#Runtime parameters
grp = file.create_group("/RuntimePars")
grp.attrs["PeriodicBoundariesOn"] = periodic
# write gas particles
grp0 = file.create_group("/PartType0")
ds = grp0.create_dataset('Coordinates', (numGas, 3), 'f')
ds[()] = pos
ds = grp0.create_dataset('Velocities', (numGas, 3), 'f')
ds[()] = vel
ds = grp0.create_dataset('Masses', (numGas,), 'f')
ds[()] = mass
ds = grp0.create_dataset('SmoothingLength', (numGas,), 'f')
ds[()] = h
ds = grp0.create_dataset('InternalEnergy', (numGas,), 'f')
u = numpy.full((numGas, ), utherm)
if (entropy_flag == 1):
ds[()] = entropy
else:
ds[()] = u
ids = 1 + numpy.linspace(0, numGas, numGas, endpoint=False, dtype='L')
ds = grp0.create_dataset('ParticleIDs', (numGas, ), 'L')
ds[()] = ids
print "Internal energy:", u[0]
# generate dark matter particles if needed
if(numPart > 0):
# set seed for random number
numpy.random.seed(1234)
grp1 = file.create_group("/PartType1")
radius = Radius * (numpy.random.rand(N))**(1./3.)
ctheta = -1. + 2 * numpy.random.rand(N)
stheta = numpy.sqrt(1.-ctheta**2)
phi = 2 * math.pi * numpy.random.rand(N)
r = numpy.zeros((numPart, 3))
speed = vrot
v = numpy.zeros((numPart, 3))
omega = speed / radius
period = 2.*math.pi/omega
print 'period = minimum = ',min(period), ' maximum = ',max(period)
v[:,0] = -omega * r[:,1]
v[:,1] = omega * r[:,0]
ds = grp1.create_dataset('Coordinates', (numPart, 3), 'd')
ds[()] = r
ds = grp1.create_dataset('Velocities', (numPart, 3), 'f')
ds[()] = v
v = numpy.zeros(1)
m = numpy.full((numPart, ),10)
ds = grp1.create_dataset('Masses', (numPart,), 'f')
ds[()] = m
m = numpy.zeros(1)
ids = 1 + numpy.linspace(0, numPart, numPart, endpoint=False, dtype='L')
ds = grp1.create_dataset('ParticleIDs', (numPart, ), 'L')
ds[()] = ids
file.close()
sys.exit()
;
; test energy / angular momentum conservation of test problem
;
iplot = 1 ; if iplot = 1, make plot of E/Lz conservation, else, simply compare final and initial energy
; set physical constants
@physunits
indir = './'
basefile = 'Disk-Patch_'
; set properties of potential
uL = phys.pc ; unit of length
uM = phys.msun ; unit of mass
uV = 1d5 ; unit of velocity
; properties of patch
surface_density = 10.
scale_height = 100.
; derived units
constG = 10.^(alog10(phys.g)+alog10(uM)-2d0*alog10(uV)-alog10(uL)) ;
pcentre = [0.,0.,200.] * pc / uL
;
infile = indir + basefile + '*'
spawn,'ls -1 '+infile,res
nfiles = n_elements(res)
; choose: calculate change of energy and Lz, comparing first and last
; snapshots for all particles, or do so for a subset
; compare all
ifile = 0
inf = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
id = h5rd(inf,'PartType0/ParticleIDs')
nfollow = n_elements(id)
; follow a subset
; nfollow = min(4000, nfollow) ; number of particles to follow
;
if (iplot eq 1) then begin
nskip = 1
nsave = nfiles
endif else begin
nskip = nfiles - 2
nsave = 2
endelse
;
lout = fltarr(nfollow, nsave) ; Lz
xout = fltarr(nfollow, nsave) ; x
yout = fltarr(nfollow, nsave) ; y
zout = fltarr(nfollow, nsave) ; z
vzout = fltarr(nfollow, nsave) ; z
rout = fltarr(nfollow, nsave) ; rho
hout = fltarr(nfollow, nsave) ; h
uout = fltarr(nfollow, nsave) ; thermal energy
eout = fltarr(nfollow, nsave) ; energies
ekin = fltarr(nfollow, nsave)
epot = fltarr(nfollow, nsave) ; 2 pi G Sigma b ln(cosh(z/b)) + const
tout = fltarr(nsave)
ifile = 0
isave = 0
for ifile=0,nfiles-1,nskip do begin
inf = indir + basefile + strtrim(string(ifile,'(i3.3)'),1) + '.hdf5'
time = h5ra(inf, 'Header','Time')
p = h5rd(inf,'PartType0/Coordinates')
v = h5rd(inf,'PartType0/Velocities')
id = h5rd(inf,'PartType0/ParticleIDs')
rho = h5rd(inf,'PartType0/Density')
h = h5rd(inf,'PartType0/SmoothingLength')
utherm = h5rd(inf,'PartType0/InternalEnergy')
indx = sort(id)
; if you want to sort particles by ID
id = id[indx]
rho = rho[indx]
utherm = utherm[indx]
h = h[indx]
for ic=0,2 do begin
tmp = reform(p[ic,*]) & p[ic,*] = tmp[indx]
tmp = reform(v[ic,*]) & v[ic,*] = tmp[indx]
endfor
; calculate energy
dd = size(p,/dimen) & npart = dd[1]
ener = fltarr(npart)
dr = fltarr(npart) & dv = dr
for ic=0,2 do dr[*] = dr[*] + (p[ic,*]-pcentre[ic])^2
for ic=0,2 do dv[*] = dv[*] + v[ic,*]^2
xout[*,isave] = p[0,0:nfollow-1]-pcentre[0]
yout[*,isave] = p[1,0:nfollow-1]-pcentre[1]
zout[*,isave] = p[2,0:nfollow-1]-pcentre[2]
vzout[*,isave]= v[2,0:nfollow-1]
rout[*,isave] = rho[0:nfollow-1]
hout[*,isave] = h[0:nfollow-1]
uout[*,isave] = utherm[0:nfollow-1]
Lz = (p[0,*]-pcentre[0]) * v[1,*] - (p[1,*]-pcentre[1]) * v[0,*]
dz = reform(p[2,0:nfollow-1]-pcentre[2])
; print,'time = ',time,p[0,0],v[0,0],id[0]
ek = 0.5 * dv
ep = fltarr(nfollow)
ep = 2 * !pi * constG * surface_density * scale_height * alog(cosh(abs(dz)/scale_height))
ener = ek + ep
tout(isave) = time
lout[*,isave] = lz[0:nfollow-1]
eout(*,isave) = ener[0:nfollow-1]
ekin(*,isave) = ek[0:nfollow-1]
epot(*,isave) = ep[0:nfollow-1]
print,format='('' time= '',f7.1,'' E= '',f9.2,'' Lz= '',e9.2)', time,eout[0],lz[0]
isave = isave + 1
endfor
x0 = reform(xout[0,*])
y0 = reform(xout[1,*])
z0 = reform(xout[2,*])
; plot density profile and compare to analytic profile
nplot = nfollow
; plot density profile
wset,0
xr = [0, 3*scale_height]
nbins = 100
zpos = findgen(nbins)/float(nbins-1) * max(xr)
dens = (surface_density/(2.d0*scale_height)) * 1./cosh(zpos/scale_height)^2
plot,[0],[0],xr=xr,/xs,yr=[0,max(dens)*1.4],/ys,/nodata,xtitle='|z|',ytitle='density'
oplot,zpos,dens,color=black,thick=3
;oplot,abs(zout[*,1]),rout[*,1],psym=3 ; initial profile
oplot,abs(zout[*,nsave-1]),rout[*,nsave-1],psym=3,color=red
end
......@@ -83,7 +83,7 @@ grp.attrs["Time"] = 0.0
grp.attrs["NumFilesPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = [0, 0, 0, 0, 0, 0]
grp.attrs["Dimension"] = 3
#Runtime parameters
grp = file.create_group("/RuntimePars")
......
......@@ -87,6 +87,7 @@ grp.attrs["Time"] = 0.0
grp.attrs["NumFileOutputsPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = [0, 0, 0, 0, 0, 0]
grp.attrs["Dimension"] = 2
#Runtime parameters
grp = fileOutput.create_group("/RuntimePars")
......
......@@ -101,7 +101,7 @@ grp.attrs["Time"] = 0.0
grp.attrs["NumFilesPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = [0, 0, 0, 0, 0, 0]
grp.attrs["Dimension"] = 3
#Runtime parameters
grp = file.create_group("/RuntimePars")
......
......@@ -127,7 +127,7 @@ print,' relative Lz change: (per cent) ',minmax(dl) * 100.
if(iplot eq 1) then begin
; plot results on energy conservation for some particles
nplot = min(10, nfollow)
wset,0
win,0
xr = [min(tout), max(tout)]
yr = [-2,2]*1d-2 ; in percent
plot,[0],[0],xr=xr,yr=yr,/xs,/ys,/nodata,xtitle='time',ytitle='dE/E, dL/L (%)'
......@@ -137,7 +137,7 @@ if(iplot eq 1) then begin
screen_to_png,'e-time.png'
; plot orbits of those particles
wset,2
win,2
xr = [-100,100]
yr = xr
plot,[0],[0],xr=xr,yr=yr,/xs,/ys,/iso,/nodata,xtitle='x',ytitle='y'
......@@ -146,7 +146,7 @@ if(iplot eq 1) then begin
screen_to_png,'orbit.png'
; plot radial position of these particles
wset,4
win,4
xr = [min(tout), max(tout)]
yr = [0,80]
plot,[0],[0],xr=xr,yr=yr,/xs,/ys,/nodata,xtitle='t',ytitle='r'
......@@ -155,7 +155,7 @@ for i=0,nplot-1 do begin dr = sqrt(reform(xout[i,*])^2 + reform(yout[i,*])^2) &
screen_to_png,'r-time.png'
; make histogram of energy changes at end
wset,6
win,6
ohist,de,x,y,-0.05,0.05,0.001
plot,x,y,psym=10,xtitle='de (%)'
screen_to_png,'de-hist.png'
......
......@@ -120,6 +120,7 @@ grp.attrs["Time"] = 0.0
grp.attrs["NumFileOutputsPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = [0, 0, 0, 0, 0, 0]
grp.attrs["Dimension"] = 2
#Runtime parameters
grp = fileOutput.create_group("/RuntimePars")
......
......@@ -61,6 +61,7 @@ grp.attrs["Time"] = 0.0
grp.attrs["NumFilesPerSnapshot"] = 1
grp.attrs["MassTable"] = [0.0, massDM, 0.0, 0.0, 0.0, 0.0]
grp.attrs["Flag_Entropy_ICs"] = 0
grp.attrs["Dimension"] = 3
#Runtime parameters
grp = file.create_group("/RuntimePars")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment