From 985fd6b9eda2ee0b082a0aa5649934c49226ff56 Mon Sep 17 00:00:00 2001 From: djairoh Date: Mon, 22 Apr 2024 15:01:33 +0200 Subject: [PATCH] feat (WIP): base VTK visualisation of Eulerian flow fields --- vtk/.gitignore | 6 +++ vtk/README.md | 39 ++++++++++++++++++ vtk/src/CMakeLists.txt | 55 ++++++++++++++++++++++++ vtk/src/main.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 vtk/.gitignore create mode 100644 vtk/README.md create mode 100644 vtk/src/CMakeLists.txt create mode 100644 vtk/src/main.cpp diff --git a/vtk/.gitignore b/vtk/.gitignore new file mode 100644 index 0000000..95abd3d --- /dev/null +++ b/vtk/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +src/.DS_Store +src/.cache +src/build +.idea +src/cmake-build-debug \ No newline at end of file diff --git a/vtk/README.md b/vtk/README.md new file mode 100644 index 0000000..ec2a268 --- /dev/null +++ b/vtk/README.md @@ -0,0 +1,39 @@ +## Location of data +The data path is hardcoded such that the following tree structure is assumed: +``` +data/ + grid.h5 + hydrodynamic_U.h5 + hydrodynamic_V.h5 +interactive-track-and-trace/ + opening-hdf5/ + ... +``` + +## Compiling +Let the current directory be the `src` directory. Run: +```shell +mkdir build +cd build +cmake .. +make +``` + +### Building with Linux +Makes use of `mdspan` which is not supported by glibc++ at time of writing. See [compiler support](https://en.cppreference.com/w/cpp/compiler_support/23) for `mdspan`. The solution to this is to use Clang and libc++; this is configured in our CMake setup, however the default installation of the `netcdf-cxx` package on at least Arch linux (and suspectedly Debian derivatives as well) specifically builds for the glibc implementation. To get the netcdf C++ bindings functional with the libc++ implementation, one needs to build from source. On Linux, this requires a few changes to the CMake file included with the netcdf-cxx source code, which are detailed below. + +Step-by-step to build the program using clang++ and libc++ on linux: + 1. Download the source code of netcdf-cxx, found at 'https://github.com/Unidata/netcdf-cxx4/releases/tag/v4.3.1' (make sure to download the release source code, as the master branch contains non-compilable code). + 2. Edit the CMakeLists.txt file, by appending '-stdlib=libc++' to the `CMAKE_CXX_FLAGS` variable in line 430. This means line 430 should read: + ```cmake + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wno-unused-variable -Wno-unused-parameter -stdlib=libc++") + ``` + 2. Build the source code with the following: + ```sh + mkdir build && cd build + cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/clang++ + make + ctest + sudo make install + ``` + 3. Now the code should compile through the standard steps described in the Compiling section. diff --git a/vtk/src/CMakeLists.txt b/vtk/src/CMakeLists.txt new file mode 100644 index 0000000..a97a1e0 --- /dev/null +++ b/vtk/src/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(VtkBase) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +find_package(VTK COMPONENTS + CommonColor + CommonCore + CommonDataModel + FiltersGeneral + InteractionStyle + RenderingContextOpenGL2 + RenderingCore + RenderingFreeType + RenderingGL2PSOpenGL2 + RenderingOpenGL2 + CommonColor + FiltersGeometry + RenderingCore) + +if (NOT VTK_FOUND) + message(FATAL_ERROR "VtkBase: Unable to find the VTK build folder.") +endif() + +# netcdf setup +find_package(netCDF REQUIRED) + +add_executable(VtkBase MACOSX_BUNDLE main.cpp ) + +execute_process( + COMMAND nc-config --includedir + OUTPUT_VARIABLE NETCDF_INCLUDE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +execute_process( + COMMAND ncxx4-config --libdir + OUTPUT_VARIABLE NETCDFCXX_LIB_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +target_include_directories(VtkBase PUBLIC ${netCDF_INCLUDE_DIR}) + +find_library(NETCDF_LIB NAMES netcdf-cxx4 netcdf_c++4 PATHS ${NETCDFCXX_LIB_DIR} NO_DEFAULT_PATH) + +# Prevent a "command line is too long" failure in Windows. +set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.") +target_link_libraries(VtkBase ${NETCDF_LIB} ${VTK_LIBRARIES}) + +# vtk_module_autoinit is needed +vtk_module_autoinit( + TARGETS VtkBase + MODULES ${VTK_LIBRARIES} +) diff --git a/vtk/src/main.cpp b/vtk/src/main.cpp new file mode 100644 index 0000000..2f7c56f --- /dev/null +++ b/vtk/src/main.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NLATS 67 +#define NLONS 116 + +using namespace std; +using namespace netCDF; + +template +vector getVarVector(const NcVar &var) { + int length = 1; + for (NcDim dim : var.getDims()) { + length *= dim.getSize(); + } + + vector vec(length); + + var.getVar(vec.data()); + + return vec; +} + +tuple, vector, vector> readGrid() { + netCDF::NcFile data("../../../../data/grid.h5", netCDF::NcFile::read); + multimap< string, NcVar > vars = data.getVars(); + vector time = getVarVector(vars.find("times")->second); + vector longitude = getVarVector(vars.find("longitude")->second); + vector latitude = getVarVector(vars.find("latitude")->second); + + return {time, latitude, longitude}; +} + +int main() { + vtkNew colors; + + + vtkNew pCoords; + pCoords->SetNumberOfComponents(3); + pCoords->SetNumberOfTuples(NLATS*NLONS); + auto [times, lats, lons] = readGrid(); + + double i = 0; + for (double lat : lats) { + for (double lon : lons) { + pCoords->InsertTuple3(i++, 0, lat, lon); + } + } + + + vtkNew points; + points->SetData(pCoords); + + vtkNew polydata; + polydata->SetPoints(points); + + + vtkNew mapper; + mapper->SetInputData(polydata); + mapper->SetScalarRange(0, 40); + + vtkNew actor; + actor->SetMapper(mapper); + + vtkNew ren; + ren->AddActor(actor); + ren->SetBackground(colors->GetColor3d("DarkSlateGray").GetData()); + + vtkNew renWin; + renWin->AddRenderer(ren); + renWin->SetSize(900, 600); + + vtkNew iren; + iren->SetRenderWindow(renWin); + iren->Start(); + + return EXIT_SUCCESS; +} +