Skip to content

Commit

Permalink
Data in exported .vtk files is now automatically converted to SI unit…
Browse files Browse the repository at this point in the history
…s, faster .vtk export with multithreading, fixed missing scaling of coordinates to SI units in LBM::write_mesh_to_vtk()
  • Loading branch information
ProjectPhysX committed Feb 11, 2024
1 parent e890d3c commit 4bcb324
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 83 deletions.
8 changes: 7 additions & 1 deletion DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ git clone https://github.com/ProjectPhysX/FluidX3D.git
chmod +x make.sh
./make.sh
```
- [`INTERACTIVE_GRAPHICS`](src/defines.hpp) mode is not supported on macOS, as no X11 is available. You can still use [`INTERACTIVE_GRAPHICS_ASCII`](src/defines.hpp) preview though, or [render video](#video-rendering) to the hard drive with regular [`GRAPHICS`](src/defines.hpp) mode.

### Android
- Select [`TARGET=Android`](make.sh#L6) in [`make.sh`](make.sh#L6).
Expand All @@ -49,6 +50,7 @@ git clone https://github.com/ProjectPhysX/FluidX3D.git
chmod +x make.sh
./make.sh
```
- [`INTERACTIVE_GRAPHICS`](src/defines.hpp) mode is not supported on Android, as no X11 is available. You can still use [`INTERACTIVE_GRAPHICS_ASCII`](src/defines.hpp) preview though, or [render video](#video-rendering) to the hard drive with regular [`GRAPHICS`](src/defines.hpp) mode.

<br>

Expand Down Expand Up @@ -115,7 +117,10 @@ git clone https://github.com/ProjectPhysX/FluidX3D.git
```c
const uint3 lbm_N = resolution(float3(1.0f, 2.0f, 0.5f), 2000u);
```
This takes as inputs the desired aspect ratio of the simulation box and the VRAM occupation in MB, and returns the grid resolution as a `uint3` with `.x`/`.y`/`.z` components. You can also directly feed the `uint3` into the LBM constructor as resolution: `LBM lbm(lbm_N, nu, ...);`
This takes as inputs the desired aspect ratio of the simulation box and the VRAM occupation in MB, and returns the grid resolution as a `uint3` with `.x`/`.y`/`.z` components. You can also directly feed the `uint3` into the LBM constructor as resolution:
```c
LBM lbm(lbm_N, nu, ...);
```

### Unit Conversion
- The LBM simulation uses a different unit system from SI units, where density `rho=1` and velocity `u≈0.001-0.1`, because floating-point arithmetic is most accurate close to `1`.
Expand Down Expand Up @@ -235,6 +240,7 @@ git clone https://github.com/ProjectPhysX/FluidX3D.git
lbm.write_mesh_to_vtk(const Mesh* mesh); // for exporting triangle meshes
```
- These functions first pull the data from the GPU(s) into CPU RAM, and then write it to the hard drive.
- If [unit conversion](#unit-conversion) with `units.set_m_kg_s(...)` was specified, the data in exported `.vtk` files is automaticlally converted to SI units.
- Exported files will automatically be assigned the current simulation time step in their name, in the format `bin/export/u-123456789.vtk`.
- Be aware that these volumetric files can be gigantic in file size, tens of GigaByte for a single file.
- You can view/evaluate the `.vtk` files for example in [ParaView](https://www.paraview.org/).
Expand Down
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,20 @@ The fastest and most memory efficient lattice Boltzmann CFD software, running on
- fixed flickering with frustrum culling at very small field of view
- fixed bug where rendered/exported frame was not updated when `visualization_modes` changed
- v2.12 (18.01.2024)
- significantly (~3x) faster source code compiling on Linux using multiple CPU cores if [`make`](https://www.gnu.org/software/make/) is installed
- ~3x faster source code compiling on Linux using multiple CPU cores if [`make`](https://www.gnu.org/software/make/) is installed
- significantly faster simulation initialization (~40% single-GPU, ~15% multi-GPU)
- minor bug fix in `Memory_Container::reset()` function
- v2.13 (11.02.2023)
- data in exported `.vtk` files is now automatically converted to SI units
- ~2x faster `.vtk` export with multithreading
- added unit conversion functions for `TEMPERATURE` extension
- fixed graphical artifacts with axis-aligned camera in raytracing
- fixed `get_exe_path()` for macOS
- fixed X11 multi-monitor issues on Linux
- workaround for Nvidia driver bug: `enqueueFillBuffer` is broken for large buffers on Nvidia GPUs
- fixed slow numeric drift issues caused by `-cl-fast-relaxed-math`
- fixed wrong Maximum Allocation Size reporting in `LBM::write_status()`
- fixed missing scaling of coordinates to SI units in `LBM::write_mesh_to_vtk()`

</details>

Expand Down Expand Up @@ -218,7 +229,7 @@ $$f_j(i\\%2\\ ?\\ \vec{x}+\vec{e}_i\\ :\\ \vec{x},\\ t+\Delta t)=f_i^\textrm{tem

- domain decomposition allows pooling VRAM from multiple GPUs for much larger grid resolution
- each domain (GPU) can hold up to 4.29 billion (2³², 1624³) lattice points (225 GB memory)
- GPUs don't have to be identical (not even from the same vendor), but similar VRAM capacity/bandwidth is recommended
- GPUs don't have to be identical (<a href="https://youtu.be/PscbxGVs52o">not even from the same vendor</a>), but similar VRAM capacity/bandwidth is recommended
- domain communication architecture (simplified)
```diff
++ .-----------------------------------------------------------------. ++
Expand Down Expand Up @@ -339,7 +350,8 @@ $$f_j(i\\%2\\ ?\\ \vec{x}+\vec{e}_i\\ :\\ \vec{x},\\ t+\Delta t)=f_i^\textrm{tem
- FluidX3D can do simulations so large that storing the volumetric data for later rendering becomes unmanageable (like 120GB for a single frame, hundreds of TeraByte for a video)
- instead, FluidX3D allows [rendering raw simulation data directly in VRAM](https://www.researchgate.net/publication/360501260_Combined_scientific_CFD_simulation_and_interactive_raytracing_with_OpenCL), so no large volumetric files have to be exported to the hard disk (see my [technical talk](https://youtu.be/pD8JWAZ2f8o))
- the rendering is so fast that it works interactively in real time for both rasterization and raytracing
- if no monitor is available (like on a remote Linux server), there is an ASCII rendering mode to interactively visualize the simulation in the terminal (even in WSL and/or through SSH)
- rasterization and raytracing are done in OpenCL and work on all GPUs, even the ones without RTX/DXR raytracing cores or without any rendering hardware at all (like A100, MI200, ...)
- if no monitor is available (like on a remote Linux server), there is an [ASCII rendering mode](https://youtu.be/pD8JWAZ2f8o&t=1456) to interactively visualize the simulation in the terminal (even in WSL and/or through SSH)
- rendering is fully multi-GPU-parallelized via seamless domain decomposition rasterization
- with interactive graphics mode disabled, image resolution can be as large as VRAM allows for (4K/8K/16K and above)
- (interacitive) visualization modes:
Expand All @@ -365,7 +377,7 @@ $$f_j(i\\%2\\ ?\\ \vec{x}+\vec{e}_i\\ :\\ \vec{x},\\ t+\Delta t)=f_i^\textrm{tem
- native cross-vendor multi-GPU implementation
- uses PCIe communication, so no SLI/Crossfire/NVLink/InfinityFabric required
- single-node parallelization, so no MPI installation required
- GPUs don't even have to be from the same vendor, but similar memory capacity and bandwidth are recommended
- [GPUs don't even have to be from the same vendor](https://youtu.be/PscbxGVs52o), but similar memory capacity and bandwidth are recommended
- works in [Windows](DOCUMENTATION.md#windows) and [Linux](DOCUMENTATION.md#linux) with C++17, with limited support also for [macOS](DOCUMENTATION.md#macos) and [Android](DOCUMENTATION.md#android)
- supports [importing and voxelizing triangle meshes](DOCUMENTATION.md#loading-stl-files) from binary `.stl` files, with fast GPU voxelization
- supports [exporting volumetric data](DOCUMENTATION.md#data-export) as binary `.vtk` files
Expand Down
24 changes: 12 additions & 12 deletions src/info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,23 @@ double Info::time() const { // returns either elapsed time or remaining time
void Info::print_logo() const {
const int a=color_light_blue, b=color_orange, c=color_pink;
print(".-----------------------------------------------------------------------------.\n");
print("| "); print("______________ ", a); print("______________", b); print(" |\n");
print("| "); print("\\ ________ | ", a); print("| ________ /", b); print(" |\n");
print("| "); print( " ______________ ", a); print(" ______________ ", b); print(" |\n");
print("| "); print( "\\ ________ | ", a); print("| ________ /", b); print(" |\n");
print("| "); print("\\ \\ | | ", a); print("| | / /", b); print(" |\n");
print("| "); print("\\ \\ | | ", a); print("| | / /", b); print(" |\n");
print("| "); print("\\ \\ | | ", a); print("| | / /", b); print(" |\n");
print("| "); print("\\ \\_.-\" | ", a); print("| \"-._/ /", b); print(" |\n");
print("| "); print("\\ \\_.-\" | ", a); print("| \"-._/ /", b); print(" |\n");
print("| "); print("\\ _.-\" ", a); print("_ ", c); print("\"-._ /", b); print(" |\n");
print("| "); print("\\.-\" ", a); print("_.-\" \"-._ ", c); print("\"-./", b); print(" |\n");
print("| "); print(".-\" .-\"-. \"-.", c); print(" |\n");
print("| "); print("\\ v\" \"v /", c); print(" |\n");
print("| "); print("\\ \\ / /", c); print(" |\n");
print("| "); print("\\ \\ / /", c); print(" |\n");
print("| "); print("\\ \\ / /", c); print(" |\n");
print("| "); print("\\ ' /", c); print(" |\n");
print("| "); print("\\ /", c); print(" |\n");
print("| "); print("\\ /", c); print(" FluidX3D Version 2.12 |\n");
print("| "); print("'", c); print(" Copyright (c) Dr. Moritz Lehmann |\n");
print("| "); print(" .-\" .-\"-. \"-. ", c); print(" |\n");
print("| "); print("\\ v\" \"v /", c); print(" |\n");
print("| "); print("\\ \\ / /", c); print(" |\n");
print("| "); print("\\ \\ / /", c); print(" |\n");
print("| "); print("\\ \\ / /", c); print(" |\n");
print("| "); print("\\ ' /", c); print(" |\n");
print("| "); print("\\ /", c); print(" |\n");
print("| "); print("\\ /", c); print(" FluidX3D Version 2.13 |\n");
print("| "); print( "'", c); print(" Copyright (c) Dr. Moritz Lehmann |\n");
print("|-----------------------------------------------------------------------------|\n");
}
void Info::print_initialize() {
Expand Down
26 changes: 14 additions & 12 deletions src/lbm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,26 +989,28 @@ void LBM::unvoxelize_mesh_on_device(const Mesh* mesh, const uchar flag) { // rem
for(uint d=0u; d<get_D(); d++) lbm[d]->enqueue_unvoxelize_mesh_on_device(mesh, flag);
for(uint d=0u; d<get_D(); d++) lbm[d]->finish_queue();
}
void LBM::write_mesh_to_vtk(const Mesh* mesh, const string& path) const { // write mesh to binary .vtk file
void LBM::write_mesh_to_vtk(const Mesh* mesh, const string& path, const bool convert_to_si_units) const { // write mesh to binary .vtk file
const string header_1 = "# vtk DataFile Version 3.0\nData\nBINARY\nDATASET POLYDATA\nPOINTS "+to_string(3u*mesh->triangle_number)+" float\n";
const string header_2 = "POLYGONS "+to_string(mesh->triangle_number)+" "+to_string(4u*mesh->triangle_number)+"\n";
float* points = new float[9u*mesh->triangle_number];
int* triangles = new int[4u*mesh->triangle_number];
for(uint i=0u; i<mesh->triangle_number; i++) {
points[9u*i ] = reverse_bytes(mesh->p0[i].x-center().x);
points[9u*i+1u] = reverse_bytes(mesh->p0[i].y-center().y);
points[9u*i+2u] = reverse_bytes(mesh->p0[i].z-center().z);
points[9u*i+3u] = reverse_bytes(mesh->p1[i].x-center().x);
points[9u*i+4u] = reverse_bytes(mesh->p1[i].y-center().y);
points[9u*i+5u] = reverse_bytes(mesh->p1[i].z-center().z);
points[9u*i+6u] = reverse_bytes(mesh->p2[i].x-center().x);
points[9u*i+7u] = reverse_bytes(mesh->p2[i].y-center().y);
points[9u*i+8u] = reverse_bytes(mesh->p2[i].z-center().z);
const float spacing = convert_to_si_units ? units.si_x(1.0f) : 1.0f;
const float3 offset = center();
parallel_for(mesh->triangle_number, [&](uint i) {
points[9u*i ] = reverse_bytes(spacing*(mesh->p0[i].x-offset.x));
points[9u*i+1u] = reverse_bytes(spacing*(mesh->p0[i].y-offset.y));
points[9u*i+2u] = reverse_bytes(spacing*(mesh->p0[i].z-offset.z));
points[9u*i+3u] = reverse_bytes(spacing*(mesh->p1[i].x-offset.x));
points[9u*i+4u] = reverse_bytes(spacing*(mesh->p1[i].y-offset.y));
points[9u*i+5u] = reverse_bytes(spacing*(mesh->p1[i].z-offset.z));
points[9u*i+6u] = reverse_bytes(spacing*(mesh->p2[i].x-offset.x));
points[9u*i+7u] = reverse_bytes(spacing*(mesh->p2[i].y-offset.y));
points[9u*i+8u] = reverse_bytes(spacing*(mesh->p2[i].z-offset.z));
triangles[4u*i ] = reverse_bytes(3); // 3 vertices per triangle
triangles[4u*i+1u] = reverse_bytes(3*(int)i ); // vertex 0
triangles[4u*i+2u] = reverse_bytes(3*(int)i+1); // vertex 1
triangles[4u*i+3u] = reverse_bytes(3*(int)i+2); // vertex 2
}
});
const string filename = default_filename(path, "mesh", ".vtk", get_t());
create_folder(filename);
std::ofstream file(filename, std::ios::out|std::ios::binary);
Expand Down
32 changes: 20 additions & 12 deletions src/lbm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class LBM_Domain {
float nu = 1.0f/6.0f; // kinematic shear viscosity
float fx=0.0f, fy=0.0f, fz=0.0f; // global force per volume
float sigma=0.0f; // surface tension coefficient
float alpha=1.0f, beta=1.0f, T_avg=1.0f; // alpha = thermal diffusion coefficient, beta = thermal expansion coefficient, T_avg = 1 = average temperature
float alpha=1.0f, beta=1.0f, T_avg=1.0f; // alpha = thermal diffusion coefficient, beta = (volumetric) thermal expansion coefficient, T_avg = 1 = average temperature
uint particles_N = 0u;
float particles_rho = 1.0f;

Expand Down Expand Up @@ -279,8 +279,16 @@ class LBM {
else print_error("Error in vtk_type(): Type not supported.");
return "";
}
inline void write_vtk(const string& path) { // write binary .vtk file
const float spacing = units.si_x(1.0f);
inline void write_vtk(const string& path, const bool convert_to_si_units=true) { // write binary .vtk file
float spacing = 1.0f;
T unit_conversion_factor = (T)1;
if(convert_to_si_units) {
spacing = units.si_x(1.0f);
if(name=="rho") unit_conversion_factor = (T)units.si_rho(1.0f);
if(name=="u" ) unit_conversion_factor = (T)units.si_u (1.0f);
if(name=="F" ) unit_conversion_factor = (T)units.si_F (1.0f);
if(name=="T" ) unit_conversion_factor = (T)units.si_T (1.0f);
}
const float3 origin = spacing*float3(0.5f-0.5f*(float)Nx, 0.5f-0.5f*(float)Ny, 0.5f-0.5f*(float)Nz);
const string header =
"# vtk DataFile Version 3.0\nData\nBINARY\nDATASET STRUCTURED_POINTS\n"
Expand All @@ -290,11 +298,11 @@ class LBM {
"POINT_DATA "+to_string((ulong)Nx*(ulong)Ny*(ulong)Nz)+"\nSCALARS data "+vtk_type()+" "+to_string(dimensions())+"\nLOOKUP_TABLE default\n"
;
T* data = new T[range()];
for(uint d=0u; d<dimensions(); d++) {
for(ulong i=0ull; i<length(); i++) {
data[i*(ulong)dimensions()+(ulong)d] = reverse_bytes(reference(i, d)); // SoA <- AoS
parallel_for(length(), [&](ulong i) {
for(uint d=0u; d<dimensions(); d++) {
data[i*(ulong)dimensions()+(ulong)d] = reverse_bytes((T)(unit_conversion_factor*reference(i, d))); // SoA <- AoS
}
}
});
const string filename = create_file_extension(path, ".vtk");
create_folder(filename);
std::ofstream file(filename, std::ios::out|std::ios::binary);
Expand Down Expand Up @@ -366,12 +374,12 @@ class LBM {
for(uint domain=0u; domain<D; domain++) buffers[domain]->enqueue_write_to_device();
for(uint domain=0u; domain<D; domain++) buffers[domain]->finish_queue();
}
inline void write_host_to_vtk(const string& path="") { // write binary .vtk file
write_vtk(default_filename(path, name, ".vtk", lbm->get_t()));
inline void write_host_to_vtk(const string& path="", const bool convert_to_si_units=true) { // write binary .vtk file
write_vtk(default_filename(path, name, ".vtk", lbm->get_t()), convert_to_si_units);
}
inline void write_device_to_vtk(const string& path="") { // write binary .vtk file
inline void write_device_to_vtk(const string& path="", const bool convert_to_si_units=true) { // write binary .vtk file
read_from_device();
write_host_to_vtk(path);
write_host_to_vtk(path, convert_to_si_units);
}
};

Expand Down Expand Up @@ -502,7 +510,7 @@ class LBM {

void voxelize_mesh_on_device(const Mesh* mesh, const uchar flag=TYPE_S, const float3& rotation_center=float3(0.0f), const float3& linear_velocity=float3(0.0f), const float3& rotational_velocity=float3(0.0f)); // voxelize mesh
void unvoxelize_mesh_on_device(const Mesh* mesh, const uchar flag=TYPE_S); // remove voxelized triangle mesh from LBM grid
void write_mesh_to_vtk(const Mesh* mesh, const string& path="") const; // write mesh to binary .vtk file
void write_mesh_to_vtk(const Mesh* mesh, const string& path="", const bool convert_to_si_units=true) const; // write mesh to binary .vtk file
void voxelize_stl(const string& path, const float3& center, const float3x3& rotation, const float size=0.0f, const uchar flag=TYPE_S); // read and voxelize binary .stl file
void voxelize_stl(const string& path, const float3x3& rotation, const float size=0.0f, const uchar flag=TYPE_S); // read and voxelize binary .stl file (place in box center)
void voxelize_stl(const string& path, const float3& center, const float size=0.0f, const uchar flag=TYPE_S); // read and voxelize binary .stl file (no rotation)
Expand Down
Loading

0 comments on commit 4bcb324

Please sign in to comment.