Skip to content

Commit e7da245

Browse files
pgretembruggenevan1022BenWibking
authored
Add support for tracer particles (#102)
* Add Phoebus tracers * Fix/adapt tracers to AthenaPK * Add tracer support to turbulence pgen * Fix swarm interface * Fix particle init * Call FillTracer every cycle * Added brief instructions for new particle field * Update tracers.cpp filled in values for s_i * Simplify/dedup code * Add lookback time * Update turbulence.cpp * Update turbulence.cpp * Update turbulence.cpp small edits in the par_reduce in the computation of the correlations * Update tracers.cpp * Update turbulence.cpp * Update turbulence.cpp * Use MeshData in FillTracers to allow reduction * Update FillTracers internals to loop over blocks logic * Calc correlations * Dump corr to file * Import interpolation from Phoebus * Adjust interface * User interpolation for FillTracers * Use 2nd order time integrator for particles * Update tracers.cpp fixed a bug in computing the correlations * Fix csv header * Add s and sdot to csv output * Fix interface * Use upstream interfaces * Fix swarm interface * Add simple particle advection test * update GH artifact * Prevent artifact upload conflict * Move particle seeding to tracer pkg * Update particle seeding logic * Add tracer seed and init callback function, and doc * Separate default and pget FillTracer * add plotting script * add example tracer input * add tracer example input * FillTracers after seeding * Formatting, copyright, minor review comments * Add xdfm swarm comment to sample input file * Add changelog and README --------- Co-authored-by: mbruggen <mbrueggen@hs.uni-hamburg.de> Co-authored-by: evan1022 <evan.scannapieco@asu.edu> Co-authored-by: Ben Wibking <ben@wibking.com>
1 parent b76f755 commit e7da245

21 files changed

Lines changed: 1070 additions & 11 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ In between a subtle bug was introduced that resulted in inconsistent divergence
1010
refinement.
1111

1212
### Added (new features/APIs/variables/...)
13+
- [[PR102]](https://github.com/parthenon-hpc-lab/athenapk/pull/102) Add support for tracer particles
1314
- [[PR 89]](https://github.com/parthenon-hpc-lab/athenapk/pull/89) Add viscosity and resistivity
1415
- [[PR 1]](https://github.com/parthenon-hpc-lab/athenapk/pull/1) Add isotropic thermal conduction and RKL2 supertimestepping
1516

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Current features include
2222
- unsplit
2323
- operator-split, second-order RKL2 supertimestepping
2424
- optically thin cooling based on tabulated cooling tables with either Townsend 2009 exact integration or operator-split subcycling
25+
- tracer particles
2526
- static and adaptive mesh refinement
2627
- problem generators for
2728
- linear waves
@@ -84,7 +85,7 @@ The following examples are a few standard cases.
8485

8586
Most simple configuration (only CPU, no MPI).
8687
The `Kokkos_ARCH_...` parameter should be adjusted to match the target machine where AthenaPK will be executed.
87-
A full list of architecture keywords is available on the [Kokkos wiki](https://kokkos.github.io/kokkos-core-wiki/keywords.html#architecture-keywords).
88+
A full list of architecture keywords is available on the [Kokkos wiki](https://kokkos.org/kokkos-core-wiki/get-started/configuration-guide.html#keywords-arch).
8889

8990
# configure with enabling Intel Broadwell or similar architecture (AVX2) instructions
9091
cmake -S. -Bbuild-host -DKokkos_ARCH_BDW=ON -DPARTHENON_DISABLE_MPI=ON

docs/img/tracer_example.png

196 KB
Loading

docs/input.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,88 @@ d_log_temp_tol = 1e-8 # Tolerance in cooling table between subseque
323323
Finally, a more comprehensive descriptions of various conventions used for cooling
324324
functions (and the chosen implementation in AthenaPK) can be found in [Cooling Notes](cooling_notes.md)
325325
and a notebook comparing various cooling tables (and their conversion) in [cooling/cooling.ipynb](cooling/cooling.ipynb).
326+
327+
### Particles
328+
329+
#### Tracers
330+
331+
Tracer particles can be enabled by setting `tracers/enabled=true` in the input file:
332+
333+
```
334+
<tracers>
335+
enabled = true
336+
337+
initial_seed_method = random_per_block # alternative: user
338+
initial_num_tracers_per_cell = 0.125
339+
### Optional arguments
340+
#initial_rng_seed = INTEGER
341+
```
342+
343+
Two seeding methods are currently supported:
344+
345+
- `initial_seed_method=random_per_block`
346+
- seeds particles at random positions in each block
347+
- NOTE: the random number generator seed uses the unique block id. Therefore, simulations with the mesh decomposition (mesh and meshblock sizes) are identical independent of the number of MPI ranks used, but if the meshblock size is changed for given mesh (and thus the total number of blocks) the initial state will be different.
348+
- `initial_num_tracers_per_cell` determines the number of seeded particles per cell
349+
- `initial_rng_seed` (optional) is used as seed in addition to the block id.
350+
- `initial_seed_method=user`
351+
- Calls a problem specific callback function (`ProblemSeedInitialTracers`), see [tracer callback documenation](https://github.com/parthenon-hpc-lab/athenapk/blob/main/docs/pgen.md#tracers).
352+
353+
By default, swarm fields are written only to restart files.
354+
If they are required for "standard" output files (like single precision `hdf5`),
355+
they need to be added manually to the output block, e.g., (bottom two lines)
356+
```
357+
<parthenon/output2>
358+
file_type = hdf5 # Binary data dump
359+
variables = prim # variables to be output
360+
dt = 0.1 # time increment between outputs
361+
id = prim
362+
single_precision_output = true
363+
364+
swarms = tracers
365+
tracers_variables = id, x, y, z, rho
366+
#write_swarm_xdmf=true # uncomment to create an xdmf output (e.g., for Paraview or Visit)
367+
```
368+
369+
Tracers can be read/processed by Paraview or Visit (via the xdmf file)
370+
or by the `phdf` package shipped with the Parthenon submodule.
371+
A sample plotting script for the latter might look like
372+
```python
373+
import matplotlib.pyplot as plt
374+
import numpy as np
375+
import sys
376+
sys.path.insert(
377+
1,
378+
"/path/to/athenapk/external/parthenon"
379+
+ "/scripts/python/packages/parthenon_tools/parthenon_tools",
380+
)
381+
382+
try:
383+
import phdf
384+
except ModuleNotFoundError:
385+
print("Couldn't find module to read Parthenon hdf5 files.")
386+
387+
data = phdf.phdf("../run-turbulence/parthenon.prim.00010.phdf")
388+
tracers = data.GetSwarm("tracers")
389+
xs = tracers.x
390+
ys = tracers.y
391+
zs = tracers.z
392+
ids = tracers.Get("id")
393+
394+
fig = plt.figure()
395+
ax = fig.add_subplot(projection='3d')
396+
397+
ax.scatter(xs, ys, zs,s=1,c=ids)
398+
```
399+
resulting in the following image:
400+
401+
![image](img/tracer_example.png)
402+
403+
Following "restrictions" apply to the current tracer implementation:
404+
- Only 3D simulations.
405+
- Only one advection method (RK2/Heun's method).
406+
- All primitive fields (`rho`, `pressure`, `vel_x`, `vel_y`, `vel_z`, `B_x`, `B_y`, and `B_x`) are traced by default (independent of whether they're needed or not) in addition to the position (`x`, `y`, `z`) and id (`id`) fields.
407+
- Default tracer values (such as the primitive fields) are only updated right before writing an output file.
408+
- Ids are only unique if tracers are seeded at the beginning at the simulations and no new tracer particles are added dynamically while the simulation is running.
409+
410+
Please get in touch, if you interested in running simulations that require lifting one (or more) of those restrictions.

docs/pgen.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,29 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin)
189189
```
190190
callback is available, that is called once every time right before a data output
191191
(hdf5 or restart) is being written.
192+
193+
### Particles
194+
195+
#### Tracers
196+
197+
In order to allow custom seeding of tracer particles (per problem generator), the
198+
`ProblemSeedInitialTracers` function can be defined.
199+
```c++
200+
void ProblemSeedInitialTracers(Mesh *pmesh, ParameterInput *pin, parthenon::SimTime &tm);
201+
```
202+
It is executed once when a simulation is started the very first time (i.e., it
203+
is not called on subsequent restarts).
204+
See the standard tracer seeding implementation[`SeedInitialTracers`](https://github.com/parthenon-hpc-lab/athenapk/blob/main/src/tracers/tracers.cpp) for reference on how to deposit particles.
205+
206+
207+
To allow adding additional fields, the
208+
```c++
209+
void ProblemInitTracerData(ParameterInput * pin, parthenon::StateDescriptor *tracer_pkg);```
210+
callback is available.
211+
It is called at the end of the tracer package initialization and can be defined at the per-problem-generator level, see, e.g., the turbulence driver as an example.
212+
213+
Similarly, a callback is available to fill those new fields (or more) via
214+
```c++
215+
TaskStatus ProblemFillTracers(MeshData<Real> *md, parthenon::SimTime &tm, const Real dt);
216+
```
217+
It is called right after the default `FillTracers` task in the driver.

inputs/turb_with_tracers.in

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<comment>
2+
problem = Turbulence with parabolic forcing profile (using few driving modes)
3+
reference = https://github.com/parthenon-hpc-lab/athenapk/blob/main/docs/turbulence.md
4+
5+
<job>
6+
problem_id = turbulence
7+
8+
<parthenon/output1>
9+
file_type = hst # History data dump
10+
dt = 0.05 # time increment between outputs
11+
12+
<parthenon/output2>
13+
file_type = hdf5 # Binary data dump
14+
variables = prim,acc # variables to be output
15+
dt = 0.1 # time increment between outputs
16+
id = prim
17+
single_precision_output = true
18+
swarms = tracers
19+
tracers_variables = id, x, y, z, rho, s, sdot
20+
#write_swarm_xdmf=true # uncomment to create an xdmf output (e.g., for Paraview or Visit)
21+
22+
<parthenon/output3>
23+
file_type = rst # Binary data dump
24+
dt = 0.1 # time increment between outputs
25+
id = restart
26+
27+
<parthenon/time>
28+
cfl = 0.3 # The Courant, Friedrichs, & Lewy (CFL) Number
29+
nlim = 100000 # cycle limit
30+
tlim = 15.0 # time limit
31+
integrator = rk2 # time integration algorithm
32+
ncycle_out_mesh = -500 # print mesh structure every 500 cyles and on refinement
33+
34+
<parthenon/mesh>
35+
nghost = 3
36+
refinement = none
37+
nx1 = 64 # Number of zones in X1-direction
38+
x1min = 0.0 # minimum value of X1
39+
x1max = 1.0 # maximum value of X1
40+
ix1_bc = periodic # inner-X1 boundary flag
41+
ox1_bc = periodic # outer-X1 boundary flag
42+
43+
nx2 = 64 # Number of zones in X2-direction
44+
x2min = 0.0 # minimum value of X2
45+
x2max = 1.0 # maximum value of X2
46+
ix2_bc = periodic # inner-X2 boundary flag
47+
ox2_bc = periodic # outer-X2 boundary flag
48+
49+
nx3 = 64 # Number of zones in X3-direction
50+
x3min = 0.0 # minimum value of X3
51+
x3max = 1.0 # maximum value of X3
52+
ix3_bc = periodic # inner-X3 boundary flag
53+
ox3_bc = periodic # outer-X3 boundary flag
54+
55+
pack_size = -1 # pack all blocks in a single pack (currently required)
56+
57+
<parthenon/meshblock>
58+
nx1 = 32
59+
nx2 = 32
60+
nx3 = 32
61+
62+
<hydro>
63+
fluid = euler
64+
eos = adiabatic
65+
riemann = hllc
66+
reconstruction = ppm
67+
gamma = 1.66666 # gamma = C_p/C_v
68+
first_order_flux_correct = true
69+
70+
<problem/turbulence>
71+
rho0 = 1.0 #4.0 # initial mean density
72+
p0 = 0.002101 #0.015625 # initial mean pressure
73+
b0 = 0.01 # initial magnetic field (x-direction)
74+
b_config = 0 # 0 - net flux; 1 - no net flux uniform B; 2 - non net flux sin B; 4 - field loop
75+
kpeak = 2.0 # characteristic wavenumber
76+
corr_time = 1.0 # autocorrelation time of the OU forcing process
77+
rseed = 20190729 # random seed of the OU forcing process
78+
sol_weight = 0.3 # solenoidal weight of the acceleration field
79+
accel_rms = 0.45 # root mean square value of the acceleration field
80+
num_modes = 30 # number of wavemodes
81+
82+
<tracers>
83+
enabled = true
84+
initial_seed_method = random_per_block # alternative: user
85+
initial_num_tracers_per_cell = 0.125
86+
initial_rng_seed = 42 # optional
87+
88+
<modes>
89+
k_1_0 = +2
90+
k_1_1 = -1
91+
k_1_2 = +0
92+
k_2_0 = +1
93+
k_2_1 = +0
94+
k_2_2 = +2
95+
k_3_0 = +1
96+
k_3_1 = +1
97+
k_3_2 = -1
98+
k_4_0 = +2
99+
k_4_1 = +0
100+
k_4_2 = +1
101+
k_5_0 = +0
102+
k_5_1 = +0
103+
k_5_2 = -1
104+
k_6_0 = +1
105+
k_6_1 = -1
106+
k_6_2 = -2
107+
k_7_0 = +0
108+
k_7_1 = +0
109+
k_7_2 = -2
110+
k_8_0 = +1
111+
k_8_1 = +0
112+
k_8_2 = -1
113+
k_9_0 = +0
114+
k_9_1 = +2
115+
k_9_2 = +1
116+
k_10_0 = +0
117+
k_10_1 = -1
118+
k_10_2 = +2
119+
k_11_0 = +0
120+
k_11_1 = +0
121+
k_11_2 = +2
122+
k_12_0 = +0
123+
k_12_1 = +2
124+
k_12_2 = -1
125+
k_13_0 = +2
126+
k_13_1 = +1
127+
k_13_2 = +1
128+
k_14_0 = +1
129+
k_14_1 = -1
130+
k_14_2 = +0
131+
k_15_0 = +0
132+
k_15_1 = -1
133+
k_15_2 = -1
134+
k_16_0 = +1
135+
k_16_1 = +0
136+
k_16_2 = +1
137+
k_17_0 = +0
138+
k_17_1 = -1
139+
k_17_2 = +1
140+
k_18_0 = +0
141+
k_18_1 = +1
142+
k_18_2 = +0
143+
k_19_0 = +1
144+
k_19_1 = -1
145+
k_19_2 = +1
146+
k_20_0 = +2
147+
k_20_1 = +1
148+
k_20_2 = -1
149+
k_21_0 = +0
150+
k_21_1 = -1
151+
k_21_2 = -2
152+
k_22_0 = +2
153+
k_22_1 = -1
154+
k_22_2 = +1
155+
k_23_0 = +0
156+
k_23_1 = +1
157+
k_23_2 = +1
158+
k_24_0 = +1
159+
k_24_1 = -2
160+
k_24_2 = +1
161+
k_25_0 = +1
162+
k_25_1 = -2
163+
k_25_2 = +0
164+
k_26_0 = +1
165+
k_26_1 = +2
166+
k_26_2 = +0
167+
k_27_0 = +1
168+
k_27_1 = -2
169+
k_27_2 = -1
170+
k_28_0 = +2
171+
k_28_1 = -1
172+
k_28_2 = -1
173+
k_29_0 = +1
174+
k_29_1 = +2
175+
k_29_2 = -1
176+
k_30_0 = +1
177+
k_30_1 = +1
178+
k_30_2 = +2

inputs/turbulence.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<comment>
22
problem = Turbulence with parabolic forcing profile (using few driving modes)
3-
reference = to be written, see https://gitlab.com/pgrete/kathena/wikis/turbulence for now
3+
reference = https://github.com/parthenon-hpc-lab/athenapk/blob/main/docs/turbulence.md
44

55
<job>
66
problem_id = turbulence

scripts/plot_particles.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
from pathlib import Path
4+
import sys
5+
6+
sys.path.insert(
7+
1,
8+
"./external/parthenon" + "/scripts/python/packages/parthenon_tools/parthenon_tools",
9+
)
10+
11+
try:
12+
import phdf
13+
except ModuleNotFoundError:
14+
print("Couldn't find module to read Parthenon hdf5 files.")
15+
16+
if __name__ == "__main__":
17+
import argparse
18+
19+
parser = argparse.ArgumentParser()
20+
parser.add_argument("filenames", nargs="*")
21+
args = parser.parse_args()
22+
23+
for filename in args.filenames:
24+
data = phdf.phdf(filename)
25+
tracers = data.GetSwarm("tracers")
26+
xs = tracers.x
27+
ys = tracers.y
28+
zs = tracers.z
29+
ids = tracers.Get("id")
30+
31+
fig = plt.figure()
32+
ax = fig.add_subplot(projection="3d")
33+
34+
ax.scatter(xs, ys, zs, s=1, c=ids)
35+
36+
filepath = Path(filename)
37+
figfile = str(filepath.stem) + ".png"
38+
print(f"saving to {figfile}...")
39+
plt.savefig(figfile)
40+
plt.close()

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ add_executable(
2121
hydro/srcterms/tabular_cooling.cpp
2222
refinement/gradient.cpp
2323
refinement/other.cpp
24+
tracers/tracers.cpp
25+
tracers/tracers.hpp
2426
utils/few_modes_ft.cpp
27+
utils/few_modes_ft.hpp
2528
)
2629

2730
add_subdirectory(pgen)

src/hydro/hydro.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "../recon/weno3_simple.hpp"
2626
#include "../recon/wenoz_simple.hpp"
2727
#include "../refinement/refinement.hpp"
28+
#include "../tracers/tracers.hpp"
2829
#include "../units.hpp"
2930
#include "defs.hpp"
3031
#include "diffusion/diffusion.hpp"
@@ -54,6 +55,7 @@ using parthenon::HistoryOutputVar;
5455
parthenon::Packages_t ProcessPackages(std::unique_ptr<ParameterInput> &pin) {
5556
parthenon::Packages_t packages;
5657
packages.Add(Hydro::Initialize(pin.get()));
58+
packages.Add(Tracers::Initialize(pin.get()));
5759
return packages;
5860
}
5961

0 commit comments

Comments
 (0)