VirtualFluids 0.2.0
Parallel CFD LBM Solver
Loading...
Searching...
No Matches
GbVoxelMatrix3DVtiTest.cpp
Go to the documentation of this file.
1//=======================================================================================
2// ____ ____ __ ______ __________ __ __ __ __
3// \ \ | | | | | _ \ |___ ___| | | | | / \ | |
4// \ \ | | | | | |_) | | | | | | | / \ | |
5// \ \ | | | | | _ / | | | | | | / /\ \ | |
6// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____
7// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______|
8// \ \ | | ________________________________________________________________
9// \ \ | | | ______________________________________________________________|
10// \ \| | | | __ __ __ __ ______ _______
11// \ | | |_____ | | | | | | | | | _ \ / _____)
12// \ | | _____| | | | | | | | | | | \ \ \_______
13// \ | | | | |_____ | \_/ | | | | |_/ / _____ |
14// \ _____| |__| |________| \_______/ |__| |______/ (_______/
15//
16// This file is part of VirtualFluids. VirtualFluids is free software: you can
17// redistribute it and/or modify it under the terms of the GNU General Public
18// License as published by the Free Software Foundation, either version 3 of
19// the License, or (at your option) any later version.
20//
21// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
22// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24// for more details.
25//
26// SPDX-License-Identifier: GPL-3.0-or-later
27// SPDX-FileCopyrightText: Copyright © VirtualFluids Project contributors, see AUTHORS.md in root folder
28//
34//=======================================================================================
35
36#include <gtest/gtest.h>
37
38#include <fstream>
39#include <sstream>
40#include <vector>
41#include <string>
42#include <cstdio>
43#include <cstdint>
44#include <ctime>
45#include <thread>
46#include <chrono>
47#include <filesystem>
48#include <functional>
49
51
52static std::string makeTempFilename(const std::string &prefix)
53{
54 // build portable temp filename: <tempdir>/<prefix>_<timestamp>_<threadhash>.vti
55 std::ostringstream ss;
56 std::string tempDir;
57 try {
58 tempDir = std::filesystem::temp_directory_path().string();
59 } catch (...) {
60 tempDir = "."; // fallback to CWD
61 }
62
63 if (!tempDir.empty() && tempDir.back() != '/' && tempDir.back() != '\\') {
64 tempDir.push_back(std::filesystem::path::preferred_separator);
65 }
66
67 auto now = std::chrono::high_resolution_clock::now().time_since_epoch().count();
68 auto tidHash = std::hash<std::thread::id>{}(std::this_thread::get_id());
69
70 ss << tempDir << prefix << "_" << now << "_" << tidHash << ".vti";
71 return ss.str();
72}
73
74static void writeVtiAscii(const std::string &filename, int nx, int ny, int nz, const std::vector<float> &data)
75{
76 std::ofstream out(filename.c_str(), std::ios::binary);
77 ASSERT_TRUE(out.is_open());
78
79 std::ostringstream xml;
80 xml << "<?xml version=\"1.0\"?>\n";
81 xml << "<VTKFile type=\"ImageData\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
82 xml << "<ImageData WholeExtent=\"0 " << (nx - 1) << " 0 " << (ny - 1) << " 0 " << (nz - 1)
83 << "\" Origin=\"0 0 0\" Spacing=\"1 1 1\">\n";
84 xml << " <Piece Extent=\"0 " << (nx - 1) << " 0 " << (ny - 1) << " 0 " << (nz - 1) << "\">\n";
85 xml << " <PointData Scalars=\"scalars\">\n";
86 xml << " <DataArray type=\"Float32\" Name=\"scalars\" format=\"ascii\">\n";
87 for (size_t i = 0; i < data.size(); ++i) {
88 xml << data[i];
89 if (i + 1 < data.size()) xml << " ";
90 }
91 xml << "\n </DataArray>\n";
92 xml << " </PointData>\n";
93 xml << " <CellData/>\n";
94 xml << " </Piece>\n";
95 xml << "</ImageData>\n";
96 xml << "</VTKFile>\n";
97
98 out << xml.str();
99 out.close();
100}
101
102static void writeVtiAppended(const std::string &filename, int nx, int ny, int nz, const std::vector<float> &data)
103{
104 std::ofstream out(filename.c_str(), std::ios::binary);
105 ASSERT_TRUE(out.is_open());
106
107 std::ostringstream xml;
108 xml << "<?xml version=\"1.0\"?>\n";
109 xml << "<VTKFile type=\"ImageData\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
110 xml << "<ImageData WholeExtent=\"0 " << (nx - 1) << " 0 " << (ny - 1) << " 0 " << (nz - 1)
111 << "\" Origin=\"0 0 0\" Spacing=\"1 1 1\">\n";
112 xml << " <Piece Extent=\"0 " << (nx - 1) << " 0 " << (ny - 1) << " 0 " << (nz - 1) << "\">\n";
113 xml << " <PointData Scalars=\"scalars\">\n";
114 // offset 0 -> first block directly after '_' (reader expects offset relative to underscore+1)
115 xml << " <DataArray type=\"Float32\" Name=\"scalars\" format=\"appended\" offset=\"0\"/>\n";
116 xml << " </PointData>\n";
117 xml << " <CellData/>\n";
118 xml << " </Piece>\n";
119 xml << "</ImageData>\n";
120 xml << "<AppendedData encoding=\"raw\">\n";
121
122 out << xml.str();
123
124 // VTK appended data starts with '_' char
125 out.put('_');
126
127 // block size (uint32) then raw bytes
128 uint32_t rawSize = static_cast<uint32_t>(data.size() * sizeof(float));
129 // write little-endian uint32
131 sizeBytes[0] = static_cast<uint8_t>((rawSize >> 0) & 0xFF);
132 sizeBytes[1] = static_cast<uint8_t>((rawSize >> 8) & 0xFF);
133 sizeBytes[2] = static_cast<uint8_t>((rawSize >> 16) & 0xFF);
134 sizeBytes[3] = static_cast<uint8_t>((rawSize >> 24) & 0xFF);
135 out.write(reinterpret_cast<const char *>(sizeBytes), 4);
136
137 // write float data in native representation (reader expects float bytes)
138 for (size_t i = 0; i < data.size(); ++i) {
139 float v = data[i];
140 out.write(reinterpret_cast<const char *>(&v), sizeof(float));
141 }
142
143 out << "\n</AppendedData>\n";
144 out << "</VTKFile>\n";
145 out.close();
146}
147
149{
150 const int nx = 2, ny = 2, nz = 1;
151 // x fastest order: (0,0,0),(1,0,0),(0,1,0),(1,1,0)
152 std::vector<float> data = {0.5f, 2.0f, 2.0f, 2.0f};
153
154 std::string fname = makeTempFilename("test_ascii_vti");
155 writeVtiAscii(fname, nx, ny, nz, data);
156
158 sut.setThreshold(0.0, 1.0);
159
161
166
167 std::remove(fname.c_str());
168}
169
171{
172 const int nx = 2, ny = 2, nz = 1;
173 std::vector<float> data = {0.5f, 2.0f, 2.0f, 2.0f};
174
175 std::string fname = makeTempFilename("test_appended_vti");
176 writeVtiAppended(fname, nx, ny, nz, data);
177
179 sut.setThreshold(0.0, 1.0);
180
182
187
188 std::remove(fname.c_str());
189}
void setThreshold(double lowerThreshold, double upperThreshold)
std::shared_ptr< T > SPtr
static const float FLUID
void readMatrixFromVtiASCIIFile(std::string filename)
Reads a VTI file in ASCII format and fills the voxel matrix applying the thresholds....
static const float SOLID
void readMatrixFromVtiAppendedFile(std::string filename)
Reads a VTI file in appended binary format and fills the voxel matrix applying the thresholds....
TEST(GbVoxelMatrix3DVtiTest, ReadMatrixFromVtiASCIIFile)