feat: modules
This commit is contained in:
parent
4cd545c788
commit
a123071fec
|
|
@ -0,0 +1,6 @@
|
||||||
|
.DS_Store
|
||||||
|
src/.DS_Store
|
||||||
|
src/.cache
|
||||||
|
src/build
|
||||||
|
.idea
|
||||||
|
src/cmake-build-debug
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
cmake_minimum_required (VERSION 3.28)
|
||||||
|
project (LinearInterpolate)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Force use of libc++ for mdspan support
|
||||||
|
set(CMAKE_CXX_COMPILER "clang++")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ ")
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
find_package(netCDF REQUIRED)
|
||||||
|
|
||||||
|
add_executable(LinearInterpolate main.cpp
|
||||||
|
readdata.cpp
|
||||||
|
readdata.h
|
||||||
|
vecutils.cpp
|
||||||
|
vecutils.h)
|
||||||
|
|
||||||
|
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(LinearInterpolate PUBLIC ${netCDF_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_library(NETCDF_LIB NAMES netcdf-cxx4 netcdf_c++4 PATHS ${NETCDFCXX_LIB_DIR} NO_DEFAULT_PATH)
|
||||||
|
target_link_libraries(LinearInterpolate ${NETCDF_LIB})
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "readdata.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto [vec, size] = readHydrodynamicU();
|
||||||
|
|
||||||
|
auto arr = std::mdspan(vec.data(), size);
|
||||||
|
|
||||||
|
print3DMatrixSlice(arr, 100);
|
||||||
|
|
||||||
|
auto [times, lats, longs] = readGrid();
|
||||||
|
printContentsOfVec(lats);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include <print>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <netcdf>
|
||||||
|
|
||||||
|
#include "readdata.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace netCDF;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T> getVarVector(const NcVar &var) {
|
||||||
|
int length = 1;
|
||||||
|
for (NcDim dim : var.getDims()) {
|
||||||
|
length *= dim.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<T> vec(length);
|
||||||
|
|
||||||
|
var.getVar(vec.data());
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a 3D matrix from a NetCDF variable.
|
||||||
|
* Reads data into a contiguous 1D data vector.
|
||||||
|
* Returns a pair of the size of the matrix (in the form of an extent) with the data vector.
|
||||||
|
*
|
||||||
|
* Inteded usage of this function involves using the two returned values
|
||||||
|
* to create an mdspan:
|
||||||
|
*
|
||||||
|
* auto arr = mdspan(vec.data(), size);
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
pair<vector<T>, std::dextents<std::size_t, 3>> get3DMat(const NcVar &var) {
|
||||||
|
if(var.getDimCount() != 3) {
|
||||||
|
throw invalid_argument("Variable is not 3D");
|
||||||
|
}
|
||||||
|
int timeLength = var.getDim(0).getSize();
|
||||||
|
int latLength = var.getDim(1).getSize();
|
||||||
|
int longLength = var.getDim(2).getSize();
|
||||||
|
vector<T> vec(timeLength*latLength*longLength);
|
||||||
|
var.getVar(vec.data());
|
||||||
|
auto arr = std::mdspan(vec.data(), timeLength, latLength, longLength);
|
||||||
|
|
||||||
|
return {vec, arr.extents()};
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<vector<double>, std::dextents<std::size_t, 3>> readHydrodynamicU() {
|
||||||
|
netCDF::NcFile data("../../../../data/hydrodynamic_U.h5", netCDF::NcFile::read);
|
||||||
|
|
||||||
|
multimap< string, NcVar > vars = data.getVars();
|
||||||
|
|
||||||
|
return get3DMat<double>(vars.find("uo")->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple<vector<double>, vector<double>, vector<double>> readGrid() {
|
||||||
|
netCDF::NcFile data("../../../../data/grid.h5", netCDF::NcFile::read);
|
||||||
|
multimap< string, NcVar > vars = data.getVars();
|
||||||
|
vector<double> time = getVarVector<double>(vars.find("times")->second);
|
||||||
|
vector<double> longitude = getVarVector<double>(vars.find("longitude")->second);
|
||||||
|
vector<double> latitude = getVarVector<double>(vars.find("latitude")->second);
|
||||||
|
|
||||||
|
return {time, latitude, longitude};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef LINEARINTERPOLATE_READDATA_H
|
||||||
|
#define LINEARINTERPOLATE_READDATA_H
|
||||||
|
|
||||||
|
#include "vecutils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the file hydrodynamic_U.h5
|
||||||
|
* @return a pair of the data vector of the contents and its dimensions to be used with mdspan
|
||||||
|
*/
|
||||||
|
std::pair<std::vector<double>, std::dextents<std::size_t, 3>> readHydrodynamicU();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the file grid.h5
|
||||||
|
* @return a tuple of (times, latitude, longitude)
|
||||||
|
*/
|
||||||
|
std::tuple<std::vector<double>, std::vector<double>, std::vector<double>> readGrid();
|
||||||
|
|
||||||
|
#endif //LINEARINTERPOLATE_READDATA_H
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
#include "vecutils.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void print3DMatrixSlice(const arr3d<double> &arr, int t) {
|
||||||
|
for (int x = 0; x < arr.extent(1); x++) {
|
||||||
|
for (int y = 0; y < arr.extent(2); y++) {
|
||||||
|
print("{:>10.4f} ", arr[t,x,y]);
|
||||||
|
}
|
||||||
|
println("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef LINEARINTERPOLATE_VECUTILS_H
|
||||||
|
#define LINEARINTERPOLATE_VECUTILS_H
|
||||||
|
|
||||||
|
#include <mdspan>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using arr3d = std::mdspan<
|
||||||
|
T,
|
||||||
|
std::dextents<
|
||||||
|
std::size_t,
|
||||||
|
3
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print contents of vector
|
||||||
|
* @tparam T The type of the data inside the vector
|
||||||
|
* @param vec The vector to be printed
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void printContentsOfVec(const std::vector<T>& vec) {
|
||||||
|
for (const auto& element : vec) {
|
||||||
|
std::print("{} ", element);
|
||||||
|
|
||||||
|
}
|
||||||
|
std::println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print matrix [x,y] for all values arr[t,x,y]
|
||||||
|
* @param arr matrix to be printed
|
||||||
|
* @param t value to slice matrix with
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void print3DMatrixSlice(const arr3d<T> &arr, int t) {
|
||||||
|
for (int x = 0; x < arr.extent(1); x++) {
|
||||||
|
for (int y = 0; y < arr.extent(2); y++) {
|
||||||
|
std::print("{} ", arr[t,x,y]);
|
||||||
|
}
|
||||||
|
std::println("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print3DMatrixSlice(const arr3d<double> &arr, int t);
|
||||||
|
|
||||||
|
#endif //LINEARINTERPOLATE_VECUTILS_H
|
||||||
Loading…
Reference in New Issue