Skip to content

Commit 325aa8c

Browse files
authored
Square bgk (#839)
* adjusted the 2D BGK example to use a square profile as initial condition
1 parent 5415102 commit 325aa8c

5 files changed

Lines changed: 466 additions & 189 deletions

File tree

examples/bgk.py

Lines changed: 159 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,182 @@
1010

1111
if __name__ == '__main__':
1212

13+
# most of the code in this file is related to Python matplotlib
14+
# the most notable ASGarD methods are
15+
# run_with_args()
16+
# pde_snapshot()
17+
# get_aux_field()
18+
# get_moment()
19+
# plot_data2d()
20+
1321
filename = "bgk_run.h5"
22+
# the "run_with_args" method will the provided executable file with the provided
23+
# string with arguments and it will also append all arguments used in the call
24+
# to this python script, e.g.,
25+
# python3 -m bgk.py -m 8 -a 1.E-6 -n 20
26+
# will result in a call
27+
# ./bgk -of bgk_run.h5 -m 8 -a 1.E-6 -n 20
28+
#
29+
# run_with_args() accepts an additional list of arguments, e.g., modified list of sys.argv
30+
# for example:
31+
# python3 -m bgk.py run -m 8
32+
# then modify the code:
33+
# mylist = sys.argv
34+
# mylist.remove("run") if "run" in mylist else None
35+
# asgard.run_with_args("./bgk", f"-of {filename}", mylist) # runs ./bgk -of bgk_run.h5 -m 8
36+
#
1437
asgard.run_with_args("./bgk", f"-of {filename}")
1538

1639
snapshot = asgard.pde_snapshot(filename)
1740

18-
if snapshot.num_dimensions == 2:
19-
# 1x1v case
41+
# get the boundaries for the domain, this is needed to set the correct size
42+
# for the matplotlib imshow command
43+
xmin = snapshot.dimension_min[0]
44+
ymin = snapshot.dimension_min[1]
45+
xmax = snapshot.dimension_max[0]
46+
ymax = snapshot.dimension_max[1]
47+
48+
if "poisson" in snapshot.subtitle:
49+
# 1x1v case, poisson
50+
# plotting the initial and final perturbations, i.e., aux fields
51+
52+
# Try running this with the following:
53+
# python3 bgk.py -poisson -m 9 -a 1.E-6 -t 2
54+
55+
assert snapshot.num_position == 1 and snapshot.num_velocity == 1
56+
57+
# the aux fields can be requested either by name or by index,
58+
# e.g., init_pert = snapshot.get_aux_field(0)
59+
init_pert = snapshot.get_aux_field("initial perturbation")
60+
final_pert = snapshot.get_aux_field("final perturbation")
61+
62+
# generating two 2D plots
63+
z0, x, y = init_pert.plot_data2d(((), ()), num_points = 128)
64+
z1, x, y = final_pert.plot_data2d(((), ()), num_points = 128)
65+
66+
fig, (ax0, ax1) = plt.subplots(1, 2)
67+
68+
fig.suptitle(snapshot.title)
69+
70+
ax0.set_title(init_pert.title + ", t = 0")
71+
img0 = ax0.imshow(np.flipud(z0), cmap='turbo', extent=[xmin, xmax, ymin, ymax])
72+
ax0.set_xlabel("x", fontsize = 'large')
73+
ax0.set_ylabel("v", fontsize = 'large')
74+
fig.colorbar(img0, ax=ax0, orientation='vertical')
75+
76+
ax1.set_title(final_pert.title + f", t = {final_pert.time:.4f}")
77+
img1 = ax1.imshow(np.flipud(z1), cmap='turbo', extent=[xmin, xmax, ymin, ymax])
78+
ax1.set_xlabel("x", fontsize = 'large')
79+
ax1.set_ylabel("v", fontsize = 'large')
80+
fig.colorbar(img1, ax=ax1, orientation='vertical')
81+
82+
plt.show()
83+
84+
elif snapshot.num_dimensions == 2:
85+
# 1x1v case, shock1d
86+
87+
# When using high collision frequency, the density develops a stair-case pattern.
88+
#
89+
# Try running this with:
90+
# python3 bgk.py -shock1d -nu 1000 -m 8 -a 1.E-5 -n 2000
91+
92+
assert snapshot.num_position == 1 and snapshot.num_velocity == 1
93+
94+
# obtaining the auxiliary fields associated with the moments
95+
# the 3 variables are another instances of the snapshot class
2096
m0sh = snapshot.get_moment((0, ))
2197
m1sh = snapshot.get_moment((1, ))
2298
m2sh = snapshot.get_moment((2, ))
2399

24-
m0, x = m0sh.plot_data1d(((), ), num_points = 64)
25-
m1, x = m1sh.plot_data1d(((), ), num_points = 64)
26-
m2, x = m2sh.plot_data1d(((), ), num_points = 64)
100+
m0, x = m0sh.plot_data1d(((), ), num_points = 128)
101+
m1, x = m1sh.plot_data1d(((), ), num_points = 128)
102+
m2, x = m2sh.plot_data1d(((), ), num_points = 128)
103+
104+
fig, (ax0, ax1) = plt.subplots(1, 2)
27105

28-
plt.figure(1)
29-
fig, (ax1, ax2) = plt.subplots(1, 2)
106+
fig.suptitle(snapshot.title + f" ({snapshot.subtitle})")
30107

31-
ax1.plot(x, m0, 'b', label = 'mass')
108+
# instead of plotting the "raw" moment, we compute the fluid variables
109+
# density, velocity and temperature
110+
ax0.set_title("fluid variables")
111+
ax0.plot(x, m0, 'b', label = 'density')
32112
u = m1 / m0
33-
ax1.plot(x, u, 'g', label = 'avg. speed')
34-
ax1.plot(x, m2 / m0 - u * u, 'r', label = 'temperature')
113+
ax0.plot(x, u, 'g:', label = 'avg. velocity')
114+
ax0.plot(x, m2 / m0 - u * u, 'r-.', label = 'temperature')
115+
ax0.set_xlabel("x", fontsize = 'large')
116+
ax0.set_ylabel("value", fontsize = 'large')
35117

36-
ax1.legend()
118+
ax0.legend()
37119

38120
z, x, y = snapshot.plot_data2d(((), ()), num_points = 128)
39121

40-
xmin = snapshot.dimension_min[0]
41-
ymin = snapshot.dimension_min[1]
42-
xmax = snapshot.dimension_max[0]
43-
ymax = snapshot.dimension_max[1]
122+
ax1.set_title(f"solution at t = {snapshot.time:.4f}")
123+
img1 = ax1.imshow(np.flipud(z), cmap='viridis', extent=[xmin, xmax, ymin, ymax])
124+
ax1.set_xlabel("x", fontsize = 'large')
125+
ax1.set_ylabel("v", fontsize = 'large')
126+
fig.colorbar(img1, ax=ax1, orientation='vertical')
127+
128+
plt.show()
44129

45-
comp = ax2.imshow(np.flipud(z), cmap='turbo', extent=[xmin, xmax, ymin, ymax])
130+
elif snapshot.num_dimensions == 4:
131+
# 2x2v case, shock2d
132+
133+
# This is NOT the proper way to manage the 2D BGK example.
134+
# Even on a good machine, running the 2D problem can take in order of hours,
135+
# thus, it is better to separate the running and plotting logic.
136+
# Such split is beyond the scope of this example,
137+
# but look at the comment related to run_with_args() and custom arguments.
138+
139+
# example command:
140+
# python3 bgk.py -shock2d -nu 100 -m 8 -a 5.E-5 -n 2000
141+
#
142+
# This is nice visual example but also takes a while to compute.
143+
# It requires up to 90 million degrees of freedom and minimum 16GB GPU
144+
# or 32GB of system RAM. On a workstation Nvidia GPU this takes little over 2 hours.
145+
146+
assert snapshot.num_position == 2 and snapshot.num_velocity == 2
147+
148+
# the moments are now defined by 2D tuples
149+
m0sh = snapshot.get_moment((0, 0))
150+
m10sh = snapshot.get_moment((1, 0))
151+
m01sh = snapshot.get_moment((0, 1))
152+
m20sh = snapshot.get_moment((2, 0))
153+
m02sh = snapshot.get_moment((0, 2))
154+
155+
m0, x, y = m0sh.plot_data2d(((), ()), num_points = 128)
156+
m10, x, y = m10sh.plot_data2d(((), ()), num_points = 128)
157+
m01, x, y = m01sh.plot_data2d(((), ()), num_points = 128)
158+
m20, x, y = m20sh.plot_data2d(((), ()), num_points = 128)
159+
m02, x, y = m02sh.plot_data2d(((), ()), num_points = 128)
160+
161+
162+
fig, (ax0, ax1, ax2) = plt.subplots(1, 3)
163+
164+
fig.suptitle(snapshot.title + f" ({snapshot.subtitle})")
165+
166+
# instead of plotting the "raw" moment, we compute the fluid variables
167+
# density, velocity and temperature
168+
ax0.set_title("density")
169+
img0 = ax0.imshow(np.flipud(m0), cmap='viridis', extent=[xmin, xmax, ymin, ymax])
170+
fig.colorbar(img0, ax=ax0, orientation='vertical')
171+
ax0.set_xlabel("x1", fontsize = 'large')
172+
ax0.set_ylabel("x2", fontsize = 'large')
173+
174+
ax1.set_title("avg. speed")
175+
u0 = m10 / m0
176+
u1 = m01 / m0
177+
aspd = np.sqrt(u0 * u0 + u1 * u1)
178+
img1 = ax1.imshow(np.flipud(aspd), cmap='turbo', extent=[xmin, xmax, ymin, ymax])
179+
fig.colorbar(img1, ax=ax1, orientation='vertical')
180+
ax1.set_xlabel("x1", fontsize = 'large')
181+
ax1.set_ylabel("x2", fontsize = 'large')
182+
183+
ax2.set_title("temperature")
184+
temp = 0.5 * (m20 + m02) / m0 - u0 * u0 - u1 * u1
185+
img2 = ax2.imshow(np.flipud(temp), cmap='coolwarm', extent=[xmin, xmax, ymin, ymax])
186+
fig.colorbar(img2, ax=ax2, orientation='vertical')
187+
ax2.set_xlabel("x1", fontsize = 'large')
188+
ax2.set_ylabel("x2", fontsize = 'large')
46189

47190
plt.show()
48191

python/asgard.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def get_aux_field(self, auxid):
238238
else:
239239
aux.double_precision = False
240240

241-
aux.recsol = libasgard.asgard_make_freconstruct_solution_v2(
241+
aux.recsol = libasgard.asgard_make_freconstruct_solution(
242242
aux.num_dimensions, aux.num_cells, np.ctypeslib.as_ctypes(aux.cells.reshape(-1,)),
243243
self.degree, np.ctypeslib.as_ctypes(aux.state.reshape(-1,)))
244244

@@ -412,9 +412,15 @@ def __str__(self):
412412
s += " num-dimensions: %d\n" % self.num_dimensions
413413
else: # have position/velocity dimensions
414414
s += f" num-dimensions: {self.num_dimensions} ({self.num_position}x{self.num_velocity}v)\n"
415-
s += " degree: %d\n" % self.degree
416-
s += " num-indexes: %d\n" % self.num_cells
417-
s += " state size: %d\n" % self.state.size
415+
416+
snum_cells = f"{self.num_cells:,}" # convert 1663557 to 1,663,557
417+
sstate_size = f"{self.state.size:,}"
418+
419+
padspaces = ' ' * (len(sstate_size) - len(snum_cells)) # pre-pad with spaces
420+
421+
s += f" degree: {self.degree}\n"
422+
s += f" state size: {sstate_size}\n"
423+
s += f" grid-indexes: {padspaces}{snum_cells}\n"
418424
s += " time: %f\n" % self.time
419425
return s
420426

src/asgard_momentset.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ struct moment
7272
* Wrapper around an int that can be used to access a specific moment from asgard::momentset
7373
* and asgard::momentset_gpu
7474
*
75-
* The moment-id is obtained by calling pde_scheme::register_moment and should be used or created
76-
* directly from an int.
75+
* The moment-id is obtained by calling pde_scheme::register_moment and should not be created
76+
* directly from an int, let ASGarD do the correct initialization.
7777
*/
7878
class moment_id {
7979
public:

src/asgard_program_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ Options Short Value Description
130130
-time -t double accepts: positive number (zero for no stepping)
131131
Final time for integration (v2 pdes only)
132132
-num-steps -n int Positive integer indicating the number of time steps to take.
133+
If used with -restart, -n sets the additional time steps.
133134
-dt double Fixed time step to use (must be positive).
134135
-safe-step -sstep - Checks every time step and if it contains inf or nan
135136
then the time-advance method will not accept the step

0 commit comments

Comments
 (0)