Peano
Loading...
Searching...
No Matches
makeIC-multiscale.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3import h5py
4import argparse
5import numpy as np
6
7"""!
8Generates 2D uniform particle distribution with randomized small
9displacements with multiple scales, i.e. recursively nested boxes
10such that the grid will contain multiple scales.
11"""
12
13fileName = "test_sml_multiscale_2D.hdf5"
14boxSize = 1.0
15
16parser = argparse.ArgumentParser(description="SPH benchmarking script")
17parser.add_argument(
18 "-np",
19 "--particle-number",
20 dest="particle_number",
21 required=True,
22 type=int,
23 help="Particle number per dimension",
24)
25parser.add_argument(
26 "-s",
27 "--seed",
28 dest="random_seed",
29 required=True,
30 type=int,
31 help="Seed for RNG",
32)
33parser.add_argument(
34 "-p",
35 "--plot",
36 dest="plot",
37 action="store_true",
38 default=False,
39 help="Plot historgram of particle positions",
40)
41parser.add_argument(
42 "-dx",
43 "--displacement",
44 dest="max_displacement",
45 required=False,
46 default=0.12499,
47 type=float,
48 help="Maximal displacement in units of interparticle distance",
49)
50
51
52args = parser.parse_args()
53npart = args.particle_number
54seed = args.random_seed
55max_displacement = args.max_displacement
56
57
58# ---------------------------------------------------
59
60# Build the arrays
61npart_tot = 4 * (npart**2)
62coords = np.zeros((npart_tot, 3))
63v = np.zeros((npart_tot, 3))
64ids = np.linspace(1, npart_tot, npart_tot)
65m = np.ones(npart_tot)
66dx = boxSize / npart
67h = np.ones(npart_tot) * 2.0 * dx
68u = np.ones(npart_tot)
69
70
71rng = np.random.RandomState(seed=seed)
72
73
74def get_coords(box_xmin, box_xmax, box_ymin, box_ymax, npart):
75 """
76 Generate coordinates for particles between box_min and box_max
77 npart: number of particles in each dimension
78 """
79
80 dx = (box_xmax - box_xmin) / npart
81 dy = (box_ymax - box_ymin) / npart
82
83 npart2 = npart**2
84
85 # First get uniform coordinates.
86 new_coords = np.zeros((npart2, 3))
87 ind = 0
88 for i in range(npart):
89 x = (i + 0.5) * dx
90 for j in range(npart):
91 y = (j + 0.5) * dy
92 new_coords[ind, 0] = box_xmin + x
93 new_coords[ind, 1] = box_ymin + y
94 ind += 1
95
96 # Now randomize them a bit.
97 # Taking a completely randomly sampled particle distribution may lead
98 # to trouble the codes aren't set up to handle, such as particles which
99 # are either too close or too far from each other. So use a somewhat
100 # regular distribution instead, by randomly displacing an initially
101 # uniform particle distribution.
102
103 # rng.random returns random numbers in [0, 1). Scale that to [-1, 1)
104 displacement_x = (2.0 * rng.random((npart2, 1)) - 1.0) * max_displacement * dx
105 displacement_y = (2.0 * rng.random((npart2, 1)) - 1.0) * max_displacement * dy
106 new_coords[:, 0] += displacement_x[:, 0]
107 new_coords[:, 1] += displacement_y[:, 0]
108
109 return new_coords
110
111
112# Now generate actual coordinates
113# First the "background"
114npart2 = npart**2
115new_coords = get_coords(0.0, boxSize, 0.0, boxSize, npart)
116coords[:npart2, :2] = new_coords[:, :2]
117
118new_coords = get_coords(0.0, 2.0 / 3 * boxSize, 0.0, 2.0 / 3 * boxSize, npart)
119coords[npart2 : 2 * npart2, :2] = new_coords[:, :2]
120
121new_coords = get_coords(1.0 / 6, 2.0 / 3 * boxSize, 1.0 / 6, 2.0 / 3 * boxSize, npart)
122coords[2 * npart2 : 3 * npart2, :2] = new_coords[:, :2]
123
124new_coords = get_coords(2.0 / 6, 2.0 / 3 * boxSize, 2.0 / 6, 2.0 / 3 * boxSize, npart)
125coords[3 * npart2 :, :2] = new_coords[:, :2]
126
127
128# too many particles mean that the comparison python script takes ages.
129# too few particles mean that the search radii are going to be too big
130# for the cell size.
131# So let's scale the particles down into a smaller box than the actual
132# box size.
133scale = 0.8
134coords *= scale
135h *= scale
136# and shift them into the center
137coords += 0.1
138
139if args.plot:
140 from matplotlib import pyplot as plt
141
142 plt.figure()
143 plt.scatter(coords[:, 0], coords[:, 1], s=1, marker=",")
144 plt.show()
145
146
147# File
148file = h5py.File(fileName, "w")
149
150# Header
151grp = file.create_group("/Header")
152grp.attrs["BoxSize"] = boxSize
153grp.attrs["NumPart_Total"] = [npart**2, 0, 0, 0, 0, 0]
154grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
155grp.attrs["NumPart_ThisFile"] = [npart**2, 0, 0, 0, 0, 0]
156# This is an addition for this test to be able to estimate the search radius.
157grp.attrs["NumPart_base"] = [npart]
158grp.attrs["Time"] = 0.0
159grp.attrs["NumFilesPerSnapshot"] = 1
160grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
161grp.attrs["Flag_Entropy_ICs"] = 0
162grp.attrs["Dimension"] = 2
163# Non-swift additions
164grp.attrs["RandomSeed"] = seed
165grp.attrs["MaxDisplacement"] = max_displacement
166grp.attrs["NumpyVersion"] = np.__version__
167
168# Units
169grp = file.create_group("/Units")
170grp.attrs["Unit length in cgs (U_L)"] = 1.0
171grp.attrs["Unit mass in cgs (U_M)"] = 1.0
172grp.attrs["Unit time in cgs (U_t)"] = 1.0
173grp.attrs["Unit current in cgs (U_I)"] = 1.0
174grp.attrs["Unit temperature in cgs (U_T)"] = 1.0
175
176# Particle group
177grp = file.create_group("/PartType0")
178grp.create_dataset("Coordinates", data=coords, dtype="d")
179grp.create_dataset("Velocities", data=v, dtype="f")
180grp.create_dataset("Masses", data=m, dtype="f")
181grp.create_dataset("SmoothingLength", data=h, dtype="f")
182grp.create_dataset("InternalEnergy", data=u, dtype="f")
183grp.create_dataset("ParticleIDs", data=ids, dtype="L")
184
185
186file.close()
get_coords(box_min, box_max, npart)
Generate coordinates for particles between box_min and box_max.