6#include <unordered_map>
16 double coords[3] = { 0.0, 0.0, 0.0 };
35 return this->timeActivated;
118 return std::make_tuple( x, y, z );
132 return std::make_tuple( x, y, z );
150 std::array<int, 8> nodeIds;
153 nodeIds[1] =
get_index( x, y + 1, z + 1 );
154 nodeIds[2] =
get_index( x + 1, y + 1, z + 1 );
155 nodeIds[3] =
get_index( x + 1, y, z + 1 );
159 nodeIds[6] =
get_index( x + 1, y + 1, z );
167 for (
int i = 0; i < 8; i++ ) {
172 m_nodes[voxelNodes[i]].coords[0] = coords[0];
173 m_nodes[voxelNodes[i]].coords[1] = coords[1];
174 m_nodes[voxelNodes[i]].coords[2] = coords[2];
175 m_nodes[voxelNodes[i]].timeActivated = timeActivated;
200 for (
int i = 0; i < 8; i++ ) {
204 m_voxels[index].vofHistory.push_back( std::make_tuple( 0, 0.0 ) );
205 m_voxels[index].timeActivated = timeActivated;
221 double vof_before =
m_voxels[index].vof();
222 double vof_after = vof_before + vofIncrement;
223 if ( vof_after > 1.0 ) {
225 double excess = vof_after - 1.0;
227 m_voxels[index].vofHistory.push_back( std::make_tuple( timeActivated, vof_after ) );
230 std::vector<int> neighbor_indices, neighbor_indices_workingset;
232 neighbor_indices.push_back(
get_index( x - 1, y, z ) );
234 neighbor_indices.push_back(
get_index( x + 1, y, z ) );
236 neighbor_indices.push_back(
get_index( x, y - 1, z ) );
238 neighbor_indices.push_back(
get_index( x, y + 1, z ) );
239 if ( x > 0 && y > 0 )
240 neighbor_indices.push_back(
get_index( x - 1, y - 1, z ) );
241 if ( x > 0 && y <
m_sizes[1] - 1 )
242 neighbor_indices.push_back(
get_index( x - 1, y + 1, z ) );
243 if ( x <
m_sizes[0] - 1 && y > 0 )
244 neighbor_indices.push_back(
get_index( x + 1, y - 1, z ) );
246 neighbor_indices.push_back(
get_index( x + 1, y + 1, z ) );
248 double excess_per_neighbor = excess / neighbor_indices.size();
249 std::map<int, double> neighborVof;
250 for (
auto ni : neighbor_indices ) {
252 neighborVof[ni] =
m_voxels[ni].vof();
254 neighbor_indices_workingset = neighbor_indices;
255 while ( (excess > 0) && (neighbor_indices_workingset.size() > 0 )) {
257 std::vector<int> neighbor_indices2;
258 for (
auto ni : neighbor_indices_workingset ) {
259 if (neighborVof[ni] < 1.0) {
260 double vof_after = neighborVof[ni] + excess_per_neighbor;
261 if (vof_after > 1.0) {
262 excess += vof_after - 1.0;
264 neighborVof[ni] += excess_per_neighbor;
266 neighborVof[ni] = vof_after;
267 neighbor_indices2.push_back( ni );
270 excess += excess_per_neighbor;
273 excess_per_neighbor = excess / neighbor_indices2.size();
274 neighbor_indices_workingset = neighbor_indices2;
277 for (
auto ni : neighbor_indices ) {
278 if (neighborVof[ni] >
m_voxels[ni].vof()) {
279 m_voxels[ni].vofHistory.push_back( std::make_tuple( timeActivated, neighborVof[ni] ) );
284 m_voxels[index].vofHistory.push_back( std::make_tuple( timeActivated, vof_after ) );
390 Vertex v1( { { orig[0], orig[1], orig[2] }, { -1, -1, -1 } } );
391 Vertex v2( { { orig[0] + dx, orig[1], orig[2] }, { 1, -1, -1 } } );
392 Vertex v3( { { orig[0] + dx, orig[1] + dy, orig[2] }, { 1, 1, -1 } } );
393 Vertex v4( { { orig[0], orig[1] + dy, orig[2] }, { -1, 1, -1 } } );
395 Vertex v5( { { orig[0], orig[1], orig[2] + dz }, { -1, -1, 1 } } );
396 Vertex v6( { { orig[0] + dx, orig[1], orig[2] + dz }, { 1, -1, 1 } } );
397 Vertex v7( { { orig[0] + dx, orig[1] + dy, orig[2] + dz }, { 1, 1, 1 } } );
398 Vertex v8( { { orig[0], orig[1] + dy, orig[2] + dz }, { -1, 1, 1 } } );
400 Polygon p1( { v1, v2, v6, v5 } );
401 Polygon p2( { v8, v7, v3, v4 } );
402 Polygon p3( { v1, v5, v8, v4 } );
403 Polygon p4( { v6, v2, v3, v7 } );
404 Polygon p5( { v8, v5, v6, v7 } );
405 Polygon p6( { v4, v3, v2, v1 } );
412 std::ofstream file( filename );
413 file <<
"# vtk DataFile Version 2.0\n";
416 file <<
"DATASET UNSTRUCTURED_GRID\n";
417 file <<
"POINTS " <<
m_voxels.size() * 8 <<
" double\n";
419 for (
const auto &[i, voxel] :
m_voxels ) {
423 file << pt[0] <<
" " << pt[1] <<
" " << pt[2] <<
"\n";
424 file << pt[0] +
m_steps[0] <<
" " << pt[1] <<
" " << pt[2] <<
"\n";
425 file << pt[0] +
m_steps[0] <<
" " << pt[1] +
m_steps[1] <<
" " << pt[2] <<
"\n";
426 file << pt[0] <<
" " << pt[1] +
m_steps[1] <<
" " << pt[2] <<
"\n";
428 file << pt[0] <<
" " << pt[1] <<
" " << pt[2] +
m_steps[2] <<
"\n";
429 file << pt[0] +
m_steps[0] <<
" " << pt[1] <<
" " << pt[2] +
m_steps[2] <<
"\n";
431 file << pt[0] <<
" " << pt[1] +
m_steps[1] <<
" " << pt[2] +
m_steps[2] <<
"\n";
436 for (
size_t i = 0; i <
m_voxels.size(); i++ ) {
438 for (
int j = 0; j < 8; j++ ) {
439 file << i * 8 + j <<
" ";
444 file <<
"CELL_TYPES " <<
m_voxels.size() <<
"\n";
446 for (
size_t i = 0; i <
m_voxels.size(); i++ ) {
450 file <<
"CELL_DATA " <<
m_voxels.size() <<
"\n";
451 file <<
"SCALARS vof double 1\n";
452 file <<
"LOOKUP_TABLE default\n";
454 for (
auto &[index, voxel] :
m_voxels ) {
455 file << voxel.vof() <<
"\n";
Model modelfrompolygons(const std::vector< Polygon > &polygons)
std::array< double, 3 > steps()
Get the step sizes in each dimension.
int size()
Get the size of the grid.
Voxel & get_voxel(int index)
Get the voxel at a given index.
void activateNodes(int index, double timeActivated)
VoxelGrid(std::array< double, 3 > steps, std::array< int, 3 > sizes)
Constructor for VoxelGrid.
std::array< double, 3 > get_vector_3d(int i)
Get the 3D vector of a voxel (origin) from its 1D index.
bool is_active_node(int index)
Check if a node at a given index is active.
int active_elements()
Get the number of active elements (voxels) in the grid.
std::array< int, 3 > sizes()
Get the number of steps in each dimension.
Voxel & activate(int index, double timeActivated, double vofIncrement)
Activate a voxel at a given index in a given time and store the corresponding vof value.
void writeVTK(std::string filename)
std::unordered_map< int, VoxelNode > m_nodes
std::array< double, 3 > m_steps
std::unordered_map< int, VoxelNode > & giveNodes()
Get the map of nodes in the grid.
std::array< int, 3 > m_sizes
Voxel & createVoxel(int index, double timeActivated)
Create a Vovel at given index and at given time.
bool is_active(int index)
Check if a voxel at a given index is active.
VoxelNode & get_node(int index)
Get the node at a given index.
std::unordered_map< int, Voxel > m_voxels
std::array< int, 8 > giveVoxelNodeIds(int index)
std::tuple< int, int, int > get_indices_from_point(std::array< double, 3 > point)
Get the 3D indices of a voxel from a point in space.
int active_nodes()
Get the number of active nodes in the grid.
int get_index(int i, int j, int k)
Get the 1D index of a voxel in the grid.
std::unordered_map< int, Voxel > & giveVoxels()
Get the map of nodes in the grid.
std::tuple< int, int, int > get_indices(int i)
Get the 3D indices of a voxel from its 1D index.
Model get_model(int index)
Get the triangulated model of a voxel at a given index.
A struct to represent a 3D model.
A struct to represent a single voxel.
double getVofAt(double time)
std::vector< std::tuple< double, double > > vofHistory
double vof()
Get the volume of fluid (infill percentage) of the voxel.
double time_activated()
Get the time the voxel was activated.
std::array< int, 8 > nodes