AutoPas  3.0.0
Loading...
Searching...
No Matches
OctreeLogger.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <array>
10#include <cstring>
11#include <fstream>
12#include <iostream>
13#include <string>
14#include <vector>
15
18
19namespace autopas {
24template <typename Particle_T>
26 public:
30 explicit OctreeLogger() = default;
31
35 ~OctreeLogger() = default;
36
41 void logTree(OctreeNodeWrapper<Particle_T> *wrapper) { logTree(wrapper->getRaw()); }
42
48 // Load the leaf boxes
49 using Position = std::array<double, 3>;
50 using Box = std::pair<Position, Position>;
51 std::vector<Box> boxes;
52 root->appendAllLeafBoxes(boxes);
53 auto boxCount = boxes.size();
54 auto pointCount = 8 * boxCount;
55
56 // Open the VTK file
57 char filename[256] = {0};
58 snprintf(filename, sizeof(filename), "octree_%d.vtk", iteration++);
59 std::ofstream vtkFile;
60 vtkFile.open(filename);
61
62 if (not vtkFile.is_open()) {
63 throw std::runtime_error("OctreeLogger::logTree(): Failed to open file \"" + std::string(filename) + "\".");
64 }
65
66 // Write the header
67 vtkFile << "# vtk DataFile Version 2.0\n"
68 << "Octree boxes\n"
69 << "ASCII\n"
70
71 << "DATASET UNSTRUCTURED_GRID\n"
72 << "\n";
73
74 // Write points
75 vtkFile << "POINTS " << pointCount << " float\n"; // Points header
76 for (Box box : boxes) {
77 Position min = box.first;
78 Position max = box.second;
79
80 auto [minX, minY, minZ] = min;
81 auto [maxX, maxY, maxZ] = max;
82
83 // Write the points in the order of the VTK_HEXAHEDRON. Each point is
84 // written on its own line.
85
86 vtkFile << minX << " " << minY << " " << minZ << "\n"; // 0 ---
87 vtkFile << maxX << " " << minY << " " << minZ << "\n"; // 1 +--
88 vtkFile << maxX << " " << maxY << " " << minZ << "\n"; // 2 ++-
89 vtkFile << minX << " " << maxY << " " << minZ << "\n"; // 3 -+-
90 vtkFile << minX << " " << minY << " " << maxZ << "\n"; // 4 --+
91 vtkFile << maxX << " " << minY << " " << maxZ << "\n"; // 5 +-+
92 vtkFile << maxX << " " << maxY << " " << maxZ << "\n"; // 6 +++
93 vtkFile << minX << " " << maxY << " " << maxZ << "\n"; // 7 -++
94 }
95 vtkFile << "\n";
96
97 // Write cells
98 auto cellListSize = pointCount + boxCount;
99 vtkFile << "CELLS " << boxCount << " " << cellListSize << "\n";
100 for (auto boxIndex = 0; boxIndex < boxCount; ++boxIndex) {
101 vtkFile << "8 "; // Output # of elements in the following line.
102 for (auto pointIndex = 0; pointIndex < 8; ++pointIndex) {
103 // Generate an index that points to the corresponding point in the points list.
104 auto offset = 8 * boxIndex + pointIndex;
105 vtkFile << offset;
106 if (pointIndex < 7) {
107 vtkFile << " ";
108 }
109 }
110 vtkFile << "\n";
111 }
112 vtkFile << "\n";
113
114 // Write cell types
115 vtkFile << "CELL_TYPES " << boxCount << "\n";
116 for (int i = 0; i < boxes.size(); ++i) {
117 vtkFile << "12\n"; // Write VTK_HEXAHEDRON type for each cell
118 }
119
120 // Cleanup
121 vtkFile.close();
122
123 // TODO(johannes): Enclose with macro
124 // #ifdef AUTOPAS_LOG_OCTREE
125 // #endif
126 }
127
151 static FILE *leavesToJSON(FILE *out, std::vector<OctreeLeafNode<Particle_T> *> &leaves) {
152 if (out) {
153 fprintf(out, "[\n");
154 for (int leafIndex = 0; leafIndex < leaves.size(); ++leafIndex) {
155 auto leaf = leaves[leafIndex];
156 fprintf(out, "{\"minmax\": ");
157 outBoxCoordinatesJSON(out, leaf);
158
159 // Print face neighbors
160 fprintf(out, ", \"fn\": [");
161 bool first = true;
162 for (auto face : octree::Tables::faces) {
163 auto neighbor = leaf->GTEQ_FACE_NEIGHBOR(face);
164 if (neighbor) {
165 if (!first) {
166 fprintf(out, ", ");
167 }
168 first = false;
169 outBoxCoordinatesJSON(out, neighbor);
170 }
171 }
172
173 // Print face neighbor leaves
174 fprintf(out, "], \"fnl\": [");
175 first = true;
176 for (auto face : octree::Tables::faces) {
177 auto neighbor = leaf->GTEQ_FACE_NEIGHBOR(face);
178 if (neighbor) {
179 auto neighborLeaves = neighbor->getNeighborLeaves(face);
180 for (auto neighborLeaf : neighborLeaves) {
181 if (!first) {
182 fprintf(out, ", ");
183 }
184 first = false;
185 outBoxCoordinatesJSON(out, neighborLeaf);
186 }
187 }
188 }
189
190 // Print edge neighbors
191 fprintf(out, "], \"en\": [");
192 first = true;
193 for (auto edge : octree::Tables::edges) {
194 auto neighbor = leaf->GTEQ_EDGE_NEIGHBOR(edge);
195 if (neighbor) {
196 if (!first) {
197 fprintf(out, ", ");
198 }
199 first = false;
200 outBoxCoordinatesJSON(out, neighbor);
201 }
202 }
203
204 // Print edge neighbor leaves
205 fprintf(out, "], \"enl\": [");
206 first = true;
207 for (auto edge : octree::Tables::edges) {
208 auto neighbor = leaf->GTEQ_EDGE_NEIGHBOR(edge);
209 if (neighbor) {
210 auto neighborLeaves = neighbor->getNeighborLeaves(edge);
211 for (auto neighborLeaf : neighborLeaves) {
212 if (!first) {
213 fprintf(out, ", ");
214 }
215 first = false;
216 outBoxCoordinatesJSON(out, neighborLeaf);
217 }
218 }
219 }
220
221 // Print vertex neighbors
222 fprintf(out, "], \"vn\": [");
223 first = true;
224 for (auto vertex : octree::Tables::vertices) {
225 auto neighbor = leaf->GTEQ_VERTEX_NEIGHBOR(vertex);
226 if (neighbor) {
227 if (!first) {
228 fprintf(out, ", ");
229 }
230 first = false;
231 outBoxCoordinatesJSON(out, neighbor);
232 }
233 }
234
235 // Print vertex neighbor leaves
236 fprintf(out, "], \"vnl\": [");
237 first = true;
238 for (auto vertex : octree::Tables::vertices) {
239 auto neighbor = leaf->GTEQ_VERTEX_NEIGHBOR(vertex);
240 if (neighbor) {
241 auto neighborLeaves = neighbor->getNeighborLeaves(vertex);
242
243 for (auto neighborLeaf : neighborLeaves) {
244 if (!first) {
245 fprintf(out, ", ");
246 }
247 first = false;
248 outBoxCoordinatesJSON(out, neighborLeaf);
249 }
250 }
251 }
252
253 fprintf(out, "]}");
254 if (leafIndex < (leaves.size() - 1)) {
255 fprintf(out, ",");
256 }
257 fprintf(out, "\n");
258 }
259 fprintf(out, "]\n");
260 } else {
261 fprintf(stderr, "ERROR: Dump file is nullptr.\n");
262 }
263
264 return out;
265 }
266
273 static FILE *particlesToJSON(FILE *out, OctreeNodeInterface<Particle_T> *root) {
274 if (out) {
275 // Get all leaves
276 std::vector<OctreeLeafNode<Particle_T> *> leaves;
277 root->appendAllLeaves(leaves);
278
279 fprintf(out, "[");
280 for (int leafIndex = 0; leafIndex < leaves.size(); ++leafIndex) {
281 OctreeLeafNode<Particle_T> *leaf = leaves[leafIndex];
282
283 auto n = leaf->size();
284 for (int particleIndex = 0; particleIndex < n; ++particleIndex) {
285 Particle_T &particle = leaf->at(particleIndex);
286 auto p = particle.getR();
287 fputc('[', out);
288 out3(out, p[0], p[1], p[2]);
289 fputc(']', out);
290 if ((particleIndex < (n - 1)) || (leafIndex < (leaves.size() - 1))) {
291 fprintf(out, ",");
292 }
293 }
294 }
295 fprintf(out, "]");
296 } else {
297 fprintf(stderr, "ERROR: Dump file is nullptr.\n");
298 }
299
300 return out;
301 }
302
311 std::vector<OctreeLeafNode<Particle_T> *> &ownedLeaves,
312 std::vector<OctreeLeafNode<Particle_T> *> &haloLeaves) {
313#if AUTOPAS_LOG_OCTREE
314 // Log all owned leaves for this octree
315 fclose(OctreeLogger::leavesToJSON(fopen("owned.json", "w"), ownedLeaves));
316 // Log all halo leaves for this octree
317 fclose(OctreeLogger::leavesToJSON(fopen("halo.json", "w"), haloLeaves));
318 FILE *particles = fopen("particles.json", "w");
319 fprintf(particles, "{\"owned\": ");
321 fprintf(particles, ", \"halo\": \n");
323 fprintf(particles, "}");
324 fclose(particles);
325#endif
326 }
327
328 private:
336 static void out3(FILE *out, double x, double y, double z) { fprintf(out, "%.3f,%.3f,%.3f", x, y, z); }
337
345 static void outLocationArrayJSON(FILE *out, const std::array<double, 3> &min, const std::array<double, 3> &max) {
346 fputc('[', out);
347 out3(out, min[0], min[1], min[2]);
348 fputc(',', out);
349 out3(out, max[0], max[1], max[2]);
350 fputc(']', out);
351 }
352
358 static void outBoxCoordinatesJSON(FILE *out, OctreeNodeInterface<Particle_T> *node) {
359 const auto min = node->getBoxMin();
360 const auto max = node->getBoxMax();
361 outLocationArrayJSON(out, min, max);
362 }
363
367 int unsigned iteration = 0;
368};
369} // namespace autopas
Particle_T & at(size_t index)
Returns the particle at position index.
Definition: FullParticleCell.h:212
An octree leaf node.
Definition: OctreeLeafNode.h:27
size_t size() const override
Get the total number of particles saved in the container (owned + halo + dummy).
Definition: OctreeLeafNode.h:147
Log an octree to a .vtk file.
Definition: OctreeLogger.h:25
~OctreeLogger()=default
Destructor.
static void octreeToJSON(OctreeNodeInterface< Particle_T > *owned, OctreeNodeInterface< Particle_T > *halo, std::vector< OctreeLeafNode< Particle_T > * > &ownedLeaves, std::vector< OctreeLeafNode< Particle_T > * > &haloLeaves)
Log the octree to JSON files understandable by https://github.com/AutoPas/OctreeVisualization.
Definition: OctreeLogger.h:310
OctreeLogger()=default
Constructor.
void logTree(OctreeNodeWrapper< Particle_T > *wrapper)
Write the octree below the wrapper to a .vtk file.
Definition: OctreeLogger.h:41
void logTree(OctreeNodeInterface< Particle_T > *root)
This function writes the octree to a .vtk file.
Definition: OctreeLogger.h:47
static FILE * leavesToJSON(FILE *out, std::vector< OctreeLeafNode< Particle_T > * > &leaves)
Convert a list of octree leaves to JSON and write it to an output file.
Definition: OctreeLogger.h:151
static FILE * particlesToJSON(FILE *out, OctreeNodeInterface< Particle_T > *root)
Print a list of particle positions to a file as JSON.
Definition: OctreeLogger.h:273
The base class that provides the necessary function definitions that can be applied to an octree.
Definition: OctreeNodeInterface.h:32
virtual void appendAllLeaves(std::vector< OctreeLeafNode< Particle_T > * > &leaves) const =0
Put all leaves below this subtree into a given list.
virtual void appendAllLeafBoxes(std::vector< std::pair< std::array< double, 3 >, std::array< double, 3 > > > &boxes) const =0
Put the min/max corner coordinates of every leaf into the vector.
This class wraps the functionality provided by the octree leaves and inner nodes in a structure that ...
Definition: OctreeNodeWrapper.h:37
OctreeNodeInterface< Particle_T > * getRaw() const
Get a raw pointer to the enclosed cell.
Definition: OctreeNodeWrapper.h:273
static constexpr std::array< Face, 6 > faces
All available faces for a cube.
Definition: OctreeDirection.h:98
static constexpr std::array< Edge, 12 > edges
All available edges for a cube.
Definition: OctreeDirection.h:103
static constexpr std::array< Vertex, 8 > vertices
All available vertices for a cube.
Definition: OctreeDirection.h:108
constexpr std::array< T, SIZE > max(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise maximum and returns the result.
Definition: ArrayMath.h:96
constexpr std::array< T, SIZE > min(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise minimum, returns the result.
Definition: ArrayMath.h:62
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32
@ halo
Halo state, a particle with this state is an actual particle, but not owned by the current AutoPas ob...
@ owned
Owned state, a particle with this state is an actual particle and owned by the current AutoPas object...