diff --git a/.gitignore b/.gitignore index 3521b353ec4b1c4dea7192047e197596f083fe99..1a43373acd789366119becb30662be2855db4a51 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ examples/used_parameters.yml examples/energy.txt examples/*/*.xmf examples/*/*.hdf5 +examples/*/*.png examples/*/*.txt examples/*/used_parameters.yml examples/*/*/*.xmf diff --git a/configure.ac b/configure.ac index 483937a9ce4b166410ee42e312b24b13551b5d6a..a798372c2f219a8da71f2b79321c140aba23e790 100644 --- a/configure.ac +++ b/configure.ac @@ -469,7 +469,7 @@ if test "$enable_warn" != "no"; then CFLAGS="$CFLAGS -Wall" ;; intel) - CFLAGS="$CFLAGS -w2" + CFLAGS="$CFLAGS -w2 -Wunused-variable" ;; *) AX_CFLAGS_WARN_ALL diff --git a/examples/GreshoVortex/solution.py b/examples/GreshoVortex/solution.py deleted file mode 100644 index 5b282caf2d7f3311ddb595781fed74c51bb4819f..0000000000000000000000000000000000000000 --- a/examples/GreshoVortex/solution.py +++ /dev/null @@ -1,69 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -from numpy import * - -# Computes the analytical solution of the Gresho-Chan vortex -# The script works for a given initial box and background pressure and computes the solution for any time t (The solution is constant over time). -# The code writes five files rho.dat, P.dat, v.dat, u.dat and s.dat with the density, pressure, internal energy and -# entropic function on N radial points between r=0 and r=R_max. - -# Parameters -rho0 = 1. # Background Density -P0 = 0. # Background Pressure -gamma = 5./3. # Gas polytropic index -N = 1000 # Number of radial points -R_max = 1. # Maximal radius - -# --------------------------------------------------------------- -# Don't touch anything after this. -# --------------------------------------------------------------- - -r = arange(0, R_max, R_max / N) -rho = ones(N) -P = zeros(N) -v = zeros(N) -u = zeros(N) -s = zeros(N) - - -for i in range(N): - if r[i] < 0.2: - P[i] = P0 + 5. + 12.5*r[i]**2 - v[i] = 5.*r[i] - elif r[i] < 0.4: - P[i] = P0 + 9. + 12.5*r[i]**2 - 20.*r[i] + 4.*log(r[i]/0.2) - v[i] = 2. -5.*r[i] - else: - P[i] = P0 + 3. + 4.*log(2.) - v[i] = 0. - rho[i] = rho0 - s[i] = P[i] / rho[i]**gamma - u[i] = P[i] /((gamma - 1.)*rho[i]) - -savetxt("rho.dat", column_stack((r, rho))) -savetxt("P.dat", column_stack((r, P))) -savetxt("v.dat", column_stack((r, v))) -savetxt("u.dat", column_stack((r, u))) -savetxt("s.dat", column_stack((r, s))) - - - diff --git a/examples/GreshoVortex_2D/getGlass.sh b/examples/GreshoVortex_2D/getGlass.sh new file mode 100755 index 0000000000000000000000000000000000000000..ae3c977064f5e7a408aa249c5fd9089b3c52ecb1 --- /dev/null +++ b/examples/GreshoVortex_2D/getGlass.sh @@ -0,0 +1,2 @@ +#!/bin/bash +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassPlane_128.hdf5 diff --git a/examples/GreshoVortex_2D/gresho.yml b/examples/GreshoVortex_2D/gresho.yml new file mode 100644 index 0000000000000000000000000000000000000000..b4de5bde517556cacb94d996f5a11cbe05188bf9 --- /dev/null +++ b/examples/GreshoVortex_2D/gresho.yml @@ -0,0 +1,35 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 1. # The end time of the simulation (in internal units). + dt_min: 1e-6 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: gresho # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-1 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-2 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.02 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./greshoVortex.hdf5 # The file to read diff --git a/examples/GreshoVortex_2D/makeIC.py b/examples/GreshoVortex_2D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..96fa7f098d5eb26c42a984e2b5ec94bafc710dc3 --- /dev/null +++ b/examples/GreshoVortex_2D/makeIC.py @@ -0,0 +1,120 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the Gresho-Chan vortex in a periodic box + +# Parameters +gamma = 5./3. # Gas adiabatic index +rho0 = 1 # Gas density +P0 = 0. # Constant additional pressure (should have no impact on the dynamics) +fileOutputName = "greshoVortex.hdf5" +fileGlass = "glassPlane_128.hdf5" +#--------------------------------------------------- + +# Get position and smoothing lengths from the glass +fileInput = h5py.File(fileGlass, 'r') +coords = fileInput["/PartType0/Coordinates"][:,:] +h = fileInput["/PartType0/SmoothingLength"][:] +ids = fileInput["/PartType0/ParticleIDs"][:] +boxSize = fileInput["/Header"].attrs["BoxSize"][0] +numPart = size(h) +fileInput.close() + +# Now generate the rest +m = ones(numPart) * rho0 * boxSize**2 / numPart +u = zeros(numPart) +v = zeros((numPart, 3)) + +for i in range(numPart): + + x = coords[i,0] + y = coords[i,1] + + r2 = (x - boxSize / 2)**2 + (y - boxSize / 2)**2 + r = sqrt(r2) + + v_phi = 0. + if r < 0.2: + v_phi = 5.*r + elif r < 0.4: + v_phi = 2. - 5.*r + else: + v_phi = 0. + v[i,0] = -v_phi * (y - boxSize / 2) / r + v[i,1] = v_phi * (x - boxSize / 2) / r + v[i,2] = 0. + + P = P0 + if r < 0.2: + P = P + 5. + 12.5*r2 + elif r < 0.4: + P = P + 9. + 12.5*r2 - 20.*r + 4.*log(r/0.2) + else: + P = P + 3. + 4.*log(2.) + u[i] = P / ((gamma - 1.)*rho0) + + + +#File +fileOutput = h5py.File(fileOutputName, 'w') + +# Header +grp = fileOutput.create_group("/Header") +grp.attrs["BoxSize"] = [boxSize, boxSize, 0.2] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 0, 0, 0, 0] +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] + +#Runtime parameters +grp = fileOutput.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = fileOutput.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = fileOutput.create_group("/PartType0") +ds = grp.create_dataset('Coordinates', (numPart, 3), 'd') +ds[()] = coords +ds = grp.create_dataset('Velocities', (numPart, 3), 'f') +ds[()] = v +ds = grp.create_dataset('Masses', (numPart, 1), 'f') +ds[()] = m.reshape((numPart,1)) +ds = grp.create_dataset('SmoothingLength', (numPart,1), 'f') +ds[()] = h.reshape((numPart,1)) +ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f') +ds[()] = u.reshape((numPart,1)) +ds = grp.create_dataset('ParticleIDs', (numPart,1), 'L') +ds[()] = ids.reshape((numPart,1)) + +fileOutput.close() + + diff --git a/examples/GreshoVortex_2D/plotSolution.py b/examples/GreshoVortex_2D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..050bca39a6b7d6f985d630e057a475945471086a --- /dev/null +++ b/examples/GreshoVortex_2D/plotSolution.py @@ -0,0 +1,198 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the Gresho-Chan vortex and plots the SPH answer + +# Parameters +gas_gamma = 5./3. # Gas adiabatic index +rho0 = 1 # Gas density +P0 = 0. # Constant additional pressure (should have no impact on the dynamics) + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + +# Generate the analytic solution at this time +N = 200 +R_max = 0.8 +solution_r = arange(0, R_max, R_max / N) +solution_P = zeros(N) +solution_v_phi = zeros(N) +solution_v_r = zeros(N) + +for i in range(N): + if solution_r[i] < 0.2: + solution_P[i] = P0 + 5. + 12.5*solution_r[i]**2 + solution_v_phi[i] = 5.*solution_r[i] + elif solution_r[i] < 0.4: + solution_P[i] = P0 + 9. + 12.5*solution_r[i]**2 - 20.*solution_r[i] + 4.*log(solution_r[i]/0.2) + solution_v_phi[i] = 2. -5.*solution_r[i] + else: + solution_P[i] = P0 + 3. + 4.*log(2.) + solution_v_phi[i] = 0. + +solution_rho = ones(N) * rho0 +solution_s = solution_P / solution_rho**gas_gamma +solution_u = solution_P /((gas_gamma - 1.)*solution_rho) + +# Read the simulation data +sim = h5py.File("gresho_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +pos = sim["/PartType0/Coordinates"][:,:] +x = pos[:,0] - boxSize / 2 +y = pos[:,1] - boxSize / 2 +vel = sim["/PartType0/Velocities"][:,:] +r = sqrt(x**2 + y**2) +v_r = (x * vel[:,0] + y * vel[:,1]) / r +v_phi = (-y * vel[:,0] + x * vel[:,1]) / r +v_norm = sqrt(vel[:,0]**2 + vel[:,1]**2) +rho = sim["/PartType0/Density"][:] +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] + +# Plot the interesting quantities +figure() + + +# Azimuthal velocity profile ----------------------------- +subplot(231) + +plot(r, v_phi, '.', color='r', ms=0.5) +plot(solution_r, solution_v_phi, '--', color='k', alpha=0.8, lw=1.2) +plot([0.2, 0.2], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +plot([0.4, 0.4], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Azimuthal~velocity}}~v_\\phi$", labelpad=0) +xlim(0,R_max) +ylim(-0.1, 1.2) + +# Radial density profile -------------------------------- +subplot(232) + +plot(r, rho, '.', color='r', ms=0.5) +plot(solution_r, solution_rho, '--', color='k', alpha=0.8, lw=1.2) +plot([0.2, 0.2], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +plot([0.4, 0.4], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=0) +xlim(0,R_max) +ylim(rho0-0.3, rho0 + 0.3) +#yticks([-0.2, -0.1, 0., 0.1, 0.2]) + +# Radial pressure profile -------------------------------- +subplot(233) + +plot(r, P, '.', color='r', ms=0.5) +plot(solution_r, solution_P, '--', color='k', alpha=0.8, lw=1.2) +plot([0.2, 0.2], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +plot([0.4, 0.4], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(0, R_max) +ylim(4.9 + P0, P0 + 6.1) + +# Internal energy profile -------------------------------- +subplot(234) + +plot(r, u, '.', color='r', ms=0.5) +plot(solution_r, solution_u, '--', color='k', alpha=0.8, lw=1.2) +plot([0.2, 0.2], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +plot([0.4, 0.4], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(0,R_max) +ylim(7.3, 9.1) + + +# Radial entropy profile -------------------------------- +subplot(235) + +plot(r, S, '.', color='r', ms=0.5) +plot(solution_r, solution_s, '--', color='k', alpha=0.8, lw=1.2) +plot([0.2, 0.2], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +plot([0.4, 0.4], [-100, 100], ':', color='k', alpha=0.4, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(0, R_max) +ylim(4.9 + P0, P0 + 6.1) + +# Image -------------------------------------------------- +#subplot(234) +#scatter(pos[:,0], pos[:,1], c=v_norm, cmap="PuBu", edgecolors='face', s=4, vmin=0, vmax=1) +#text(0.95, 0.95, "$|v|$", ha="right", va="top") +#xlim(0,1) +#ylim(0,1) +#xlabel("$x$", labelpad=0) +#ylabel("$y$", labelpad=0) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Gresho-Chan vortex with $\\gamma=%.3f$ at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Background $\\rho_0=%.3f$"%rho0, fontsize=10) +text(-0.49, 0.7, "Background $P_0=%.3f$"%P0, fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + +savefig("GreshoVortex.png", dpi=200) diff --git a/examples/GreshoVortex_2D/run.sh b/examples/GreshoVortex_2D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..81c016f4775a1e5d693e3c2f78c7d1e5dc532701 --- /dev/null +++ b/examples/GreshoVortex_2D/run.sh @@ -0,0 +1,19 @@ +#!/bin/bash + + # Generate the initial conditions if they are not present. +if [ ! -e glassPlane_128.hdf5 ] +then + echo "Fetching initial glass file for the Gresho-Chan vortex example..." + ./getGlass.sh +fi +if [ ! -e greshoVortex.hdf5 ] +then + echo "Generating initial conditions for the Gresho-Chan vortex example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 gresho.yml + +# Plot the solution +python plotSolution.py 11 diff --git a/examples/KelvinHelmoltz_2D/kelvinHelmholtz.yml b/examples/KelvinHelmoltz_2D/kelvinHelmholtz.yml new file mode 100644 index 0000000000000000000000000000000000000000..38dd16880a209b885f7ad9c30c024988f4d8228f --- /dev/null +++ b/examples/KelvinHelmoltz_2D/kelvinHelmholtz.yml @@ -0,0 +1,35 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 1.5 # The end time of the simulation (in internal units). + dt_min: 1e-6 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: kelvinHelmholtz # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 0.25 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-2 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.01 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./kelvinHelmholtz.hdf5 # The file to read diff --git a/examples/KelvinHelmoltz_2D/makeIC.py b/examples/KelvinHelmoltz_2D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..5c8632dea52ef301c453cfbf21c35923f12e2d5a --- /dev/null +++ b/examples/KelvinHelmoltz_2D/makeIC.py @@ -0,0 +1,153 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * +import sys + +# Generates a swift IC file for the Kelvin-Helmholtz vortex in a periodic box + +# Parameters +L2 = 128 # Particles along one edge in the low-density region +gamma = 5./3. # Gas adiabatic index +P1 = 2.5 # Central region pressure +P2 = 2.5 # Outskirts pressure +v1 = 0.5 # Central region velocity +v2 = -0.5 # Outskirts vlocity +rho1 = 2 # Central density +rho2 = 1 # Outskirts density +omega0 = 0.1 +sigma = 0.05 / sqrt(2) +fileOutputName = "kelvinHelmholtz.hdf5" +#--------------------------------------------------- + +# Start by generating grids of particles at the two densities +numPart2 = L2 * L2 +L1 = int(sqrt(numPart2 / rho2 * rho1)) +numPart1 = L1 * L1 + +#print "N2 =", numPart2, "N1 =", numPart1 +#print "L2 =", L2, "L1 = ", L1 +#print "rho2 =", rho2, "rho1 =", (float(L1*L1)) / (float(L2*L2)) + +coords1 = zeros((numPart1, 3)) +coords2 = zeros((numPart2, 3)) +h1 = ones(numPart1) * 1.2348 / L1 +h2 = ones(numPart2) * 1.2348 / L2 +m1 = zeros(numPart1) +m2 = zeros(numPart2) +u1 = zeros(numPart1) +u2 = zeros(numPart2) +vel1 = zeros((numPart1, 3)) +vel2 = zeros((numPart2, 3)) + +# Particles in the central region +for i in range(L1): + for j in range(L1): + + index = i * L1 + j + + x = i / float(L1) + 1. / (2. * L1) + y = j / float(L1) + 1. / (2. * L1) + + coords1[index, 0] = x + coords1[index, 1] = y + u1[index] = P1 / (rho1 * (gamma-1.)) + vel1[index, 0] = v1 + +# Particles in the outskirts +for i in range(L2): + for j in range(L2): + + index = i * L2 + j + + x = i / float(L2) + 1. / (2. * L2) + y = j / float(L2) + 1. / (2. * L2) + + coords2[index, 0] = x + coords2[index, 1] = y + u2[index] = P2 / (rho2 * (gamma-1.)) + vel2[index, 0] = v2 + + +# Now concatenate arrays +where1 = abs(coords1[:,1]-0.5) < 0.25 +where2 = abs(coords2[:,1]-0.5) > 0.25 + +coords = append(coords1[where1, :], coords2[where2, :], axis=0) + +#print L2*(L2/2), L1*(L1/2) +#print shape(coords), shape(coords1[where1,:]), shape(coords2[where2,:]) +#print shape(coords), shape(logical_not(coords1[where1,:])), shape(logical_not(coords2[where2,:])) + +vel = append(vel1[where1, :], vel2[where2, :], axis=0) +h = append(h1[where1], h2[where2], axis=0) +m = append(m1[where1], m2[where2], axis=0) +u = append(u1[where1], u2[where2], axis=0) +numPart = size(h) +ids = linspace(1, numPart, numPart) +m[:] = (0.5 * rho1 + 0.5 * rho2) / float(numPart) + +# Velocity perturbation +vel[:,1] = omega0 * sin(4*pi*coords[:,0]) * (exp(-(coords[:,1]-0.25)**2 / (2 * sigma**2)) + exp(-(coords[:,1]-0.75)**2 / (2 * sigma**2))) + +#File +fileOutput = h5py.File(fileOutputName, 'w') + +# Header +grp = fileOutput.create_group("/Header") +grp.attrs["BoxSize"] = [1., 1., 0.1] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 0, 0, 0, 0] +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] + +#Runtime parameters +grp = fileOutput.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = fileOutput.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = fileOutput.create_group("/PartType0") +ds = grp.create_dataset('Coordinates', (numPart, 3), 'd') +ds[()] = coords +ds = grp.create_dataset('Velocities', (numPart, 3), 'f') +ds[()] = vel +ds = grp.create_dataset('Masses', (numPart, 1), 'f') +ds[()] = m.reshape((numPart,1)) +ds = grp.create_dataset('SmoothingLength', (numPart,1), 'f') +ds[()] = h.reshape((numPart,1)) +ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f') +ds[()] = u.reshape((numPart,1)) +ds = grp.create_dataset('ParticleIDs', (numPart,1), 'L') +ds[()] = ids.reshape((numPart,1)) + +fileOutput.close() + + diff --git a/examples/KelvinHelmoltz_2D/plotSolution.py b/examples/KelvinHelmoltz_2D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..9191f3ac7ec75c61d5fdab5d347c86222f787fab --- /dev/null +++ b/examples/KelvinHelmoltz_2D/plotSolution.py @@ -0,0 +1,159 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the Gresho-Chan vortex and plots the SPH answer + +# Parameters +gas_gamma = 5./3. # Gas adiabatic index +P1 = 2.5 # Central region pressure +P2 = 2.5 # Outskirts pressure +v1 = 0.5 # Central region velocity +v2 = -0.5 # Outskirts vlocity +rho1 = 2 # Central density +rho2 = 1 # Outskirts density + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + +# Read the simulation data +sim = h5py.File("kelvinHelmholtz_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +pos = sim["/PartType0/Coordinates"][:,:] +x = pos[:,0] - boxSize / 2 +y = pos[:,1] - boxSize / 2 +vel = sim["/PartType0/Velocities"][:,:] +v_norm = sqrt(vel[:,0]**2 + vel[:,1]**2) +rho = sim["/PartType0/Density"][:] +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] + +# Plot the interesting quantities +figure() + + +# Azimuthal velocity profile ----------------------------- +subplot(231) +scatter(pos[:,0], pos[:,1], c=vel[:,0], cmap="PuBu", edgecolors='face', s=4, vmin=-1., vmax=1.) +text(0.97, 0.97, "${\\rm{Velocity~along}}~x$", ha="right", va="top", backgroundcolor="w") +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=0) +xlim(0, 1) +ylim(0, 1) + +# Radial density profile -------------------------------- +subplot(232) +scatter(pos[:,0], pos[:,1], c=rho, cmap="PuBu", edgecolors='face', s=4, vmin=0.8, vmax=2.2) +text(0.97, 0.97, "${\\rm{Density}}$", ha="right", va="top", backgroundcolor="w") +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=0) +xlim(0, 1) +ylim(0, 1) + +# Radial pressure profile -------------------------------- +subplot(233) +scatter(pos[:,0], pos[:,1], c=P, cmap="PuBu", edgecolors='face', s=4, vmin=1, vmax=4) +text(0.97, 0.97, "${\\rm{Pressure}}$", ha="right", va="top", backgroundcolor="w") +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=0) +xlim(0, 1) +ylim(0, 1) + +# Internal energy profile -------------------------------- +subplot(234) +scatter(pos[:,0], pos[:,1], c=u, cmap="PuBu", edgecolors='face', s=4, vmin=1.5, vmax=5.) +text(0.97, 0.97, "${\\rm{Internal~energy}}$", ha="right", va="top", backgroundcolor="w") +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=0) +xlim(0, 1) +ylim(0, 1) + +# Radial entropy profile -------------------------------- +subplot(235) +scatter(pos[:,0], pos[:,1], c=S, cmap="PuBu", edgecolors='face', s=4, vmin=0.5, vmax=3.) +text(0.97, 0.97, "${\\rm{Entropy}}$", ha="right", va="top", backgroundcolor="w") +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=0) +xlim(0, 1) +ylim(0, 1) + +# Image -------------------------------------------------- +#subplot(234) +#scatter(pos[:,0], pos[:,1], c=v_norm, cmap="PuBu", edgecolors='face', s=4, vmin=0, vmax=1) +#text(0.95, 0.95, "$|v|$", ha="right", va="top") +#xlim(0,1) +#ylim(0,1) +#xlabel("$x$", labelpad=0) +#ylabel("$y$", labelpad=0) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Kelvin-Helmholtz instability at $t=%.2f$"%(time), fontsize=10) +text(-0.49, 0.8, "Centre:~~~ $(P, \\rho, v) = (%.3f, %.3f, %.3f)$"%(P1, rho1, v1), fontsize=10) +text(-0.49, 0.7, "Outskirts: $(P, \\rho, v) = (%.3f, %.3f, %.3f)$"%(P2, rho2, v2), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + +savefig("KelvinHelmholtz.png", dpi=200) diff --git a/examples/KelvinHelmoltz_2D/run.sh b/examples/KelvinHelmoltz_2D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..4899ca89bc7bbbf72d15d6ecd3961c146a9c9821 --- /dev/null +++ b/examples/KelvinHelmoltz_2D/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + + # Generate the initial conditions if they are not present. +if [ ! -e kelvinHelmholtz.hdf5 ] +then + echo "Generating initial conditions for the Kelvin-Helmholtz example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 kelvinHelmholtz.yml + +# Plot the solution +python plotSolution.py 6 diff --git a/examples/GreshoVortex/makeIC.py b/examples/PerturbedBox_2D/makeIC.py similarity index 55% rename from examples/GreshoVortex/makeIC.py rename to examples/PerturbedBox_2D/makeIC.py index 12edcb6e8154ec6f865d28a6daeb02d385d14bbf..20b720419ff095016daad23828b81ca880ea9c2e 100644 --- a/examples/GreshoVortex/makeIC.py +++ b/examples/PerturbedBox_2D/makeIC.py @@ -1,7 +1,6 @@ ############################################################################### # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@durham.ac.uk) + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 @@ -19,28 +18,28 @@ ############################################################################## import h5py +import sys import random from numpy import * -# Generates a swift IC file for the Gresho Vortex in a periodic box +# Generates a swift IC file containing a perturbed cartesian distribution of particles +# at a constant density and pressure in a cubic box # Parameters -periodic= 1 # 1 For periodic box -factor = 3 -boxSize = [ 1.0 , 1.0, 1.0/factor ] -L = 120 # Number of particles along one axis -gamma = 5./3. # Gas adiabatic index -eta = 1.2349 # 48 ngbs with cubic spline kernel -rho = 1 # Gas density -P0 = 0. # Constant additional pressure (should have no impact on the dynamics) -fileName = "greshoVortex.hdf5" -vol = boxSize[0] * boxSize[1] * boxSize[2] +periodic= 1 # 1 For periodic box +boxSize = 1. +L = int(sys.argv[1]) # Number of particles along one axis +rho = 1. # Density +P = 1. # Pressure +gamma = 5./3. # Gas adiabatic index +pert = 0.1 # Perturbation scale (in units of the interparticle separation) +fileName = "perturbedPlane.hdf5" #--------------------------------------------------- - -numPart = L**3 / factor -mass = boxSize[0]*boxSize[1]*boxSize[2] * rho / numPart +numPart = L**2 +mass = boxSize**2 * rho / numPart +internalEnergy = P / ((gamma - 1.)*rho) #Generate particles coords = zeros((numPart, 3)) @@ -50,43 +49,26 @@ h = zeros((numPart, 1)) u = zeros((numPart, 1)) ids = zeros((numPart, 1), dtype='L') -partId=0 for i in range(L): for j in range(L): - for k in range(L/factor): - index = i*L*L/factor + j*L/factor + k - x = i * boxSize[0] / L + boxSize[0] / (2*L) - y = j * boxSize[0] / L + boxSize[0] / (2*L) - z = k * boxSize[0] / L + boxSize[0] / (2*L) - r2 = (x - boxSize[0] / 2)**2 + (y - boxSize[1] / 2)**2 - r = sqrt(r2) - coords[index,0] = x - coords[index,1] = y - coords[index,2] = z - v_phi = 0. - if r < 0.2: - v_phi = 5.*r - elif r < 0.4: - v_phi = 2. - 5.*r - else: - v_phi = 0. - v[index,0] = -v_phi * (y - boxSize[0] / 2) / r - v[index,1] = v_phi * (x - boxSize[0] / 2) / r - v[index,2] = 0. - m[index] = mass - h[index] = eta * boxSize[0] / L - P = P0 - if r < 0.2: - P = P + 5. + 12.5*r2 - elif r < 0.4: - P = P + 9. + 12.5*r2 - 20.*r + 4.*log(r/0.2) - else: - P = P + 3. + 4.*log(2.) - u[index] = P / ((gamma - 1.)*rho) - ids[index] = partId + 1 - partId = partId + 1 - - + index = i*L + j + x = i * boxSize / L + boxSize / (2*L) + random.random() * pert * boxSize/(2.*L) + y = j * boxSize / L + boxSize / (2*L) + random.random() * pert * boxSize/(2.*L) + z = 0 + coords[index,0] = x + coords[index,1] = y + coords[index,2] = z + v[index,0] = 0. + v[index,1] = 0. + v[index,2] = 0. + m[index] = mass + h[index] = 1.23485 * boxSize / L + u[index] = internalEnergy + ids[index] = index + + + +#-------------------------------------------------- #File file = h5py.File(fileName, 'w') @@ -101,6 +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["NumPart_Total"] = numPart #Runtime parameters grp = file.create_group("/RuntimePars") @@ -126,9 +109,7 @@ ds = grp.create_dataset('SmoothingLength', (numPart,1), 'f') ds[()] = h ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f') ds[()] = u -ds = grp.create_dataset('ParticleIDs', (numPart,1), 'L') -ds[()] = ids[:] +ds = grp.create_dataset('ParticleIDs', (numPart, 1), 'L') +ds[()] = ids + 1 file.close() - - diff --git a/examples/PerturbedBox_2D/perturbedPlane.yml b/examples/PerturbedBox_2D/perturbedPlane.yml new file mode 100644 index 0000000000000000000000000000000000000000..e810131cc4b1c66b46b483b1605f9d84bcf203b3 --- /dev/null +++ b/examples/PerturbedBox_2D/perturbedPlane.yml @@ -0,0 +1,35 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 10. # The end time of the simulation (in internal units). + dt_min: 1e-6 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: perturbedPlane # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-1 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-3 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.1 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./perturbedPlane.hdf5 # The file to read diff --git a/examples/PerturbedBox/makeIC.py b/examples/PerturbedBox_3D/makeIC.py similarity index 100% rename from examples/PerturbedBox/makeIC.py rename to examples/PerturbedBox_3D/makeIC.py diff --git a/examples/PerturbedBox/perturbedBox.yml b/examples/PerturbedBox_3D/perturbedBox.yml similarity index 100% rename from examples/PerturbedBox/perturbedBox.yml rename to examples/PerturbedBox_3D/perturbedBox.yml diff --git a/examples/PerturbedBox/run.sh b/examples/PerturbedBox_3D/run.sh similarity index 100% rename from examples/PerturbedBox/run.sh rename to examples/PerturbedBox_3D/run.sh diff --git a/examples/SedovBlast/makeIC_fcc.py b/examples/SedovBlast/makeIC_fcc.py deleted file mode 100644 index 0d3a017a9b7f3b30b61e723e3d1646d7797b40a4..0000000000000000000000000000000000000000 --- a/examples/SedovBlast/makeIC_fcc.py +++ /dev/null @@ -1,122 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -from numpy import * - -# Generates a swift IC file for the Sedov blast test in a periodic cubic box - -# Parameters -periodic= 1 # 1 For periodic box -boxSize = 5. -L = 64 # Number of particles boxes along one axis -rho = 1. # Density -P = 1.e-5 # Pressure -E0= 1.e2 # Energy of the explosion -pert = 0.025 -gamma = 5./3. # Gas adiabatic index -eta = 1.2349 # 48 ngbs with cubic spline kernel -fileName = "sedov.hdf5" - - -#--------------------------------------------------- -numPart = 4*(L**3) -mass = boxSize**3 * rho / numPart -internalEnergy = P / ((gamma - 1.)*rho) -off = array( [ [ 0.0 , 0.0 , 0.0 ] , [ 0.0 , 0.5 , 0.5 ] , [ 0.5 , 0.0 , 0.5 ] , [ 0.5 , 0.5 , 0.0 ] ] ); -hbox = boxSize / L - -# if L%2 == 0: -# print "Number of particles along each dimension must be odd." -# exit() - -#Generate particles -coords = zeros((numPart, 3)) -v = zeros((numPart, 3)) -m = zeros(numPart) -h = zeros(numPart) -u = zeros(numPart) -ids = zeros(numPart, dtype='L') - -for i in range(L): - for j in range(L): - for k in range(L): - x = (i + 0.25) * hbox - y = (j + 0.25) * hbox - z = (k + 0.25) * hbox - for ell in range(4): - index = 4*(i*L*L + j*L + k) + ell - coords[index,0] = x + off[ell,0] * hbox - coords[index,1] = y + off[ell,1] * hbox - coords[index,2] = z + off[ell,2] * hbox - v[index,0] = 0. - v[index,1] = 0. - v[index,2] = 0. - m[index] = mass - h[index] = eta * hbox - u[index] = internalEnergy - ids[index] = index + 1 - if sqrt((x - boxSize/2.)**2 + (y - boxSize/2.)**2 + (z - boxSize/2.)**2) < 1.2 * hbox: - u[index] = u[index] + E0 / (28. * mass) - print "Particle " , index , " set to detonate." - coords[index,0] += random.random() * pert * hbox - coords[index,1] += random.random() * pert * hbox - coords[index,2] += random.random() * pert * hbox - - -#-------------------------------------------------- - -#File -file = h5py.File(fileName, 'w') - -# Header -grp = file.create_group("/Header") -grp.attrs["BoxSize"] = boxSize -grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] -grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] -grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 - -#Runtime parameters -grp = file.create_group("/RuntimePars") -grp.attrs["PeriodicBoundariesOn"] = periodic - -#Units -grp = file.create_group("/Units") -grp.attrs["Unit length in cgs (U_L)"] = 1. -grp.attrs["Unit mass in cgs (U_M)"] = 1. -grp.attrs["Unit time in cgs (U_t)"] = 1. -grp.attrs["Unit current in cgs (U_I)"] = 1. -grp.attrs["Unit temperature in cgs (U_T)"] = 1. - -#Particle group -grp = file.create_group("/PartType0") -grp.create_dataset('Coordinates', data=coords, dtype='d') -grp.create_dataset('Velocities', data=v, dtype='f') -grp.create_dataset('Masses', data=m, dtype='f') -grp.create_dataset('SmoothingLength', data=h, dtype='f') -grp.create_dataset('InternalEnergy', data=u, dtype='f') -grp.create_dataset('ParticleIDs', data=ids, dtype='L') - -file.close() diff --git a/examples/SedovBlast/profile.py b/examples/SedovBlast/profile.py deleted file mode 100644 index 1b1dfb389b2c9f6d0e5af02a17a07068f03bfd92..0000000000000000000000000000000000000000 --- a/examples/SedovBlast/profile.py +++ /dev/null @@ -1,46 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2015 Bert Vandenbroucke (bert.vandenbroucke@ugent.be) - # - # 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 numpy as np -import h5py -import matplotlib -matplotlib.use('Agg') -import pylab as pl -import glob -import sedov - -# plot the radial density profile for all snapshots in the current directory, -# as well as the analytical solution of Sedov - -for f in sorted(glob.glob("output*.hdf5")): - file = h5py.File(f, "r") - t = file["/Header"].attrs["Time"] - coords = np.array(file["/PartType0/Coordinates"]) - rho = np.array(file["/PartType0/Density"]) - - radius = np.sqrt( (coords[:,0]-5.)**2 + (coords[:,1]-5.)**2 + \ - (coords[:,2]-5.)**2 ) - - r_theory, rho_theory = sedov.get_analytical_solution(100., 5./3., 3, t, - max(radius)) - - pl.plot(r_theory, rho_theory, "r-") - pl.plot(radius, rho, "k.") - pl.savefig("{name}.png".format(name = f[:-5])) - pl.close() diff --git a/examples/SedovBlast/rdf.py b/examples/SedovBlast/rdf.py deleted file mode 100644 index 7f932cc814dc36e14e1bef52e33cf5ed1f527dfd..0000000000000000000000000000000000000000 --- a/examples/SedovBlast/rdf.py +++ /dev/null @@ -1,121 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -import sys -import math -from numpy import * - -# Reads the HDF5 output of SWIFT and generates a radial density profile -# of the different physical values. - -# Input values? -if len(sys.argv) < 3 : - print "Usage: " , sys.argv[0] , " <filename> <nr. bins>" - exit() - -# Get the input arguments -fileName = sys.argv[1]; -nr_bins = int( sys.argv[2] ); - - -# Open the file -fileName = sys.argv[1]; -file = h5py.File( fileName , 'r' ) - -# Get the space dimensions. -grp = file[ "/Header" ] -boxsize = grp.attrs[ 'BoxSize' ] -if len( boxsize ) > 0: - boxsize = boxsize[0] - -# Get the particle data -grp = file.get( '/PartType0' ) -ds = grp.get( 'Coordinates' ) -coords = ds[...] -ds = grp.get( 'Velocities' ) -v = ds[...] -ds = grp.get( 'Masses' ) -m = ds[...] -ds = grp.get( 'SmoothingLength' ) -h = ds[...] -ds = grp.get( 'InternalEnergy' ) -u = ds[...] -ds = grp.get( 'ParticleIDs' ) -ids = ds[...] -ds = grp.get( 'Density' ) -rho = ds[...] - -# Set the origin to be the middle of the box -origin = [ boxsize / 2 , boxsize / 2 , boxsize / 2 ] - -# Get the maximum radius -r_max = boxsize / 2 - -# Init the bins -nr_parts = coords.shape[0] -bins_v = zeros( nr_bins ) -bins_m = zeros( nr_bins ) -bins_h = zeros( nr_bins ) -bins_u = zeros( nr_bins ) -bins_rho = zeros( nr_bins ) -bins_count = zeros( nr_bins ) -bins_P = zeros( nr_bins ) - -# Loop over the particles and fill the bins. -for i in range( nr_parts ): - - # Get the box index. - r = coords[i] - origin - r = sqrt( r[0]*r[0] + r[1]*r[1] + r[2]*r[2] ) - ind = floor( r / r_max * nr_bins ) - - # Update the bins - if ( ind < nr_bins ): - bins_count[ind] += 1 - bins_v[ind] += sqrt( v[i,0]*v[i,0] + v[i,1]*v[i,1] + v[i,2]*v[i,2] ) - bins_m[ind] += m[i] - bins_h[ind] += h[i] - bins_u[ind] += u[i] - bins_rho[ind] += rho[i] - bins_P[ind] += (2.0/3)*u[i]*rho[i] - -# Loop over the bins and dump them -print "# bucket left right count v m h u rho" -for i in range( nr_bins ): - - # Normalize by the bin volume. - r_left = r_max * i / nr_bins - r_right = r_max * (i+1) / nr_bins - vol = 4/3*math.pi*(r_right*r_right*r_right - r_left*r_left*r_left) - ivol = 1.0 / vol - - print "%i %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e" % \ - ( i , r_left , r_right , \ - bins_count[i] * ivol , \ - bins_v[i] / bins_count[i] , \ - bins_m[i] * ivol , \ - bins_h[i] / bins_count[i] , \ - bins_u[i] / bins_count[i] , \ - bins_rho[i] / bins_count[i] , - bins_P[i] / bins_count[i] ) - - diff --git a/examples/SedovBlast/run.sh b/examples/SedovBlast/run.sh deleted file mode 100755 index f71830eb6a66a9ea84e93fd1bed1261b1cb42b7b..0000000000000000000000000000000000000000 --- a/examples/SedovBlast/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Generate the initial conditions if they are not present. -if [ ! -e sedov.hdf5 ] -then - echo "Generating initial conditions for the SedovBlast example..." - python makeIC_fcc.py -fi - -../swift -s -t 16 sedov.yml diff --git a/examples/SedovBlast/sedov.py b/examples/SedovBlast/sedov.py deleted file mode 100755 index ca908fe65cd15ddd2b0e4fb41a402492432a0690..0000000000000000000000000000000000000000 --- a/examples/SedovBlast/sedov.py +++ /dev/null @@ -1,212 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2015 Bert Vandenbroucke (bert.vandenbroucke@ugent.be) - # - # 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 numpy as np -import scipy.integrate as integrate -import scipy.optimize as optimize -import os - -# Calculate the analytical solution of the Sedov-Taylor shock wave for a given -# number of dimensions, gamma and time. We assume dimensionless units and a -# setup with constant density 1, pressure and velocity 0. An energy 1 is -# inserted in the center at t 0. -# -# The solution is a self-similar shock wave, which was described in detail by -# Sedov (1959). We follow his notations and solution method. -# -# The position of the shock at time t is given by -# r2 = (E/rho1)^(1/(2+nu)) * t^(2/(2+nu)) -# the energy E is related to the inserted energy E0 by E0 = alpha*E, with alpha -# a constant which has to be calculated by imposing energy conservation. -# -# The density for a given radius at a certain time is determined by introducing -# the dimensionless position coordinate lambda = r/r2. The density profile as -# a function of lambda is constant in time and given by -# rho = rho1 * R(V, gamma, nu) -# and -# V = V(lambda, gamma, nu) -# -# The function V(lambda, gamma, nu) is found by solving a differential equation -# described in detail in Sedov (1959) chapter 4, section 5. Alpha is calculated -# from the integrals in section 11 of the same chapter. -# -# Numerically, the complete solution requires the use of 3 quadratures and 1 -# root solver, which are implemented using the GNU Scientific Library (GSL). -# Since some quadratures call functions that themselves contain quadratures, -# the problem is highly non-linear and complex and takes a while to converge. -# Therefore, we tabulate the alpha values and profile values the first time -# a given set of gamma and nu values is requested and reuse these tabulated -# values. -# -# Reference: -# Sedov (1959): Sedov, L., Similitude et dimensions en mecanique (7th ed.; -# Moscou: Editions Mir) - french translation of the original -# book from 1959. - -# dimensionless variable z = gamma*P/R as a function of V (and gamma and nu) -# R is a dimensionless density, while P is a dimensionless pressure -# z is hence a sort of dimensionless sound speed -# The expression below corresponds to eq. 11.9 in Sedov (1959), chapter 4 -def _z(V, gamma, nu): - if V == 2./(nu+2.)/gamma: - return 0. - else: - return (gamma-1.)*V*V*(V-2./(2.+nu))/2./(2./(2.+nu)/gamma-V) - -# differential equation that needs to be solved to obtain lambda for a given V -# corresponds to eq. 5.11 in Sedov (1959), chapter 4 (omega = 0) -def _dlnlambda_dV(V, gamma, nu): - nom = _z(V, gamma, nu) - (V-2./(nu+2.))*(V-2./(nu+2.)) - denom = V*(V-1.)*(V-2./(nu+2.))+nu*(2./(nu+2.)/gamma-V)*_z(V, gamma, nu) - return nom/denom - -# dimensionless variable lambda = r/r2 as a function of V (and gamma and nu) -# found by solving differential equation 5.11 in Sedov (1959), chapter 4 -# (omega = 0) -def _lambda(V, gamma, nu): - if V == 2./(nu+2.)/gamma: - return 0. - else: - V0 = 4./(nu+2.)/(gamma+1.) - integral, err = integrate.quad(_dlnlambda_dV, V, V0, (gamma, nu), - limit = 8000) - return np.exp(-integral) - -# dimensionless variable R = rho/rho1 as a function of V (and gamma and nu) -# found by inverting eq. 5.12 in Sedov (1959), chapter 4 (omega = 0) -# the integration constant C is found by inserting the R, V and z values -# at the shock wave, where lambda is 1. These correspond to eq. 11.8 in Sedov -# (1959), chapter 4. -def _R(V, gamma, nu): - if V == 2./(nu+2.)/gamma: - return 0. - else: - C = 8.*gamma*(gamma-1.)/(nu+2.)/(nu+2.)/(gamma+1.)/(gamma+1.) \ - *((gamma-1.)/(gamma+1.))**(gamma-2.) \ - *(4./(nu+2.)/(gamma+1.)-2./(nu+2.)) - lambda1 = _lambda(V, gamma, nu) - lambda5 = lambda1**(nu+2) - return (_z(V, gamma, nu)*(V-2./(nu+2.))*lambda5/C)**(1./(gamma-2.)) - -# function of which we need to find the zero point to invert lambda(V) -def _lambda_min_lambda(V, lambdax, gamma, nu): - return _lambda(V, gamma, nu) - lambdax - -# dimensionless variable V = v*t/r as a function of lambda (and gamma and nu) -# found by inverting the function lamdba(V) which is found by solving -# differential equation 5.11 in Sedov (1959), chapter 4 (omega = 0) -# the invertion is done by searching the zero point of the function -# lambda_min_lambda defined above -def _V_inv(lambdax, gamma, nu): - if lambdax == 0.: - return 2./(2.+nu)/gamma; - else: - return optimize.brentq(_lambda_min_lambda, 2./(nu+2.)/gamma, - 4./(nu+2.)/(gamma+1.), (lambdax, gamma, nu)) - -# integrand of the first integral in eq. 11.24 in Sedov (1959), chapter 4 -def _integrandum1(lambdax, gamma, nu): - V = _V_inv(lambdax, gamma, nu) - if nu == 2: - return _R(V, gamma, nu)*V**2*lambdax**3 - else: - return _R(V, gamma, nu)*V**2*lambdax**4 - -# integrand of the second integral in eq. 11.24 in Sedov (1959), chapter 4 -def _integrandum2(lambdax, gamma, nu): - V = _V_inv(lambdax, gamma, nu) - if V == 2./(nu+2.)/gamma: - P = 0. - else: - P = _z(V, gamma, nu)*_R(V, gamma, nu)/gamma - if nu == 2: - return P*lambdax**3 - else: - return P*lambdax**4 - -# calculate alpha = E0/E -# this corresponds to eq. 11.24 in Sedov (1959), chapter 4 -def get_alpha(gamma, nu): - integral1, err1 = integrate.quad(_integrandum1, 0., 1., (gamma, nu)) - integral2, err2 = integrate.quad(_integrandum2, 0., 1., (gamma, nu)) - - if nu == 2: - return np.pi*integral1+2.*np.pi/(gamma-1.)*integral2 - else: - return 2.*np.pi*integral1+4.*np.pi/(gamma-1.)*integral2 - -# get the analytical solution for the Sedov-Taylor blastwave given an input -# energy E, adiabatic index gamma, and number of dimensions nu, at time t and -# with a maximal outer region radius maxr -def get_analytical_solution(E, gamma, nu, t, maxr = 1.): - # we check for the existance of a datafile with precomputed alpha and - # profile values - # if it does not exist, we calculate it here and write it out - # calculation of alpha and the profile takes a while... - lvec = np.zeros(1000) - Rvec = np.zeros(1000) - fname = "sedov_profile_gamma_{gamma}_nu_{nu}.dat".format(gamma = gamma, - nu = nu) - if os.path.exists(fname): - file = open(fname, "r") - lines = file.readlines() - alpha = float(lines[0]) - for i in range(len(lines)-1): - data = lines[i+1].split() - lvec[i] = float(data[0]) - Rvec[i] = float(data[1]) - else: - alpha = get_alpha(gamma, nu) - for i in range(1000): - lvec[i] = (i+1)*0.001 - V = _V_inv(lvec[i], gamma, nu) - Rvec[i] = _R(V, gamma, nu) - file = open(fname, "w") - file.write("{alpha}\n".format(alpha = alpha)) - for i in range(1000): - file.write("{l}\t{R}\n".format(l = lvec[i], R = Rvec[i])) - - xvec = np.zeros(1002) - rhovec = np.zeros(1002) - if nu == 2: - r2 = (E/alpha)**0.25*np.sqrt(t) - else: - r2 = (E/alpha)**0.2*t**0.4 - - for i in range(1000): - xvec[i] = lvec[i]*r2 - rhovec[i] = Rvec[i] - xvec[1000] = 1.001*r2 - xvec[1001] = maxr - rhovec[1000] = 1. - rhovec[1001] = 1. - - return xvec, rhovec - -def main(): - E = 1. - gamma = 1.66667 - nu = 3 - t = 0.001 - x, rho = get_analytical_solution(E, gamma, nu, t) - for i in range(len(x)): - print x[i], rho[i] - -if __name__ == "__main__": - main() diff --git a/examples/SedovBlast/solution.py b/examples/SedovBlast/solution.py deleted file mode 100644 index 9335e22bdd76585e8d53d3dba9f9a435197f92fc..0000000000000000000000000000000000000000 --- a/examples/SedovBlast/solution.py +++ /dev/null @@ -1,114 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -from numpy import * - -# Computes the analytical solution of the 3D Sedov blast wave. -# The script works for a given initial box and dumped energy and computes the solution at a later time t. -# The code writes five files rho.dat, P.dat, v.dat, u.dat and s.dat with the density, pressure, internal energy and -# entropic function on N radial points between r=0 and r=R_max. -# Follows the solution in Landau & Lifschitz - -# Parameters -rho_0 = 1. # Background Density -P_0 = 1.e-5 # Background Pressure -E_0 = 1.e2 # Energy of the explosion -gamma = 5./3. # Gas polytropic index - -t = 0.275 # Time of the solution - -N = 1000 # Number of radial points -R_max = 3. # Maximal radius - -# --------------------------------------------------------------- -# Don't touch anything after this. -# --------------------------------------------------------------- - -if gamma == 5./3.: - alpha = 0.49 -else: - print "Unknown value for alpha" - exit - -# Position and velocity of the shock -r_shock = (E_0 / (alpha * rho_0))**(1./5.) * t**(2./5.) -v_shock = (1./5.) * (1./alpha)**(1./5.) * ((E_0 * t**2. / rho_0)**(-4./5.)) * E_0 * (t / rho_0) - -# Prepare arrays -delta_r = R_max / N -r_s = arange(0, R_max, delta_r) -rho_s = ones(N) * rho_0 -P_s = ones(N) * P_0 -u_s = ones(N) -v_s = zeros(N) - -# State on the shock -rho_shock = rho_0 * (gamma+1.)/(gamma-1.) -P_shock = 2./(gamma+1.) * rho_shock * v_shock**2 - -# Integer position of the shock -i_shock = min(floor(r_shock /delta_r), N) - -# Dimensionless velocity and its spatial derivative -v_bar0 = (gamma+1.)/(2.*gamma) -deltaV_bar = (1.0 - v_bar0) / (i_shock - 1) - -def rho_dimensionless(v_bar): - power1 = (2./(gamma-2.)) - power2 = -(12.-7.*gamma+13.*gamma**2)/(2.-3.*gamma-11.*gamma**2+6.*gamma**3) - power3 = 3./(1.+2.*gamma) - term1 = ((1.+ gamma - 2.*v_bar)/(gamma-1.))**power1 - term2 = ((5.+5.*gamma+2.*v_bar-6.*gamma*v_bar)/(7.-gamma))**power2 - term3 = ((2.*gamma*v_bar - gamma -1.)/(gamma-1.))**power3 - return term1 * term2 * term3 - -def P_dimensionless(v_bar): - return (gamma+1. - 2.*v_bar)/(2.*gamma*v_bar - gamma - 1.)*v_bar**2 * rho_dimensionless(v_bar) - -def r_dimensionless(v_bar): - power1 = (-12.+7.*gamma-13.*gamma**2)/(5.*(-1.+gamma+6.*gamma**2)) - power2 = (gamma - 1.)/(1.+2.*gamma) - term1 = ((5.+5.*gamma+2.*v_bar-6.*gamma*v_bar)/(7.-gamma))**power1 - term2 = ((2.*gamma*v_bar-gamma-1.)/(gamma-1.))**power2 - return v_bar**(-2./5.)*term1*term2 - -# Generate solution -for i in range(1,int(i_shock)): - v_bar = v_bar0 + (i-1)*deltaV_bar - r_s[i] = r_dimensionless(v_bar) * r_shock - rho_s[i] = rho_dimensionless(v_bar) * rho_shock - P_s[i] = P_shock * (r_s[i]/r_shock)**2 * P_dimensionless(v_bar) - v_s[i] = (4./(5.*(gamma+1.)) * r_s[i] / t * v_bar) - -u_s = P_s / ((gamma - 1.)*rho_s) # internal energy -s_s = P_s / rho_s**gamma # entropic function -rho_s[0] = 0. -P_s[0] = P_s[1] # dirty... - - -savetxt("rho.dat", column_stack((r_s, rho_s))) -savetxt("P.dat", column_stack((r_s, P_s))) -savetxt("v.dat", column_stack((r_s, v_s))) -savetxt("u.dat", column_stack((r_s, u_s))) -savetxt("s.dat", column_stack((r_s, s_s))) - - - diff --git a/examples/SedovBlast/makeIC.py b/examples/SedovBlast_1D/makeIC.py similarity index 54% rename from examples/SedovBlast/makeIC.py rename to examples/SedovBlast_1D/makeIC.py index e64942e8e92ee6fe67142f841f566019b1a668be..4bdf69eee99d98956d5e657be3f963d0cf9ea15b 100644 --- a/examples/SedovBlast/makeIC.py +++ b/examples/SedovBlast_1D/makeIC.py @@ -1,7 +1,6 @@ ############################################################################### # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@durham.ac.uk) + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 @@ -19,65 +18,42 @@ ############################################################################## import h5py -import random from numpy import * # Generates a swift IC file for the Sedov blast test in a periodic cubic box # Parameters -periodic= 1 # 1 For periodic box -boxSize = 10. -L = 101 # Number of particles along one axis -rho = 1. # Density -P = 1.e-5 # Pressure -E0= 1.e2 # Energy of the explosion -pert = 0.1 -gamma = 5./3. # Gas adiabatic index -eta = 1.2349 # 48 ngbs with cubic spline kernel +numPart = 1000 +gamma = 5./3. # Gas adiabatic index +rho0 = 1. # Background density +P0 = 1.e-6 # Background pressure +E0= 1. # Energy of the explosion +N_inject = 3 # Number of particles in which to inject energy fileName = "sedov.hdf5" - #--------------------------------------------------- -numPart = L**3 -mass = boxSize**3 * rho / numPart -internalEnergy = P / ((gamma - 1.)*rho) +coords = zeros((numPart, 3)) +h = zeros(numPart) +vol = 1. -if L%2 == 0: - print "Number of particles along each dimension must be odd." - exit() +for i in range(numPart): + coords[i,0] = i * vol/numPart + vol/(2.*numPart) + h[i] = 1.2348 * vol / numPart -#Generate particles -coords = zeros((numPart, 3)) -v = zeros((numPart, 3)) -m = zeros(numPart) -h = zeros(numPart) -u = zeros(numPart) -ids = zeros(numPart, dtype='L') +# Generate extra arrays +v = zeros((numPart, 3)) +ids = linspace(1, numPart, numPart) +m = zeros(numPart) +u = zeros(numPart) +r = zeros(numPart) -for i in range(L): - for j in range(L): - for k in range(L): - index = i*L*L + j*L + k - x = i * boxSize / L + boxSize / (2*L) - y = j * boxSize / L + boxSize / (2*L) - z = k * boxSize / L + boxSize / (2*L) - coords[index,0] = x - coords[index,1] = y - coords[index,2] = z - v[index,0] = 0. - v[index,1] = 0. - v[index,2] = 0. - m[index] = mass - h[index] = eta * boxSize / L - u[index] = internalEnergy - ids[index] = index + 1 - if sqrt((x - boxSize/2.)**2 + (y - boxSize/2.)**2 + (z - boxSize/2.)**2) < 2.01 * boxSize/L: - u[index] = u[index] + E0 / (33. * mass) - print "Particle " , index , " set to detonate." - coords[index,0] = x + random.random() * pert * boxSize/(2.*L) - coords[index,1] = y + random.random() * pert * boxSize/(2.*L) - coords[index,2] = z + random.random() * pert * boxSize/(2.*L) +r = abs(coords[:,0] - 0.5) +m[:] = rho0 * vol / numPart +u[:] = P0 / (rho0 * (gamma - 1)) +# Make the central particle detonate +index = argsort(r) +u[index[0:N_inject]] = E0 / (N_inject * m[0]) #-------------------------------------------------- @@ -86,7 +62,7 @@ file = h5py.File(fileName, 'w') # Header grp = file.create_group("/Header") -grp.attrs["BoxSize"] = boxSize +grp.attrs["BoxSize"] = [1., 1., 1.] grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] grp.attrs["NumPart_ThisFile"] = [numPart, 0, 0, 0, 0, 0] @@ -97,7 +73,7 @@ grp.attrs["Flag_Entropy_ICs"] = 0 #Runtime parameters grp = file.create_group("/RuntimePars") -grp.attrs["PeriodicBoundariesOn"] = periodic +grp.attrs["PeriodicBoundariesOn"] = 1 #Units grp = file.create_group("/Units") diff --git a/examples/SedovBlast_1D/plotSolution.py b/examples/SedovBlast_1D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..a62775b012edda3217558031c266ed6e9b48f423 --- /dev/null +++ b/examples/SedovBlast_1D/plotSolution.py @@ -0,0 +1,279 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2015 Bert Vandenbroucke (bert.vandenbroucke@ugent.be) + # Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the 2D Sedov blast wave. +# The script works for a given initial box and dumped energy and computes the solution at a later time t. + +# Parameters +rho_0 = 1. # Background Density +P_0 = 1.e-6 # Background Pressure +E_0 = 1. # Energy of the explosion +gas_gamma = 5./3. # Gas polytropic index + + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + + +# Read the simulation data +sim = h5py.File("sedov_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +pos = sim["/PartType0/Coordinates"][:,:] +x = pos[:,0] - boxSize / 2 +vel = sim["/PartType0/Velocities"][:,:] +r = abs(x) +v_r = x * vel[:,0] / r +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +rho = sim["/PartType0/Density"][:] + + +# Now, work our the solution.... + +from scipy.special import gamma as Gamma +from numpy import * + +def calc_a(g,nu=3): + """ + exponents of the polynomials of the sedov solution + g - the polytropic gamma + nu - the dimension + """ + a = [0]*8 + + a[0] = 2.0 / (nu + 2) + a[2] = (1-g) / (2*(g-1) + nu) + a[3] = nu / (2*(g-1) + nu) + a[5] = 2 / (g-2) + a[6] = g / (2*(g-1) + nu) + + a[1] = (((nu+2)*g)/(2.0+nu*(g-1.0)) ) * ( (2.0*nu*(2.0-g))/(g*(nu+2.0)**2) - a[2]) + a[4] = a[1]*(nu+2) / (2-g) + a[7] = (2 + nu*(g-1))*a[1]/(nu*(2-g)) + return a + +def calc_beta(v, g, nu=3): + """ + beta values for the sedov solution (coefficients of the polynomials of the similarity variables) + v - the similarity variable + g - the polytropic gamma + nu- the dimension + """ + + beta = (nu+2) * (g+1) * array((0.25, (g/(g-1))*0.5, + -(2 + nu*(g-1))/2.0 / ((nu+2)*(g+1) -2*(2 + nu*(g-1))), + -0.5/(g-1)), dtype=float64) + + beta = outer(beta, v) + + beta += (g+1) * array((0.0, -1.0/(g-1), + (nu+2) / ((nu+2)*(g+1) -2.0*(2 + nu*(g-1))), + 1.0/(g-1)), dtype=float64).reshape((4,1)) + + return beta + + +def sedov(t, E0, rho0, g, n=1000, nu=3): + """ + solve the sedov problem + t - the time + E0 - the initial energy + rho0 - the initial density + n - number of points (10000) + nu - the dimension + g - the polytropic gas gamma + """ + # the similarity variable + v_min = 2.0 / ((nu + 2) * g) + v_max = 4.0 / ((nu + 2) * (g + 1)) + + v = v_min + arange(n) * (v_max - v_min) / (n - 1.0) + + a = calc_a(g, nu) + beta = calc_beta(v, g=g, nu=nu) + lbeta = log(beta) + + r = exp(-a[0] * lbeta[0] - a[2] * lbeta[1] - a[1] * lbeta[2]) + rho = ((g + 1.0) / (g - 1.0)) * exp(a[3] * lbeta[1] + a[5] * lbeta[3] + a[4] * lbeta[2]) + p = exp(nu * a[0] * lbeta[0] + (a[5] + 1) * lbeta[3] + (a[4] - 2 * a[1]) * lbeta[2]) + u = beta[0] * r * 4.0 / ((g + 1) * (nu + 2)) + p *= 8.0 / ((g + 1) * (nu + 2) * (nu + 2)) + + # we have to take extra care at v=v_min, since this can be a special point. + # It is not a singularity, however, the gradients of our variables (wrt v) are. + # r -> 0, u -> 0, rho -> 0, p-> constant + + u[0] = 0.0; rho[0] = 0.0; r[0] = 0.0; p[0] = p[1] + + # volume of an n-sphere + vol = (pi ** (nu / 2.0) / Gamma(nu / 2.0 + 1)) * power(r, nu) + + # note we choose to evaluate the integral in this way because the + # volumes of the first few elements (i.e near v=vmin) are shrinking + # very slowly, so we dramatically improve the error convergence by + # finding the volumes exactly. This is most important for the + # pressure integral, as this is on the order of the volume. + + # (dimensionless) energy of the model solution + de = rho * u * u * 0.5 + p / (g - 1) + # integrate (trapezium rule) + q = inner(de[1:] + de[:-1], diff(vol)) * 0.5 + + # the factor to convert to this particular problem + fac = (q * (t ** nu) * rho0 / E0) ** (-1.0 / (nu + 2)) + + # shock speed + shock_speed = fac * (2.0 / (nu + 2)) + rho_s = ((g + 1) / (g - 1)) * rho0 + r_s = shock_speed * t * (nu + 2) / 2.0 + p_s = (2.0 * rho0 * shock_speed * shock_speed) / (g + 1) + u_s = (2.0 * shock_speed) / (g + 1) + + r *= fac * t + u *= fac + p *= fac * fac * rho0 + rho *= rho0 + return r, p, rho, u, r_s, p_s, rho_s, u_s, shock_speed + + +# The main properties of the solution +r_s, P_s, rho_s, v_s, r_shock, _, _, _, _ = sedov(time, E_0, rho_0, gas_gamma, 1000, 1) + +# Append points for after the shock +r_s = np.insert(r_s, np.size(r_s), [r_shock, r_shock*1.5]) +rho_s = np.insert(rho_s, np.size(rho_s), [rho_0, rho_0]) +P_s = np.insert(P_s, np.size(P_s), [P_0, P_0]) +v_s = np.insert(v_s, np.size(v_s), [0, 0]) + +# Additional arrays +u_s = P_s / (rho_s * (gas_gamma - 1.)) #internal energy +s_s = P_s / rho_s**gas_gamma # entropic function + + + +# Plot the interesting quantities +figure() + +# Velocity profile -------------------------------- +subplot(231) +plot(r, v_r, '.', color='r', ms=2.) +plot(r_s, v_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Radial~velocity}}~v_r$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-0.2, 3.8) + +# Density profile -------------------------------- +subplot(232) +plot(r, rho, '.', color='r', ms=2.) +plot(r_s, rho_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=2) +xlim(0, 1.3 * r_shock) +ylim(-0.2, 5.2) + +# Pressure profile -------------------------------- +subplot(233) +plot(r, P, '.', color='r', ms=2.) +plot(r_s, P_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-1, 12.5) + +# Internal energy profile ------------------------- +subplot(234) +plot(r, u, '.', color='r', ms=2.) +plot(r_s, u_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-2, 22) + +# Entropy profile --------------------------------- +subplot(235) +plot(r, S, '.', color='r', ms=2.) +plot(r_s, s_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-5, 50) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Sedov blast with $\\gamma=%.3f$ in 1D at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Background $\\rho_0=%.2f$"%(rho_0), fontsize=10) +text(-0.49, 0.7, "Energy injected $E_0=%.2f$"%(E_0), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + + +savefig("Sedov.png", dpi=200) + + + + diff --git a/examples/SedovBlast_1D/run.sh b/examples/SedovBlast_1D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..911b595a604cae2db72c6cab070189848e677010 --- /dev/null +++ b/examples/SedovBlast_1D/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + + # Generate the initial conditions if they are not present. +if [ ! -e sedov.hdf5 ] +then + echo "Generating initial conditions for the Sedov blast example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 sedov.yml + +# Plot the solution +python plotSolution.py 5 diff --git a/examples/SedovBlast/sedov.yml b/examples/SedovBlast_1D/sedov.yml similarity index 83% rename from examples/SedovBlast/sedov.yml rename to examples/SedovBlast_1D/sedov.yml index eb95fd85d5599145b2ff037256dcde72fc306209..6f519835d26ff5aa851ffb8999e650815c522cd3 100644 --- a/examples/SedovBlast/sedov.yml +++ b/examples/SedovBlast_1D/sedov.yml @@ -9,15 +9,15 @@ InternalUnitSystem: # Parameters governing the time integration TimeIntegration: time_begin: 0. # The starting time of the simulation (in internal units). - time_end: 1. # The end time of the simulation (in internal units). + time_end: 5e-2 # The end time of the simulation (in internal units). dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). - dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + dt_max: 1e-4 # The maximal time-step size of the simulation (in internal units). # Parameters governing the snapshots Snapshots: basename: sedov # Common part of the name of output files time_first: 0. # Time of the first output (in internal units) - delta_time: 0.1 # Time difference between consecutive outputs (in internal units) + delta_time: 1e-2 # Time difference between consecutive outputs (in internal units) # Parameters governing the conserved quantities statistics Statistics: @@ -27,7 +27,7 @@ Statistics: SPH: resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. - max_smoothing_length: 1. # Maximal smoothing length allowed (in internal units). + max_smoothing_length: 0.1 # Maximal smoothing length allowed (in internal units). CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. # Parameters related to the initial conditions diff --git a/examples/SedovBlast_2D/getGlass.sh b/examples/SedovBlast_2D/getGlass.sh new file mode 100755 index 0000000000000000000000000000000000000000..ae3c977064f5e7a408aa249c5fd9089b3c52ecb1 --- /dev/null +++ b/examples/SedovBlast_2D/getGlass.sh @@ -0,0 +1,2 @@ +#!/bin/bash +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassPlane_128.hdf5 diff --git a/examples/SedovBlast_2D/makeIC.py b/examples/SedovBlast_2D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..05233576f63f90b8d448aaa75fa6bfe7fce1f0e8 --- /dev/null +++ b/examples/SedovBlast_2D/makeIC.py @@ -0,0 +1,95 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the Sedov blast test in a periodic cubic box + +# Parameters +gamma = 5./3. # Gas adiabatic index +rho0 = 1. # Background density +P0 = 1.e-6 # Background pressure +E0= 1. # Energy of the explosion +N_inject = 21 # Number of particles in which to inject energy +fileName = "sedov.hdf5" + +#--------------------------------------------------- +glass = h5py.File("glassPlane_128.hdf5", "r") + +# Read particle positions and h from the glass +pos = glass["/PartType0/Coordinates"][:,:] +h = glass["/PartType0/SmoothingLength"][:] * 0.3 + +numPart = size(h) +vol = 1. + +# Generate extra arrays +v = zeros((numPart, 3)) +ids = linspace(1, numPart, numPart) +m = zeros(numPart) +u = zeros(numPart) +r = zeros(numPart) + +r = sqrt((pos[:,0] - 0.5)**2 + (pos[:,1] - 0.5)**2) +m[:] = rho0 * vol / numPart +u[:] = P0 / (rho0 * (gamma - 1)) + +# Make the central particle detonate +index = argsort(r) +u[index[0:N_inject]] = E0 / (N_inject * m[0]) + +#-------------------------------------------------- + +#File +file = h5py.File(fileName, 'w') + +# Header +grp = file.create_group("/Header") +grp.attrs["BoxSize"] = [1., 1., 1.0] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 + +#Runtime parameters +grp = file.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = file.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = file.create_group("/PartType0") +grp.create_dataset('Coordinates', data=pos, dtype='d') +grp.create_dataset('Velocities', data=v, dtype='f') +grp.create_dataset('Masses', data=m, dtype='f') +grp.create_dataset('SmoothingLength', data=h, dtype='f') +grp.create_dataset('InternalEnergy', data=u, dtype='f') +grp.create_dataset('ParticleIDs', data=ids, dtype='L') + +file.close() diff --git a/examples/SedovBlast_2D/plotSolution.py b/examples/SedovBlast_2D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..69e4e1232dd5c14b06e8a705f4add391f1f597f0 --- /dev/null +++ b/examples/SedovBlast_2D/plotSolution.py @@ -0,0 +1,280 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2015 Bert Vandenbroucke (bert.vandenbroucke@ugent.be) + # Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the 2D Sedov blast wave. +# The script works for a given initial box and dumped energy and computes the solution at a later time t. + +# Parameters +rho_0 = 1. # Background Density +P_0 = 1.e-6 # Background Pressure +E_0 = 1. # Energy of the explosion +gas_gamma = 5./3. # Gas polytropic index + + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + + +# Read the simulation data +sim = h5py.File("sedov_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +pos = sim["/PartType0/Coordinates"][:,:] +x = pos[:,0] - boxSize / 2 +y = pos[:,1] - boxSize / 2 +vel = sim["/PartType0/Velocities"][:,:] +r = sqrt(x**2 + y**2) +v_r = (x * vel[:,0] + y * vel[:,1]) / r +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +rho = sim["/PartType0/Density"][:] + + +# Now, work our the solution.... + +from scipy.special import gamma as Gamma +from numpy import * + +def calc_a(g,nu=3): + """ + exponents of the polynomials of the sedov solution + g - the polytropic gamma + nu - the dimension + """ + a = [0]*8 + + a[0] = 2.0 / (nu + 2) + a[2] = (1-g) / (2*(g-1) + nu) + a[3] = nu / (2*(g-1) + nu) + a[5] = 2 / (g-2) + a[6] = g / (2*(g-1) + nu) + + a[1] = (((nu+2)*g)/(2.0+nu*(g-1.0)) ) * ( (2.0*nu*(2.0-g))/(g*(nu+2.0)**2) - a[2]) + a[4] = a[1]*(nu+2) / (2-g) + a[7] = (2 + nu*(g-1))*a[1]/(nu*(2-g)) + return a + +def calc_beta(v, g, nu=3): + """ + beta values for the sedov solution (coefficients of the polynomials of the similarity variables) + v - the similarity variable + g - the polytropic gamma + nu- the dimension + """ + + beta = (nu+2) * (g+1) * array((0.25, (g/(g-1))*0.5, + -(2 + nu*(g-1))/2.0 / ((nu+2)*(g+1) -2*(2 + nu*(g-1))), + -0.5/(g-1)), dtype=float64) + + beta = outer(beta, v) + + beta += (g+1) * array((0.0, -1.0/(g-1), + (nu+2) / ((nu+2)*(g+1) -2.0*(2 + nu*(g-1))), + 1.0/(g-1)), dtype=float64).reshape((4,1)) + + return beta + + +def sedov(t, E0, rho0, g, n=1000, nu=3): + """ + solve the sedov problem + t - the time + E0 - the initial energy + rho0 - the initial density + n - number of points (10000) + nu - the dimension + g - the polytropic gas gamma + """ + # the similarity variable + v_min = 2.0 / ((nu + 2) * g) + v_max = 4.0 / ((nu + 2) * (g + 1)) + + v = v_min + arange(n) * (v_max - v_min) / (n - 1.0) + + a = calc_a(g, nu) + beta = calc_beta(v, g=g, nu=nu) + lbeta = log(beta) + + r = exp(-a[0] * lbeta[0] - a[2] * lbeta[1] - a[1] * lbeta[2]) + rho = ((g + 1.0) / (g - 1.0)) * exp(a[3] * lbeta[1] + a[5] * lbeta[3] + a[4] * lbeta[2]) + p = exp(nu * a[0] * lbeta[0] + (a[5] + 1) * lbeta[3] + (a[4] - 2 * a[1]) * lbeta[2]) + u = beta[0] * r * 4.0 / ((g + 1) * (nu + 2)) + p *= 8.0 / ((g + 1) * (nu + 2) * (nu + 2)) + + # we have to take extra care at v=v_min, since this can be a special point. + # It is not a singularity, however, the gradients of our variables (wrt v) are. + # r -> 0, u -> 0, rho -> 0, p-> constant + + u[0] = 0.0; rho[0] = 0.0; r[0] = 0.0; p[0] = p[1] + + # volume of an n-sphere + vol = (pi ** (nu / 2.0) / Gamma(nu / 2.0 + 1)) * power(r, nu) + + # note we choose to evaluate the integral in this way because the + # volumes of the first few elements (i.e near v=vmin) are shrinking + # very slowly, so we dramatically improve the error convergence by + # finding the volumes exactly. This is most important for the + # pressure integral, as this is on the order of the volume. + + # (dimensionless) energy of the model solution + de = rho * u * u * 0.5 + p / (g - 1) + # integrate (trapezium rule) + q = inner(de[1:] + de[:-1], diff(vol)) * 0.5 + + # the factor to convert to this particular problem + fac = (q * (t ** nu) * rho0 / E0) ** (-1.0 / (nu + 2)) + + # shock speed + shock_speed = fac * (2.0 / (nu + 2)) + rho_s = ((g + 1) / (g - 1)) * rho0 + r_s = shock_speed * t * (nu + 2) / 2.0 + p_s = (2.0 * rho0 * shock_speed * shock_speed) / (g + 1) + u_s = (2.0 * shock_speed) / (g + 1) + + r *= fac * t + u *= fac + p *= fac * fac * rho0 + rho *= rho0 + return r, p, rho, u, r_s, p_s, rho_s, u_s, shock_speed + + +# The main properties of the solution +r_s, P_s, rho_s, v_s, r_shock, _, _, _, _ = sedov(time, E_0, rho_0, gas_gamma, 1000, 2) + +# Append points for after the shock +r_s = np.insert(r_s, np.size(r_s), [r_shock, r_shock*1.5]) +rho_s = np.insert(rho_s, np.size(rho_s), [rho_0, rho_0]) +P_s = np.insert(P_s, np.size(P_s), [P_0, P_0]) +v_s = np.insert(v_s, np.size(v_s), [0, 0]) + +# Additional arrays +u_s = P_s / (rho_s * (gas_gamma - 1.)) #internal energy +s_s = P_s / rho_s**gas_gamma # entropic function + + + +# Plot the interesting quantities +figure() + +# Velocity profile -------------------------------- +subplot(231) +plot(r, v_r, '.', color='r', ms=1.) +plot(r_s, v_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Radial~velocity}}~v_r$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-0.2, 3.8) + +# Density profile -------------------------------- +subplot(232) +plot(r, rho, '.', color='r', ms=1.) +plot(r_s, rho_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=2) +xlim(0, 1.3 * r_shock) +ylim(-0.2, 5.2) + +# Pressure profile -------------------------------- +subplot(233) +plot(r, P, '.', color='r', ms=1.) +plot(r_s, P_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-1, 12.5) + +# Internal energy profile ------------------------- +subplot(234) +plot(r, u, '.', color='r', ms=1.) +plot(r_s, u_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-2, 22) + +# Entropy profile --------------------------------- +subplot(235) +plot(r, S, '.', color='r', ms=1.) +plot(r_s, s_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-5, 50) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Sedov blast with $\\gamma=%.3f$ in 2D at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Background $\\rho_0=%.2f$"%(rho_0), fontsize=10) +text(-0.49, 0.7, "Energy injected $E_0=%.2f$"%(E_0), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + + +savefig("Sedov.png", dpi=200) + + + + diff --git a/examples/SedovBlast_2D/run.sh b/examples/SedovBlast_2D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..b6f6f73db3ff281492d2abc21eb5ded67e528516 --- /dev/null +++ b/examples/SedovBlast_2D/run.sh @@ -0,0 +1,19 @@ +#!/bin/bash + + # Generate the initial conditions if they are not present. +if [ ! -e glassPlane_128.hdf5 ] +then + echo "Fetching initial glass file for the Sedov blast example..." + ./getGlass.sh +fi +if [ ! -e sedov.hdf5 ] +then + echo "Generating initial conditions for the Sedov blast example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 sedov.yml + +# Plot the solution +python plotSolution.py 5 diff --git a/examples/SedovBlast_2D/sedov.yml b/examples/SedovBlast_2D/sedov.yml new file mode 100644 index 0000000000000000000000000000000000000000..6f519835d26ff5aa851ffb8999e650815c522cd3 --- /dev/null +++ b/examples/SedovBlast_2D/sedov.yml @@ -0,0 +1,36 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 5e-2 # The end time of the simulation (in internal units). + dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-4 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: sedov # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-2 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-3 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.1 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./sedov.hdf5 # The file to read + diff --git a/examples/SedovBlast_3D/getGlass.sh b/examples/SedovBlast_3D/getGlass.sh new file mode 100755 index 0000000000000000000000000000000000000000..d5c5f590ac37c9c9431d626a2ea61b0c12c1513c --- /dev/null +++ b/examples/SedovBlast_3D/getGlass.sh @@ -0,0 +1,2 @@ +#!/bin/bash +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassCube_64.hdf5 diff --git a/examples/SedovBlast_3D/makeIC.py b/examples/SedovBlast_3D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..3c1e36a74b53ece8b886e2fcbe5d9178d9deefbc --- /dev/null +++ b/examples/SedovBlast_3D/makeIC.py @@ -0,0 +1,95 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the Sedov blast test in a periodic cubic box + +# Parameters +gamma = 5./3. # Gas adiabatic index +rho0 = 1. # Background density +P0 = 1.e-6 # Background pressure +E0= 1. # Energy of the explosion +N_inject = 15 # Number of particles in which to inject energy +fileName = "sedov.hdf5" + +#--------------------------------------------------- +glass = h5py.File("glassCube_64.hdf5", "r") + +# Read particle positions and h from the glass +pos = glass["/PartType0/Coordinates"][:,:] +h = glass["/PartType0/SmoothingLength"][:] * 0.3 + +numPart = size(h) +vol = 1. + +# Generate extra arrays +v = zeros((numPart, 3)) +ids = linspace(1, numPart, numPart) +m = zeros(numPart) +u = zeros(numPart) +r = zeros(numPart) + +r = sqrt((pos[:,0] - 0.5)**2 + (pos[:,1] - 0.5)**2 + (pos[:,2] - 0.5)**2) +m[:] = rho0 * vol / numPart +u[:] = P0 / (rho0 * (gamma - 1)) + +# Make the central particles detonate +index = argsort(r) +u[index[0:N_inject]] = E0 / (N_inject * m[0]) + +#-------------------------------------------------- + +#File +file = h5py.File(fileName, 'w') + +# Header +grp = file.create_group("/Header") +grp.attrs["BoxSize"] = [1., 1., 1.] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 + +#Runtime parameters +grp = file.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = file.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = file.create_group("/PartType0") +grp.create_dataset('Coordinates', data=pos, dtype='d') +grp.create_dataset('Velocities', data=v, dtype='f') +grp.create_dataset('Masses', data=m, dtype='f') +grp.create_dataset('SmoothingLength', data=h, dtype='f') +grp.create_dataset('InternalEnergy', data=u, dtype='f') +grp.create_dataset('ParticleIDs', data=ids, dtype='L') + +file.close() diff --git a/examples/SedovBlast_3D/plotSolution.py b/examples/SedovBlast_3D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..f86ce17206ae1d15ff846fb14c61bbb6926e03bf --- /dev/null +++ b/examples/SedovBlast_3D/plotSolution.py @@ -0,0 +1,281 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2015 Bert Vandenbroucke (bert.vandenbroucke@ugent.be) + # Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the 2D Sedov blast wave. +# The script works for a given initial box and dumped energy and computes the solution at a later time t. + +# Parameters +rho_0 = 1. # Background Density +P_0 = 1.e-6 # Background Pressure +E_0 = 1. # Energy of the explosion +gas_gamma = 5./3. # Gas polytropic index + + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + + +# Read the simulation data +sim = h5py.File("sedov_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +pos = sim["/PartType0/Coordinates"][:,:] +x = pos[:,0] - boxSize / 2 +y = pos[:,1] - boxSize / 2 +z = pos[:,2] - boxSize / 2 +vel = sim["/PartType0/Velocities"][:,:] +r = sqrt(x**2 + y**2 + z**2) +v_r = (x * vel[:,0] + y * vel[:,1] + z * vel[:,2]) / r +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +rho = sim["/PartType0/Density"][:] + + +# Now, work our the solution.... + +from scipy.special import gamma as Gamma +from numpy import * + +def calc_a(g,nu=3): + """ + exponents of the polynomials of the sedov solution + g - the polytropic gamma + nu - the dimension + """ + a = [0]*8 + + a[0] = 2.0 / (nu + 2) + a[2] = (1-g) / (2*(g-1) + nu) + a[3] = nu / (2*(g-1) + nu) + a[5] = 2 / (g-2) + a[6] = g / (2*(g-1) + nu) + + a[1] = (((nu+2)*g)/(2.0+nu*(g-1.0)) ) * ( (2.0*nu*(2.0-g))/(g*(nu+2.0)**2) - a[2]) + a[4] = a[1]*(nu+2) / (2-g) + a[7] = (2 + nu*(g-1))*a[1]/(nu*(2-g)) + return a + +def calc_beta(v, g, nu=3): + """ + beta values for the sedov solution (coefficients of the polynomials of the similarity variables) + v - the similarity variable + g - the polytropic gamma + nu- the dimension + """ + + beta = (nu+2) * (g+1) * array((0.25, (g/(g-1))*0.5, + -(2 + nu*(g-1))/2.0 / ((nu+2)*(g+1) -2*(2 + nu*(g-1))), + -0.5/(g-1)), dtype=float64) + + beta = outer(beta, v) + + beta += (g+1) * array((0.0, -1.0/(g-1), + (nu+2) / ((nu+2)*(g+1) -2.0*(2 + nu*(g-1))), + 1.0/(g-1)), dtype=float64).reshape((4,1)) + + return beta + + +def sedov(t, E0, rho0, g, n=1000, nu=3): + """ + solve the sedov problem + t - the time + E0 - the initial energy + rho0 - the initial density + n - number of points (10000) + nu - the dimension + g - the polytropic gas gamma + """ + # the similarity variable + v_min = 2.0 / ((nu + 2) * g) + v_max = 4.0 / ((nu + 2) * (g + 1)) + + v = v_min + arange(n) * (v_max - v_min) / (n - 1.0) + + a = calc_a(g, nu) + beta = calc_beta(v, g=g, nu=nu) + lbeta = log(beta) + + r = exp(-a[0] * lbeta[0] - a[2] * lbeta[1] - a[1] * lbeta[2]) + rho = ((g + 1.0) / (g - 1.0)) * exp(a[3] * lbeta[1] + a[5] * lbeta[3] + a[4] * lbeta[2]) + p = exp(nu * a[0] * lbeta[0] + (a[5] + 1) * lbeta[3] + (a[4] - 2 * a[1]) * lbeta[2]) + u = beta[0] * r * 4.0 / ((g + 1) * (nu + 2)) + p *= 8.0 / ((g + 1) * (nu + 2) * (nu + 2)) + + # we have to take extra care at v=v_min, since this can be a special point. + # It is not a singularity, however, the gradients of our variables (wrt v) are. + # r -> 0, u -> 0, rho -> 0, p-> constant + + u[0] = 0.0; rho[0] = 0.0; r[0] = 0.0; p[0] = p[1] + + # volume of an n-sphere + vol = (pi ** (nu / 2.0) / Gamma(nu / 2.0 + 1)) * power(r, nu) + + # note we choose to evaluate the integral in this way because the + # volumes of the first few elements (i.e near v=vmin) are shrinking + # very slowly, so we dramatically improve the error convergence by + # finding the volumes exactly. This is most important for the + # pressure integral, as this is on the order of the volume. + + # (dimensionless) energy of the model solution + de = rho * u * u * 0.5 + p / (g - 1) + # integrate (trapezium rule) + q = inner(de[1:] + de[:-1], diff(vol)) * 0.5 + + # the factor to convert to this particular problem + fac = (q * (t ** nu) * rho0 / E0) ** (-1.0 / (nu + 2)) + + # shock speed + shock_speed = fac * (2.0 / (nu + 2)) + rho_s = ((g + 1) / (g - 1)) * rho0 + r_s = shock_speed * t * (nu + 2) / 2.0 + p_s = (2.0 * rho0 * shock_speed * shock_speed) / (g + 1) + u_s = (2.0 * shock_speed) / (g + 1) + + r *= fac * t + u *= fac + p *= fac * fac * rho0 + rho *= rho0 + return r, p, rho, u, r_s, p_s, rho_s, u_s, shock_speed + + +# The main properties of the solution +r_s, P_s, rho_s, v_s, r_shock, _, _, _, _ = sedov(time, E_0, rho_0, gas_gamma, 1000, 3) + +# Append points for after the shock +r_s = np.insert(r_s, np.size(r_s), [r_shock, r_shock*1.5]) +rho_s = np.insert(rho_s, np.size(rho_s), [rho_0, rho_0]) +P_s = np.insert(P_s, np.size(P_s), [P_0, P_0]) +v_s = np.insert(v_s, np.size(v_s), [0, 0]) + +# Additional arrays +u_s = P_s / (rho_s * (gas_gamma - 1.)) #internal energy +s_s = P_s / rho_s**gas_gamma # entropic function + + + +# Plot the interesting quantities +figure() + +# Velocity profile -------------------------------- +subplot(231) +plot(r, v_r, '.', color='r', ms=1.) +plot(r_s, v_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Radial~velocity}}~v_r$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-0.2, 3.8) + +# Density profile -------------------------------- +subplot(232) +plot(r, rho, '.', color='r', ms=1.) +plot(r_s, rho_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=2) +xlim(0, 1.3 * r_shock) +ylim(-0.2, 5.2) + +# Pressure profile -------------------------------- +subplot(233) +plot(r, P, '.', color='r', ms=1.) +plot(r_s, P_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-1, 12.5) + +# Internal energy profile ------------------------- +subplot(234) +plot(r, u, '.', color='r', ms=1.) +plot(r_s, u_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-2, 22) + +# Entropy profile --------------------------------- +subplot(235) +plot(r, S, '.', color='r', ms=1.) +plot(r_s, s_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Radius}}~r$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(0, 1.3 * r_shock) +ylim(-5, 50) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Sedov blast with $\\gamma=%.3f$ in 2D at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Background $\\rho_0=%.2f$"%(rho_0), fontsize=10) +text(-0.49, 0.7, "Energy injected $E_0=%.2f$"%(E_0), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + + +savefig("Sedov.png", dpi=200) + + + + diff --git a/examples/SedovBlast_3D/run.sh b/examples/SedovBlast_3D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..afc9ff257eff334d700dbd139c7ffbf0225fbf7b --- /dev/null +++ b/examples/SedovBlast_3D/run.sh @@ -0,0 +1,19 @@ +#!/bin/bash + + # Generate the initial conditions if they are not present. +if [ ! -e glassCube_64.hdf5 ] +then + echo "Fetching initial glass file for the Sedov blast example..." + ./getGlass.sh +fi +if [ ! -e sedov.hdf5 ] +then + echo "Generating initial conditions for the Sedov blast example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 4 sedov.yml + +# Plot the solution +python plotSolution.py 5 diff --git a/examples/SedovBlast_3D/sedov.yml b/examples/SedovBlast_3D/sedov.yml new file mode 100644 index 0000000000000000000000000000000000000000..6f519835d26ff5aa851ffb8999e650815c522cd3 --- /dev/null +++ b/examples/SedovBlast_3D/sedov.yml @@ -0,0 +1,36 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 5e-2 # The end time of the simulation (in internal units). + dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-4 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: sedov # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-2 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-3 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.1 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./sedov.hdf5 # The file to read + diff --git a/examples/SodShock/glass_001.hdf5 b/examples/SodShock/glass_001.hdf5 deleted file mode 100644 index a371826c2ef4c1d53ad5f50a6bc7eb590017220e..0000000000000000000000000000000000000000 Binary files a/examples/SodShock/glass_001.hdf5 and /dev/null differ diff --git a/examples/SodShock/glass_002.hdf5 b/examples/SodShock/glass_002.hdf5 deleted file mode 100644 index dffb8d343157a9ae8318e9572fc752eecd8955fb..0000000000000000000000000000000000000000 Binary files a/examples/SodShock/glass_002.hdf5 and /dev/null differ diff --git a/examples/SodShock/makeIC.py b/examples/SodShock/makeIC.py deleted file mode 100644 index 8ae19050c11c0712579b44646c8870d7574d113b..0000000000000000000000000000000000000000 --- a/examples/SodShock/makeIC.py +++ /dev/null @@ -1,135 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -from numpy import * - -# Generates a swift IC file for the Sod Shock in a periodic box - -# Parameters -periodic= 1 # 1 For periodic box -factor = 8 -boxSize = [ 1.0 , 1.0/factor , 1.0/factor ] -L = 100 # Number of particles along one axis -P1 = 1. # Pressure left state -P2 = 0.1795 # Pressure right state -gamma = 5./3. # Gas adiabatic index -fileName = "sodShock.hdf5" -vol = boxSize[0] * boxSize[1] * boxSize[2] - - -#--------------------------------------------------- - -#Read in high density glass -# glass1 = h5py.File("../Glass/glass_200000.hdf5") -glass1 = h5py.File("glass_001.hdf5") -pos1 = glass1["/PartType0/Coordinates"][:,:] -pos1 = pos1 / factor # Particles are in [0:0.25, 0:0.25, 0:0.25] -glass_h1 = glass1["/PartType0/SmoothingLength"][:] / factor - -#Read in high density glass -# glass2 = h5py.File("../Glass/glass_50000.hdf5") -glass2 = h5py.File("glass_002.hdf5") -pos2 = glass2["/PartType0/Coordinates"][:,:] -pos2 = pos2 / factor # Particles are in [0:0.25, 0:0.25, 0:0.25] -glass_h2 = glass2["/PartType0/SmoothingLength"][:] / factor - -#Generate high density region -rho1 = 1. -coord1 = append(pos1, pos1 + [0.125, 0, 0], 0) -coord1 = append(coord1, coord1 + [0.25, 0, 0], 0) -# coord1 = append(pos1, pos1 + [0, 0.5, 0], 0) -# coord1 = append(coord1, pos1 + [0, 0, 0.5], 0) -# coord1 = append(coord1, pos1 + [0, 0.5, 0.5], 0) -N1 = size(coord1)/3 -v1 = zeros((N1, 3)) -u1 = ones(N1) * P1 / ((gamma - 1.) * rho1) -m1 = ones(N1) * vol * 0.5 * rho1 / N1 -h1 = append(glass_h1, glass_h1, 0) -h1 = append(h1, h1, 0) - -#Generate low density region -rho2 = 0.25 -coord2 = append(pos2, pos2 + [0.125, 0, 0], 0) -coord2 = append(coord2, coord2 + [0.25, 0, 0], 0) -# coord2 = append(pos2, pos2 + [0, 0.5, 0], 0) -# coord2 = append(coord2, pos2 + [0, 0, 0.5], 0) -# coord2 = append(coord2, pos2 + [0, 0.5, 0.5], 0) -N2 = size(coord2)/3 -v2 = zeros((N2, 3)) -u2 = ones(N2) * P2 / ((gamma - 1.) * rho2) -m2 = ones(N2) * vol * 0.5 * rho2 / N2 -h2 = append(glass_h2, glass_h2, 0) -h2 = append(h2, h2, 0) - -#Merge arrays -numPart = N1 + N2 -coords = append(coord1, coord2+[0.5, 0., 0.], 0) -v = append(v1, v2,0) -h = append(h1, h2,0) -u = append(u1, u2,0) -m = append(m1, m2,0) -ids = zeros(numPart, dtype='L') -for i in range(1, numPart+1): - ids[i-1] = i - -#Final operation since we come from Gadget-2 cubic spline ICs -h /= 1.825752 - -#File -file = h5py.File(fileName, 'w') - -# Header -grp = file.create_group("/Header") -grp.attrs["BoxSize"] = boxSize -grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] -grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] -grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 - -#Runtime parameters -grp = file.create_group("/RuntimePars") -grp.attrs["PeriodicBoundariesOn"] = periodic - -#Units -grp = file.create_group("/Units") -grp.attrs["Unit length in cgs (U_L)"] = 1. -grp.attrs["Unit mass in cgs (U_M)"] = 1. -grp.attrs["Unit time in cgs (U_t)"] = 1. -grp.attrs["Unit current in cgs (U_I)"] = 1. -grp.attrs["Unit temperature in cgs (U_T)"] = 1. - -#Particle group -grp = file.create_group("/PartType0") -grp.create_dataset('Coordinates', data=coords, dtype='d') -grp.create_dataset('Velocities', data=v, dtype='f') -grp.create_dataset('Masses', data=m, dtype='f') -grp.create_dataset('SmoothingLength', data=h, dtype='f') -grp.create_dataset('InternalEnergy', data=u, dtype='f') -grp.create_dataset('ParticleIDs', data=ids, dtype='L') - - -file.close() - - diff --git a/examples/SodShock/rhox.py b/examples/SodShock/rhox.py deleted file mode 100644 index 70493be3728cdeb27409a79f616fa3ec5bb9cdfd..0000000000000000000000000000000000000000 --- a/examples/SodShock/rhox.py +++ /dev/null @@ -1,115 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -import sys -import math -from numpy import * - -# Reads the HDF5 output of SWIFT and generates a radial density profile -# of the different physical values. - -# Input values? -if len(sys.argv) < 3 : - print "Usage: " , sys.argv[0] , " <filename> <nr. bins>" - exit() - -# Get the input arguments -fileName = sys.argv[1]; -nr_bins = int( sys.argv[2] ); - - -# Open the file -fileName = sys.argv[1]; -file = h5py.File( fileName , 'r' ) - -# Get the space dimensions. -grp = file[ "/Header" ] -boxsize = grp.attrs[ 'BoxSize' ] -boxsize = boxsize[0] - -# Get the particle data -grp = file.get( '/PartType0' ) -ds = grp.get( 'Coordinates' ) -coords = ds[...] -ds = grp.get( 'Velocities' ) -v = ds[...] -# ds = grp.get( 'Mass' ) -# m = ds[...] -ds = grp.get( 'SmoothingLength' ) -h = ds[...] -ds = grp.get( 'InternalEnergy' ) -u = ds[...] -ds = grp.get( 'ParticleIDs' ) -ids = ds[...] -ds = grp.get( 'Density' ) -rho = ds[...] - -# Get the maximum radius -r_max = boxsize - -# Init the bins -nr_parts = coords.shape[0] -bins_v = zeros( nr_bins ) -bins_m = zeros( nr_bins ) -bins_h = zeros( nr_bins ) -bins_u = zeros( nr_bins ) -bins_rho = zeros( nr_bins ) -bins_count = zeros( nr_bins ) -bins_P = zeros( nr_bins ) - -# Loop over the particles and fill the bins. -for i in range( nr_parts ): - - # Get the box index. - r = coords[i,0] - ind = floor( r / r_max * nr_bins ) - - # Update the bins - bins_count[ind] += 1 - bins_v[ind] += v[i,0] # sqrt( v[i,0]*v[i,0] + v[i,1]*v[i,1] + v[i,2]*v[i,2] ) - # bins_m[ind] += m[i] - bins_h[ind] += h[i] - bins_u[ind] += u[i] - bins_rho[ind] += rho[i] - bins_P[ind] += (2.0/3)*u[i]*rho[i] - -# Loop over the bins and dump them -print "# bucket left right count v m h u rho" -for i in range( nr_bins ): - - # Normalize by the bin volume. - r_left = r_max * i / nr_bins - r_right = r_max * (i+1) / nr_bins - vol = 4/3*math.pi*(r_right*r_right*r_right - r_left*r_left*r_left) - ivol = 1.0 / vol - - print "%i %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e" % \ - ( i , r_left , r_right , \ - bins_count[i] * ivol , \ - bins_v[i] / bins_count[i] , \ - bins_m[i] * ivol , \ - bins_h[i] / bins_count[i] , \ - bins_u[i] / bins_count[i] , \ - bins_rho[i] / bins_count[i] , - bins_P[i] / bins_count[i] ) - - diff --git a/examples/SodShock/run.sh b/examples/SodShock/run.sh deleted file mode 100755 index b8141e51543f348d6ec6be505d136aed7d803b2e..0000000000000000000000000000000000000000 --- a/examples/SodShock/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Generate the initial conditions if they are not present. -if [ ! -e sodShock.hdf5 ] -then - echo "Generating initial conditions for the SodShock example..." - python makeIC.py -fi - -../swift -s -t 16 sodShock.yml diff --git a/examples/SodShock/solution.py b/examples/SodShock/solution.py deleted file mode 100644 index 39f25c625232eee9bae0300339955f775f3b46ed..0000000000000000000000000000000000000000 --- a/examples/SodShock/solution.py +++ /dev/null @@ -1,186 +0,0 @@ -############################################################################### - # This file is part of SWIFT. - # Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - # Matthieu Schaller (matthieu.schaller@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 random -from numpy import * - -# Generates the analytical solution for the Sod shock test case -# The script works for a given left (x<0) and right (x>0) state and computes the solution at a later time t. -# The code writes five files rho.dat, P.dat, v.dat, u.dat and s.dat with the density, pressure, internal energy and -# entropic function on N points between x_min and x_max. -# This follows the solution given in (Toro, 2009) - - -# Parameters -rho_L = 1 -P_L = 1 -v_L = 0. - -rho_R = 0.25 -P_R = 0.1795 -v_R = 0. - -gamma = 5./3. # Polytropic index - -t = 0.12 # Time of the evolution - -N = 1000 # Number of points -x_min = -0.25 -x_max = 0.25 - - -# --------------------------------------------------------------- -# Don't touch anything after this. -# --------------------------------------------------------------- - -c_L = sqrt(gamma * P_L / rho_L) # Speed of the rarefaction wave -c_R = sqrt(gamma * P_R / rho_R) # Speed of the shock front - -# Helpful variable -Gama = (gamma - 1.) / (gamma + 1.) -beta = (gamma - 1.) / (2. * gamma) - -# Characteristic function and its derivative, following Toro (2009) -def compute_f(P_3, P, c): - u = P_3 / P - if u > 1: - term1 = gamma*((gamma+1.)*u + gamma-1.) - term2 = sqrt(2./term1) - fp = (u - 1.)*c*term2 - dfdp = c*term2/P + (u - 1.)*c/term2*(-1./term1**2)*gamma*(gamma+1.)/P - else: - fp = (u**beta - 1.)*(2.*c/(gamma-1.)) - dfdp = 2.*c/(gamma-1.)*beta*u**(beta-1.)/P - return (fp, dfdp) - -# Solution of the Riemann problem following Toro (2009) -def RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R): - P_new = ((c_L + c_R + (v_L - v_R)*0.5*(gamma-1.))/(c_L / P_L**beta + c_R / P_R**beta))**(1./beta) - P_3 = 0.5*(P_R + P_L) - f_L = 1. - while fabs(P_3 - P_new) > 1e-6: - P_3 = P_new - (f_L, dfdp_L) = compute_f(P_3, P_L, c_L) - (f_R, dfdp_R) = compute_f(P_3, P_R, c_R) - f = f_L + f_R + (v_R - v_L) - df = dfdp_L + dfdp_R - dp = -f/df - prnew = P_3 + dp - v_3 = v_L - f_L - return (P_new, v_3) - - -# Solve Riemann problem for post-shock region -(P_3, v_3) = RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R) - -# Check direction of shocks and wave -shock_R = (P_3 > P_R) -shock_L = (P_3 > P_L) - -# Velocity of shock front and and rarefaction wave -if shock_R: - v_right = v_R + c_R**2*(P_3/P_R - 1.)/(gamma*(v_3-v_R)) -else: - v_right = c_R + 0.5*(gamma+1.)*v_3 - 0.5*(gamma-1.)*v_R - -if shock_L: - v_left = v_L + c_L**2*(P_3/p_L - 1.)/(gamma*(v_3-v_L)) -else: - v_left = c_L - 0.5*(gamma+1.)*v_3 + 0.5*(gamma-1.)*v_L - -# Compute position of the transitions -x_23 = -fabs(v_left) * t -if shock_L : - x_12 = -fabs(v_left) * t -else: - x_12 = -(c_L - v_L) * t - -x_34 = v_3 * t - -x_45 = fabs(v_right) * t -if shock_R: - x_56 = fabs(v_right) * t -else: - x_56 = (c_R + v_R) * t - - -# Prepare arrays -delta_x = (x_max - x_min) / N -x_s = arange(x_min, x_max, delta_x) -rho_s = zeros(N) -P_s = zeros(N) -v_s = zeros(N) - -# Compute solution in the different regions -for i in range(N): - if x_s[i] <= x_12: - rho_s[i] = rho_L - P_s[i] = P_L - v_s[i] = v_L - if x_s[i] >= x_12 and x_s[i] < x_23: - if shock_L: - rho_s[i] = rho_L*(Gama + P_3/P_L)/(1. + Gama * P_3/P_L) - P_s[i] = P_3 - v_s[i] = v_3 - else: - rho_s[i] = rho_L*(Gama * (0. - x_s[i])/(c_L * t) + Gama * v_L/c_L + (1.-Gama))**(2./(gamma-1.)) - P_s[i] = P_L*(rho_s[i] / rho_L)**gamma - v_s[i] = (1.-Gama)*(c_L -(0. - x_s[i]) / t) + Gama*v_L - if x_s[i] >= x_23 and x_s[i] < x_34: - if shock_L: - rho_s[i] = rho_L*(Gama + P_3/P_L)/(1+Gama * P_3/p_L) - else: - rho_s[i] = rho_L*(P_3 / P_L)**(1./gamma) - P_s[i] = P_3 - v_s[i] = v_3 - if x_s[i] >= x_34 and x_s[i] < x_45: - if shock_R: - rho_s[i] = rho_R*(Gama + P_3/P_R)/(1. + Gama * P_3/P_R) - else: - rho_s[i] = rho_R*(P_3 / P_R)**(1./gamma) - P_s[i] = P_3 - v_s[i] = v_3 - if x_s[i] >= x_45 and x_s[i] < x_56: - if shock_R: - rho_s[i] = rho_R - P_s[i] = P_R - v_s[i] = v_R - else: - rho_s[i] = rho_R*(Gama*(x_s[i])/(c_R*t) - Gama*v_R/c_R + (1.-Gama))**(2./(gamma-1.)) - P_s[i] = p_R*(rho_s[i]/rho_R)**gamma - v_s[i] = (1.-Gama)*(-c_R - (-x_s[i])/t) + Gama*v_R - if x_s[i] >= x_56: - rho_s[i] = rho_R - P_s[i] = P_R - v_s[i] = v_R - - -# Additional arrays -u_s = P_s / (rho_s * (gamma - 1.)) #internal energy -s_s = P_s / rho_s**gamma # entropic function - -#--------------------------------------------------------------- -# Print arrays - -savetxt("rho.dat", column_stack((x_s, rho_s))) -savetxt("P.dat", column_stack((x_s, P_s))) -savetxt("v.dat", column_stack((x_s, v_s))) -savetxt("u.dat", column_stack((x_s, u_s))) -savetxt("s.dat", column_stack((x_s, s_s))) diff --git a/examples/SodShock_1D/makeIC.py b/examples/SodShock_1D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..e024188e867c1f2636187c2c53157c214752d6f7 --- /dev/null +++ b/examples/SodShock_1D/makeIC.py @@ -0,0 +1,118 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the 1D Sod Shock in a periodic box + +# Parameters +gamma = 5./3. # Gas adiabatic index +numPart_L = 800 # Number of particles in the left state +x_min = -1. +x_max = 1. +rho_L = 1. # Density left state +rho_R = 0.125 # Density right state +v_L = 0. # Velocity left state +v_R = 0. # Velocity right state +P_L = 1. # Pressure left state +P_R = 0.1 # Pressure right state +fileName = "sodShock.hdf5" + + +#--------------------------------------------------- + +# Find how many particles we actually have +boxSize = x_max - x_min +numPart_R = int(numPart_L * (rho_R / rho_L)) +numPart = numPart_L + numPart_R + +# Now get the distances +delta_L = (boxSize/2) / numPart_L +delta_R = (boxSize/2) / numPart_R +offset_L = delta_L / 2 +offset_R = delta_R / 2 + +# Build the arrays +coords = zeros((numPart, 3)) +v = zeros((numPart, 3)) +ids = linspace(1, numPart, numPart) +m = zeros(numPart) +h = zeros(numPart) +u = zeros(numPart) + +# Set the particles on the left +for i in range(numPart_L): + coords[i,0] = x_min + offset_L + i * delta_L + u[i] = P_L / (rho_L * (gamma - 1.)) + h[i] = 1.2348 * delta_L + m[i] = boxSize * rho_L / (2. * numPart_L) + v[i,0] = v_L + +# Set the particles on the right +for j in range(numPart_R): + i = numPart_L + j + coords[i,0] = offset_R + j * delta_R + u[i] = P_R / (rho_R * (gamma - 1.)) + h[i] = 1.2348 * delta_R + m[i] = boxSize * rho_R / (2. * numPart_R) + v[i,0] = v_R + +# Shift particles +coords[:,0] -= x_min + +#File +file = h5py.File(fileName, 'w') + +# Header +grp = file.create_group("/Header") +grp.attrs["BoxSize"] = boxSize +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 + +#Runtime parameters +grp = file.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = file.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = file.create_group("/PartType0") +grp.create_dataset('Coordinates', data=coords, dtype='d') +grp.create_dataset('Velocities', data=v, dtype='f') +grp.create_dataset('Masses', data=m, dtype='f') +grp.create_dataset('SmoothingLength', data=h, dtype='f') +grp.create_dataset('InternalEnergy', data=u, dtype='f') +grp.create_dataset('ParticleIDs', data=ids, dtype='L') + + +file.close() + + diff --git a/examples/SodShock_1D/plotSolution.py b/examples/SodShock_1D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..0a7720f4a6cf26e5a8acda1101bd438850d8d553 --- /dev/null +++ b/examples/SodShock_1D/plotSolution.py @@ -0,0 +1,288 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the Sod shock and plots the SPH answer + + +# Generates the analytical solution for the Sod shock test case +# The script works for a given left (x<0) and right (x>0) state and computes the solution at a later time t. +# This follows the solution given in (Toro, 2009) + + +# Parameters +gas_gamma = 5./3. # Polytropic index +rho_L = 1. # Density left state +rho_R = 0.125 # Density right state +v_L = 0. # Velocity left state +v_R = 0. # Velocity right state +P_L = 1. # Pressure left state +P_R = 0.1 # Pressure right state + + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + + +# Read the simulation data +sim = h5py.File("sodShock_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +x = sim["/PartType0/Coordinates"][:,0] +v = sim["/PartType0/Velocities"][:,0] +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +rho = sim["/PartType0/Density"][:] + +N = 1000 # Number of points +x_min = -1. +x_max = 1. + +x += x_min + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +c_L = sqrt(gas_gamma * P_L / rho_L) # Speed of the rarefaction wave +c_R = sqrt(gas_gamma * P_R / rho_R) # Speed of the shock front + +# Helpful variable +Gama = (gas_gamma - 1.) / (gas_gamma + 1.) +beta = (gas_gamma - 1.) / (2. * gas_gamma) + +# Characteristic function and its derivative, following Toro (2009) +def compute_f(P_3, P, c): + u = P_3 / P + if u > 1: + term1 = gas_gamma*((gas_gamma+1.)*u + gas_gamma-1.) + term2 = sqrt(2./term1) + fp = (u - 1.)*c*term2 + dfdp = c*term2/P + (u - 1.)*c/term2*(-1./term1**2)*gas_gamma*(gas_gamma+1.)/P + else: + fp = (u**beta - 1.)*(2.*c/(gas_gamma-1.)) + dfdp = 2.*c/(gas_gamma-1.)*beta*u**(beta-1.)/P + return (fp, dfdp) + +# Solution of the Riemann problem following Toro (2009) +def RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R): + P_new = ((c_L + c_R + (v_L - v_R)*0.5*(gas_gamma-1.))/(c_L / P_L**beta + c_R / P_R**beta))**(1./beta) + P_3 = 0.5*(P_R + P_L) + f_L = 1. + while fabs(P_3 - P_new) > 1e-6: + P_3 = P_new + (f_L, dfdp_L) = compute_f(P_3, P_L, c_L) + (f_R, dfdp_R) = compute_f(P_3, P_R, c_R) + f = f_L + f_R + (v_R - v_L) + df = dfdp_L + dfdp_R + dp = -f/df + prnew = P_3 + dp + v_3 = v_L - f_L + return (P_new, v_3) + + +# Solve Riemann problem for post-shock region +(P_3, v_3) = RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R) + +# Check direction of shocks and wave +shock_R = (P_3 > P_R) +shock_L = (P_3 > P_L) + +# Velocity of shock front and and rarefaction wave +if shock_R: + v_right = v_R + c_R**2*(P_3/P_R - 1.)/(gas_gamma*(v_3-v_R)) +else: + v_right = c_R + 0.5*(gas_gamma+1.)*v_3 - 0.5*(gas_gamma-1.)*v_R + +if shock_L: + v_left = v_L + c_L**2*(P_3/p_L - 1.)/(gas_gamma*(v_3-v_L)) +else: + v_left = c_L - 0.5*(gas_gamma+1.)*v_3 + 0.5*(gas_gamma-1.)*v_L + +# Compute position of the transitions +x_23 = -fabs(v_left) * time +if shock_L : + x_12 = -fabs(v_left) * time +else: + x_12 = -(c_L - v_L) * time + +x_34 = v_3 * time + +x_45 = fabs(v_right) * time +if shock_R: + x_56 = fabs(v_right) * time +else: + x_56 = (c_R + v_R) * time + + +# Prepare arrays +delta_x = (x_max - x_min) / N +x_s = arange(x_min, x_max, delta_x) +rho_s = zeros(N) +P_s = zeros(N) +v_s = zeros(N) + +# Compute solution in the different regions +for i in range(N): + if x_s[i] <= x_12: + rho_s[i] = rho_L + P_s[i] = P_L + v_s[i] = v_L + if x_s[i] >= x_12 and x_s[i] < x_23: + if shock_L: + rho_s[i] = rho_L*(Gama + P_3/P_L)/(1. + Gama * P_3/P_L) + P_s[i] = P_3 + v_s[i] = v_3 + else: + rho_s[i] = rho_L*(Gama * (0. - x_s[i])/(c_L * time) + Gama * v_L/c_L + (1.-Gama))**(2./(gas_gamma-1.)) + P_s[i] = P_L*(rho_s[i] / rho_L)**gas_gamma + v_s[i] = (1.-Gama)*(c_L -(0. - x_s[i]) / time) + Gama*v_L + if x_s[i] >= x_23 and x_s[i] < x_34: + if shock_L: + rho_s[i] = rho_L*(Gama + P_3/P_L)/(1+Gama * P_3/p_L) + else: + rho_s[i] = rho_L*(P_3 / P_L)**(1./gas_gamma) + P_s[i] = P_3 + v_s[i] = v_3 + if x_s[i] >= x_34 and x_s[i] < x_45: + if shock_R: + rho_s[i] = rho_R*(Gama + P_3/P_R)/(1. + Gama * P_3/P_R) + else: + rho_s[i] = rho_R*(P_3 / P_R)**(1./gas_gamma) + P_s[i] = P_3 + v_s[i] = v_3 + if x_s[i] >= x_45 and x_s[i] < x_56: + if shock_R: + rho_s[i] = rho_R + P_s[i] = P_R + v_s[i] = v_R + else: + rho_s[i] = rho_R*(Gama*(x_s[i])/(c_R*time) - Gama*v_R/c_R + (1.-Gama))**(2./(gas_gamma-1.)) + P_s[i] = p_R*(rho_s[i]/rho_R)**gas_gamma + v_s[i] = (1.-Gama)*(-c_R - (-x_s[i])/time) + Gama*v_R + if x_s[i] >= x_56: + rho_s[i] = rho_R + P_s[i] = P_R + v_s[i] = v_R + + +# Additional arrays +u_s = P_s / (rho_s * (gas_gamma - 1.)) #internal energy +s_s = P_s / rho_s**gas_gamma # entropic function + + +# Plot the interesting quantities +figure() + +# Velocity profile -------------------------------- +subplot(231) +plot(x, v, '.', color='r', ms=4.0) +plot(x_s, v_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Velocity}}~v_x$", labelpad=0) +xlim(-0.5, 0.5) +ylim(-0.1, 0.95) + +# Density profile -------------------------------- +subplot(232) +plot(x, rho, '.', color='r', ms=4.0) +plot(x_s, rho_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.05, 1.1) + +# Pressure profile -------------------------------- +subplot(233) +plot(x, P, '.', color='r', ms=4.0) +plot(x_s, P_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.01, 1.1) + +# Internal energy profile ------------------------- +subplot(234) +plot(x, u, '.', color='r', ms=4.0) +plot(x_s, u_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.8, 2.2) + +# Entropy profile --------------------------------- +subplot(235) +plot(x, S, '.', color='r', ms=4.0) +plot(x_s, s_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.8, 3.8) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Sod shock with $\\gamma=%.3f$ in 1D at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Left:~~ $(P_L, \\rho_L, v_L) = (%.3f, %.3f, %.3f)$"%(P_L, rho_L, v_L), fontsize=10) +text(-0.49, 0.7, "Right: $(P_R, \\rho_R, v_R) = (%.3f, %.3f, %.3f)$"%(P_R, rho_R, v_R), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + + +savefig("SodShock.png", dpi=200) diff --git a/examples/SodShock_1D/run.sh b/examples/SodShock_1D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..e3ac218c56caa81d0e7a6817e03a8db20bb575d5 --- /dev/null +++ b/examples/SodShock_1D/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Generate the initial conditions if they are not present. +if [ ! -e sodShock.hdf5 ] +then + echo "Generating initial conditions for the 1D SodShock example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 sodShock.yml + +# Plot the result +python plotSolution.py 1 diff --git a/examples/SodShock/sodShock.yml b/examples/SodShock_1D/sodShock.yml similarity index 77% rename from examples/SodShock/sodShock.yml rename to examples/SodShock_1D/sodShock.yml index 19bacb57f3bfb173063dbac5d752929763dede29..d5c4d0b034ff5351222d2162e37e3e40ceab834f 100644 --- a/examples/SodShock/sodShock.yml +++ b/examples/SodShock_1D/sodShock.yml @@ -9,15 +9,15 @@ InternalUnitSystem: # Parameters governing the time integration TimeIntegration: time_begin: 0. # The starting time of the simulation (in internal units). - time_end: 1. # The end time of the simulation (in internal units). + time_end: 0.2 # The end time of the simulation (in internal units). dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). # Parameters governing the snapshots Snapshots: - basename: sod # Common part of the name of output files - time_first: 0. # Time of the first output (in internal units) - delta_time: 0.1 # Time difference between consecutive outputs (in internal units) + basename: sodShock # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 0.2 # Time difference between consecutive outputs (in internal units) # Parameters governing the conserved quantities statistics Statistics: @@ -27,7 +27,7 @@ Statistics: SPH: resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. - max_smoothing_length: 0.01 # Maximal smoothing length allowed (in internal units). + max_smoothing_length: 0.4 # Maximal smoothing length allowed (in internal units). CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. # Parameters related to the initial conditions diff --git a/examples/SodShock_2D/getGlass.sh b/examples/SodShock_2D/getGlass.sh new file mode 100755 index 0000000000000000000000000000000000000000..f4cb4ebcb4b452b2b123462bc97eed532f43ba25 --- /dev/null +++ b/examples/SodShock_2D/getGlass.sh @@ -0,0 +1,3 @@ +#!/bin/bash +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassPlane_128.hdf5 +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassPlane_48.hdf5 diff --git a/examples/SodShock_2D/makeIC.py b/examples/SodShock_2D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..ac2b9ab45fb68921bce7971c46048b344955140d --- /dev/null +++ b/examples/SodShock_2D/makeIC.py @@ -0,0 +1,122 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the 2D Sod Shock in a periodic box + +# Parameters +gamma = 5./3. # Gas adiabatic index +x_min = -1. +x_max = 1. +rho_L = 1. # Density left state +rho_R = 0.140625 # Density right state +v_L = 0. # Velocity left state +v_R = 0. # Velocity right state +P_L = 1. # Pressure left state +P_R = 0.1 # Pressure right state +fileName = "sodShock.hdf5" + + +#--------------------------------------------------- +boxSize = (x_max - x_min) + +glass_L = h5py.File("glassPlane_128.hdf5", "r") +glass_R = h5py.File("glassPlane_48.hdf5", "r") + +pos_L = glass_L["/PartType0/Coordinates"][:,:] * 0.5 +pos_R = glass_R["/PartType0/Coordinates"][:,:] * 0.5 +h_L = glass_L["/PartType0/SmoothingLength"][:] * 0.5 +h_R = glass_R["/PartType0/SmoothingLength"][:] * 0.5 + +# Merge things +aa = pos_L - array([0.5, 0., 0.]) +pos_LL = append(pos_L, pos_L + array([0.5, 0., 0.]), axis=0) +pos_RR = append(pos_R, pos_R + array([0.5, 0., 0.]), axis=0) +pos = append(pos_LL - array([1.0, 0., 0.]), pos_RR, axis=0) +h_LL = append(h_L, h_L) +h_RR = append(h_R, h_R) +h = append(h_LL, h_RR) + +numPart_L = size(h_LL) +numPart_R = size(h_RR) +numPart = size(h) + +vol_L = 0.5 +vol_R = 0.5 + +# Generate extra arrays +v = zeros((numPart, 3)) +ids = linspace(1, numPart, numPart) +m = zeros(numPart) +u = zeros(numPart) + +for i in range(numPart): + x = pos[i,0] + + if x < 0: #left + u[i] = P_L / (rho_L * (gamma - 1.)) + m[i] = rho_L * vol_L / numPart_L + v[i,0] = v_L + else: #right + u[i] = P_R / (rho_R * (gamma - 1.)) + m[i] = rho_R * vol_R / numPart_R + v[i,0] = v_R + +# Shift particles +pos[:,0] -= x_min + +#File +file = h5py.File(fileName, 'w') + +# Header +grp = file.create_group("/Header") +grp.attrs["BoxSize"] = [boxSize, 0.5, 0.1] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 + +#Runtime parameters +grp = file.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = file.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = file.create_group("/PartType0") +grp.create_dataset('Coordinates', data=pos, dtype='d') +grp.create_dataset('Velocities', data=v, dtype='f') +grp.create_dataset('Masses', data=m, dtype='f') +grp.create_dataset('SmoothingLength', data=h, dtype='f') +grp.create_dataset('InternalEnergy', data=u, dtype='f') +grp.create_dataset('ParticleIDs', data=ids, dtype='L') + + +file.close() diff --git a/examples/SodShock_2D/plotSolution.py b/examples/SodShock_2D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..99ba7e9a6e9ae4b6d50688a1428f07e9a08b3b85 --- /dev/null +++ b/examples/SodShock_2D/plotSolution.py @@ -0,0 +1,288 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the Sod shock and plots the SPH answer + + +# Generates the analytical solution for the Sod shock test case +# The script works for a given left (x<0) and right (x>0) state and computes the solution at a later time t. +# This follows the solution given in (Toro, 2009) + + +# Parameters +gas_gamma = 5./3. # Polytropic index +rho_L = 1. # Density left state +rho_R = 0.140625 # Density right state +v_L = 0. # Velocity left state +v_R = 0. # Velocity right state +P_L = 1. # Pressure left state +P_R = 0.1 # Pressure right state + + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + + +# Read the simulation data +sim = h5py.File("sodShock_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +x = sim["/PartType0/Coordinates"][:,0] +v = sim["/PartType0/Velocities"][:,0] +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +rho = sim["/PartType0/Density"][:] + +N = 1000 # Number of points +x_min = -1. +x_max = 1. + +x += x_min + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +c_L = sqrt(gas_gamma * P_L / rho_L) # Speed of the rarefaction wave +c_R = sqrt(gas_gamma * P_R / rho_R) # Speed of the shock front + +# Helpful variable +Gama = (gas_gamma - 1.) / (gas_gamma + 1.) +beta = (gas_gamma - 1.) / (2. * gas_gamma) + +# Characteristic function and its derivative, following Toro (2009) +def compute_f(P_3, P, c): + u = P_3 / P + if u > 1: + term1 = gas_gamma*((gas_gamma+1.)*u + gas_gamma-1.) + term2 = sqrt(2./term1) + fp = (u - 1.)*c*term2 + dfdp = c*term2/P + (u - 1.)*c/term2*(-1./term1**2)*gas_gamma*(gas_gamma+1.)/P + else: + fp = (u**beta - 1.)*(2.*c/(gas_gamma-1.)) + dfdp = 2.*c/(gas_gamma-1.)*beta*u**(beta-1.)/P + return (fp, dfdp) + +# Solution of the Riemann problem following Toro (2009) +def RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R): + P_new = ((c_L + c_R + (v_L - v_R)*0.5*(gas_gamma-1.))/(c_L / P_L**beta + c_R / P_R**beta))**(1./beta) + P_3 = 0.5*(P_R + P_L) + f_L = 1. + while fabs(P_3 - P_new) > 1e-6: + P_3 = P_new + (f_L, dfdp_L) = compute_f(P_3, P_L, c_L) + (f_R, dfdp_R) = compute_f(P_3, P_R, c_R) + f = f_L + f_R + (v_R - v_L) + df = dfdp_L + dfdp_R + dp = -f/df + prnew = P_3 + dp + v_3 = v_L - f_L + return (P_new, v_3) + + +# Solve Riemann problem for post-shock region +(P_3, v_3) = RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R) + +# Check direction of shocks and wave +shock_R = (P_3 > P_R) +shock_L = (P_3 > P_L) + +# Velocity of shock front and and rarefaction wave +if shock_R: + v_right = v_R + c_R**2*(P_3/P_R - 1.)/(gas_gamma*(v_3-v_R)) +else: + v_right = c_R + 0.5*(gas_gamma+1.)*v_3 - 0.5*(gas_gamma-1.)*v_R + +if shock_L: + v_left = v_L + c_L**2*(P_3/p_L - 1.)/(gas_gamma*(v_3-v_L)) +else: + v_left = c_L - 0.5*(gas_gamma+1.)*v_3 + 0.5*(gas_gamma-1.)*v_L + +# Compute position of the transitions +x_23 = -fabs(v_left) * time +if shock_L : + x_12 = -fabs(v_left) * time +else: + x_12 = -(c_L - v_L) * time + +x_34 = v_3 * time + +x_45 = fabs(v_right) * time +if shock_R: + x_56 = fabs(v_right) * time +else: + x_56 = (c_R + v_R) * time + + +# Prepare arrays +delta_x = (x_max - x_min) / N +x_s = arange(x_min, x_max, delta_x) +rho_s = zeros(N) +P_s = zeros(N) +v_s = zeros(N) + +# Compute solution in the different regions +for i in range(N): + if x_s[i] <= x_12: + rho_s[i] = rho_L + P_s[i] = P_L + v_s[i] = v_L + if x_s[i] >= x_12 and x_s[i] < x_23: + if shock_L: + rho_s[i] = rho_L*(Gama + P_3/P_L)/(1. + Gama * P_3/P_L) + P_s[i] = P_3 + v_s[i] = v_3 + else: + rho_s[i] = rho_L*(Gama * (0. - x_s[i])/(c_L * time) + Gama * v_L/c_L + (1.-Gama))**(2./(gas_gamma-1.)) + P_s[i] = P_L*(rho_s[i] / rho_L)**gas_gamma + v_s[i] = (1.-Gama)*(c_L -(0. - x_s[i]) / time) + Gama*v_L + if x_s[i] >= x_23 and x_s[i] < x_34: + if shock_L: + rho_s[i] = rho_L*(Gama + P_3/P_L)/(1+Gama * P_3/p_L) + else: + rho_s[i] = rho_L*(P_3 / P_L)**(1./gas_gamma) + P_s[i] = P_3 + v_s[i] = v_3 + if x_s[i] >= x_34 and x_s[i] < x_45: + if shock_R: + rho_s[i] = rho_R*(Gama + P_3/P_R)/(1. + Gama * P_3/P_R) + else: + rho_s[i] = rho_R*(P_3 / P_R)**(1./gas_gamma) + P_s[i] = P_3 + v_s[i] = v_3 + if x_s[i] >= x_45 and x_s[i] < x_56: + if shock_R: + rho_s[i] = rho_R + P_s[i] = P_R + v_s[i] = v_R + else: + rho_s[i] = rho_R*(Gama*(x_s[i])/(c_R*time) - Gama*v_R/c_R + (1.-Gama))**(2./(gas_gamma-1.)) + P_s[i] = p_R*(rho_s[i]/rho_R)**gas_gamma + v_s[i] = (1.-Gama)*(-c_R - (-x_s[i])/time) + Gama*v_R + if x_s[i] >= x_56: + rho_s[i] = rho_R + P_s[i] = P_R + v_s[i] = v_R + + +# Additional arrays +u_s = P_s / (rho_s * (gas_gamma - 1.)) #internal energy +s_s = P_s / rho_s**gas_gamma # entropic function + + +# Plot the interesting quantities +figure() + +# Velocity profile -------------------------------- +subplot(231) +plot(x, v, '.', color='r', ms=0.5) +plot(x_s, v_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Velocity}}~v_x$", labelpad=0) +xlim(-0.5, 0.5) +ylim(-0.1, 0.95) + +# Density profile -------------------------------- +subplot(232) +plot(x, rho, '.', color='r', ms=0.5) +plot(x_s, rho_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.05, 1.1) + +# Pressure profile -------------------------------- +subplot(233) +plot(x, P, '.', color='r', ms=0.5) +plot(x_s, P_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.01, 1.1) + +# Internal energy profile ------------------------- +subplot(234) +plot(x, u, '.', color='r', ms=0.5) +plot(x_s, u_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.8, 2.2) + +# Entropy profile --------------------------------- +subplot(235) +plot(x, S, '.', color='r', ms=0.5) +plot(x_s, s_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.8, 3.8) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Sod shock with $\\gamma=%.3f$ in 2D at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Left:~~ $(P_L, \\rho_L, v_L) = (%.3f, %.3f, %.3f)$"%(P_L, rho_L, v_L), fontsize=10) +text(-0.49, 0.7, "Right: $(P_R, \\rho_R, v_R) = (%.3f, %.3f, %.3f)$"%(P_R, rho_R, v_R), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + + +savefig("SodShock.png", dpi=200) diff --git a/examples/SodShock_2D/run.sh b/examples/SodShock_2D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..3d1f4beb3ac4c4becfda24ed39390efec8074da7 --- /dev/null +++ b/examples/SodShock_2D/run.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Generate the initial conditions if they are not present. +if [ ! -e glassPlane_128.hdf5 ] +then + echo "Fetching initial glass file for the Sod shock example..." + ./getGlass.sh +fi +if [ ! -e sodShock.hdf5 ] +then + echo "Generating initial conditions for the Sod shock example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 sodShock.yml + +python plotSolution.py 1 diff --git a/examples/SodShock_2D/sodShock.yml b/examples/SodShock_2D/sodShock.yml new file mode 100644 index 0000000000000000000000000000000000000000..6805724ff58defebc41f3fb5b636d0003b0d6680 --- /dev/null +++ b/examples/SodShock_2D/sodShock.yml @@ -0,0 +1,36 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 0.2 # The end time of the simulation (in internal units). + dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: sodShock # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 0.2 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-2 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.02 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./sodShock.hdf5 # The file to read + diff --git a/examples/SodShock_3D/getGlass.sh b/examples/SodShock_3D/getGlass.sh new file mode 100755 index 0000000000000000000000000000000000000000..f61b61d4e6c51b44576fd7cdd6242cb9f0133039 --- /dev/null +++ b/examples/SodShock_3D/getGlass.sh @@ -0,0 +1,3 @@ +#!/bin/bash +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassCube_64.hdf5 +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassCube_32.hdf5 diff --git a/examples/SodShock_3D/makeIC.py b/examples/SodShock_3D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..84283732afc497825417546be8bc25e183ecb1cb --- /dev/null +++ b/examples/SodShock_3D/makeIC.py @@ -0,0 +1,122 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the 3D Sod Shock in a periodic box + +# Parameters +gamma = 5./3. # Gas adiabatic index +x_min = -1. +x_max = 1. +rho_L = 1. # Density left state +rho_R = 0.125 # Density right state +v_L = 0. # Velocity left state +v_R = 0. # Velocity right state +P_L = 1. # Pressure left state +P_R = 0.1 # Pressure right state +fileName = "sodShock.hdf5" + + +#--------------------------------------------------- +boxSize = (x_max - x_min) + +glass_L = h5py.File("glassCube_64.hdf5", "r") +glass_R = h5py.File("glassCube_32.hdf5", "r") + +pos_L = glass_L["/PartType0/Coordinates"][:,:] * 0.5 +pos_R = glass_R["/PartType0/Coordinates"][:,:] * 0.5 +h_L = glass_L["/PartType0/SmoothingLength"][:] * 0.5 +h_R = glass_R["/PartType0/SmoothingLength"][:] * 0.5 + +# Merge things +aa = pos_L - array([0.5, 0., 0.]) +pos_LL = append(pos_L, pos_L + array([0.5, 0., 0.]), axis=0) +pos_RR = append(pos_R, pos_R + array([0.5, 0., 0.]), axis=0) +pos = append(pos_LL - array([1.0, 0., 0.]), pos_RR, axis=0) +h_LL = append(h_L, h_L) +h_RR = append(h_R, h_R) +h = append(h_LL, h_RR) + +numPart_L = size(h_LL) +numPart_R = size(h_RR) +numPart = size(h) + +vol_L = 0.25 +vol_R = 0.25 + +# Generate extra arrays +v = zeros((numPart, 3)) +ids = linspace(1, numPart, numPart) +m = zeros(numPart) +u = zeros(numPart) + +for i in range(numPart): + x = pos[i,0] + + if x < 0: #left + u[i] = P_L / (rho_L * (gamma - 1.)) + m[i] = rho_L * vol_L / numPart_L + v[i,0] = v_L + else: #right + u[i] = P_R / (rho_R * (gamma - 1.)) + m[i] = rho_R * vol_R / numPart_R + v[i,0] = v_R + +# Shift particles +pos[:,0] -= x_min + +#File +file = h5py.File(fileName, 'w') + +# Header +grp = file.create_group("/Header") +grp.attrs["BoxSize"] = [boxSize, 0.5, 0.5] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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 + +#Runtime parameters +grp = file.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = file.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = file.create_group("/PartType0") +grp.create_dataset('Coordinates', data=pos, dtype='d') +grp.create_dataset('Velocities', data=v, dtype='f') +grp.create_dataset('Masses', data=m, dtype='f') +grp.create_dataset('SmoothingLength', data=h, dtype='f') +grp.create_dataset('InternalEnergy', data=u, dtype='f') +grp.create_dataset('ParticleIDs', data=ids, dtype='L') + + +file.close() diff --git a/examples/SodShock_3D/plotSolution.py b/examples/SodShock_3D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..23a16e6aed73a7281cf78a215940ccdcff722a79 --- /dev/null +++ b/examples/SodShock_3D/plotSolution.py @@ -0,0 +1,288 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the Sod shock and plots the SPH answer + + +# Generates the analytical solution for the Sod shock test case +# The script works for a given left (x<0) and right (x>0) state and computes the solution at a later time t. +# This follows the solution given in (Toro, 2009) + + +# Parameters +gas_gamma = 5./3. # Polytropic index +rho_L = 1. # Density left state +rho_R = 0.125 # Density right state +v_L = 0. # Velocity left state +v_R = 0. # Velocity right state +P_L = 1. # Pressure left state +P_R = 0.1 # Pressure right state + + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + + +snap = int(sys.argv[1]) + + +# Read the simulation data +sim = h5py.File("sodShock_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +x = sim["/PartType0/Coordinates"][:,0] +v = sim["/PartType0/Velocities"][:,0] +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +rho = sim["/PartType0/Density"][:] + +N = 1000 # Number of points +x_min = -1. +x_max = 1. + +x += x_min + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +c_L = sqrt(gas_gamma * P_L / rho_L) # Speed of the rarefaction wave +c_R = sqrt(gas_gamma * P_R / rho_R) # Speed of the shock front + +# Helpful variable +Gama = (gas_gamma - 1.) / (gas_gamma + 1.) +beta = (gas_gamma - 1.) / (2. * gas_gamma) + +# Characteristic function and its derivative, following Toro (2009) +def compute_f(P_3, P, c): + u = P_3 / P + if u > 1: + term1 = gas_gamma*((gas_gamma+1.)*u + gas_gamma-1.) + term2 = sqrt(2./term1) + fp = (u - 1.)*c*term2 + dfdp = c*term2/P + (u - 1.)*c/term2*(-1./term1**2)*gas_gamma*(gas_gamma+1.)/P + else: + fp = (u**beta - 1.)*(2.*c/(gas_gamma-1.)) + dfdp = 2.*c/(gas_gamma-1.)*beta*u**(beta-1.)/P + return (fp, dfdp) + +# Solution of the Riemann problem following Toro (2009) +def RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R): + P_new = ((c_L + c_R + (v_L - v_R)*0.5*(gas_gamma-1.))/(c_L / P_L**beta + c_R / P_R**beta))**(1./beta) + P_3 = 0.5*(P_R + P_L) + f_L = 1. + while fabs(P_3 - P_new) > 1e-6: + P_3 = P_new + (f_L, dfdp_L) = compute_f(P_3, P_L, c_L) + (f_R, dfdp_R) = compute_f(P_3, P_R, c_R) + f = f_L + f_R + (v_R - v_L) + df = dfdp_L + dfdp_R + dp = -f/df + prnew = P_3 + dp + v_3 = v_L - f_L + return (P_new, v_3) + + +# Solve Riemann problem for post-shock region +(P_3, v_3) = RiemannProblem(rho_L, P_L, v_L, rho_R, P_R, v_R) + +# Check direction of shocks and wave +shock_R = (P_3 > P_R) +shock_L = (P_3 > P_L) + +# Velocity of shock front and and rarefaction wave +if shock_R: + v_right = v_R + c_R**2*(P_3/P_R - 1.)/(gas_gamma*(v_3-v_R)) +else: + v_right = c_R + 0.5*(gas_gamma+1.)*v_3 - 0.5*(gas_gamma-1.)*v_R + +if shock_L: + v_left = v_L + c_L**2*(P_3/p_L - 1.)/(gas_gamma*(v_3-v_L)) +else: + v_left = c_L - 0.5*(gas_gamma+1.)*v_3 + 0.5*(gas_gamma-1.)*v_L + +# Compute position of the transitions +x_23 = -fabs(v_left) * time +if shock_L : + x_12 = -fabs(v_left) * time +else: + x_12 = -(c_L - v_L) * time + +x_34 = v_3 * time + +x_45 = fabs(v_right) * time +if shock_R: + x_56 = fabs(v_right) * time +else: + x_56 = (c_R + v_R) * time + + +# Prepare arrays +delta_x = (x_max - x_min) / N +x_s = arange(x_min, x_max, delta_x) +rho_s = zeros(N) +P_s = zeros(N) +v_s = zeros(N) + +# Compute solution in the different regions +for i in range(N): + if x_s[i] <= x_12: + rho_s[i] = rho_L + P_s[i] = P_L + v_s[i] = v_L + if x_s[i] >= x_12 and x_s[i] < x_23: + if shock_L: + rho_s[i] = rho_L*(Gama + P_3/P_L)/(1. + Gama * P_3/P_L) + P_s[i] = P_3 + v_s[i] = v_3 + else: + rho_s[i] = rho_L*(Gama * (0. - x_s[i])/(c_L * time) + Gama * v_L/c_L + (1.-Gama))**(2./(gas_gamma-1.)) + P_s[i] = P_L*(rho_s[i] / rho_L)**gas_gamma + v_s[i] = (1.-Gama)*(c_L -(0. - x_s[i]) / time) + Gama*v_L + if x_s[i] >= x_23 and x_s[i] < x_34: + if shock_L: + rho_s[i] = rho_L*(Gama + P_3/P_L)/(1+Gama * P_3/p_L) + else: + rho_s[i] = rho_L*(P_3 / P_L)**(1./gas_gamma) + P_s[i] = P_3 + v_s[i] = v_3 + if x_s[i] >= x_34 and x_s[i] < x_45: + if shock_R: + rho_s[i] = rho_R*(Gama + P_3/P_R)/(1. + Gama * P_3/P_R) + else: + rho_s[i] = rho_R*(P_3 / P_R)**(1./gas_gamma) + P_s[i] = P_3 + v_s[i] = v_3 + if x_s[i] >= x_45 and x_s[i] < x_56: + if shock_R: + rho_s[i] = rho_R + P_s[i] = P_R + v_s[i] = v_R + else: + rho_s[i] = rho_R*(Gama*(x_s[i])/(c_R*time) - Gama*v_R/c_R + (1.-Gama))**(2./(gas_gamma-1.)) + P_s[i] = p_R*(rho_s[i]/rho_R)**gas_gamma + v_s[i] = (1.-Gama)*(-c_R - (-x_s[i])/time) + Gama*v_R + if x_s[i] >= x_56: + rho_s[i] = rho_R + P_s[i] = P_R + v_s[i] = v_R + + +# Additional arrays +u_s = P_s / (rho_s * (gas_gamma - 1.)) #internal energy +s_s = P_s / rho_s**gas_gamma # entropic function + + +# Plot the interesting quantities +figure() + +# Velocity profile -------------------------------- +subplot(231) +plot(x, v, '.', color='r', ms=0.5) +plot(x_s, v_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Velocity}}~v_x$", labelpad=0) +xlim(-0.5, 0.5) +ylim(-0.1, 0.95) + +# Density profile -------------------------------- +subplot(232) +plot(x, rho, '.', color='r', ms=0.5) +plot(x_s, rho_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Density}}~\\rho$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.05, 1.1) + +# Pressure profile -------------------------------- +subplot(233) +plot(x, P, '.', color='r', ms=0.5) +plot(x_s, P_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Pressure}}~P$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.01, 1.1) + +# Internal energy profile ------------------------- +subplot(234) +plot(x, u, '.', color='r', ms=0.5) +plot(x_s, u_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Internal~Energy}}~u$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.8, 2.2) + +# Entropy profile --------------------------------- +subplot(235) +plot(x, S, '.', color='r', ms=0.5) +plot(x_s, s_s, '--', color='k', alpha=0.8, lw=1.2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Entropy}}~S$", labelpad=0) +xlim(-0.5, 0.5) +ylim(0.8, 3.8) + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Sod shock with $\\gamma=%.3f$ in 3D at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Left:~~ $(P_L, \\rho_L, v_L) = (%.3f, %.3f, %.3f)$"%(P_L, rho_L, v_L), fontsize=10) +text(-0.49, 0.7, "Right: $(P_R, \\rho_R, v_R) = (%.3f, %.3f, %.3f)$"%(P_R, rho_R, v_R), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + + +savefig("SodShock.png", dpi=200) diff --git a/examples/SodShock_3D/run.sh b/examples/SodShock_3D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..0f9e63be334475d98196189c49b95fc46982704a --- /dev/null +++ b/examples/SodShock_3D/run.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Generate the initial conditions if they are not present. +if [ ! -e glassCube_64.hdf5 ] +then + echo "Fetching initial glass file for the Sod shock example..." + ./getGlass.sh +fi +if [ ! -e sodShock.hdf5 ] +then + echo "Generating initial conditions for the Sod shock example..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 4 sodShock.yml + +python plotSolution.py 1 diff --git a/examples/SodShock_3D/sodShock.yml b/examples/SodShock_3D/sodShock.yml new file mode 100644 index 0000000000000000000000000000000000000000..1ab6eb626db09678f66322e8f0e8674c0931ddb6 --- /dev/null +++ b/examples/SodShock_3D/sodShock.yml @@ -0,0 +1,36 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 0.2 # The end time of the simulation (in internal units). + dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: sodShock # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 0.2 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-2 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.05 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./sodShock.hdf5 # The file to read + diff --git a/examples/SquareTest_2D/makeIC.py b/examples/SquareTest_2D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..2cb624f9944fcd421d95934ffeded089613e8bc9 --- /dev/null +++ b/examples/SquareTest_2D/makeIC.py @@ -0,0 +1,127 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 +from numpy import * + +# Generates a swift IC file for the Square test in a periodic box + +# Parameters +L = 64 # Number of particles on the side +gamma = 5./3. # Gas adiabatic index +rho0 = 4 # Gas central density +rho1 = 1 # Gas outskirt density +P0 = 2.5 # Gas central pressure +P1 = 2.5 # Gas central pressure +vx = 142.3 # Random velocity for all particles +vy = -31.4 +fileOutputName = "square.hdf5" +#--------------------------------------------------- + +vol = 1. + +numPart_out = L * L +numPart_in = L * L * rho0 / rho1 / 4 + +L_out = int(sqrt(numPart_out)) +L_in = int(sqrt(numPart_in)) + +pos_out = zeros((numPart_out, 3)) +for i in range(L_out): + for j in range(L_out): + index = i * L_out + j + pos_out[index, 0] = i / (float(L_out)) + 1./(2. * L_out) + pos_out[index, 1] = j / (float(L_out)) + 1./(2. * L_out) +h_out = ones(numPart_out) * (1. / L_out) * 1.2348 +m_out = ones(numPart_out) * vol * rho1 / numPart_out +u_out = ones(numPart_out) * P1 / (rho1 * (gamma - 1.)) + +pos_in = zeros((numPart_in, 3)) +for i in range(L_in): + for j in range(L_in): + index = i * L_in + j + pos_in[index, 0] = 0.25 + i / float(2. * L_in) + 1./(2. * 2. * L_in) + pos_in[index, 1] = 0.25 + j / float(2. * L_in) + 1./(2. * 2. * L_in) +h_in = ones(numPart_in) * (1. / L_in) * 1.2348 +m_in = ones(numPart_in) * 0.25 * vol * rho0 / numPart_in +u_in = ones(numPart_in) * P0 / (rho0 * (gamma - 1.)) + +# Remove the central particles +select_out = logical_or(logical_or(pos_out[:,0] < 0.25 , pos_out[:,0] > 0.75), logical_or(pos_out[:,1] < 0.25, pos_out[:,1] > 0.75)) +pos_out = pos_out[select_out, :] +h_out = h_out[select_out] +u_out = u_out[select_out] +m_out = m_out[select_out] + +# Add the central region +pos = append(pos_out, pos_in, axis=0) +h = append(h_out, h_in, axis=0) +u = append(u_out, u_in) +m = append(m_out, m_in) +numPart = size(h) +ids = linspace(1, numPart, numPart) +vel = zeros((numPart, 3)) +vel[:,0] = vx +vel[:,1] = vy + + +#File +fileOutput = h5py.File(fileOutputName, 'w') + +# Header +grp = fileOutput.create_group("/Header") +grp.attrs["BoxSize"] = [vol, vol, 0.2] +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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] + +#Runtime parameters +grp = fileOutput.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = 1 + +#Units +grp = fileOutput.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = fileOutput.create_group("/PartType0") +ds = grp.create_dataset('Coordinates', (numPart, 3), 'd') +ds[()] = pos +ds = grp.create_dataset('Velocities', (numPart, 3), 'f') +ds[()] = vel +ds = grp.create_dataset('Masses', (numPart, 1), 'f') +ds[()] = m.reshape((numPart,1)) +ds = grp.create_dataset('SmoothingLength', (numPart,1), 'f') +ds[()] = h.reshape((numPart,1)) +ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f') +ds[()] = u.reshape((numPart,1)) +ds = grp.create_dataset('ParticleIDs', (numPart,1), 'L') +ds[()] = ids.reshape((numPart,1)) + +fileOutput.close() + + diff --git a/examples/SquareTest_2D/plotSolution.py b/examples/SquareTest_2D/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..b9efe76de1e6c5993fa5333be76a13ba95bdab0f --- /dev/null +++ b/examples/SquareTest_2D/plotSolution.py @@ -0,0 +1,186 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + # + ############################################################################## + +# Computes the analytical solution of the square test + +# Parameters +gas_gamma = 5./3. # Gas adiabatic index +gamma = 5./3. # Gas adiabatic index +rho0 = 4 # Gas central density +rho1 = 1 # Gas outskirt density +P0 = 2.5 # Gas central pressure +P1 = 2.5 # Gas central pressure +vx = 142.3 # Random velocity for all particles +vy = -31.4 + +# --------------------------------------------------------------- +# Don't touch anything after this. +# --------------------------------------------------------------- + +import matplotlib +matplotlib.use("Agg") +from pylab import * +import h5py + +# Plot parameters +params = {'axes.labelsize': 10, +'axes.titlesize': 10, +'font.size': 12, +'legend.fontsize': 12, +'xtick.labelsize': 10, +'ytick.labelsize': 10, +'text.usetex': True, + 'figure.figsize' : (9.90,6.45), +'figure.subplot.left' : 0.045, +'figure.subplot.right' : 0.99, +'figure.subplot.bottom' : 0.05, +'figure.subplot.top' : 0.99, +'figure.subplot.wspace' : 0.15, +'figure.subplot.hspace' : 0.12, +'lines.markersize' : 6, +'lines.linewidth' : 3., +'text.latex.unicode': True +} +rcParams.update(params) +rc('font',**{'family':'sans-serif','sans-serif':['Times']}) + +snap = int(sys.argv[1]) + +# Read the simulation data +sim = h5py.File("square_%03d.hdf5"%snap, "r") +boxSize = sim["/Header"].attrs["BoxSize"][0] +time = sim["/Header"].attrs["Time"][0] +scheme = sim["/HydroScheme"].attrs["Scheme"] +kernel = sim["/HydroScheme"].attrs["Kernel function"] +neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"] +eta = sim["/HydroScheme"].attrs["Kernel eta"] +git = sim["Code"].attrs["Git Revision"] + +# Analytical soltion +centre_x = 0.5 + time * vx +centre_y = 0.5 + time * vy + +while centre_x > 1.: + centre_x -= 1. +while centre_x < 0.: + centre_x += 1. +while centre_y > 1.: + centre_y -= 1. +while centre_y < 0.: + centre_y += 1. + +pos = sim["/PartType0/Coordinates"][:,:] +vel = sim["/PartType0/Velocities"][:,:] +v_norm = sqrt(vel[:,0]**2 + vel[:,1]**2) +rho = sim["/PartType0/Density"][:] +u = sim["/PartType0/InternalEnergy"][:] +S = sim["/PartType0/Entropy"][:] +P = sim["/PartType0/Pressure"][:] +x = pos[:,0] - centre_x +y = pos[:,1] - centre_y + +# Box wrapping +x[x>0.5] -= 1. +x[x<-0.5] += 1. +y[y>0.5] -= 1. +y[y<-0.5] += 1. + +# Azimuthal velocity profile ----------------------------- +subplot(231) +scatter(x, y, c=v_norm, cmap="PuBu", edgecolors='face', s=4, vmin=-1., vmax=1.) +text(0.47, 0.47, "${\\rm{Velocity~norm}}$", ha="right", va="top", backgroundcolor="w") +plot([-0.25, 0.25], [0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, 0.25], [-0.25, -0.25], '--', color='k', alpha=0.8, lw=2) +plot([0.25, 0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, -0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=-7) +xlim(-0.5, 0.5) +ylim(-0.5, 0.5) + +# Radial density profile -------------------------------- +subplot(232) +scatter(x, y, c=rho, cmap="PuBu", edgecolors='face', s=4, vmin=0., vmax=4.) +text(0.47, 0.47, "${\\rm{Density}}$", ha="right", va="top", backgroundcolor="w") +plot([-0.25, 0.25], [0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, 0.25], [-0.25, -0.25], '--', color='k', alpha=0.8, lw=2) +plot([0.25, 0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, -0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=-7) +xlim(-0.5, 0.5) +ylim(-0.5, 0.5) + +# Radial pressure profile -------------------------------- +subplot(233) +scatter(x, y, c=P, cmap="PuBu", edgecolors='face', s=4, vmin=2, vmax=4) +text(0.47, 0.47, "${\\rm{Pressure}}$", ha="right", va="top", backgroundcolor="w") +plot([-0.25, 0.25], [0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, 0.25], [-0.25, -0.25], '--', color='k', alpha=0.8, lw=2) +plot([0.25, 0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, -0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=-7) +xlim(-0.5, 0.5) +ylim(-0.5, 0.5) + +# Internal energy profile -------------------------------- +subplot(234) +scatter(x, y, c=u, cmap="PuBu", edgecolors='face', s=4, vmin=0.5, vmax=4.) +text(0.47, 0.47, "${\\rm{Internal~energy}}$", ha="right", va="top", backgroundcolor="w") +plot([-0.25, 0.25], [0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, 0.25], [-0.25, -0.25], '--', color='k', alpha=0.8, lw=2) +plot([0.25, 0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, -0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=-7) +xlim(-0.5, 0.5) +ylim(-0.5, 0.5) + +# Radial entropy profile -------------------------------- +subplot(235) +scatter(x, y, c=S, cmap="PuBu", edgecolors='face', s=4, vmin=0., vmax=3.) +text(0.47, 0.47, "${\\rm{Entropy}}$", ha="right", va="top", backgroundcolor="w") +plot([-0.25, 0.25], [0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, 0.25], [-0.25, -0.25], '--', color='k', alpha=0.8, lw=2) +plot([0.25, 0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +plot([-0.25, -0.25], [-0.25, 0.25], '--', color='k', alpha=0.8, lw=2) +xlabel("${\\rm{Position}}~x$", labelpad=0) +ylabel("${\\rm{Position}}~y$", labelpad=-7) +xlim(-0.5, 0.5) +ylim(-0.5, 0.5) + + +# Information ------------------------------------- +subplot(236, frameon=False) + +text(-0.49, 0.9, "Square test with $\\gamma=%.3f$ at $t=%.2f$"%(gas_gamma,time), fontsize=10) +text(-0.49, 0.8, "Centre:~~~ $(P, \\rho) = (%.3f, %.3f)$"%(P0, rho0), fontsize=10) +text(-0.49, 0.7, "Outskirts: $(P, \\rho) = (%.3f, %.3f)$"%(P1, rho1), fontsize=10) +plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1) +text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10) +text(-0.49, 0.4, scheme, fontsize=10) +text(-0.49, 0.3, kernel, fontsize=10) +text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10) +xlim(-0.5, 0.5) +ylim(0, 1) +xticks([]) +yticks([]) + +savefig("SquareTest.png", dpi=200) diff --git a/examples/SquareTest_2D/run.sh b/examples/SquareTest_2D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..21f5ee9093ca2b50830c46bb2117d8138d23ee94 --- /dev/null +++ b/examples/SquareTest_2D/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + + # Generate the initial conditions if they are not present. +if [ ! -e square.hdf5 ] +then + echo "Generating initial conditions for the square test ..." + python makeIC.py +fi + +# Run SWIFT +../swift -s -t 1 square.yml + +# Plot the solution +python plotSolution.py 40 diff --git a/examples/SquareTest_2D/square.yml b/examples/SquareTest_2D/square.yml new file mode 100644 index 0000000000000000000000000000000000000000..4f39c6490899cfaafeda17fb0c28281cbadcbbea --- /dev/null +++ b/examples/SquareTest_2D/square.yml @@ -0,0 +1,35 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 4. # The end time of the simulation (in internal units). + dt_min: 1e-6 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: square # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-1 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-2 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.02 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./square.hdf5 # The file to read diff --git a/examples/UniformBox_2D/makeIC.py b/examples/UniformBox_2D/makeIC.py new file mode 100644 index 0000000000000000000000000000000000000000..41b7d695a2376b990703706977ef111be8f3a355 --- /dev/null +++ b/examples/UniformBox_2D/makeIC.py @@ -0,0 +1,114 @@ +############################################################################### + # This file is part of SWIFT. + # Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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 random +from numpy import * + +# Generates a swift IC file containing a perturbed cartesian distribution of particles +# at a constant density and pressure in a cubic box + +# Parameters +periodic= 1 # 1 For periodic box +boxSize = 1. +L = int(sys.argv[1]) # Number of particles along one axis +rho = 1. # Density +P = 1. # Pressure +gamma = 5./3. # Gas adiabatic index +fileName = "uniformPlane.hdf5" + + +#--------------------------------------------------- +numPart = L**2 +mass = boxSize**2 * rho / numPart +internalEnergy = P / ((gamma - 1.)*rho) + +#Generate particles +coords = zeros((numPart, 3)) +v = zeros((numPart, 3)) +m = zeros((numPart, 1)) +h = zeros((numPart, 1)) +u = zeros((numPart, 1)) +ids = zeros((numPart, 1), dtype='L') + +for i in range(L): + for j in range(L): + index = i*L + j + x = i * boxSize / L + boxSize / (2*L) + boxSize/(2.*L) + y = j * boxSize / L + boxSize / (2*L) + boxSize/(2.*L) + z = 0 + coords[index,0] = x + coords[index,1] = y + coords[index,2] = z + v[index,0] = 0. + v[index,1] = 0. + v[index,2] = 0. + m[index] = mass + h[index] = 1.23485 * boxSize / L + u[index] = internalEnergy + ids[index] = index + + + +#-------------------------------------------------- + +#File +file = h5py.File(fileName, 'w') + +# Header +grp = file.create_group("/Header") +grp.attrs["BoxSize"] = boxSize +grp.attrs["NumPart_Total"] = [numPart, 0, 0, 0, 0, 0] +grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0] +grp.attrs["NumPart_ThisFile"] = [numPart, 0, 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["NumPart_Total"] = numPart + +#Runtime parameters +grp = file.create_group("/RuntimePars") +grp.attrs["PeriodicBoundariesOn"] = periodic + +#Units +grp = file.create_group("/Units") +grp.attrs["Unit length in cgs (U_L)"] = 1. +grp.attrs["Unit mass in cgs (U_M)"] = 1. +grp.attrs["Unit time in cgs (U_t)"] = 1. +grp.attrs["Unit current in cgs (U_I)"] = 1. +grp.attrs["Unit temperature in cgs (U_T)"] = 1. + +#Particle group +grp = file.create_group("/PartType0") +ds = grp.create_dataset('Coordinates', (numPart, 3), 'd') +ds[()] = coords +ds = grp.create_dataset('Velocities', (numPart, 3), 'f') +ds[()] = v +ds = grp.create_dataset('Masses', (numPart,1), 'f') +ds[()] = m +ds = grp.create_dataset('SmoothingLength', (numPart,1), 'f') +ds[()] = h +ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f') +ds[()] = u +ds = grp.create_dataset('ParticleIDs', (numPart, 1), 'L') +ds[()] = ids + 1 + +file.close() diff --git a/examples/UniformBox_2D/run.sh b/examples/UniformBox_2D/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..fbabedb1cd564e0831228591ce32d9a73fe08d9a --- /dev/null +++ b/examples/UniformBox_2D/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Generate the initial conditions if they are not present. +if [ ! -e uniformPlane.hdf5 ] +then + echo "Generating initial conditions for the uniform box example..." + python makeIC.py 100 +fi + +../swift -s -t 16 uniformPlane.yml diff --git a/examples/UniformBox_2D/uniformPlane.yml b/examples/UniformBox_2D/uniformPlane.yml new file mode 100644 index 0000000000000000000000000000000000000000..a3e2d275e50fb20f66ea6494c1202319e462dbed --- /dev/null +++ b/examples/UniformBox_2D/uniformPlane.yml @@ -0,0 +1,35 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1 # Grams + UnitLength_in_cgs: 1 # Centimeters + UnitVelocity_in_cgs: 1 # 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: 10. # The end time of the simulation (in internal units). + dt_min: 1e-6 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: uniformPlane # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-1 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-3 # Time between statistics output + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + delta_neighbours: 0.1 # The tolerance for the targetted number of neighbours. + max_smoothing_length: 0.1 # Maximal smoothing length allowed (in internal units). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./uniformPlane.hdf5 # The file to read diff --git a/examples/UniformBox/makeIC.py b/examples/UniformBox_3D/makeIC.py similarity index 100% rename from examples/UniformBox/makeIC.py rename to examples/UniformBox_3D/makeIC.py diff --git a/examples/UniformBox/makeICbig.py b/examples/UniformBox_3D/makeICbig.py similarity index 100% rename from examples/UniformBox/makeICbig.py rename to examples/UniformBox_3D/makeICbig.py diff --git a/examples/UniformBox/run.sh b/examples/UniformBox_3D/run.sh similarity index 100% rename from examples/UniformBox/run.sh rename to examples/UniformBox_3D/run.sh diff --git a/examples/UniformBox/uniformBox.yml b/examples/UniformBox_3D/uniformBox.yml similarity index 100% rename from examples/UniformBox/uniformBox.yml rename to examples/UniformBox_3D/uniformBox.yml diff --git a/examples/main.c b/examples/main.c index 4aa7e7cd53c6df8b2ea5e611e902fce627a6dea6..59f1a638284da3b3817a2fa0ab1b9e78175e3d4c 100644 --- a/examples/main.c +++ b/examples/main.c @@ -456,9 +456,6 @@ int main(int argc, char *argv[]) { fflush(stdout); } - /* Write the state of the system before starting time integration. */ - if (!dry_run) engine_dump_snapshot(&e); - /* Init the runner history. */ #ifdef HIST for (k = 0; k < runner_hist_N; k++) runner_hist_bins[k] = 0; @@ -494,6 +491,9 @@ int main(int argc, char *argv[]) { /* Initialise the particles */ engine_init_particles(&e, flag_entropy_ICs); + /* Write the state of the system before starting time integration. */ + engine_dump_snapshot(&e); + /* Legend */ if (myrank == 0) printf("# %6s %14s %14s %10s %10s %16s [%s]\n", "Step", "Time", "Time-step", diff --git a/src/Makefile.am b/src/Makefile.am index 7e2ceeb6067bb831620472b50ccd51fdfd50b494..4d6a67c7569464486a017d8306c3e54730ebb3b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,7 +56,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \ nobase_noinst_HEADERS = approx_math.h atomic.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \ kernel_long_gravity.h vector.h runner_doiact.h runner_doiact_grav.h runner_doiact_fft.h \ units.h intrinsics.h minmax.h kick.h timestep.h drift.h adiabatic_index.h io_properties.h \ - equation_of_state.h \ + dimension.h equation_of_state.h \ gravity.h gravity_io.h \ gravity/Default/gravity.h gravity/Default/gravity_iact.h gravity/Default/gravity_io.h \ gravity/Default/gravity_debug.h gravity/Default/gravity_part.h \ diff --git a/src/adiabatic_index.h b/src/adiabatic_index.h index 50d24e881585abfb9c482b936780b5e1935df314..78d1cc9d2deaf60c5d933b74a089c77446b44414 100644 --- a/src/adiabatic_index.h +++ b/src/adiabatic_index.h @@ -19,6 +19,12 @@ #ifndef SWIFT_ADIABATIC_INDEX_H #define SWIFT_ADIABATIC_INDEX_H +/** + * @file adiabatic_index.h + * @brief Defines the adiabatic index (polytropix index) \f$\gamma\f$ of the + * problem and (fast) mathematical functions involving it. + */ + /* Config parameters. */ #include "../config.h" @@ -124,8 +130,8 @@ __attribute__((always_inline)) INLINE static float pow_minus_gamma_minus_one( #if defined(HYDRO_GAMMA_5_3) - const float inv_cbrt = 1.f / cbrtf(x); /* x^(-1/3) */ - return inv_cbrt * inv_cbrt; /* x^(-2/3) */ + const float cbrt_inv = 1.f / cbrtf(x); /* x^(-1/3) */ + return cbrt_inv * cbrt_inv; /* x^(-2/3) */ #elif defined(HYDRO_GAMMA_4_3) diff --git a/src/const.h b/src/const.h index f98d2ba28d0236448fe1c23e54072f8bd41156d0..d2110be497fbe821c62911fcb3f9c3079770de0b 100644 --- a/src/const.h +++ b/src/const.h @@ -36,6 +36,11 @@ /* Time integration constants. */ #define const_max_u_change 0.1f +/* Dimensionality of the problem */ +#define HYDRO_DIMENSION_3D +//#define HYDRO_DIMENSION_2D +//#define HYDRO_DIMENSION_1D + /* Hydrodynamical adiabatic index. */ #define HYDRO_GAMMA_5_3 //#define HYDRO_GAMMA_4_3 diff --git a/src/dimension.h b/src/dimension.h new file mode 100644 index 0000000000000000000000000000000000000000..6395d4d04e50d40b733e7a74dafb7d0ab277d204 --- /dev/null +++ b/src/dimension.h @@ -0,0 +1,180 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@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/>. + * + ******************************************************************************/ +#ifndef SWIFT_DIMENSION_H +#define SWIFT_DIMENSION_H + +/** + * @file dimension.h + * @brief Defines the dimensionality \f$d\f$ of the problem and (fast) + * mathematical functions involving it + */ + +/* Config parameters. */ +#include "../config.h" + +/* Local headers. */ +#include "const.h" +#include "inline.h" +#include "vector.h" + +/* First define some constants */ +#if defined(HYDRO_DIMENSION_3D) + +#define hydro_dimension 3.f +#define hydro_dimension_inv 0.3333333333f +#define hydro_dimention_unit_sphere ((float)(4. * M_PI / 3.)) + +#elif defined(HYDRO_DIMENSION_2D) + +#define hydro_dimension 2.f +#define hydro_dimension_inv 0.5f +#define hydro_dimention_unit_sphere ((float)M_PI) + +#elif defined(HYDRO_DIMENSION_1D) + +#define hydro_dimension 1.f +#define hydro_dimension_inv 1.f +#define hydro_dimention_unit_sphere 2.f + +#else + +#error "A problem dimensionality must be chosen in const.h !" + +#endif + +/** + * @brief Returns the argument to the power given by the dimension + * + * Computes \f$x^d\f$. + */ +__attribute__((always_inline)) INLINE static float pow_dimension(float x) { + +#if defined(HYDRO_DIMENSION_3D) + + return x * x * x; + +#elif defined(HYDRO_DIMENSION_2D) + + return x * x; + +#elif defined(HYDRO_DIMENSION_1D) + + return x; + +#else + + error("The dimension is not defined !"); + return 0.f; + +#endif +} + +/** + * @brief Returns the argument to the power given by the dimension plus one + * + * Computes \f$x^{d+1}\f$. + */ +__attribute__((always_inline)) INLINE static float pow_dimension_plus_one( + float x) { + +#if defined(HYDRO_DIMENSION_3D) + + const float x2 = x * x; + return x2 * x2; + +#elif defined(HYDRO_DIMENSION_2D) + + return x * x * x; + +#elif defined(HYDRO_DIMENSION_1D) + + return x * x; + +#else + + error("The dimension is not defined !"); + return 0.f; + +#endif +} + +/* ------------------------------------------------------------------------- */ +#ifdef WITH_VECTORIZATION + +/** + * @brief Returns the argument to the power given by the dimension (vector + * version) + * + * Computes \f$x^d\f$. + */ +__attribute__((always_inline)) INLINE static vector pow_dimension_vec( + vector x) { + +#if defined(HYDRO_DIMENSION_3D) + + return (vector)(x.v * x.v * x.v); + +#elif defined(HYDRO_DIMENSION_2D) + + return (vector)(x.v * x.v); + +#elif defined(HYDRO_DIMENSION_1D) + + return x; + +#else + + error("The dimension is not defined !"); + return vec_set(0.f); + +#endif +} + +/** + * @brief Returns the argument to the power given by the dimension plus one + * (vector version) + * + * Computes \f$x^{d+1}\f$. + */ +__attribute__((always_inline)) INLINE static vector pow_dimension_plus_one_vec( + vector x) { + +#if defined(HYDRO_DIMENSION_3D) + + const vector x2 = (vector)(x.v * x.v); + return (vector)(x2.v * x2.v); + +#elif defined(HYDRO_DIMENSION_2D) + + return (vector)(x.v * x.v * x.v); + +#elif defined(HYDRO_DIMENSION_1D) + + return (vector)(x.v * x.v); + +#else + + error("The dimension is not defined !"); + return vec_set(0.f); + +#endif +} +#endif + +#endif /* SWIFT_DIMENSION_H */ diff --git a/src/drift.h b/src/drift.h index a6e347cc337385f89bece53bc477bff7d163c202..880595dc59e3e5174ee5e888e595a9204ad383e2 100644 --- a/src/drift.h +++ b/src/drift.h @@ -25,6 +25,7 @@ /* Local headers. */ #include "const.h" #include "debug.h" +#include "dimension.h" #include "hydro.h" #include "part.h" @@ -85,7 +86,7 @@ __attribute__((always_inline)) INLINE static void drift_part( p->h *= expf(w1); /* Predict density */ - const float w2 = -3.0f * w1; + const float w2 = -hydro_dimension * w1; if (fabsf(w2) < 0.2f) p->rho *= approx_expf(w2); /* 4th order expansion of exp(w) */ else diff --git a/src/engine.c b/src/engine.c index ebd589bbb0af01cec3196c658c4d014daca8df38..a980bcbc9c2f42127fb43b30c7d5573a8e9957ef 100644 --- a/src/engine.c +++ b/src/engine.c @@ -2411,17 +2411,7 @@ void engine_init_particles(struct engine *e, int flag_entropy_ICs) { struct clocks_time time1, time2; clocks_gettime(&time1); - if (e->nodeID == 0) message("Initialising particles"); - - /* Make sure all particles are ready to go */ - /* i.e. clean-up any stupid state in the ICs */ - if (e->policy & engine_policy_hydro) { - space_map_cells_pre(s, 0, cell_init_parts, NULL); - } - if ((e->policy & engine_policy_self_gravity) || - (e->policy & engine_policy_external_gravity)) { - space_map_cells_pre(s, 0, cell_init_gparts, NULL); - } + if (e->nodeID == 0) message("Running initialisation fake time-step."); engine_prepare(e); diff --git a/src/equation_of_state.h b/src/equation_of_state.h index 5103d6e475f38f2166447c30b87b9798373df8f9..672b44c55d298be3408126415be90de133342656 100644 --- a/src/equation_of_state.h +++ b/src/equation_of_state.h @@ -19,6 +19,13 @@ #ifndef SWIFT_EQUATION_OF_STATE_H #define SWIFT_EQUATION_OF_STATE_H +/** + * @file equation_of_state.h + * @brief Defines the equation of state of the gas we simulate in the form of + * relations between thermodynamic quantities. These are later used internally + * by all hydro schemes + */ + /* Config parameters. */ #include "../config.h" diff --git a/src/gravity/Default/gravity.h b/src/gravity/Default/gravity.h index 1fb67220977d029ba821ef66e93ee61cae1394e2..025c881d169186e7efd483fee0c74a601b85cc50 100644 --- a/src/gravity/Default/gravity.h +++ b/src/gravity/Default/gravity.h @@ -85,6 +85,9 @@ gravity_compute_timestep_self(const struct phys_const* const phys_const, */ __attribute__((always_inline)) INLINE static void gravity_first_init_gpart( struct gpart* gp) { + + gp->ti_begin = 0; + gp->ti_end = 0; gp->epsilon = 0.; // MATTHIEU } diff --git a/src/hydro/Default/hydro.h b/src/hydro/Default/hydro.h index 7fe78f75fc00569ee8d34ea30a822bac394531e2..51e09a5d943a7f3782e484289faddece2567f15d 100644 --- a/src/hydro/Default/hydro.h +++ b/src/hydro/Default/hydro.h @@ -137,7 +137,15 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep( * @param xp The extended particle data to act upon */ __attribute__((always_inline)) INLINE static void hydro_first_init_part( - struct part *restrict p, struct xpart *restrict xp) {} + struct part *restrict p, struct xpart *restrict xp) { + + p->ti_begin = 0; + p->ti_end = 0; + xp->v_full[0] = p->v[0]; + xp->v_full[1] = p->v[1]; + xp->v_full[2] = p->v[2]; + xp->u_full = p->u; +} /** * @brief Prepares a particle for the density calculation. @@ -173,33 +181,33 @@ __attribute__((always_inline)) INLINE static void hydro_end_density( /* Some smoothing length multiples. */ const float h = p->h; - const float ih = 1.0f / h; - const float ih2 = ih * ih; - const float ih4 = ih2 * ih2; + const float h_inv = 1.0f / h; /* 1/h */ + const float h_inv_dim = pow_dimension(h_inv); /* 1/h^d */ + const float h_inv_dim_plus_one = h_inv_dim * h_inv; /* 1/h^(d+1) */ /* Final operation on the density (add self-contribution). */ p->rho += p->mass * kernel_root; - p->rho_dh -= 3.0f * p->mass * kernel_root; + p->rho_dh -= hydro_dimension * p->mass * kernel_root; p->density.wcount += kernel_root; /* Finish the calculation by inserting the missing h-factors */ - p->rho *= ih * ih2; - p->rho_dh *= ih4; + p->rho *= h_inv_dim; + p->rho_dh *= h_inv_dim_plus_one; p->density.wcount *= kernel_norm; - p->density.wcount_dh *= ih * kernel_gamma * kernel_norm; + p->density.wcount_dh *= h_inv * kernel_gamma * kernel_norm; const float irho = 1.f / p->rho; /* Compute the derivative term */ - p->rho_dh = 1.f / (1.f + 0.33333333f * p->h * p->rho_dh * irho); + p->rho_dh = 1.f / (1.f + hydro_dimension_inv * p->h * p->rho_dh * irho); /* Finish calculation of the velocity curl components */ - p->density.rot_v[0] *= ih4 * irho; - p->density.rot_v[1] *= ih4 * irho; - p->density.rot_v[2] *= ih4 * irho; + p->density.rot_v[0] *= h_inv_dim_plus_one * irho; + p->density.rot_v[1] *= h_inv_dim_plus_one * irho; + p->density.rot_v[2] *= h_inv_dim_plus_one * irho; /* Finish calculation of the velocity divergence */ - p->density.div_v *= ih4 * irho; + p->density.div_v *= h_inv_dim_plus_one * irho; } /** @@ -217,7 +225,7 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force( /* Some smoothing length multiples. */ const float h = p->h; - const float ih = 1.0f / h; + const float h_inv = 1.0f / h; /* Pre-compute some stuff for the balsara switch. */ const float normDiv_v = fabs(p->density.div_v); @@ -231,11 +239,11 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force( sqrtf(hydro_gamma * hydro_gamma_minus_one * u); /* Compute the P/Omega/rho2. */ - xp->omega = 1.0f + 0.3333333333f * h * p->rho_dh / p->rho; + xp->omega = 1.0f + hydro_dimension_inv * h * p->rho_dh / p->rho; p->force.P_over_rho2 = u * hydro_gamma_minus_one / (p->rho * xp->omega); /* Balsara switch */ - p->force.balsara = normDiv_v / (normDiv_v + normRot_v + 0.0001f * fc * ih); + p->force.balsara = normDiv_v / (normDiv_v + normRot_v + 0.0001f * fc * h_inv); /* Viscosity parameter decay time */ const float tau = h / (2.f * const_viscosity_length * p->force.soundspeed); @@ -309,7 +317,7 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra( */ __attribute__((always_inline)) INLINE static void hydro_end_force( struct part *restrict p) { - p->force.h_dt *= p->h * 0.333333333f; + p->force.h_dt *= p->h * hydro_dimension_inv; } /** diff --git a/src/hydro/Default/hydro_iact.h b/src/hydro/Default/hydro_iact.h index 141ab8f884da7f120f2b636933904f0d795a5d8b..4975cac35aaa3d4b4b9f99319dfd061998014453 100644 --- a/src/hydro/Default/hydro_iact.h +++ b/src/hydro/Default/hydro_iact.h @@ -75,7 +75,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( kernel_deval(xi, &wi, &wi_dx); pi->rho += mj * wi; - pi->rho_dh -= mj * (3.0f * wi + xi * wi_dx); + pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx); pi->density.wcount += wi; pi->density.wcount_dh -= xi * wi_dx; @@ -88,7 +88,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( kernel_deval(xj, &wj, &wj_dx); pj->rho += mi * wj; - pj->rho_dh -= mi * (3.0f * wj + xj * wj_dx); + pj->rho_dh -= mi * (hydro_dimension * wj + xj * wj_dx); pj->density.wcount += wj; pj->density.wcount_dh -= xj * wj_dx; @@ -174,14 +174,14 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_density( for (k = 0; k < 3; k++) curlvr[k].v *= ri.v; rhoi.v = mj.v * wi.v; - rhoi_dh.v = mj.v * (vec_set1(3.0f) * wi.v + xi.v * wi_dx.v); + rhoi_dh.v = mj.v * (vec_set1(hydro_dimension) * wi.v + xi.v * wi_dx.v); wcounti.v = wi.v; wcounti_dh.v = xi.v * wi_dx.v; div_vi.v = mj.v * dvdr.v * wi_dx.v; for (k = 0; k < 3; k++) rot_vi[k].v = mj.v * curlvr[k].v * wi_dx.v; rhoj.v = mi.v * wj.v; - rhoj_dh.v = mi.v * (vec_set1(3.0f) * wj.v + xj.v * wj_dx.v); + rhoj_dh.v = mi.v * (vec_set1(hydro_dimension) * wj.v + xj.v * wj_dx.v); wcountj.v = wj.v; wcountj_dh.v = xj.v * wj_dx.v; div_vj.v = mi.v * dvdr.v * wj_dx.v; @@ -250,7 +250,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( kernel_deval(xi, &wi, &wi_dx); pi->rho += mj * wi; - pi->rho_dh -= mj * (3.0f * wi + xi * wi_dx); + pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx); pi->density.wcount += wi; pi->density.wcount_dh -= xi * wi_dx; @@ -327,7 +327,7 @@ runner_iact_nonsym_vec_density(float *R2, float *Dx, float *Hi, float *Hj, for (k = 0; k < 3; k++) curlvr[k].v *= ri.v; rhoi.v = mj.v * wi.v; - rhoi_dh.v = mj.v * (vec_set1(3.0f) * wi.v + xi.v * wi_dx.v); + rhoi_dh.v = mj.v * (vec_set1(hydro_dimension) * wi.v + xi.v * wi_dx.v); wcounti.v = wi.v; wcounti_dh.v = xi.v * wi_dx.v; div_vi.v = mj.v * dvdr.v * wi_dx.v; @@ -358,8 +358,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( float r = sqrtf(r2), ri = 1.0f / r; float xi, xj; - float hi_inv, hi2_inv; - float hj_inv, hj2_inv; + float hi_inv, hid_inv; + float hj_inv, hjd_inv; float wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, w, dvdr; float mi, mj, POrho2i, POrho2j, rhoi, rhoj; float v_sig, omega_ij, Pi_ij, alpha_ij, tc, v_sig_u; @@ -376,17 +376,17 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( /* Get the kernel for hi. */ hi_inv = 1.0f / hi; - hi2_inv = hi_inv * hi_inv; + hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ xi = r * hi_inv; kernel_deval(xi, &wi, &wi_dx); - wi_dr = hi2_inv * hi2_inv * wi_dx; + wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ hj_inv = 1.0f / hj; - hj2_inv = hj_inv * hj_inv; + hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ xj = r * hj_inv; kernel_deval(xj, &wj, &wj_dx); - wj_dr = hj2_inv * hj2_inv * wj_dx; + wj_dr = hjd_inv * wj_dx; /* Compute dv dot r. */ dvdr = (pi->v[0] - pj->v[0]) * dx[0] + (pi->v[1] - pj->v[1]) * dx[1] + @@ -457,7 +457,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_force( vector r, r2, ri; vector xi, xj; vector hi, hj, hi_inv, hj_inv; - vector hi2_inv, hj2_inv; + vector hid_inv, hjd_inv; vector wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, dvdr; vector w; vector piPOrho2, pjPOrho2, pirho, pjrho, piu, pju; @@ -564,19 +564,19 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_force( hi.v = vec_load(Hi); hi_inv.v = vec_rcp(hi.v); hi_inv.v = hi_inv.v - hi_inv.v * (hi.v * hi_inv.v - vec_set1(1.0f)); - hi2_inv.v = hi_inv.v * hi_inv.v; + hid_inv = pow_dimension_plus_one_vec(hi_inv); xi.v = r.v * hi_inv.v; kernel_deval_vec(&xi, &wi, &wi_dx); - wi_dr.v = hi2_inv.v * hi2_inv.v * wi_dx.v; + wi_dr.v = hid_inv.v * wi_dx.v; /* Get the kernel for hj. */ hj.v = vec_load(Hj); hj_inv.v = vec_rcp(hj.v); hj_inv.v = hj_inv.v - hj_inv.v * (hj.v * hj_inv.v - vec_set1(1.0f)); - hj2_inv.v = hj_inv.v * hj_inv.v; + hjd_inv = pow_dimension_plus_one_vec(hj_inv); xj.v = r.v * hj_inv.v; kernel_deval_vec(&xj, &wj, &wj_dx); - wj_dr.v = hj2_inv.v * hj2_inv.v * wj_dx.v; + wj_dr.v = hjd_inv.v * wj_dx.v; /* Compute dv dot r. */ dvdr.v = ((vi[0].v - vj[0].v) * dx[0].v) + ((vi[1].v - vj[1].v) * dx[1].v) + @@ -659,8 +659,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( float r = sqrtf(r2), ri = 1.0f / r; float xi, xj; - float hi_inv, hi2_inv; - float hj_inv, hj2_inv; + float hi_inv, hid_inv; + float hj_inv, hjd_inv; float wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, w, dvdr; float /*mi,*/ mj, POrho2i, POrho2j, rhoi, rhoj; float v_sig, omega_ij, Pi_ij, alpha_ij, tc, v_sig_u; @@ -677,17 +677,17 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /* Get the kernel for hi. */ hi_inv = 1.0f / hi; - hi2_inv = hi_inv * hi_inv; + hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ xi = r * hi_inv; kernel_deval(xi, &wi, &wi_dx); - wi_dr = hi2_inv * hi2_inv * wi_dx; + wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ hj_inv = 1.0f / hj; - hj2_inv = hj_inv * hj_inv; + hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ xj = r * hj_inv; kernel_deval(xj, &wj, &wj_dx); - wj_dr = hj2_inv * hj2_inv * wj_dx; + wj_dr = hjd_inv * wj_dx; /* Compute dv dot r. */ dvdr = (pi->v[0] - pj->v[0]) * dx[0] + (pi->v[1] - pj->v[1]) * dx[1] + @@ -752,7 +752,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_vec_force( vector r, r2, ri; vector xi, xj; vector hi, hj, hi_inv, hj_inv; - vector hi2_inv, hj2_inv; + vector hid_inv, hjd_inv; vector wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, dvdr; vector w; vector piPOrho2, pjPOrho2, pirho, pjrho, piu, pju; @@ -856,19 +856,19 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_vec_force( hi.v = vec_load(Hi); hi_inv.v = vec_rcp(hi.v); hi_inv.v = hi_inv.v - hi_inv.v * (hi.v * hi_inv.v - vec_set1(1.0f)); - hi2_inv.v = hi_inv.v * hi_inv.v; + hid_inv = pow_dimension_plus_one_vec(hi_inv); xi.v = r.v * hi_inv.v; kernel_deval_vec(&xi, &wi, &wi_dx); - wi_dr.v = hi2_inv.v * hi2_inv.v * wi_dx.v; + wi_dr.v = hid_inv.v * wi_dx.v; /* Get the kernel for hj. */ hj.v = vec_load(Hj); hj_inv.v = vec_rcp(hj.v); hj_inv.v = hj_inv.v - hj_inv.v * (hj.v * hj_inv.v - vec_set1(1.0f)); - hj2_inv.v = hj_inv.v * hj_inv.v; + hjd_inv = pow_dimension_plus_one_vec(hj_inv); xj.v = r.v * hj_inv.v; kernel_deval_vec(&xj, &wj, &wj_dx); - wj_dr.v = hj2_inv.v * hj2_inv.v * wj_dx.v; + wj_dr.v = hjd_inv.v * wj_dx.v; /* Compute dv dot r. */ dvdr.v = ((vi[0].v - vj[0].v) * dx[0].v) + ((vi[1].v - vj[1].v) * dx[1].v) + diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h index a415e725abdf6e9e2262200ee95e871ac751cb81..d2d4450fa12374a8a8dec624c5e54ba3d47b99aa 100644 --- a/src/hydro/Gadget2/hydro.h +++ b/src/hydro/Gadget2/hydro.h @@ -18,7 +18,10 @@ ******************************************************************************/ #include "adiabatic_index.h" +#include "dimension.h" #include "equation_of_state.h" +#include "hydro_properties.h" +#include "kernel_hydro.h" /** * @brief Returns the internal energy of a particle @@ -133,7 +136,14 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep( * @param xp The extended particle data to act upon */ __attribute__((always_inline)) INLINE static void hydro_first_init_part( - struct part *restrict p, struct xpart *restrict xp) {} + struct part *restrict p, struct xpart *restrict xp) { + + p->ti_begin = 0; + p->ti_end = 0; + xp->v_full[0] = p->v[0]; + xp->v_full[1] = p->v[1]; + xp->v_full[2] = p->v[2]; +} /** * @brief Prepares a particle for the density calculation. @@ -169,33 +179,33 @@ __attribute__((always_inline)) INLINE static void hydro_end_density( /* Some smoothing length multiples. */ const float h = p->h; - const float ih = 1.0f / h; - const float ih2 = ih * ih; - const float ih4 = ih2 * ih2; + const float h_inv = 1.0f / h; /* 1/h */ + const float h_inv_dim = pow_dimension(h_inv); /* 1/h^d */ + const float h_inv_dim_plus_one = h_inv_dim * h_inv; /* 1/h^(d+1) */ /* Final operation on the density (add self-contribution). */ p->rho += p->mass * kernel_root; - p->rho_dh -= 3.0f * p->mass * kernel_root; + p->rho_dh -= hydro_dimension * p->mass * kernel_root; p->density.wcount += kernel_root; /* Finish the calculation by inserting the missing h-factors */ - p->rho *= ih * ih2; - p->rho_dh *= ih4; + p->rho *= h_inv_dim; + p->rho_dh *= h_inv_dim_plus_one; p->density.wcount *= kernel_norm; - p->density.wcount_dh *= ih * kernel_gamma * kernel_norm; + p->density.wcount_dh *= h_inv * kernel_gamma * kernel_norm; const float irho = 1.f / p->rho; /* Compute the derivative term */ - p->rho_dh = 1.f / (1.f + 0.33333333f * p->h * p->rho_dh * irho); + p->rho_dh = 1.f / (1.f + hydro_dimension_inv * p->h * p->rho_dh * irho); /* Finish calculation of the velocity curl components */ - p->density.rot_v[0] *= ih4 * irho; - p->density.rot_v[1] *= ih4 * irho; - p->density.rot_v[2] *= ih4 * irho; + p->density.rot_v[0] *= h_inv_dim_plus_one * irho; + p->density.rot_v[1] *= h_inv_dim_plus_one * irho; + p->density.rot_v[2] *= h_inv_dim_plus_one * irho; /* Finish calculation of the velocity divergence */ - p->density.div_v *= ih4 * irho; + p->density.div_v *= h_inv_dim_plus_one * irho; } /** @@ -225,6 +235,7 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force( /* Compute the pressure */ const float half_dt = (ti_current - (p->ti_begin + p->ti_end) / 2) * timeBase; const float pressure = hydro_get_pressure(p, half_dt); + const float irho = 1.f / p->rho; /* Divide the pressure by the density and density gradient */ @@ -307,18 +318,10 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra( __attribute__((always_inline)) INLINE static void hydro_end_force( struct part *restrict p) { - p->force.h_dt *= p->h * 0.333333333f; - p->entropy = hydro_update_entropy(p->rho, p->entropy); - p->entropy_dt *= hydro_update_entropy_rate(p->rho, p->entropy); - - -/* #ifdef EOS_ISOTHERMAL_GAS */ -/* p->entropy_dt = 0; */ -/* float dummy = 1; */ -/* p->entropy = gas_entropy_from_internal_energy(p->rho, dummy); */ -/* #else */ -/* p->entropy_dt *= hydro_gamma_minus_one * pow_minus_gamma_minus_one(p->rho); */ -/* #endif */ + p->force.h_dt *= p->h * hydro_dimension_inv; + + p->entropy_dt *= + 0.5f * hydro_gamma_minus_one * pow_minus_gamma_minus_one(p->rho); } /** diff --git a/src/hydro/Gadget2/hydro_iact.h b/src/hydro/Gadget2/hydro_iact.h index 323f066db6a047db7ae3401a3525afa941bfc047..6766e98e6a6ecda12372bee7354b1cd4ca090885 100644 --- a/src/hydro/Gadget2/hydro_iact.h +++ b/src/hydro/Gadget2/hydro_iact.h @@ -58,7 +58,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( /* Compute contribution to the density */ pi->rho += mj * wi; - pi->rho_dh -= mj * (3.f * wi + ui * wi_dx); + pi->rho_dh -= mj * (hydro_dimension * wi + ui * wi_dx); /* Compute contribution to the number of neighbours */ pi->density.wcount += wi; @@ -71,7 +71,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( /* Compute contribution to the density */ pj->rho += mi * wj; - pj->rho_dh -= mi * (3.f * wj + uj * wj_dx); + pj->rho_dh -= mi * (hydro_dimension * wj + uj * wj_dx); /* Compute contribution to the number of neighbours */ pj->density.wcount += wj; @@ -191,7 +191,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_density( /* Compute density of pi. */ rhoi.v = mj.v * wi.v; - rhoi_dh.v = mj.v * (vec_set1(3.0f) * wi.v + xi.v * wi_dx.v); + rhoi_dh.v = mj.v * (vec_set1(hydro_dimension) * wi.v + xi.v * wi_dx.v); wcounti.v = wi.v; wcounti_dh.v = xi.v * wi_dx.v; div_vi.v = mj.v * dvdr.v * wi_dx.v; @@ -199,7 +199,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_density( /* Compute density of pj. */ rhoj.v = mi.v * wj.v; - rhoj_dh.v = mi.v * (vec_set1(3.0f) * wj.v + xj.v * wj_dx.v); + rhoj_dh.v = mi.v * (vec_set1(hydro_dimension) * wj.v + xj.v * wj_dx.v); wcountj.v = wj.v; wcountj_dh.v = xj.v * wj_dx.v; div_vj.v = mi.v * dvdr.v * wj_dx.v; @@ -253,7 +253,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( /* Compute contribution to the density */ pi->rho += mj * wi; - pi->rho_dh -= mj * (3.f * wi + u * wi_dx); + pi->rho_dh -= mj * (hydro_dimension * wi + u * wi_dx); /* Compute contribution to the number of neighbours */ pi->density.wcount += wi; @@ -356,7 +356,7 @@ runner_iact_nonsym_vec_density(float *R2, float *Dx, float *Hi, float *Hj, /* Compute density of pi. */ rhoi.v = mj.v * wi.v; - rhoi_dh.v = mj.v * (vec_set1(3.0f) * wi.v + xi.v * wi_dx.v); + rhoi_dh.v = mj.v * (vec_set1(hydro_dimension) * wi.v + xi.v * wi_dx.v); wcounti.v = wi.v; wcounti_dh.v = xi.v * wi_dx.v; div_vi.v = mj.v * dvdr.v * wi_dx.v; @@ -402,17 +402,17 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( /* Get the kernel for hi. */ const float hi_inv = 1.0f / hi; - const float hi2_inv = hi_inv * hi_inv; + const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ const float ui = r * hi_inv; kernel_deval(ui, &wi, &wi_dx); - const float wi_dr = hi2_inv * hi2_inv * wi_dx; + const float wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ const float hj_inv = 1.0f / hj; - const float hj2_inv = hj_inv * hj_inv; + const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ const float xj = r * hj_inv; kernel_deval(xj, &wj, &wj_dx); - const float wj_dr = hj2_inv * hj2_inv * wj_dx; + const float wj_dr = hjd_inv * wj_dx; /* Compute gradient terms */ const float P_over_rho2_i = pi->force.P_over_rho2; @@ -469,8 +469,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( pj->force.v_sig = fmaxf(pj->force.v_sig, v_sig); /* Change in entropy */ - pi->entropy_dt += 0.5f * mj * visc_term * dvdr; - pj->entropy_dt += 0.5f * mi * visc_term * dvdr; + pi->entropy_dt += mj * visc_term * dvdr; + pj->entropy_dt += mi * visc_term * dvdr; } /** @@ -485,7 +485,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_force( vector r, r2, ri; vector xi, xj; vector hi, hj, hi_inv, hj_inv; - vector hi2_inv, hj2_inv; + vector hid_inv, hjd_inv; vector wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, dvdr; vector piPOrho, pjPOrho, pirho, pjrho; vector mi, mj; @@ -580,19 +580,19 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_force( hi.v = vec_load(Hi); hi_inv.v = vec_rcp(hi.v); hi_inv.v = hi_inv.v - hi_inv.v * (hi.v * hi_inv.v - vec_set1(1.0f)); - hi2_inv.v = hi_inv.v * hi_inv.v; + hid_inv = pow_dimension_plus_one_vec(hi_inv); /* 1/h^(d+1) */ xi.v = r.v * hi_inv.v; kernel_deval_vec(&xi, &wi, &wi_dx); - wi_dr.v = hi2_inv.v * hi2_inv.v * wi_dx.v; + wi_dr.v = hid_inv.v * wi_dx.v; /* Get the kernel for hj. */ hj.v = vec_load(Hj); hj_inv.v = vec_rcp(hj.v); hj_inv.v = hj_inv.v - hj_inv.v * (hj.v * hj_inv.v - vec_set1(1.0f)); - hj2_inv.v = hj_inv.v * hj_inv.v; + hjd_inv = pow_dimension_plus_one_vec(hj_inv); /* 1/h^(d+1) */ xj.v = r.v * hj_inv.v; kernel_deval_vec(&xj, &wj, &wj_dx); - wj_dr.v = hj2_inv.v * hj2_inv.v * wj_dx.v; + wj_dr.v = hjd_inv.v * wj_dx.v; /* Compute dv dot r. */ dvdr.v = ((vi[0].v - vj[0].v) * dx[0].v) + ((vi[1].v - vj[1].v) * dx[1].v) + @@ -631,7 +631,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_force( pjh_dt.v = mi.v * dvdr.v * ri.v / pirho.v * wj_dr.v; /* Change in entropy */ - entropy_dt.v = vec_set1(0.5f) * visc_term.v * dvdr.v; + entropy_dt.v = visc_term.v * dvdr.v; /* Store the forces back on the particles. */ for (k = 0; k < VEC_SIZE; k++) { @@ -644,7 +644,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_vec_force( pi[k]->force.v_sig = fmaxf(pi[k]->force.v_sig, v_sig.f[k]); pj[k]->force.v_sig = fmaxf(pj[k]->force.v_sig, v_sig.f[k]); pi[k]->entropy_dt += entropy_dt.f[k] * mj.f[k]; - pj[k]->entropy_dt -= entropy_dt.f[k] * mi.f[k]; + pj[k]->entropy_dt += entropy_dt.f[k] * mi.f[k]; } #else @@ -677,17 +677,17 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /* Get the kernel for hi. */ const float hi_inv = 1.0f / hi; - const float hi2_inv = hi_inv * hi_inv; + const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ const float ui = r * hi_inv; kernel_deval(ui, &wi, &wi_dx); - const float wi_dr = hi2_inv * hi2_inv * wi_dx; + const float wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ const float hj_inv = 1.0f / hj; - const float hj2_inv = hj_inv * hj_inv; + const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ const float xj = r * hj_inv; kernel_deval(xj, &wj, &wj_dx); - const float wj_dr = hj2_inv * hj2_inv * wj_dx; + const float wj_dr = hjd_inv * wj_dx; /* Compute gradient terms */ const float P_over_rho2_i = pi->force.P_over_rho2; @@ -738,7 +738,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( pi->force.v_sig = fmaxf(pi->force.v_sig, v_sig); /* Change in entropy */ - pi->entropy_dt += 0.5f * mj * visc_term * dvdr; + pi->entropy_dt += mj * visc_term * dvdr; } /** @@ -753,7 +753,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_vec_force( vector r, r2, ri; vector xi, xj; vector hi, hj, hi_inv, hj_inv; - vector hi2_inv, hj2_inv; + vector hid_inv, hjd_inv; vector wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, dvdr; vector piPOrho, pjPOrho, pirho, pjrho; vector mj; @@ -845,19 +845,19 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_vec_force( hi.v = vec_load(Hi); hi_inv.v = vec_rcp(hi.v); hi_inv.v = hi_inv.v - hi_inv.v * (hi.v * hi_inv.v - vec_set1(1.0f)); - hi2_inv.v = hi_inv.v * hi_inv.v; + hid_inv = pow_dimension_plus_one_vec(hi_inv); xi.v = r.v * hi_inv.v; kernel_deval_vec(&xi, &wi, &wi_dx); - wi_dr.v = hi2_inv.v * hi2_inv.v * wi_dx.v; + wi_dr.v = hid_inv.v * wi_dx.v; /* Get the kernel for hj. */ hj.v = vec_load(Hj); hj_inv.v = vec_rcp(hj.v); hj_inv.v = hj_inv.v - hj_inv.v * (hj.v * hj_inv.v - vec_set1(1.0f)); - hj2_inv.v = hj_inv.v * hj_inv.v; + hjd_inv = pow_dimension_plus_one_vec(hj_inv); xj.v = r.v * hj_inv.v; kernel_deval_vec(&xj, &wj, &wj_dx); - wj_dr.v = hj2_inv.v * hj2_inv.v * wj_dx.v; + wj_dr.v = hjd_inv.v * wj_dx.v; /* Compute dv dot r. */ dvdr.v = ((vi[0].v - vj[0].v) * dx[0].v) + ((vi[1].v - vj[1].v) * dx[1].v) + @@ -894,7 +894,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_vec_force( pih_dt.v = mj.v * dvdr.v * ri.v / pjrho.v * wi_dr.v; /* Change in entropy */ - entropy_dt.v = vec_set1(0.5f) * mj.v * visc_term.v * dvdr.v; + entropy_dt.v = mj.v * visc_term.v * dvdr.v; /* Store the forces back on the particles. */ for (k = 0; k < VEC_SIZE; k++) { diff --git a/src/hydro/Gadget2/hydro_io.h b/src/hydro/Gadget2/hydro_io.h index 17aae18ab07c3c6476c0e48ea1a657ca65df71dc..54f55c79aaf489942f59be2d3623627e30f672a2 100644 --- a/src/hydro/Gadget2/hydro_io.h +++ b/src/hydro/Gadget2/hydro_io.h @@ -18,6 +18,7 @@ ******************************************************************************/ #include "adiabatic_index.h" +#include "hydro.h" #include "io_properties.h" #include "kernel_hydro.h" #include "equation_of_state.h" @@ -55,10 +56,12 @@ void hydro_read_particles(struct part* parts, struct io_props* list, float convert_u(struct engine* e, struct part* p) { - return gas_internal_energy_from_entropy(p->rho, p->entropy); + return hydro_get_internal_energy(p, 0); +} + +float convert_P(struct engine* e, struct part* p) { - /* return p->entropy * pow_gamma_minus_one(p->rho) * */ - /* hydro_one_over_gamma_minus_one; */ + return hydro_get_pressure(p, 0); } /** @@ -71,7 +74,7 @@ float convert_u(struct engine* e, struct part* p) { void hydro_write_particles(struct part* parts, struct io_props* list, int* num_fields) { - *num_fields = 9; + *num_fields = 10; /* List what we want to write */ list[0] = io_make_output_field("Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, @@ -93,6 +96,8 @@ void hydro_write_particles(struct part* parts, struct io_props* list, list[8] = io_make_output_field_convert_part("InternalEnergy", FLOAT, 1, UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, rho, convert_u); + list[9] = io_make_output_field_convert_part( + "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, rho, convert_P); } /** diff --git a/src/hydro/Minimal/hydro.h b/src/hydro/Minimal/hydro.h index 444920ab2bec940af9c10ea0a6ba471b2ab79762..842a028b9031b3c1cf36e4735089d05e038abdca 100644 --- a/src/hydro/Minimal/hydro.h +++ b/src/hydro/Minimal/hydro.h @@ -145,6 +145,11 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep( __attribute__((always_inline)) INLINE static void hydro_first_init_part( struct part *restrict p, struct xpart *restrict xp) { + p->ti_begin = 0; + p->ti_end = 0; + xp->v_full[0] = p->v[0]; + xp->v_full[1] = p->v[1]; + xp->v_full[2] = p->v[2]; xp->u_full = p->u; } @@ -182,25 +187,25 @@ __attribute__((always_inline)) INLINE static void hydro_end_density( /* Some smoothing length multiples. */ const float h = p->h; - const float ih = 1.0f / h; - const float ih2 = ih * ih; - const float ih4 = ih2 * ih2; + const float h_inv = 1.0f / h; /* 1/h */ + const float h_inv_dim = pow_dimension(h_inv); /* 1/h^d */ + const float h_inv_dim_plus_one = h_inv_dim * h_inv; /* 1/h^(d+1) */ /* Final operation on the density (add self-contribution). */ p->rho += p->mass * kernel_root; - p->rho_dh -= 3.0f * p->mass * kernel_root; + p->rho_dh -= hydro_dimension * p->mass * kernel_root; p->density.wcount += kernel_root; /* Finish the calculation by inserting the missing h-factors */ - p->rho *= ih * ih2; - p->rho_dh *= ih4; + p->rho *= h_inv_dim; + p->rho_dh *= h_inv_dim_plus_one; p->density.wcount *= kernel_norm; - p->density.wcount_dh *= ih * kernel_gamma * kernel_norm; + p->density.wcount_dh *= h_inv * kernel_gamma * kernel_norm; const float irho = 1.f / p->rho; /* Compute the derivative term */ - p->rho_dh = 1.f / (1.f + 0.33333333f * p->h * p->rho_dh * irho); + p->rho_dh = 1.f / (1.f + hydro_dimension_inv * p->h * p->rho_dh * irho); } /** @@ -281,7 +286,7 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra( __attribute__((always_inline)) INLINE static void hydro_end_force( struct part *restrict p) { - p->force.h_dt *= p->h * 0.333333333f; + p->force.h_dt *= p->h * hydro_dimension_inv; } /** diff --git a/src/hydro/Minimal/hydro_iact.h b/src/hydro/Minimal/hydro_iact.h index 311bdc90744059ea1272c2ca6cf419e5fbc1ba82..9eda45760248ebc0dde18e503abe0b1288659518 100644 --- a/src/hydro/Minimal/hydro_iact.h +++ b/src/hydro/Minimal/hydro_iact.h @@ -48,7 +48,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( kernel_deval(xi, &wi, &wi_dx); pi->rho += mj * wi; - pi->rho_dh -= mj * (3.f * wi + xi * wi_dx); + pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx); pi->density.wcount += wi; pi->density.wcount_dh -= xi * wi_dx; @@ -58,7 +58,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( kernel_deval(xj, &wj, &wj_dx); pj->rho += mi * wj; - pj->rho_dh -= mi * (3.f * wj + xj * wj_dx); + pj->rho_dh -= mi * (hydro_dimension * wj + xj * wj_dx); pj->density.wcount += wj; pj->density.wcount_dh -= xj * wj_dx; } @@ -93,7 +93,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( kernel_deval(xi, &wi, &wi_dx); pi->rho += mj * wi; - pi->rho_dh -= mj * (3.f * wi + xi * wi_dx); + pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx); pi->density.wcount += wi; pi->density.wcount_dh -= xi * wi_dx; } @@ -128,19 +128,19 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( /* Get the kernel for hi. */ const float hi_inv = 1.0f / hi; - const float hi2_inv = hi_inv * hi_inv; + const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ const float xi = r * hi_inv; float wi, wi_dx; kernel_deval(xi, &wi, &wi_dx); - const float wi_dr = hi2_inv * hi2_inv * wi_dx; + const float wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ const float hj_inv = 1.0f / hj; - const float hj2_inv = hj_inv * hj_inv; + const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ const float xj = r * hj_inv; float wj, wj_dx; kernel_deval(xj, &wj, &wj_dx); - const float wj_dr = hj2_inv * hj2_inv * wj_dx; + const float wj_dr = hjd_inv * wj_dx; /* Compute gradient terms */ const float P_over_rho_i = pressurei / (rhoi * rhoi) * pi->rho_dh; @@ -211,19 +211,19 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /* Get the kernel for hi. */ const float hi_inv = 1.0f / hi; - const float hi2_inv = hi_inv * hi_inv; + const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ const float xi = r * hi_inv; float wi, wi_dx; kernel_deval(xi, &wi, &wi_dx); - const float wi_dr = hi2_inv * hi2_inv * wi_dx; + const float wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ const float hj_inv = 1.0f / hj; - const float hj2_inv = hj_inv * hj_inv; + const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ const float xj = r * hj_inv; float wj, wj_dx; kernel_deval(xj, &wj, &wj_dx); - const float wj_dr = hj2_inv * hj2_inv * wj_dx; + const float wj_dr = hjd_inv * wj_dx; /* Compute gradient terms */ const float P_over_rho_i = pressurei / (rhoi * rhoi) * pi->rho_dh; diff --git a/src/hydro_properties.c b/src/hydro_properties.c index 8dde4a23be3705b4a679c6d17eb8f28c1a8ff6b7..c425ecce6de38b32645b367886e039bb950df68d 100644 --- a/src/hydro_properties.c +++ b/src/hydro_properties.c @@ -27,6 +27,7 @@ /* Local headers. */ #include "adiabatic_index.h" #include "common_io.h" +#include "dimension.h" #include "error.h" #include "hydro.h" #include "kernel_hydro.h" @@ -39,8 +40,7 @@ void hydro_props_init(struct hydro_props *p, /* Kernel properties */ p->eta_neighbours = parser_get_param_float(params, "SPH:resolution_eta"); - const float eta3 = p->eta_neighbours * p->eta_neighbours * p->eta_neighbours; - p->target_neighbours = eta3 * kernel_norm; + p->target_neighbours = pow_dimension(p->eta_neighbours) * kernel_norm; p->delta_neighbours = parser_get_param_float(params, "SPH:delta_neighbours"); /* Ghost stuff */ @@ -51,21 +51,26 @@ void hydro_props_init(struct hydro_props *p, p->CFL_condition = parser_get_param_float(params, "SPH:CFL_condition"); const float max_volume_change = parser_get_opt_param_float( params, "SPH:max_volume_change", hydro_props_default_volume_change); - p->log_max_h_change = logf(powf(max_volume_change, 0.33333333333f)); + p->log_max_h_change = logf(powf(max_volume_change, hydro_dimension_inv)); } void hydro_props_print(const struct hydro_props *p) { message("Adiabatic index gamma: %f.", hydro_gamma); - message("Hydrodynamic scheme: %s.", SPH_IMPLEMENTATION); + + message("Hydrodynamic scheme: %s in %dD.", SPH_IMPLEMENTATION, + (int)hydro_dimension); + message("Hydrodynamic kernel: %s with %.2f +/- %.2f neighbours (eta=%f).", kernel_name, p->target_neighbours, p->delta_neighbours, p->eta_neighbours); + message("Hydrodynamic integration: CFL parameter: %.4f.", p->CFL_condition); + message( "Hydrodynamic integration: Max change of volume: %.2f " "(max|dlog(h)/dt|=%f).", - powf(expf(p->log_max_h_change), 3.f), p->log_max_h_change); + powf(expf(p->log_max_h_change), hydro_dimension), p->log_max_h_change); if (p->max_smoothing_iterations != hydro_props_default_max_iterations) message("Maximal iterations in ghost task set to %d (default is %d)", @@ -76,6 +81,7 @@ void hydro_props_print(const struct hydro_props *p) { void hydro_props_print_snapshot(hid_t h_grpsph, const struct hydro_props *p) { writeAttribute_f(h_grpsph, "Adiabatic index", hydro_gamma); + writeAttribute_i(h_grpsph, "Dimension", (int)hydro_dimension); writeAttribute_s(h_grpsph, "Scheme", SPH_IMPLEMENTATION); writeAttribute_s(h_grpsph, "Kernel function", kernel_name); writeAttribute_f(h_grpsph, "Kernel target N_ngb", p->target_neighbours); diff --git a/src/kernel_hydro.h b/src/kernel_hydro.h index 7a73bf4f3d51550c5bf9096c0121d0faab819c0b..a53465571dbea73c1e2460491500bf6561066e85 100644 --- a/src/kernel_hydro.h +++ b/src/kernel_hydro.h @@ -20,10 +20,23 @@ #ifndef SWIFT_KERNEL_HYDRO_H #define SWIFT_KERNEL_HYDRO_H +/** + * @file kernel_hydro.h + * @brief Kernel functions for SPH (scalar and vector version). + * + * All constants and kernel coefficients are taken from table 1 of + * Dehnen & Aly, MNRAS, 425, pp. 1062-1082 (2012). + */ + +/* Config parameters. */ +#include "../config.h" + +/* Some standard headers. */ #include <math.h> -/* Includes. */ +/* Local headers. */ #include "const.h" +#include "dimension.h" #include "error.h" #include "inline.h" #include "vector.h" @@ -35,8 +48,16 @@ #define kernel_name "Cubic spline (M4)" #define kernel_degree 3 /* Degree of the polynomial */ #define kernel_ivals 2 /* Number of branches */ +#if defined(HYDRO_DIMENSION_3D) #define kernel_gamma ((float)(1.825742)) #define kernel_constant ((float)(16. * M_1_PI)) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma ((float)(1.778002)) +#define kernel_constant ((float)(80. * M_1_PI / 7.)) +#elif defined(HYDRO_DIMENSION_1D) +#define kernel_gamma ((float)(1.732051)) +#define kernel_constant ((float)(8. / 3.)) +#endif static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] __attribute__((aligned(16))) = {3.f, -3.f, 0.f, 0.5f, /* 0 < u < 0.5 */ -1.f, 3.f, -3.f, 1.f, /* 0.5 < u < 1 */ @@ -47,10 +68,18 @@ static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] /* Coefficients for the kernel. */ #define kernel_name "Quartic spline (M5)" -#define kernel_degree 4 -#define kernel_ivals 5 +#define kernel_degree 4 /* Degree of the polynomial */ +#define kernel_ivals 5 /* Number of branches */ +#if defined(HYDRO_DIMENSION_3D) #define kernel_gamma ((float)(2.018932)) #define kernel_constant ((float)(15625. * M_1_PI / 512.)) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma ((float)(1.977173)) +#define kernel_constant ((float)(46875. * M_1_PI / 2398.)) +#elif defined(HYDRO_DIMENSION_1D) +#define kernel_gamma ((float)(1.936492)) +#define kernel_constant ((float)(3125. / 768.)) +#endif static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] __attribute__((aligned(16))) = { 6.f, 0.f, -2.4f, 0.f, 0.368f, /* 0 < u < 0.2 */ @@ -65,10 +94,18 @@ static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] /* Coefficients for the kernel. */ #define kernel_name "Quintic spline (M6)" -#define kernel_degree 5 -#define kernel_ivals 3 +#define kernel_degree 5 /* Degree of the polynomial */ +#define kernel_ivals 3 /* Number of branches */ +#if defined(HYDRO_DIMENSION_3D) #define kernel_gamma ((float)(2.195775)) #define kernel_constant ((float)(2187. * M_1_PI / 40.)) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma ((float)(2.158131)) +#define kernel_constant ((float)(15309. * M_1_PI / 478.)) +#elif defined(HYDRO_DIMENSION_1D) +#define kernel_gamma ((float)(2.121321)) +#define kernel_constant ((float)(243. / 40.)) +#endif static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] __attribute__((aligned(16))) = { -10.f, 10.f, 0.f, @@ -85,10 +122,17 @@ static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] /* Coefficients for the kernel. */ #define kernel_name "Wendland C2" -#define kernel_degree 5 -#define kernel_ivals 1 +#define kernel_degree 5 /* Degree of the polynomial */ +#define kernel_ivals 1 /* Number of branches */ +#if defined(HYDRO_DIMENSION_3D) #define kernel_gamma ((float)(1.936492)) #define kernel_constant ((float)(21. * M_1_PI / 2.)) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma ((float)(1.897367)) +#define kernel_constant ((float)(7. * M_1_PI)) +#elif defined(HYDRO_DIMENSION_1D) +#error "Wendland C2 kernel not defined in 1D." +#endif static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] __attribute__((aligned(16))) = { 4.f, -15.f, 20.f, -10.f, 0.f, 1.f, /* 0 < u < 1 */ @@ -99,10 +143,17 @@ static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] /* Coefficients for the kernel. */ #define kernel_name "Wendland C4" -#define kernel_degree 8 -#define kernel_ivals 1 +#define kernel_degree 8 /* Degree of the polynomial */ +#define kernel_ivals 1 /* Number of branches */ +#if defined(HYDRO_DIMENSION_3D) #define kernel_gamma ((float)(2.207940)) #define kernel_constant ((float)(495. * M_1_PI / 32.)) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma ((float)(2.171239)) +#define kernel_constant ((float)(9. * M_1_PI)) +#elif defined(HYDRO_DIMENSION_1D) +#error "Wendland C4 kernel not defined in 1D." +#endif static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] __attribute__((aligned(16))) = { 11.666667f, -64.f, 140.f, -149.333333f, 70.f, @@ -115,10 +166,17 @@ static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] /* Coefficients for the kernel. */ #define kernel_name "Wendland C6" -#define kernel_degree 11 -#define kernel_ivals 1 +#define kernel_degree 11 /* Degree of the polynomial */ +#define kernel_ivals 1 /* Number of branches */ +#if defined(HYDRO_DIMENSION_3D) #define kernel_gamma ((float)(2.449490)) #define kernel_constant ((float)(1365. * M_1_PI / 64.)) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma ((float)(2.415230)) +#define kernel_constant ((float)(78. * M_1_PI / 7.)) +#elif defined(HYDRO_DIMENSION_1D) +#error "Wendland C6 kernel not defined in 1D." +#endif static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] __attribute__((aligned(16))) = { 32.f, -231.f, 704.f, -1155.f, 1056.f, -462.f, @@ -137,30 +195,50 @@ static const float kernel_coeffs[(kernel_degree + 1) * (kernel_ivals + 1)] /* Ok, now comes the real deal. */ /* First some powers of gamma = H/h */ +#define kernel_gamma_inv ((float)(1. / kernel_gamma)) #define kernel_gamma2 ((float)(kernel_gamma * kernel_gamma)) -#define kernel_gamma3 ((float)(kernel_gamma * kernel_gamma * kernel_gamma)) -#define kernel_gamma4 \ + +/* define gamma^d, gamma^(d+1), 1/gamma^d and 1/gamma^(d+1) */ +#if defined(HYDRO_DIMENSION_3D) +#define kernel_gamma_dim ((float)(kernel_gamma * kernel_gamma * kernel_gamma)) +#define kernel_gamma_dim_plus_one \ ((float)(kernel_gamma * kernel_gamma * kernel_gamma * kernel_gamma)) -#define kernel_igamma ((float)(1. / kernel_gamma)) -#define kernel_igamma2 ((float)(kernel_igamma * kernel_igamma)) -#define kernel_igamma3 ((float)(kernel_igamma * kernel_igamma * kernel_igamma)) -#define kernel_igamma4 \ - ((float)(kernel_igamma * kernel_igamma * kernel_igamma * kernel_igamma)) +#define kernel_gamma_inv_dim \ + ((float)(1. / (kernel_gamma * kernel_gamma * kernel_gamma))) +#define kernel_gamma_inv_dim_plus_one \ + ((float)(1. / (kernel_gamma * kernel_gamma * kernel_gamma * kernel_gamma))) +#elif defined(HYDRO_DIMENSION_2D) +#define kernel_gamma_dim ((float)(kernel_gamma * kernel_gamma)) +#define kernel_gamma_dim_plus_one \ + ((float)(kernel_gamma * kernel_gamma * kernel_gamma)) +#define kernel_gamma_inv_dim ((float)(1. / (kernel_gamma * kernel_gamma))) +#define kernel_gamma_inv_dim_plus_one \ + ((float)(1. / (kernel_gamma * kernel_gamma * kernel_gamma))) +#elif defined(HYDRO_DIMENSION_1D) +#define kernel_gamma_dim ((float)(kernel_gamma)) +#define kernel_gamma_dim_plus_one ((float)(kernel_gamma * kernel_gamma)) +#define kernel_gamma_inv_dim ((float)(1. / (kernel_gamma))) +#define kernel_gamma_inv_dim_plus_one \ + ((float)(1. / (kernel_gamma * kernel_gamma))) +#endif -/* The number of branches */ +/* The number of branches (floating point conversion) */ #define kernel_ivals_f ((float)(kernel_ivals)) /* Kernel self contribution (i.e. W(0,h)) */ -#define kernel_root \ - ((float)(kernel_coeffs[kernel_degree]) * kernel_constant * kernel_igamma3) +#define kernel_root \ + ((float)(kernel_coeffs[kernel_degree]) * kernel_constant * \ + kernel_gamma_inv_dim) /* Kernel normalisation constant (volume term) */ -#define kernel_norm ((float)(4.0 * M_PI * kernel_gamma3 / 3.0)) +#define kernel_norm ((float)(hydro_dimention_unit_sphere * kernel_gamma_dim)) + +/* ------------------------------------------------------------------------- */ /** * @brief Computes the kernel function and its derivative. * - * Return 0 if $u > \\gamma = H/h$ + * Returns garbage if $u > \\gamma = H/h$ * * @param u The ratio of the distance to the smoothing length $u = x/h$. * @param W (return) The value of the kernel function $W(x,h)$. @@ -170,17 +248,17 @@ __attribute__((always_inline)) INLINE static void kernel_deval( float u, float *restrict W, float *restrict dW_dx) { /* Go to the range [0,1[ from [0,H[ */ - const float x = u * kernel_igamma; + const float x = u * kernel_gamma_inv; -#if kernel_ivals == 1 - /* Only one branch in this case */ - const float *const coeffs = &kernel_coeffs[0]; -#else + //#if kernel_ivals == 1 + ///* Only one branch in this case */ + // const float *const coeffs = &kernel_coeffs[0]; + //#else /* Pick the correct branch of the kernel */ const int temp = (int)(x * kernel_ivals_f); const int ind = temp > kernel_ivals ? kernel_ivals : temp; const float *const coeffs = &kernel_coeffs[ind * (kernel_degree + 1)]; -#endif + //#endif /* First two terms of the polynomial ... */ float w = coeffs[0] * x + coeffs[1]; @@ -193,30 +271,32 @@ __attribute__((always_inline)) INLINE static void kernel_deval( } /* Return everything */ - *W = w * kernel_constant * kernel_igamma3; - *dW_dx = dw_dx * kernel_constant * kernel_igamma4; + *W = w * kernel_constant * kernel_gamma_inv_dim; + *dW_dx = dw_dx * kernel_constant * kernel_gamma_inv_dim_plus_one; } /** * @brief Computes the kernel function. * + * Returns garbage if $u > \\gamma = H/h$ + * * @param u The ratio of the distance to the smoothing length $u = x/h$. * @param W (return) The value of the kernel function $W(x,h)$. */ __attribute__((always_inline)) INLINE static void kernel_eval( float u, float *restrict W) { /* Go to the range [0,1[ from [0,H[ */ - const float x = u * kernel_igamma; + const float x = u * kernel_gamma_inv; -#if kernel_ivals == 1 - /* Only one branch in this case */ - const float *const coeffs = &kernel_coeffs[0]; -#else + //#if kernel_ivals == 1 + ///* Only one branch in this case */ + // const float *const coeffs = &kernel_coeffs[0]; + //#else /* Pick the correct branch of the kernel */ const int temp = (int)(x * kernel_ivals_f); const int ind = temp > kernel_ivals ? kernel_ivals : temp; const float *const coeffs = &kernel_coeffs[ind * (kernel_degree + 1)]; -#endif + //#endif /* First two terms of the polynomial ... */ float w = coeffs[0] * x + coeffs[1]; @@ -225,20 +305,24 @@ __attribute__((always_inline)) INLINE static void kernel_eval( for (int k = 2; k <= kernel_degree; k++) w = x * w + coeffs[k]; /* Return everything */ - *W = w * kernel_constant * kernel_igamma3; + *W = w * kernel_constant * kernel_gamma_inv_dim; } +/* ------------------------------------------------------------------------- */ + #ifdef WITH_VECTORIZATION -static const vector kernel_igamma_vec = FILL_VEC((float)kernel_igamma); +static const vector kernel_gamma_inv_vec = FILL_VEC((float)kernel_gamma_inv); static const vector kernel_ivals_vec = FILL_VEC((float)kernel_ivals); static const vector kernel_constant_vec = FILL_VEC((float)kernel_constant); -static const vector kernel_igamma3_vec = FILL_VEC((float)kernel_igamma3); +static const vector kernel_gamma_inv_dim_vec = + FILL_VEC((float)kernel_gamma_inv_dim); -static const vector kernel_igamma4_vec = FILL_VEC((float)kernel_igamma4); +static const vector kernel_gamma_inv_dim_plus_one_vec = + FILL_VEC((float)kernel_gamma_inv_dim_plus_one); /** * @brief Computes the kernel function and its derivative (Vectorised version). @@ -254,7 +338,7 @@ __attribute__((always_inline)) INLINE static void kernel_deval_vec( /* Go to the range [0,1[ from [0,H[ */ vector x; - x.v = u->v * kernel_igamma_vec.v; + x.v = u->v * kernel_gamma_inv_vec.v; /* Load x and get the interval id. */ vector ind; @@ -277,8 +361,9 @@ __attribute__((always_inline)) INLINE static void kernel_deval_vec( } /* Return everything */ - w->v = w->v * kernel_constant_vec.v * kernel_igamma3_vec.v; - dw_dx->v = dw_dx->v * kernel_constant_vec.v * kernel_igamma4_vec.v; + w->v = w->v * kernel_constant_vec.v * kernel_gamma_inv_dim_vec.v; + dw_dx->v = + dw_dx->v * kernel_constant_vec.v * kernel_gamma_inv_dim_plus_one_vec.v; } #endif diff --git a/src/space.c b/src/space.c index 8b7e5f81b539fb02da44dac67a3575356c08c45e..2a6250e1c19eef77b48e9e54dc813312e64aa32d 100644 --- a/src/space.c +++ b/src/space.c @@ -41,8 +41,11 @@ /* Local headers. */ #include "atomic.h" +#include "const.h" #include "engine.h" #include "error.h" +#include "gravity.h" +#include "hydro.h" #include "kernel_hydro.h" #include "lock.h" #include "minmax.h" @@ -1416,6 +1419,59 @@ struct cell *space_getcell(struct space *s) { return c; } +/** + * @brief Initialises all the particles by setting them into a valid state + * + * Calls hydro_first_init_part() on all the particles + */ +void space_init_parts(struct space *s) { + + const size_t nr_parts = s->nr_parts; + struct part *restrict p = s->parts; + struct xpart *restrict xp = s->xparts; + + for (size_t i = 0; i < nr_parts; ++i) { + +#ifdef HYDRO_DIMENSION_2D + p[i].x[2] = 0.f; + p[i].v[2] = 0.f; +#endif + +#ifdef HYDRO_DIMENSION_1D + p[i].x[1] = p[i].x[2] = 0.f; + p[i].v[1] = p[i].v[2] = 0.f; +#endif + + hydro_first_init_part(&p[i], &xp[i]); + } +} + +/** + * @brief Initialises all the g-particles by setting them into a valid state + * + * Calls gravity_first_init_gpart() on all the particles + */ +void space_init_gparts(struct space *s) { + + const size_t nr_gparts = s->nr_gparts; + struct gpart *restrict gp = s->gparts; + + for (size_t i = 0; i < nr_gparts; ++i) { + +#ifdef HYDRO_DIMENSION_2D + gp[i].x[2] = 0.f; + gp[i].v_full[2] = 0.f; +#endif + +#ifdef HYDRO_DIMENSION_1D + gp[i].x[1] = gp[i].x[2] = 0.f; + gp[i].v_full[1] = gp[i].v_full[2] = 0.f; +#endif + + gravity_first_init_gpart(&gp[i]); + } +} + /** * @brief Split the space into cells given the array of particles. * @@ -1549,6 +1605,10 @@ void space_init(struct space *s, const struct swift_params *params, bzero(s->xparts, Npart * sizeof(struct xpart)); } + /* Set the particles in a state where they are ready for a run */ + space_init_parts(s); + space_init_gparts(s); + /* Init the space lock. */ if (lock_init(&s->lock) != 0) error("Failed to create space spin-lock."); diff --git a/src/space.h b/src/space.h index 180759f2af69dd0d77e6e681229353358d554291..6fe3681c85068979a555ff1d78e32ba7577cf3f0 100644 --- a/src/space.h +++ b/src/space.h @@ -162,6 +162,8 @@ void space_split(struct space *s, struct cell *cells, int verbose); void space_do_split(struct space *s, struct cell *c); void space_do_parts_sort(); void space_do_gparts_sort(); +void space_init_parts(struct space *s); +void space_init_gparts(struct space *s); void space_link_cleanup(struct space *s); void space_clean(struct space *s); diff --git a/src/tools.c b/src/tools.c index b4a37328ff7df9de76adceebb5ed6801fa417851..b64e17849081994e1969d5f8de0636768dcb729a 100644 --- a/src/tools.c +++ b/src/tools.c @@ -144,10 +144,7 @@ void pairs_single_density(double *dim, long long int pid, p = parts[k]; printf("pairs_single: part[%i].id == %lli.\n", k, pid); - p.rho = 0.0; - p.density.wcount = 0.0; - // p.icount = 0; - p.rho_dh = 0.0; + hydro_init_part(&p); /* Loop over all particle pairs. */ for (k = 0; k < N; k++) { @@ -487,25 +484,24 @@ void density_dump(int N) { */ void engine_single_density(double *dim, long long int pid, struct part *restrict parts, int N, int periodic) { - int i, k; double r2, dx[3]; - float fdx[3], ih; + float fdx[3]; struct part p; /* Find "our" part. */ + int k; for (k = 0; k < N && parts[k].id != pid; k++) ; if (k == N) error("Part not found."); p = parts[k]; /* Clear accumulators. */ - ih = 1.0f / p.h; hydro_init_part(&p); /* Loop over all particle pairs (force). */ - for (k = 0; k < N; k++) { + for (int k = 0; k < N; k++) { if (parts[k].id == p.id) continue; - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { dx[i] = p.x[i] - parts[k].x[i]; if (periodic) { if (dx[i] < -dim[i] / 2) @@ -522,12 +518,9 @@ void engine_single_density(double *dim, long long int pid, } /* Dump the result. */ - p.rho = ih * ih * ih * (p.rho + p.mass * kernel_root); - p.rho_dh = p.rho_dh * ih * ih * ih * ih; - p.density.wcount = - (p.density.wcount + kernel_root) * (4.0f / 3.0 * M_PI * kernel_gamma3); - message("part %lli (h=%e) has wcount=%e, rho=%e, rho_dh=%e.", p.id, p.h, - p.density.wcount, p.rho, p.rho_dh); + hydro_end_density(&p, 0); + message("part %lli (h=%e) has wcount=%e, rho=%e.", p.id, p.h, + p.density.wcount, p.rho); fflush(stdout); } diff --git a/tests/difffloat.py b/tests/difffloat.py index 57707c5920997e3ef688606a0839f59a69d2e4f2..e0f0864372264899c6de1bf2f83ab678b7dd9ead 100644 --- a/tests/difffloat.py +++ b/tests/difffloat.py @@ -89,13 +89,12 @@ for i in range(n_lines_to_check): abs_diff = abs(data1[i,j] - data2[i,j]) sum = abs(data1[i,j] + data2[i,j]) - if abs(data1[i,j]) + abs(data2[i,j]) < 2.5e-7: continue if sum > 0: rel_diff = abs(data1[i,j] - data2[i,j]) / sum else: rel_diff = 0. - if( abs_diff > absTol[j]): + if( abs_diff > 1.1*absTol[j]): print "Absolute difference larger than tolerance (%e) for particle %d, column %d:"%(absTol[j], i,j) print "%10s: a = %e"%("File 1", data1[i,j]) print "%10s: b = %e"%("File 2", data2[i,j]) @@ -103,7 +102,9 @@ for i in range(n_lines_to_check): print "" error = True - if( rel_diff > relTol[j]): + if abs(data1[i,j]) < 1e-6 and + abs(data2[i,j]) < 1e-6 : continue + + if( rel_diff > 1.1*relTol[j]): print "Relative difference larger than tolerance (%e) for particle %d, column %d:"%(relTol[j], i,j) print "%10s: a = %e"%("File 1", data1[i,j]) print "%10s: b = %e"%("File 2", data2[i,j]) diff --git a/tests/test125cells.c b/tests/test125cells.c index 4a045307a7d731a71dabaa96ed39b66d013d4627..37d530fa7b3750a3304cb11868ac43e6df62781d 100644 --- a/tests/test125cells.c +++ b/tests/test125cells.c @@ -247,9 +247,6 @@ struct cell *make_cell(size_t n, const double offset[3], double size, double h, part->ti_begin = 0; part->ti_end = 1; - xpart->v_full[0] = part->v[0]; - xpart->v_full[1] = part->v[1]; - xpart->v_full[2] = part->v[2]; hydro_first_init_part(part, xpart); ++part; ++xpart; @@ -328,15 +325,16 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, hydro_get_soundspeed(&main_cell->parts[pid], 0.f), main_cell->parts[pid].a_hydro[0], main_cell->parts[pid].a_hydro[1], main_cell->parts[pid].a_hydro[2], main_cell->parts[pid].force.h_dt, - main_cell->parts[pid].force.v_sig, #if defined(GADGET2_SPH) - main_cell->parts[pid].entropy_dt, 0.f + main_cell->parts[pid].force.v_sig, main_cell->parts[pid].entropy_dt, + 0.f #elif defined(DEFAULT_SPH) - 0.f, main_cell->parts[pid].force.u_dt + main_cell->parts[pid].force.v_sig, 0.f, + main_cell->parts[pid].force.u_dt #elif defined(MINIMAL_SPH) - 0.f, main_cell->parts[pid].u_dt + main_cell->parts[pid].force.v_sig, 0.f, main_cell->parts[pid].u_dt #else - 0.f, 0.f + 0.f, 0.f, 0.f #endif ); } @@ -447,7 +445,7 @@ int main(int argc, char *argv[]) { message("Hydro implementation: %s", SPH_IMPLEMENTATION); message("Smoothing length: h = %f", h * size); message("Kernel: %s", kernel_name); - message("Neighbour target: N = %f", h * h * h * kernel_norm); + message("Neighbour target: N = %f", pow_dimension(h) * kernel_norm); message("Density target: rho = %f", rho); message("div_v target: div = %f", vel == 2 ? 3.f : 0.f); message("curl_v target: curl = [0., 0., %f]", vel == 3 ? -2.f : 0.f); @@ -460,6 +458,11 @@ int main(int argc, char *argv[]) { printf("\n"); +#if !defined(HYDRO_DIMENSION_3D) + message("test125cells only useful in 3D. Change parameters in const.h !"); + return 1; +#endif + /* Build the infrastructure */ struct space space; space.periodic = 0; @@ -469,8 +472,8 @@ int main(int argc, char *argv[]) { prog_const.const_newton_G = 1.f; struct hydro_props hp; - hp.target_neighbours = h * h * h * kernel_norm; - hp.delta_neighbours = 1.; + hp.target_neighbours = pow_dimension(h) * kernel_norm; + hp.delta_neighbours = 2.; hp.max_smoothing_iterations = 1; hp.CFL_condition = 0.1; diff --git a/tests/test27cells.c b/tests/test27cells.c index 8dc8af5dad60c5d59e66411d9612153afcf86114..3d1d56d9245f9a9aee9e705754c46bb22ba0ef0a 100644 --- a/tests/test27cells.c +++ b/tests/test27cells.c @@ -147,8 +147,6 @@ void clean_up(struct cell *ci) { */ void zero_particle_fields(struct cell *c) { for (size_t pid = 0; pid < c->count; pid++) { - c->parts[pid].rho = 0.f; - c->parts[pid].rho_dh = 0.f; hydro_init_part(&c->parts[pid]); } } @@ -187,7 +185,12 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, main_cell->parts[pid].x[1], main_cell->parts[pid].x[2], main_cell->parts[pid].v[0], main_cell->parts[pid].v[1], main_cell->parts[pid].v[2], main_cell->parts[pid].rho, - main_cell->parts[pid].rho_dh, main_cell->parts[pid].density.wcount, +#if defined(GIZMO_SPH) + 0.f, +#else + main_cell->parts[pid].rho_dh, +#endif + main_cell->parts[pid].density.wcount, main_cell->parts[pid].density.wcount_dh, #if defined(GADGET2_SPH) main_cell->parts[pid].density.div_v, @@ -223,7 +226,12 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, "%13e %13e %13e\n", cj->parts[pjd].id, cj->parts[pjd].x[0], cj->parts[pjd].x[1], cj->parts[pjd].x[2], cj->parts[pjd].v[0], cj->parts[pjd].v[1], - cj->parts[pjd].v[2], cj->parts[pjd].rho, cj->parts[pjd].rho_dh, + cj->parts[pjd].v[2], cj->parts[pjd].rho, +#if defined(GIZMO_SPH) + 0.f, +#else + main_cell->parts[pjd].rho_dh, +#endif cj->parts[pjd].density.wcount, cj->parts[pjd].density.wcount_dh, #if defined(GADGET2_SPH) cj->parts[pjd].density.div_v, cj->parts[pjd].density.rot_v[0], @@ -321,7 +329,7 @@ int main(int argc, char *argv[]) { message("Hydro implementation: %s", SPH_IMPLEMENTATION); message("Smoothing length: h = %f", h * size); message("Kernel: %s", kernel_name); - message("Neighbour target: N = %f", h * h * h * kernel_norm); + message("Neighbour target: N = %f", pow_dimension(h) * kernel_norm); message("Density target: rho = %f", rho); message("div_v target: div = %f", vel == 2 ? 3.f : 0.f); message("curl_v target: curl = [0., 0., %f]", vel == 3 ? -2.f : 0.f); diff --git a/tests/testInteractions.c b/tests/testInteractions.c index 55858b17a51eb37e9e6184b8cf4fc853951bfd57..9d8dca79f3f84ea06e42d61390e68467a5f1b415 100644 --- a/tests/testInteractions.c +++ b/tests/testInteractions.c @@ -17,6 +17,12 @@ * ******************************************************************************/ +#include "../config.h" + +#ifndef WITH_VECTORIZATION +int main() { return 0; } +#else + #include <fenv.h> #include <stdio.h> #include <stdlib.h> @@ -138,7 +144,7 @@ void write_header(char *fileName) { fclose(file); } -/* +/** * @brief Calls the serial and vectorised version of the non-symmetrical density * interaction. * @@ -324,3 +330,5 @@ int main(int argc, char *argv[]) { return 0; } + +#endif /* WITH_VECTORIZATION */ diff --git a/tests/testPair.c b/tests/testPair.c index 385e9a9e709b95685d86559e34b3b4c5fb3d3884..8afc2250434de7fdfeaa19a36a213dd9ea79d861 100644 --- a/tests/testPair.c +++ b/tests/testPair.c @@ -106,8 +106,6 @@ void clean_up(struct cell *ci) { */ void zero_particle_fields(struct cell *c) { for (size_t pid = 0; pid < c->count; pid++) { - c->parts[pid].rho = 0.f; - c->parts[pid].rho_dh = 0.f; hydro_init_part(&c->parts[pid]); } } @@ -133,9 +131,14 @@ void dump_particle_fields(char *fileName, struct cell *ci, struct cell *cj) { "%13e %13e %13e\n", ci->parts[pid].id, ci->parts[pid].x[0], ci->parts[pid].x[1], ci->parts[pid].x[2], ci->parts[pid].v[0], ci->parts[pid].v[1], - ci->parts[pid].v[2], ci->parts[pid].rho, ci->parts[pid].rho_dh, + ci->parts[pid].v[2], ci->parts[pid].rho, +#if defined(GIZMO_SPH) + 0.f, +#else + cj->parts[pid].rho_dh, +#endif ci->parts[pid].density.wcount, ci->parts[pid].density.wcount_dh, -#ifdef GADGET2_SPH +#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) ci->parts[pid].density.div_v, ci->parts[pid].density.rot_v[0], ci->parts[pid].density.rot_v[1], ci->parts[pid].density.rot_v[2] #else @@ -152,9 +155,14 @@ void dump_particle_fields(char *fileName, struct cell *ci, struct cell *cj) { "%13e %13e %13e\n", cj->parts[pjd].id, cj->parts[pjd].x[0], cj->parts[pjd].x[1], cj->parts[pjd].x[2], cj->parts[pjd].v[0], cj->parts[pjd].v[1], - cj->parts[pjd].v[2], cj->parts[pjd].rho, cj->parts[pjd].rho_dh, + cj->parts[pjd].v[2], cj->parts[pjd].rho, +#if defined(GIZMO_SPH) + 0.f, +#else + cj->parts[pjd].rho_dh, +#endif cj->parts[pjd].density.wcount, cj->parts[pjd].density.wcount_dh, -#ifdef GADGET2_SPH +#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) cj->parts[pjd].density.div_v, cj->parts[pjd].density.rot_v[0], cj->parts[pjd].density.rot_v[1], cj->parts[pjd].density.rot_v[2] #else