You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<imgsrc="assets/parcel_openpmd_logo.png"alt="Parcel logo showing a cardboard box holding a beam of electrons"width="600" >
2
2
3
-
**Par**cel: a package of **par**ticle and mesh data.
4
-
A single header C implementation of the [OpenPMD standard](https://github.com/openPMD/openPMD-standard) with the BeamPhysics extension.
3
+
----
5
4
5
+
Read and write particle-tracking code and particle-in-cell code data in the [OpenPMD standard](https://github.com/openPMD/openPMD-standard).
6
+
7
+
Parcel is a single header C implementation of the OpenPMD standard with the BeamPhysics extension using [HDF5](https://www.hdfgroup.org/solutions/hdf5/) as its backend.
8
+
It is designed for simple integration with existing physics simulation codes.
9
+
Drop the single file `parcel.h` into your codebase and call it to allow your tool to interchange particle data with the many other codes that use the OpenPMD format.
10
+
11
+
12
+
## Dependencies
13
+
14
+
Parcel is C99 compliant and its only dependency is HDF5.
6
15
7
16
## Usage
8
17
@@ -14,7 +23,193 @@ Then, in one and only one of your `.c` files, use the following line to include
14
23
#include"../parcel.h"
15
24
```
16
25
17
-
## Implementation Notes
26
+
The following examples illustrate typical use-cases of reading and writing data to an OpenPMD file.
27
+
28
+
### Basic Read Example
29
+
30
+
```c
31
+
#definePARCEL_IMPLEMENTATION
32
+
#include"parcel.h"
33
+
34
+
intmain(void) {
35
+
pmd_series *series;
36
+
pmd_iteration *iter;
37
+
ParticleGroup *pg;
38
+
pmd_status status;
39
+
int64_t *iterations = NULL;
40
+
int64_t num_iterations;
41
+
42
+
/* Open an OpenPMD data series */
43
+
/* Use '%T' in the filename for a file-based series and parcel will autodetect */
44
+
/* files of the form data_1.h5, data_2.h5, data_3.h5, etc. You may also use */
45
+
/* the path of a single file in the file-based series, or the path to a */
46
+
/* group-based series. */
47
+
status = pmd_open_series("data_%T.h5", &series, PMD_RDONLY);
48
+
if (status != PMD_SUCCESS) return 1;
49
+
50
+
/* List available iteration indices */
51
+
status = pmd_list_iterations(series, &iterations, &num_iterations);
for (int64_t i = 0; i < pg->num_particles && i < 5; i++) {
90
+
printf(" Particle %lld: x=%.3e, px=%.3e eV/c\n",
91
+
(long long)i, pg->x[i], pg->px[i]);
92
+
}
93
+
94
+
/* Clean up */
95
+
for (int i = 0; i < num_species; i++) {
96
+
free(species_names[i]);
97
+
}
98
+
free(species_names);
99
+
free(iterations);
100
+
pmd_free_particle_group(pg);
101
+
pmd_close_iteration(iter);
102
+
pmd_close_series(series);
103
+
return 0;
104
+
}
105
+
```
106
+
107
+
### Basic Write Example
108
+
109
+
```c
110
+
#define PARCEL_IMPLEMENTATION
111
+
#include "parcel.h"
112
+
113
+
int main(void) {
114
+
pmd_series *series;
115
+
pmd_iteration *iter;
116
+
ParticleGroup pg = {0};
117
+
pmd_status status;
118
+
const int64_t N = 1000;
119
+
120
+
/* Create a new OpenPMD data series */
121
+
/* Using '%T' in filename will open series in file-based iteration mode */
122
+
/* and embed iteration index in filename. Ommit '%T' in name to open in */
123
+
/* group-based iteration mode and store iterations within HDF5 file */
124
+
status = pmd_open_series("output_%T.h5", &series, PMD_TRUNC);
125
+
if (status != PMD_SUCCESS) return 1;
126
+
127
+
/* Create and open iteration 0 for writing */
128
+
status = pmd_open_iteration(series, 0, &iter);
129
+
if (status != PMD_SUCCESS) return 1;
130
+
131
+
/* Allocate and populate particle data */
132
+
pg.num_particles = N;
133
+
pg.x = (double *)malloc(N * sizeof(double));
134
+
pg.y = (double *)malloc(N * sizeof(double));
135
+
pg.z = (double *)malloc(N * sizeof(double));
136
+
pg.px = (double *)malloc(N * sizeof(double));
137
+
pg.py = (double *)malloc(N * sizeof(double));
138
+
pg.pz = (double *)malloc(N * sizeof(double));
139
+
pg.weight = (double *)malloc(N * sizeof(double));
140
+
141
+
/* Fill with sample data */
142
+
for (int64_t i = 0; i < N; i++) {
143
+
pg.x[i] = 0.001 * i;
144
+
pg.y[i] = 0.0;
145
+
pg.z[i] = 0.0;
146
+
pg.px[i] = 0.0; /* momentum in eV/c */
147
+
pg.py[i] = 0.0;
148
+
pg.pz[i] = 1e6;
149
+
pg.weight[i] = 1.0;
150
+
}
151
+
152
+
/* Write particle data */
153
+
/* Instead of allocating arrays in pmd_particle_group, you may set pointers to */
154
+
/* user-supplied arrays in existing code to write directly from them. Set any */
155
+
/* pointer to NULL to ignore writing. */
156
+
status = pmd_write_particle_group(iter, "electron", &pg);
157
+
if (status != PMD_SUCCESS) return 1;
158
+
159
+
/* Clean up */
160
+
free(pg.x); free(pg.y); free(pg.z);
161
+
free(pg.px); free(pg.py); free(pg.pz);
162
+
free(pg.weight);
163
+
pmd_close_iteration(iter);
164
+
pmd_close_series(series);
165
+
return 0;
166
+
}
167
+
```
168
+
169
+
## Compiling and Running Tests
170
+
171
+
The tests in this project are built using CMake and have additional dependencies beyond HDF5 in order to generate test files.
172
+
Follow these steps to build the tests and then run them.
173
+
1) Install required dependencies through conda environment and activate. This will download and install HDF5 and the required python dependencies.
174
+
```
175
+
conda env create -f environment.yml
176
+
conda activate parcel-dev
177
+
```
178
+
2) Use CMake to build the tests.
179
+
```
180
+
mkdir build
181
+
cd build
182
+
cmake ..
183
+
make
184
+
```
185
+
3) Run the tests. This should run all C tests and check generated test files with the [OpenPMD Validator](https://github.com/openPMD/openPMD-validator).
186
+
```
187
+
# From inside of build/
188
+
ctest
189
+
```
190
+
4)[Optional] If any errors occur, running the individual test binaries may reveal more information.
191
+
```
192
+
./tests/test_read
193
+
./tests/test_write
194
+
./tests/test_read_write
195
+
./tests/test_utilitis
196
+
./tests/test_generate_openpmd
197
+
```
198
+
199
+
### Optional CMake Arguments
200
+
The following options may be used in the CMake command to enable additional debug features.
201
+
-`-DDEBUG=ON`: Enable debug flags (ie for use with valgrind).
202
+
-`-DCLANG_TIDY=ON`: Run `clang-tidy` during builds and error out on issues.
203
+
204
+
205
+
## Name
206
+
207
+
**Par**cel: a package containing **par**ticle data.
208
+
209
+
## License
210
+
This code was written by Christopher M. Pierce and is released under the BSD 3-Clause License.
0 commit comments