diff --git a/linear-interpolation/src/CMakeLists.txt b/linear-interpolation/src/CMakeLists.txt index b8b6abb..e293e85 100644 --- a/linear-interpolation/src/CMakeLists.txt +++ b/linear-interpolation/src/CMakeLists.txt @@ -16,7 +16,13 @@ add_executable(LinearInterpolate main.cpp readdata.cpp readdata.h vecutils.cpp - vecutils.h) + vecutils.h + interpolate.cpp + interpolate.h + UVGrid.cpp + UVGrid.h + point.h + point.cpp) execute_process( COMMAND nc-config --includedir diff --git a/linear-interpolation/src/UVGrid.cpp b/linear-interpolation/src/UVGrid.cpp new file mode 100644 index 0000000..aa493eb --- /dev/null +++ b/linear-interpolation/src/UVGrid.cpp @@ -0,0 +1,28 @@ +#include +#include + +#include "UVGrid.h" +#include "readdata.h" + +using namespace std; + +UVGrid::UVGrid() { + auto [us, sizeU] = readHydrodynamicU(); + auto [vs, sizeV] = readHydrodynamicV(); + // Assuming sizeU == sizeV + uvData = views::zip(us, vs) | ranges::to(); + uvMatrix = mdspan(uvData.data(), sizeU); + tie(times, lats, lons) = readGrid(); +} + +double UVGrid::lonStep() const { + return lons[1] - lons[0]; +} + +double UVGrid::latStep() const { + return lats[1]-lats[0]; +} + +int UVGrid::timeStep() const { + return times[1]-times[0]; +} \ No newline at end of file diff --git a/linear-interpolation/src/UVGrid.h b/linear-interpolation/src/UVGrid.h new file mode 100644 index 0000000..23642f3 --- /dev/null +++ b/linear-interpolation/src/UVGrid.h @@ -0,0 +1,30 @@ +#ifndef LINEARINTERPOLATE_UVGRID_H +#define LINEARINTERPOLATE_UVGRID_H + +#include +#include "vecutils.h" +#include "point.h" + +class UVGrid { +private: + /** + * u == Eastward Current Velocity in the Water Column + * v == Northward Current Velocity in the Water Column + */ + std::vector uvData; +public: + UVGrid(); + + // The step functions assume regular spacing + double lonStep() const; + double latStep() const; + int timeStep() const; + + std::vector times; + std::vector lats; + std::vector lons; + + arr3d uvMatrix; +}; + +#endif //LINEARINTERPOLATE_UVGRID_H diff --git a/linear-interpolation/src/interpolate.cpp b/linear-interpolation/src/interpolate.cpp new file mode 100644 index 0000000..f39e801 --- /dev/null +++ b/linear-interpolation/src/interpolate.cpp @@ -0,0 +1,43 @@ +#include + +#include +#include "interpolate.h" + +using namespace std; + +// Inspired by https://numerical.recipes/book.html Chapter 3.6 +point bilinearInterpolate(const UVGrid &uvGrid, std::tuple timeLatLon) { + auto [time, lat, lon] = timeLatLon; + + double latStep = uvGrid.latStep(); + double lonStep = uvGrid.lonStep(); + int timeStep = uvGrid.timeStep(); + + int latIndex = (lat-uvGrid.lats[0])/latStep; + int lonIndex = (lon-uvGrid.lons[0])/lonStep; + int timeIndex = (time-uvGrid.times[0])/timeStep; + + double timeRatio = (static_cast(time)-uvGrid.times[timeIndex])/timeStep; + double latRatio = (lat-uvGrid.lats[latIndex]) / latStep; + double lonRatio = (lon-uvGrid.lons[lonIndex]) / lonStep; + + point point = {0, 0}; + for(int time = 0; time <= 1; time++) { + for(int lat = 0; lat <= 1; lat++) { + for(int lon = 0; lon <= 1; lon++) { + auto vertex = uvGrid.uvMatrix[ + timeIndex + time < uvGrid.uvMatrix.extent(0) ? timeIndex + 1 : timeIndex, + latIndex + lat < uvGrid.uvMatrix.extent(1) ? latIndex + 1 : latIndex, + lonIndex + lon < uvGrid.uvMatrix.extent(2) ? lonIndex + 1 : lonIndex + ]; + + double timeRation = (1 - time)*(1-timeRatio) + time*timeRatio; + double latRation = (1 - lat)*(1-latRatio) + lat*latRatio; + double lonRation = (1 - lon)*(1-lonRatio) + lon*lonRatio; + point += timeRation * latRation * lonRation * vertex; + } + } + } + + return point; +} diff --git a/linear-interpolation/src/interpolate.h b/linear-interpolation/src/interpolate.h new file mode 100644 index 0000000..131b747 --- /dev/null +++ b/linear-interpolation/src/interpolate.h @@ -0,0 +1,12 @@ +#ifndef LINEARINTERPOLATE_INTERPOLATE_H +#define LINEARINTERPOLATE_INTERPOLATE_H + +#include + +#include "UVGrid.h" + +point bilinearInterpolate(const UVGrid &uvGrid, std::tuple timeLatLong); + +std::vector bilinearInterpolate(); + +#endif //LINEARINTERPOLATE_INTERPOLATE_H diff --git a/linear-interpolation/src/main.cpp b/linear-interpolation/src/main.cpp index 8792393..dc36897 100644 --- a/linear-interpolation/src/main.cpp +++ b/linear-interpolation/src/main.cpp @@ -1,18 +1,13 @@ -#include "readdata.h" - -#include +#include "interpolate.h" using namespace std; int main() { - auto [vec, size] = readHydrodynamicU(); + UVGrid uvGrid; + auto p = bilinearInterpolate(uvGrid, {392400, 53, -14.5}); - auto arr = std::mdspan(vec.data(), size); - - print3DMatrixSlice(arr, 100); - - auto [times, lats, longs] = readGrid(); - printContentsOfVec(lats); + println("({}, {})", p.first, p.second); + p = bilinearInterpolate(uvGrid, {802400, 62, -14.5}); return 0; } diff --git a/linear-interpolation/src/point.cpp b/linear-interpolation/src/point.cpp new file mode 100644 index 0000000..a84800f --- /dev/null +++ b/linear-interpolation/src/point.cpp @@ -0,0 +1,11 @@ +#include "point.h" + +point operator+(const point& p1, const point& p2) { + return {p1.first + p2.first, p1.second + p2.second}; +} + +point& operator+=(point& p1, const point& p2) { + p1.first += p2.first; + p1.second += p2.second; + return p1; +} \ No newline at end of file diff --git a/linear-interpolation/src/point.h b/linear-interpolation/src/point.h new file mode 100644 index 0000000..4a22f35 --- /dev/null +++ b/linear-interpolation/src/point.h @@ -0,0 +1,27 @@ +#ifndef LINEARINTERPOLATE_POINT_H +#define LINEARINTERPOLATE_POINT_H + +#include + +using point = std::pair; // {u, v} + +point operator+(const point& p1, const point& p2); + +point& operator+=(point& p1, const point& p2); + +template +point operator*(const point& p, Scalar scalar) { + return {p.first * scalar, p.second * scalar}; +} + +template +point operator*(Scalar scalar, const point& p) { + return {p.first * scalar, p.second * scalar}; +} + +template +point operator/(const point& p, Scalar scalar) { + return {p.first / scalar, p.second / scalar}; +} + +#endif //LINEARINTERPOLATE_POINT_H diff --git a/linear-interpolation/src/readdata.cpp b/linear-interpolation/src/readdata.cpp index 6cc7726..bc4f364 100644 --- a/linear-interpolation/src/readdata.cpp +++ b/linear-interpolation/src/readdata.cpp @@ -55,10 +55,18 @@ pair, std::dextents> readHydrodynamicU() { return get3DMat(vars.find("uo")->second); } -tuple, vector, vector> readGrid() { +pair, std::dextents> readHydrodynamicV() { + netCDF::NcFile data("../../../../data/hydrodynamic_V.h5", netCDF::NcFile::read); + + multimap< string, NcVar > vars = data.getVars(); + + return get3DMat(vars.find("vo")->second); +} + +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 time = getVarVector(vars.find("times")->second); vector longitude = getVarVector(vars.find("longitude")->second); vector latitude = getVarVector(vars.find("latitude")->second); diff --git a/linear-interpolation/src/readdata.h b/linear-interpolation/src/readdata.h index c5effb5..3008924 100644 --- a/linear-interpolation/src/readdata.h +++ b/linear-interpolation/src/readdata.h @@ -4,15 +4,21 @@ #include "vecutils.h" /** - * Reads the file hydrodynamic_U.h5 + * 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::dextents> readHydrodynamicU(); +/** + * reads the file hydrodynamic_V.h5 + * @return a pair of the data vector of the contents and its dimensions to be used with mdspan + */ +std::pair, std::dextents> readHydrodynamicV(); + /** * Reads the file grid.h5 * @return a tuple of (times, latitude, longitude) */ -std::tuple, std::vector, std::vector> readGrid(); +std::tuple, std::vector, std::vector> readGrid(); #endif //LINEARINTERPOLATE_READDATA_H diff --git a/linear-interpolation/src/vecutils.cpp b/linear-interpolation/src/vecutils.cpp index f367b3d..1b02df9 100644 --- a/linear-interpolation/src/vecutils.cpp +++ b/linear-interpolation/src/vecutils.cpp @@ -12,3 +12,13 @@ void print3DMatrixSlice(const arr3d &arr, int t) { println(""); } } + +void print3DMatrixSlice(const arr3d> &arr, int t) { + for (int x = 0; x < arr.extent(1); x++) { + for (int y = 0; y < arr.extent(2); y++) { + auto [u,v] = arr[t,x,y]; + print("({:>7.4f}, {:>7.4f}) ", u, v); + } + println(""); + } +} diff --git a/linear-interpolation/src/vecutils.h b/linear-interpolation/src/vecutils.h index 5ddeec6..8bf3691 100644 --- a/linear-interpolation/src/vecutils.h +++ b/linear-interpolation/src/vecutils.h @@ -43,5 +43,6 @@ void print3DMatrixSlice(const arr3d &arr, int t) { } void print3DMatrixSlice(const arr3d &arr, int t); +void print3DMatrixSlice(const arr3d> &arr, int t); #endif //LINEARINTERPOLATE_VECUTILS_H