24#ifndef VTU_SURFACE_WRITER_HH
25#define VTU_SURFACE_WRITER_HH
30#include <unordered_set>
31#include <unordered_map>
39 , _cuboidDecomposition(cuboidDecomposition)
40 , _loadBalancer(loadBalancer)
42 , clout(std::cout,
"VTUsurfaceWriter3D")
48 _functorsA.push_back(&f);
54 _functors.push_back(&f);
60 for (
unsigned long i = 0; i < new_positions.size(); i++) {
61 pos.push_back(new_positions[i]);
68 pos.push_back(new_position);
74 for (
unsigned long i = 0; i < connections.size(); i++) {
75 connectivity.push_back(connections[i]);
84#ifdef PARALLEL_MODE_MPI
89 f->getSuperStructure().communicate();
92 std::string namePiece =
"data/" +
createFileName(_name, iT, 0) +
".vtu";
98 dataPVDmaster(iT, 1, fullNamePVDmaster, namePiece);
105 preambleVTU(fullNameVTU, pos.size());
108 this->dataArray(fullNameVTU);
110 closeVTU(fullNameVTU);
117 std::ofstream fout(fullName.c_str(), std::ios::trunc);
119 clout <<
"Error: could not open " << fullName << std::endl;
121 fout <<
"<?xml version=\"1.0\"?>" << std::endl << std::flush;
122 fout <<
"<VTKFile type=\"UnstructuredGrid\" version=\"1.0\" byte_order=\"LittleEndian\">" << std::endl;
123 fout <<
"<UnstructuredGrid>" << std::endl;
124 fout <<
"<Piece NumberOfPoints=\"" << num <<
"\" NumberOfCells=\"" << connectivity.size() <<
"\">" << std::endl;
125 fout <<
"<PointData Vectors=\"Particles\">" << std::endl;
132 std::ofstream fout(fullNamePiece.c_str(), std::ios::app);
134 clout <<
"Error: could not open " << fullNamePiece << std::endl;
136 fout <<
"</UnstructuredGrid>\n";
137 fout <<
"</VTKFile>\n";
144 std::ofstream fout(fullNamePVD.c_str(), std::ios::app);
146 clout <<
"Error: could not open " << fullNamePVD << std::endl;
148 fout <<
"<DataSet timestep=\"" << iT <<
"\" " <<
"group=\"\" part=\" " << i <<
"\" " <<
"file=\"" << namePiece
155 const std::string& namePiece)
157 std::ofstream fout(fullNamePVDMaster.c_str(), std::ios::in | std::ios::out | std::ios::ate);
159 fout.seekp(-25, std::ios::end);
160 fout <<
"<DataSet timestep=\"" << iT <<
"\" " <<
"group=\"\" part=\" " << i <<
"\" " <<
"file=\"" << namePiece
163 closePVD(fullNamePVDMaster);
166 clout <<
"Error: could not open " << fullNamePVDMaster << std::endl;
174#ifdef PARALLEL_MODE_MPI
179 preamblePVD(fullNamePVDmaster);
180 closePVD(fullNamePVDmaster);
187 std::ofstream fout(fullNamePVD.c_str(), std::ios::trunc);
189 clout <<
"Error: could not open " << fullNamePVD << std::endl;
191 fout <<
"<?xml version=\"1.0\"?>\n";
192 fout <<
"<VTKFile type=\"Collection\" version=\"1.0\" "
193 <<
"byte_order=\"LittleEndian\">\n"
202#ifdef PARALLEL_MODE_MPI
207 std::ofstream fout(fullNamePVD.c_str(), std::ios::app);
209 clout <<
"Error: could not open " << fullNamePVD << std::endl;
211 fout <<
"</Collection>\n";
212 fout <<
"</VTKFile>\n";
221 std::ofstream fout(fullName.c_str(), std::ios::app);
223 clout <<
"Error: could not open " << fullName << std::endl;
226 for (
unsigned long i = 0; i < _functors.size(); i++) {
227 writeFunctor(fullName, fout, *_functors[i]);
230 for (
unsigned long i = 0; i < _functorsA.size(); i++) {
231 writeAnalyticalFunctor(fullName, fout, *_functorsA[i]);
235#ifdef PARALLEL_MODE_MPI
239 fout <<
"</PointData>" << std::endl;
240 fout <<
"<CellData /> " << std::endl;
241 fout <<
"<Cells>" << std::endl;
242 fout <<
"<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << std::endl;
244 if (connectivity.size() == 0) {
245 for (
int i = 0; i < 1; ++i) {
246 for (
unsigned long j = 0; j < pos.size(); ++j) {
253 for (
int i = 0; i < 1; ++i) {
254 for (
unsigned long j = 0; j < connectivity.size(); ++j) {
255 for (
unsigned long k = 0; k < connectivity[j].size(); ++k) {
256 fout << connectivity[j][k] <<
" ";
265 fout <<
"</DataArray>" << std::endl;
266 fout <<
"<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << std::endl;
268 if (connectivity.size() == 0) {
269 for (std::size_t i = 0; i < 1; ++i) {
270 for (
unsigned long j = 1; j <= connectivity.size(); ++j) {
280 for (std::size_t i = 0; i < 1; ++i) {
281 for (
unsigned long j = 1; j <= connectivity.size(); ++j) {
282 fout << j * 3 <<
" ";
290 fout <<
"</DataArray>" << std::endl;
291 fout <<
"<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << std::endl;
292 if (connectivity.size() != 0) {
293 for (
unsigned long j = 0; j < connectivity.size(); ++j) {
301 for (
unsigned long j = 0; j < pos.size(); ++j) {
309 fout <<
"</DataArray>" << std::endl;
310 fout <<
"</Cells>" << std::endl;
311 fout <<
"<Points>" << std::endl;
313 fout <<
"</Points>" << std::endl;
314 fout <<
"</Piece>" << std::endl;
323 fout <<
"<DataArray type=\"Float32\" Name=\"Point\" NumberOfComponents=\"" << 3 <<
"\">" << std::endl;
325 int num = pos.size();
326 for (
int j = 0; j < num; ++j) {
327 fout << pos[j][0] <<
" " << pos[j][1] <<
" " << pos[j][2] <<
" " << std::endl;
329 fout <<
"</DataArray>" << std::endl;
336 writeAnalyticalFunctor(fullName, fout, interpolateF);
347#ifdef PARALLEL_MODE_MPI
353 fout <<
"<DataArray type=\"Float32\" Name=\"" << f.
getName() <<
"\" NumberOfComponents=\"" << dimF <<
"\">"
357 fout <<
"<DataArray type=\"Float32\" Name=\"" << f.
getName()
358 <<
"\" format=\"binary\" encoding=\"base64\" NumberOfComponents=\"" << dimF <<
"\">" << std::endl;
365 std::size_t numPoints = pos.size();
366 std::ofstream ofstr(fullName.c_str(), std::ios::out | std::ios::app | std::ios::binary);
367 size_t binarySize = size_t(numPoints * dimF *
sizeof(
float));
369 unsigned int uintBinarySize = (
unsigned int)binarySize;
371 sizeEncoder.
encode(&uintBinarySize, 1);
375 std::vector<T> vals(dimF * numPoints, 0);
377 T* val =
new T[dimF];
379 for (std::size_t j = 0; j < numPoints; ++j) {
380 if (_loadBalancer.isLocal(_cuboidDecomposition.getC(pos[j]).value())) {
381 f(val, pos[j].data());
383 for (std::size_t i = 0; i < dimF; ++i) {
384 vals[i * numPoints + j] = val[i];
388#ifdef PARALLEL_MODE_MPI
390 std::vector<T> valsCummulated(dimF * numPoints, 0);
394 for (std::size_t j = 0; j < numPoints; ++j) {
395 for (std::size_t i = 0; i < dimF; ++i) {
397 fout << valsCummulated[i * numPoints + j] <<
" ";
400 const float helper = float(valsCummulated[j]);
401 dataEncoder.
encode(&helper, 1);
407#ifndef PARALLEL_MODE_MPI
409 for (std::size_t j = 0; j < numPoints; ++j) {
410 for (std::size_t i = 0; i < dimF; ++i) {
412 fout << vals[i * numPoints + j] <<
" ";
415 const float helper = float(vals[i * numPoints + j]);
416 dataEncoder.
encode(&helper, 1);
424 fout.open(fullName.c_str(), std::ios::out | std::ios::app);
427 fout <<
"</DataArray>" << std::endl;
435 std::size_t operator()(
const std::vector<T>& v)
const
437 return std::hash<T>()(v[0]) ^ std::hash<T>()(v[1]) ^ std::hash<T>()(v[2]);
442 bool operator()(
const std::vector<T>& a,
const std::vector<T>& b)
const
444 return a[0] == b[0] && a[1] == b[1] && a[2] == b[2];
447 std::unordered_set<std::vector<T>, VectorHash, VectorEqual> uniquePoints(points.begin(), points.end());
448 return std::vector<std::vector<T>>(uniquePoints.begin(), uniquePoints.end());
454 for (std::size_t i = 0; i < v1.size(); ++i) {
455 if (std::fabs(v1[i] - v2[i]) > epsilon) {
468 std::size_t operator()(
const std::vector<T>& v)
const
470 return std::hash<T>()(v[0]) ^ std::hash<T>()(v[1]) ^ std::hash<T>()(v[2]);
475 bool operator()(
const std::vector<T>& a,
const std::vector<T>& b)
const {
return areVectorsEqual(a, b); }
478 std::unordered_map<std::vector<T>, int, VectorHash, VectorEqual> pointIndexMap;
479 std::vector<std::vector<int>> indexedTriangles;
482 for (std::size_t i = 0; i < pos.size(); ++i) {
483 pointIndexMap[{pos[i][0], pos[i][1], pos[i][2]}] = i;
488 std::vector<int> indices(3);
489 for (
int j = 0; j < 3; ++j) {
490 std::vector<T> pt = {triangle.point[j][0], triangle.point[j][1], triangle.point[j][2]};
491 auto it = pointIndexMap.find(pt);
492 if (it != pointIndexMap.end()) {
493 indices[j] = it->second;
500 if (indices[0] != -1 && indices[1] != -1 && indices[2] != -1) {
501 indexedTriangles.push_back(indices);
505 return indexedTriangles;
512 std::vector<std::vector<T>> points;
516 std::vector<T> pt = {triangle.point[0][0], triangle.point[0][1], triangle.point[0][2]};
517 points.push_back(pt);
518 pt = {triangle.point[1][0], triangle.point[1][1], triangle.point[1][2]};
519 points.push_back(pt);
520 pt = {triangle.point[2][0], triangle.point[2][1], triangle.point[2][2]};
521 points.push_back(pt);
524 points = removeDuplicates(points);
527 for (
const std::vector<T>& point : points) {
528 pos.push_back(
Vector<T, 3>(point[0], point[1], point[2]));
531 std::vector<std::vector<int>> indexedTriangles = mapTrianglesToIndices(stlReader);
532 for (
const auto& tri : indexedTriangles) {
533 connectivity.push_back(tri);
AnalyticalF are applications from DD to XD, where X is set by the constructor.
Converts super functors to analytical functors.
void encode(const T *data, size_t length)
int getTargetDim() const
read only access to member variable _n
std::string & getName()
read and write access to name
Base class for all LoadBalancer.
std::vector< STLtriangle< T > > & getTriangles()
Returns reference to all triangles.
STLmesh< T > & getMesh()
Returns mesh.
represents all functors that operate on a SuperStructure<T,3> in general
void addPoints(std::vector< Vector< T, 3 > > &new_positions)
Add multiple locations to output set.
void addPoint(Vector< T, 3 > &new_position)
Add single location to output set.
void writeAnalyticalFunctor(const std::string &fullName, std::ofstream &fout, AnalyticalF3D< T, T > &f)
writes functors.
void addConnectivity(std::vector< std::vector< int > > &connections)
Define connectivity between previously-added output points, rendering them a surface.
void dataPVD(int iT, int i, const std::string &fullNamePVD, const std::string &namePiece)
performes <DataSet timestep= ... file=namePiece >
static bool areVectorsEqual(const std::vector< T > &v1, const std::vector< T > &v2, T epsilon=1e-6)
void closeVTU(const std::string &fullNamePiece)
performes </ImageData> and </VTKFile>
VTUsurfaceWriter(std::string name, CuboidDecomposition3D< T > &cuboidDecomposition, LoadBalancer< T > &loadBalancer, bool binary=false)
void addFunctor(AnalyticalF3D< T, T > &f)
Schedule analytical functor for output.
void write(std::size_t iT)
writes vtu files and assigns values
void closePVD(const std::string &fullNamePVD)
void writePosition(std::ofstream &fout)
writes coordinates of points
void dataPVDmaster(int iT, int i, const std::string &fullNamePVDMaster, const std::string &namePiece)
performes <DataSet timestep= ... file=namePiece >
std::vector< std::vector< T > > removeDuplicates(const std::vector< std::vector< T > > &points)
removes duplicates from points, needed for STL files
void preambleVTU(const std::string &fullName, int num)
performes <VTKFile ...>, <ImageData ...> and <PieceExtent ...>
void addSTL(STLreader< T > &stlReader)
Add full STL surface as output surface.
void writeFunctor(const std::string &fullName, std::ofstream &fout, SuperF3D< T, T > &f)
interpolates and writes functors stored at functors
void preamblePVD(const std::string &fullNamePVD)
std::vector< std::vector< int > > mapTrianglesToIndices(STLreader< T > &stlReader)
void dataArray(const std::string &fullName)
std::string getVtkOutDir() const
void reduceVect(std::vector< T > &sendVal, std::vector< T > &recvVal, MPI_Op op, int root=0, MPI_Comm comm=MPI_COMM_WORLD)
Element-per-element reduction of a vector of data.
int getRank() const
Returns the process ID.
Directories & directories()
Top level namespace for all of OpenLB.
std::string createFileName(std::string name)
for .pvd masterFile