chombo-discharge
CD_DischargeIOImplem.H
Go to the documentation of this file.
1 /* chombo-discharge
2  * Copyright © 2024 SINTEF Energy Research.
3  * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4  */
5 
12 #ifndef CD_DischargeIOImplem_H
13 #define CD_DischargeIOImplem_H
14 
15 // Std includes
16 #ifdef CH_USE_HDF5
17 #include <hdf5.h>
18 #endif
19 
20 // Our includes
21 #include <CD_DischargeIO.H>
22 #include <CD_NamespaceHeader.H>
23 
24 template <size_t M, size_t N>
25 void
26 DischargeIO::writeH5Part(const std::string a_filename,
27  const ParticleContainer<GenericParticle<M, N>>& a_particles,
28  const std::vector<std::string> a_realVars,
29  const std::vector<std::string> a_vectVars,
30  const RealVect a_shift,
31  const Real a_time) noexcept
32 {
33 #ifdef CH_USE_HDF5
34  CH_TIME("DischargeIO::writeH5Part");
35 
36  CH_assert(a_realVars.size() == 0 || a_realVars.size() == M);
37  CH_assert(a_vectVars.size() == 0 || a_vectVars.size() == N);
38 
39  std::vector<std::string> realVariables(M);
40  std::vector<std::string> vectVariables(N);
41 
42  if (a_realVars.size() == M) {
43  realVariables = a_realVars;
44 
45  for (int i = 0; i < M; i++) {
46  if (realVariables[i] == "") {
47  realVariables[i] = "real-" + std::to_string(i);
48  }
49  }
50  }
51  else {
52  for (int i = 0; i < M; i++) {
53  realVariables[i] = "real-" + std::to_string(i);
54  }
55  }
56 
57  if (a_vectVars.size() == N) {
58  vectVariables = a_vectVars;
59 
60  for (int i = 0; i < N; i++) {
61  if (vectVariables[i] == "") {
62  vectVariables[i] = "vect-" + std::to_string(i);
63  }
64  }
65  }
66  else {
67  for (int i = 0; i < N; i++) {
68  vectVariables[i] = "vect-" + std::to_string(i);
69  }
70  }
71 
72  // Figure out the number of particles on each rank
73  const unsigned long long numParticlesLocal = a_particles.getNumberOfValidParticlesLocal();
74  const unsigned long long numParticlesGlobal = a_particles.getNumberOfValidParticlesGlobal();
75 
76  std::vector<unsigned long long> particlesPerRank;
77 #ifdef CH_MPI
78  particlesPerRank.resize(numProc(), 0ULL);
79 
80  std::vector<int> recv(numProc(), 1);
81  std::vector<int> displ(numProc(), 0);
82  for (int i = 0; i < numProc(); i++) {
83  displ[i] = i;
84  }
85  MPI_Allgatherv(&numParticlesLocal,
86  1,
87  MPI_UNSIGNED_LONG_LONG,
88  &particlesPerRank[0],
89  &recv[0],
90  &displ[0],
91  MPI_UNSIGNED_LONG_LONG,
92  Chombo_MPI::comm);
93 #else
94  particlesPerRank.resize(1);
95  particlesPerRank[0] = numParticlesGlobal;
96 #endif
97 
98  // Set up file access and create the file.
99  hid_t fileAccess = 0;
100 #ifdef CH_MPI
101  fileAccess = H5Pcreate(H5P_FILE_ACCESS);
102  H5Pset_fapl_mpio(fileAccess, Chombo_MPI::comm, MPI_INFO_NULL);
103 #endif
104 
105  hid_t fileID = H5Fcreate(a_filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, fileAccess);
106  H5Pclose(fileAccess);
107 
108  // Define the top group necessary for the H5Part file format
109  hid_t grp = H5Gcreate2(fileID, "Step#0", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
110 
111  // Write the time attribute
112  hid_t scal = H5Screate(H5S_SCALAR);
113  hid_t attr = H5Acreate(grp, "time", H5T_NATIVE_DOUBLE, scal, H5P_DEFAULT, H5P_DEFAULT);
114  herr_t err = H5Awrite(attr, H5T_NATIVE_DOUBLE, &a_time);
115 
116  H5Sclose(scal);
117  H5Aclose(attr);
118 
119  // Define dataspace dimensions.
120  hsize_t dims[1];
121  dims[0] = numParticlesGlobal;
122 
123  hid_t fileSpaceID = H5Screate_simple(1, dims, nullptr);
124 
125  // Memory space
126  hsize_t memDims[1];
127  memDims[0] = numParticlesLocal;
128  hid_t memSpaceID = H5Screate_simple(1, memDims, nullptr);
129 
130  // Set hyperslabs for file and memory
131  hsize_t fileStart[1];
132  hsize_t fileCount[1];
133 
134  hsize_t memStart[1];
135  hsize_t memCount[1];
136 
137  memStart[0] = 0;
138  fileStart[0] = 0;
139  for (int i = 0; i < procID(); i++) {
140  fileStart[0] += particlesPerRank[i];
141  }
142  fileCount[0] = particlesPerRank[procID()];
143  memCount[0] = particlesPerRank[procID()];
144 
145  H5Sselect_hyperslab(fileSpaceID, H5S_SELECT_SET, fileStart, nullptr, fileCount, nullptr);
146  H5Sselect_hyperslab(memSpaceID, H5S_SELECT_SET, memStart, nullptr, memCount, nullptr);
147 
148  // Create the ID and positional data sets
149  hid_t datasetID = H5Dcreate2(grp, "id", H5T_NATIVE_ULLONG, fileSpaceID, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
150  hid_t datasetX = H5Dcreate2(grp, "x", H5T_NATIVE_DOUBLE, fileSpaceID, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
151  hid_t datasetY = H5Dcreate2(grp, "y", H5T_NATIVE_DOUBLE, fileSpaceID, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
152 #if CH_SPACEDIM == 3
153  hid_t datasetZ = H5Dcreate2(grp, "z", H5T_NATIVE_DOUBLE, fileSpaceID, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
154 #endif
155 
156  // Write ID data set
157  std::vector<unsigned long long> id;
158  std::vector<double> x;
159  std::vector<double> y;
160  std::vector<double> z;
161 
162  for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
163 
164  const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
165  const DataIterator& dit = dbl.dataIterator();
166 
167  const int nbox = dit.size();
168 
169  for (int mybox = 0; mybox < nbox; mybox++) {
170  const DataIndex& din = dit[mybox];
171 
172  const List<GenericParticle<M, N>>& particles = a_particles[lvl][din].listItems();
173 
174  for (ListIterator<GenericParticle<M, N>> lit(particles); lit.ok(); ++lit) {
175  id.push_back(procID());
176  x.push_back(lit().position()[0] - a_shift[0]);
177  y.push_back(lit().position()[1] - a_shift[1]);
178 #if CH_SPACEDIM == 3
179  z.push_back(lit().position()[2] - a_shift[2]);
180 #endif
181  }
182  }
183  }
184 
185  H5Dwrite(datasetID, H5Dget_type(datasetID), memSpaceID, fileSpaceID, H5P_DEFAULT, &id[0]);
186  H5Dwrite(datasetX, H5Dget_type(datasetX), memSpaceID, fileSpaceID, H5P_DEFAULT, &x[0]);
187  H5Dwrite(datasetY, H5Dget_type(datasetY), memSpaceID, fileSpaceID, H5P_DEFAULT, &y[0]);
188 #if CH_SPACEDIM == 3
189  H5Dwrite(datasetZ, H5Dget_type(datasetY), memSpaceID, fileSpaceID, H5P_DEFAULT, &z[0]);
190 #endif
191 
192  id.resize(0);
193  x.resize(0);
194  y.resize(0);
195  z.resize(0);
196 
197  // Close the ID and positional data sets
198  H5Dclose(datasetID);
199  H5Dclose(datasetX);
200  H5Dclose(datasetY);
201 #if CH_SPACEDIM == 3
202  H5Dclose(datasetZ);
203 #endif
204 
205  // Write the M real-variables
206  for (int curVar = 0; curVar < M; curVar++) {
207  hid_t dataset = H5Dcreate2(grp,
208  realVariables[curVar].c_str(),
209  H5T_NATIVE_DOUBLE,
210  fileSpaceID,
211  H5P_DEFAULT,
212  H5P_DEFAULT,
213  H5P_DEFAULT);
214 
215  std::vector<double> ds;
216 
217  for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
218 
219  const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
220  const DataIterator& dit = dbl.dataIterator();
221 
222  const int nbox = dit.size();
223 
224  for (int mybox = 0; mybox < nbox; mybox++) {
225  const DataIndex& din = dit[mybox];
226 
227  const List<GenericParticle<M, N>>& particles = a_particles[lvl][din].listItems();
228 
229  for (ListIterator<GenericParticle<M, N>> lit(particles); lit.ok(); ++lit) {
230  ds.push_back(lit().getReals()[curVar]);
231  }
232  }
233  }
234 
235  // Write and clsoe dataset
236  H5Dwrite(dataset, H5Dget_type(dataset), memSpaceID, fileSpaceID, H5P_DEFAULT, &ds[0]);
237  H5Dclose(dataset);
238  }
239 
240  // Write the N vector variables
241  for (int curVar = 0; curVar < N; curVar++) {
242  for (int dir = 0; dir < SpaceDim; dir++) {
243  std::string varName;
244  if (dir == 0) {
245  varName = vectVariables[curVar] + "-x";
246  }
247  else if (dir == 1) {
248  varName = vectVariables[curVar] + "-y";
249  }
250  else if (dir == 2) {
251  varName = vectVariables[curVar] + "-z";
252  }
253 
254  hid_t dataset = H5Dcreate2(grp,
255  varName.c_str(),
256  H5T_NATIVE_DOUBLE,
257  fileSpaceID,
258  H5P_DEFAULT,
259  H5P_DEFAULT,
260  H5P_DEFAULT);
261 
262  std::vector<double> ds;
263 
264  for (int lvl = 0; lvl <= a_particles.getFinestLevel(); lvl++) {
265 
266  const DisjointBoxLayout& dbl = a_particles.getGrids()[lvl];
267  const DataIterator& dit = dbl.dataIterator();
268 
269  const int nbox = dit.size();
270 
271  for (int mybox = 0; mybox < nbox; mybox++) {
272  const DataIndex& din = dit[mybox];
273 
274  const List<GenericParticle<M, N>>& particles = a_particles[lvl][din].listItems();
275 
276  for (ListIterator<GenericParticle<M, N>> lit(particles); lit.ok(); ++lit) {
277  const RealVect var = lit().getVects()[curVar];
278 
279  ds.push_back(var[dir]);
280  }
281  }
282  }
283 
284  // Write and close dataset
285  H5Dwrite(dataset, H5Dget_type(dataset), memSpaceID, fileSpaceID, H5P_DEFAULT, &ds[0]);
286  H5Dclose(dataset);
287  }
288  }
289 
290  // Close top group and file
291  H5Gclose(grp);
292  H5Fclose(fileID);
293 #endif
294 }
295 
296 #include <CD_NamespaceFooter.H>
297 
298 #endif
Silly, but useful functions that override standard Chombo HDF5 IO.
A generic particle class, holding the position and a specified number of real and vector values.
Definition: CD_GenericParticle.H:33
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition: CD_ParticleContainer.H:50
void writeH5Part(const std::string a_filename, const ParticleContainer< GenericParticle< M, N >> &a_particles, const std::vector< std::string > a_realVars=std::vector< std::string >(), const std::vector< std::string > a_vectVars=std::vector< std::string >(), const RealVect a_shift=RealVect::Zero, const Real a_time=0.0) noexcept
A shameless copy of Chombo's writeEBHDF5 but including the lower-left corner of the physical domain a...
Definition: CD_DischargeIOImplem.H:26
RealVect position(const Location::Cell a_location, const VolIndex &a_vof, const EBISBox &a_ebisbox, const Real &a_dx)
Compute the position (ignoring the "origin) of a Vof.
Definition: CD_LocationImplem.H:20