Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ option(WITH_NAN_PROTECTION "Guard against NaN/Inf in macroscopic variables" ON)
option(USE_FLOAT "Use float instead of double as real_type" OFF)
option(FORCE_USE_CPU "Force host execution even when a GPU is available" OFF)
option(BENCHMARK_MODE "Build the benchmark driver" OFF)
option(PORTLBM_BUILD_EXECUTABLE "Build the run_portlbm driver executable" ON)
option(PORTLBM_BUILD_EXECUTABLE "Build the portlbm driver executable" ON)
option(PORTLBM_BUILD_TESTS "Build the Catch2 unit and integration tests" OFF)
option(PORTLBM_FORMAT_ONLY
"Configure formatting targets only — skips all dependencies and compilation" OFF)
Expand Down Expand Up @@ -152,7 +152,7 @@ if(WITH_VISUALIZATION)
FetchContent_Declare(
glfw
GIT_REPOSITORY https://github.com/glfw/glfw.git
GIT_TAG 3.4
GIT_TAG 3.3.8
GIT_SHALLOW TRUE)
set(GLFW_BUILD_DOCS
OFF
Expand Down Expand Up @@ -231,17 +231,16 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/include/lbm/version.hpp.in"
# ---- Executable target -----------------------------------------------------

if(PORTLBM_BUILD_EXECUTABLE)
add_executable(run_portlbm src/main_gpu.cpp)
target_link_libraries(run_portlbm PRIVATE portlbm_core)
add_executable(portlbm src/main_gpu.cpp)
target_link_libraries(portlbm PRIVATE portlbm_core)

# benchmark.cpp is application-level; not compiled into the library.
if(BENCHMARK_MODE)
target_sources(run_portlbm
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/lbm/benchmark/benchmark.cpp")
target_compile_definitions(run_portlbm PRIVATE BENCHMARK_MODE)
target_sources(portlbm PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/lbm/benchmark/benchmark.cpp")
target_compile_definitions(portlbm PRIVATE BENCHMARK_MODE)
endif()

add_sycl_to_target(TARGET run_portlbm)
add_sycl_to_target(TARGET portlbm)
endif()

# ---- Tests -----------------------------------------------------------------
Expand Down
30 changes: 21 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ PortLBM is a GPU-accelerated 2D fluid simulator based on the Lattice Boltzmann M

Only two dependencies must be installed manually. Everything else is either auto-fetched by CMake or installed via the provided script.

| Software | Version | How to obtain |
| -------- | ------- | ------------- |
| [llvm](https://github.com/llvm/llvm-project) | 18.1.8 | `spack install llvm@18.1.8 +llvm_dylib -gold +clang` |
| [glfw](https://github.com/glfw/glfw) | any | Only required with `-DWITH_VISUALIZATION=ON`. Auto-fetched by CMake if not found, but requires X11 dev headers (`sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev`). Alternatively: `spack install glfw` |
| Software | Version | Manual install | Spack command |
| -------- | ------- | :------------: | -------------- |
| [llvm](https://github.com/llvm/llvm-project) | 18.1.8 | yes | `spack install llvm@18.1.8 +llvm_dylib -gold +clang` |
| [boost](https://www.boost.org) | 1.85.0 | yes | `spack install boost@1.85.0 +fiber +context +atomic +filesystem` |
| [AdaptiveCpp](https://github.com/AdaptiveCpp/AdaptiveCpp) | v24.10 | no | — |
| [glfw](https://github.com/glfw/glfw) | 3.3.8 | no | `spack install glfw@3.3.8` |

> **Note:** Building LLVM with Spack can take more than one hour depending on your machine.

[nlohmann/json](https://github.com/nlohmann/json) and [fmt](https://github.com/fmtlib/fmt) are fetched automatically by CMake if not found on the system.
AdaptiveCpp is installed automatically by the provided `install_adaptivecpp.sh` script (see below). GLFW is auto-fetched by CMake if not found on the system, but requires X11 dev headers (`sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev`); alternatively install via Spack. [nlohmann/json](https://github.com/nlohmann/json) and [fmt](https://github.com/fmtlib/fmt) are also fetched automatically by CMake.

### Installing AdaptiveCpp

Expand Down Expand Up @@ -52,12 +54,22 @@ CMake automatically picks up the installation from the build directory — no ad
# Without GUI
cmake -B build -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DWITH_NAN_PROTECTION=OFF
cmake --build build
./build/run_portlbm

# With GUI
cmake -B build -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DWITH_VISUALIZATION=ON -DWITH_NAN_PROTECTION=ON
cmake --build build
./build/run_portlbm
```

### Running

The executable locates `settings/settings.json` relative to itself, so it can be invoked from any working directory:

```bash
./build/portlbm # from the project root
/absolute/path/to/build/portlbm # absolute path

# Use a custom settings file
./portlbm /path/to/settings.json
```

### Running the tests
Expand All @@ -77,12 +89,12 @@ ctest --test-dir build --output-on-failure
| `-DUSE_FLOAT` | `OFF` | Use `float` instead of `double` as `real_type`. Changes the ABI — all targets must agree. |
| `-DFORCE_USE_CPU` | `OFF` | Use the CPU even when a faster device is available. |
| `-DBENCHMARK_MODE` | `OFF` | Enable the benchmark driver (requires `PORTLBM_BUILD_EXECUTABLE=ON`). |
| `-DPORTLBM_BUILD_EXECUTABLE` | `ON` | Build the `run_portlbm` driver executable. |
| `-DPORTLBM_BUILD_EXECUTABLE` | `ON` | Build the `portlbm` driver executable. |
| `-DPORTLBM_BUILD_TESTS` | `OFF` | Build the Catch2 unit and integration tests. |

## Simulation settings

Settings for the `run_portlbm` executable are read from `settings/settings.json`. A complete file looks like this:
Settings for the `portlbm` executable are read from `settings/settings.json`. A complete file looks like this:

```json
{
Expand Down
76 changes: 76 additions & 0 deletions clang-format.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
diff --git a/include/lbm/gui/lbm_gui.hpp b/include/lbm/gui/lbm_gui.hpp
index 6a40f8c..064dfec 100644
--- a/include/lbm/gui/lbm_gui.hpp
+++ b/include/lbm/gui/lbm_gui.hpp
@@ -1077,7 +1077,9 @@ class Gui
ImPlot::PushColormap(colormaps->density_colormap);

if (refit_plots)
+ {
ImPlot::SetNextAxesToFit();
+ }

if (ImPlot::BeginPlot(
"Density",
@@ -1169,8 +1171,7 @@ class Gui
if (windows->show_velocity && windows->enable_live_visualization)
{
ImGui::SetNextWindowPos(
- ImVec2((1.0 / 4) * monitor->viewport->WorkSize.x, windows->menu_bar_size),
- ImGuiCond_Appearing);
+ ImVec2((1.0 / 4) * monitor->viewport->WorkSize.x, windows->menu_bar_size), ImGuiCond_Appearing);

ImGui::SetNextWindowSize(
ImVec2((3.0 / 4) * monitor->viewport->WorkSize.x, (1.0 / 2) * monitor->viewport->WorkSize.y),
@@ -1200,7 +1201,9 @@ class Gui
ImPlot::PushColormap(colormaps->velocity_colormap);

if (refit_plots)
+ {
ImPlot::SetNextAxesToFit();
+ }

if (ImPlot::BeginPlot(
"Velocity",
diff --git a/src/lbm/benchmark/benchmark.cpp b/src/lbm/benchmark/benchmark.cpp
index fa391ab..fb08f1a 100644
--- a/src/lbm/benchmark/benchmark.cpp
+++ b/src/lbm/benchmark/benchmark.cpp
@@ -249,10 +249,10 @@ void lbm::benchmark::Benchmark::phase_0_and_1_helper(int phase)
properties->algorithm = algorithm;

// Create JSON file for algorithm
- std::string ofdir = (project_root_ / "benchmarks" / ("phase" + std::to_string(phase))
- / ("results_phase" + std::to_string(phase) + "_" + std::string{algorithm} + "_"
- + device_name + ".json"))
- .string();
+ std::string ofdir =
+ (project_root_ / "benchmarks" / ("phase" + std::to_string(phase))
+ / ("results_phase" + std::to_string(phase) + "_" + std::string{ algorithm } + "_" + device_name + ".json"))
+ .string();

nlohmann::json file_data = prepare_file_data_phase_0_and_1(algorithm);

@@ -412,7 +412,7 @@ void lbm::benchmark::Benchmark::phase_2()
// Create JSON file for algorithm
std::string ofdir =
(project_root_ / "benchmarks" / "phase2"
- / ("phase2_" + std::string{algorithm} + "_" + properties->scenario + "_" + device_name + ".json"))
+ / ("phase2_" + std::string{ algorithm } + "_" + properties->scenario + "_" + device_name + ".json"))
.string();
nlohmann::json file_data = prepare_file_data_phase_2();

@@ -434,10 +434,9 @@ void lbm::benchmark::Benchmark::phase_2()
lbm::file_interaction::properties_to_json(*properties);

// Create JSON file for algorithm
- std::string ofdir =
- (project_root_ / "benchmarks" / "phase2"
- / ("phase2_lptl_" + properties->scenario + "_" + device_name + ".json"))
- .string();
+ std::string ofdir = (project_root_ / "benchmarks" / "phase2"
+ / ("phase2_lptl_" + properties->scenario + "_" + device_name + ".json"))
+ .string();
nlohmann::json file_data = prepare_file_data_phase_2_tl_linear();

phase_2_inner_loop(ofdir, file_data, progress_phase);
90 changes: 90 additions & 0 deletions cmake-format.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 10b55c8..352a9ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -236,8 +236,7 @@ if(PORTLBM_BUILD_EXECUTABLE)

# benchmark.cpp is application-level; not compiled into the library.
if(BENCHMARK_MODE)
- target_sources(portlbm
- PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/lbm/benchmark/benchmark.cpp")
+ target_sources(portlbm PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/lbm/benchmark/benchmark.cpp")
target_compile_definitions(portlbm PRIVATE BENCHMARK_MODE)
endif()

diff --git a/include/lbm/gui/lbm_gui.hpp b/include/lbm/gui/lbm_gui.hpp
index 6a40f8c..064dfec 100644
--- a/include/lbm/gui/lbm_gui.hpp
+++ b/include/lbm/gui/lbm_gui.hpp
@@ -1077,7 +1077,9 @@ class Gui
ImPlot::PushColormap(colormaps->density_colormap);

if (refit_plots)
+ {
ImPlot::SetNextAxesToFit();
+ }

if (ImPlot::BeginPlot(
"Density",
@@ -1169,8 +1171,7 @@ class Gui
if (windows->show_velocity && windows->enable_live_visualization)
{
ImGui::SetNextWindowPos(
- ImVec2((1.0 / 4) * monitor->viewport->WorkSize.x, windows->menu_bar_size),
- ImGuiCond_Appearing);
+ ImVec2((1.0 / 4) * monitor->viewport->WorkSize.x, windows->menu_bar_size), ImGuiCond_Appearing);

ImGui::SetNextWindowSize(
ImVec2((3.0 / 4) * monitor->viewport->WorkSize.x, (1.0 / 2) * monitor->viewport->WorkSize.y),
@@ -1200,7 +1201,9 @@ class Gui
ImPlot::PushColormap(colormaps->velocity_colormap);

if (refit_plots)
+ {
ImPlot::SetNextAxesToFit();
+ }

if (ImPlot::BeginPlot(
"Velocity",
diff --git a/src/lbm/benchmark/benchmark.cpp b/src/lbm/benchmark/benchmark.cpp
index fa391ab..fb08f1a 100644
--- a/src/lbm/benchmark/benchmark.cpp
+++ b/src/lbm/benchmark/benchmark.cpp
@@ -249,10 +249,10 @@ void lbm::benchmark::Benchmark::phase_0_and_1_helper(int phase)
properties->algorithm = algorithm;

// Create JSON file for algorithm
- std::string ofdir = (project_root_ / "benchmarks" / ("phase" + std::to_string(phase))
- / ("results_phase" + std::to_string(phase) + "_" + std::string{algorithm} + "_"
- + device_name + ".json"))
- .string();
+ std::string ofdir =
+ (project_root_ / "benchmarks" / ("phase" + std::to_string(phase))
+ / ("results_phase" + std::to_string(phase) + "_" + std::string{ algorithm } + "_" + device_name + ".json"))
+ .string();

nlohmann::json file_data = prepare_file_data_phase_0_and_1(algorithm);

@@ -412,7 +412,7 @@ void lbm::benchmark::Benchmark::phase_2()
// Create JSON file for algorithm
std::string ofdir =
(project_root_ / "benchmarks" / "phase2"
- / ("phase2_" + std::string{algorithm} + "_" + properties->scenario + "_" + device_name + ".json"))
+ / ("phase2_" + std::string{ algorithm } + "_" + properties->scenario + "_" + device_name + ".json"))
.string();
nlohmann::json file_data = prepare_file_data_phase_2();

@@ -434,10 +434,9 @@ void lbm::benchmark::Benchmark::phase_2()
lbm::file_interaction::properties_to_json(*properties);

// Create JSON file for algorithm
- std::string ofdir =
- (project_root_ / "benchmarks" / "phase2"
- / ("phase2_lptl_" + properties->scenario + "_" + device_name + ".json"))
- .string();
+ std::string ofdir = (project_root_ / "benchmarks" / "phase2"
+ / ("phase2_lptl_" + properties->scenario + "_" + device_name + ".json"))
+ .string();
nlohmann::json file_data = prepare_file_data_phase_2_tl_linear();

phase_2_inner_loop(ofdir, file_data, progress_phase);
4 changes: 4 additions & 0 deletions include/lbm/benchmark/benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// Standard library
#include <array>
#include <filesystem>
#include <iostream>
#include <limits>
#include <string>
Expand Down Expand Up @@ -81,6 +82,9 @@ class Benchmark
private:
std::shared_ptr<execution::SYCLAlgorithmHandler> sycl_algorithm_handler;

// Project root derived from the settings path — used for all relative I/O.
std::filesystem::path project_root_;

std::string device_name;

std::unique_ptr<core::Properties> properties;
Expand Down
24 changes: 22 additions & 2 deletions include/lbm/gui/lbm_gui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "gui_constants.hpp"

// Standard library
#include <filesystem>
#include <memory>

// ImGui
Expand Down Expand Up @@ -270,6 +271,7 @@ class Gui
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////

std::string settings_path_;
std::filesystem::path project_root_;

std::unique_ptr<core::Properties> properties_gui;
std::unique_ptr<Windows> windows;
Expand All @@ -290,6 +292,9 @@ class Gui

bool properties_changed;

// Set to true when the domain changes so both plots refit their axes on the next frame.
bool refit_plots;

double fps_update_time;

// STYLES
Expand Down Expand Up @@ -369,6 +374,7 @@ class Gui
properties_changed = false;
algorithm_handler->pause();
algorithm_handler->initialize();
refit_plots = true;

colormaps->density_colormap_lower_scale =
std::min({ algorithm_handler->get_inlet_density(), algorithm_handler->get_outlet_density() });
Expand Down Expand Up @@ -1070,6 +1076,11 @@ class Gui

ImPlot::PushColormap(colormaps->density_colormap);

if (refit_plots)
{
ImPlot::SetNextAxesToFit();
}

if (ImPlot::BeginPlot(
"Density",
ImVec2(ImGui::GetContentRegionAvail().x - monitor->monitor_x_scale * 100
Expand Down Expand Up @@ -1189,6 +1200,11 @@ class Gui

ImPlot::PushColormap(colormaps->velocity_colormap);

if (refit_plots)
{
ImPlot::SetNextAxesToFit();
}

if (ImPlot::BeginPlot(
"Velocity",
ImVec2(ImGui::GetContentRegionAvail().x - monitor->monitor_x_scale * 100
Expand Down Expand Up @@ -1348,6 +1364,7 @@ class Gui
public:
explicit Gui(const std::string &&window_title, const std::string &settings_path) :
settings_path_(settings_path),
project_root_(std::filesystem::path(settings_path_).parent_path().parent_path()),
simulation_control(std::make_unique<SimulationControl>()),
progress(std::make_unique<Progress>()),
colormaps(std::make_unique<Colormaps>()),
Expand All @@ -1357,6 +1374,7 @@ class Gui
velocity_quiver_data(std::make_unique<VelocityQuiverData>(2 * properties_gui->domain_node_count)),
window_title(std::make_unique<std::string>(window_title)),
properties_changed(false),
refit_plots(false),
fps_buffer(std::make_unique<FPSBuffer>(2000)),
algorithm_handler(std::make_unique<A>(settings_path_))
{
Expand Down Expand Up @@ -1401,13 +1419,14 @@ class Gui
ImGui_ImplGlfw_InitForOpenGL(glfw_window, true);
ImGui_ImplOpenGL3_Init(glsl_version);

set_light_style();
set_dark_style();

// IO
ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
const std::string font_path = (project_root_ / "fonts" / "DroidSans.ttf").string();
io.Fonts->AddFontFromFileTTF(
"../fonts/DroidSans.ttf", 2 * sqrt(monitor->monitor_x_scale * monitor->monitor_x_scale) * 9.0f);
font_path.c_str(), 2 * sqrt(monitor->monitor_x_scale * monitor->monitor_x_scale) * 9.0f);

// ImPlot style
ImPlotStyle &implot_style = ImPlot::GetStyle();
Expand Down Expand Up @@ -1491,6 +1510,7 @@ class Gui

density_window();
velocity_window();
refit_plots = false;
debug_message();
render();

Expand Down
Loading
Loading