Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port potential Databox enhancements into Spiner from Singe -- transformations #95

Open
wants to merge 49 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
216d115
Copy databox_wrapper.hpp from Singe as a starting point for discussion.
BrendanKKrueger Aug 26, 2024
ac86b2f
Notes
BrendanKKrueger Sep 3, 2024
7d0865a
Notes again
BrendanKKrueger Sep 3, 2024
f99c241
Start adding the transformations.
BrendanKKrueger Sep 13, 2024
e0e8b0a
Started writing the transformations.
BrendanKKrueger Sep 13, 2024
5ce03cb
Modify RegularGrid1D to allow for transformations.
BrendanKKrueger Sep 13, 2024
be1acd1
Forgot include
BrendanKKrueger Sep 13, 2024
fc0f83f
Forgot (a) some templates and (b) static.
BrendanKKrueger Sep 19, 2024
622c8fb
I removed dx() from RegularGrid1D, so update the tests.
BrendanKKrueger Sep 19, 2024
2eccab5
Tests for transformations.
BrendanKKrueger Sep 19, 2024
becaae9
Add Transform template to DataBox (currently doesn't do anything yet).
BrendanKKrueger Sep 19, 2024
18cd066
Update TODO items
BrendanKKrueger Sep 19, 2024
af53549
Add dependent variable transformation.
BrendanKKrueger Sep 19, 2024
4f8fbe2
Update TODO items
BrendanKKrueger Sep 19, 2024
6e292a0
Update TODO items
BrendanKKrueger Sep 19, 2024
fa2dd5b
Add GPU testing for transformations.
BrendanKKrueger Sep 19, 2024
c54a6a5
Delete a bunch of stuff we no longer need.
BrendanKKrueger Sep 19, 2024
15aa48a
Move existing RegularGrid1D test to a new file, so I can add new test…
BrendanKKrueger Sep 19, 2024
222bdae
Add some testing with transformations.
BrendanKKrueger Sep 19, 2024
0bc4e32
Add a TODO
BrendanKKrueger Sep 19, 2024
db0323c
test tags
BrendanKKrueger Sep 19, 2024
d45bcc6
Add tests for DataBox with transformations. The current results seem…
BrendanKKrueger Sep 19, 2024
37f3840
Starting to fix operator(). Mostly lots of stream-of-consciousness n…
BrendanKKrueger Sep 19, 2024
958062e
Fix some things about accessing the dependent variable values.
BrendanKKrueger Sep 30, 2024
57ddf50
Revise discussion of operator() and accessors.
BrendanKKrueger Sep 30, 2024
4734797
Remove long TODO discussion, because it's better as a comment on the PR.
BrendanKKrueger Sep 30, 2024
ed811b5
Add transformations to PiecewiseGrid1D.
BrendanKKrueger Sep 30, 2024
78594ea
We'll push extrapolations to another MR.
BrendanKKrueger Sep 30, 2024
cac4be1
Moving some TODO comments to MR discussion.
BrendanKKrueger Sep 30, 2024
8ab5205
Moving some TODO comments to MR discussion.
BrendanKKrueger Sep 30, 2024
a178359
Edit TODO.
BrendanKKrueger Sep 30, 2024
c7afa64
format
BrendanKKrueger Sep 30, 2024
28bcf26
missing header
BrendanKKrueger Sep 30, 2024
51d11c8
Update spiner/transformations.hpp
BrendanKKrueger Oct 2, 2024
df8f052
force inline
BrendanKKrueger Oct 2, 2024
2f39150
constexpr
BrendanKKrueger Oct 2, 2024
8d76c55
Documentation
BrendanKKrueger Oct 8, 2024
09c3aed
documentation again
BrendanKKrueger Oct 8, 2024
45fe193
Change logarithmic transform's epsilon value.
BrendanKKrueger Oct 9, 2024
8578f89
format
BrendanKKrueger Oct 9, 2024
9aaa291
Merge branch 'main' into bkk_wrapper
Yurlungur Oct 11, 2024
5942d20
Switch from SFINAE to static_assert so that we can give a better erro…
BrendanKKrueger Oct 14, 2024
624d244
x is the 'ground truth' representation, so fix the bounds.
BrendanKKrueger Oct 23, 2024
0486a9d
Cleaning up things that should (probably?) be private.
BrendanKKrueger Oct 23, 2024
aba2fd4
More cleanup
BrendanKKrueger Oct 23, 2024
82fe518
Expanded tests for RegularGrid1D.
BrendanKKrueger Oct 23, 2024
ab02e9f
Expand TODO comment.
BrendanKKrueger Oct 23, 2024
1955937
format
BrendanKKrueger Oct 23, 2024
fce0f56
format (again... doing it manually because clang-format here and on G…
BrendanKKrueger Oct 23, 2024
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
237 changes: 137 additions & 100 deletions spiner/databox.hpp

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions spiner/piecewise_grid_1d.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
namespace Spiner {

template <typename T = Real, int NGRIDSMAX = 5,
typename Transform = TransformLinear,
typename =
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type>
class PiecewiseGrid1D {
Expand All @@ -46,7 +47,7 @@ class PiecewiseGrid1D {
// This is functionally equivalent because grids_ will
// be initialized to default values
PORTABLE_INLINE_FUNCTION PiecewiseGrid1D() {}
PiecewiseGrid1D(const std::vector<RegularGrid1D<T>> grids) {
PiecewiseGrid1D(const std::vector<RegularGrid1D<T, Transform>> grids) {
NGRIDS_ = grids.size();
PORTABLE_ALWAYS_REQUIRE(
NGRIDS_ <= NGRIDSMAX,
Expand All @@ -65,8 +66,8 @@ class PiecewiseGrid1D {
}
}
}
PiecewiseGrid1D(std::initializer_list<RegularGrid1D<T>> grids)
: PiecewiseGrid1D(std::vector<RegularGrid1D<T>>(grids)) {}
PiecewiseGrid1D(std::initializer_list<RegularGrid1D<T, Transform>> grids)
: PiecewiseGrid1D(std::vector<RegularGrid1D<T, Transform>>(grids)) {}

template <typename F>
PORTABLE_INLINE_FUNCTION int findGrid(const F &direction) const {
Expand Down Expand Up @@ -124,14 +125,14 @@ class PiecewiseGrid1D {
}

PORTABLE_INLINE_FUNCTION
bool operator==(const PiecewiseGrid1D<T, NGRIDSMAX> &other) const {
bool operator==(const PiecewiseGrid1D<T, NGRIDSMAX, Transform> &other) const {
for (int ig = 0; ig < NGRIDS_; ++ig) {
if (grids_[ig] != other.grids_[ig]) return false;
}
return true;
}
PORTABLE_INLINE_FUNCTION
bool operator!=(const PiecewiseGrid1D<T, NGRIDSMAX> &other) const {
bool operator!=(const PiecewiseGrid1D<T, NGRIDSMAX, Transform> &other) const {
return !(*this == other);
}
PORTABLE_INLINE_FUNCTION T min() const { return grids_[0].min(); }
Expand Down Expand Up @@ -225,7 +226,7 @@ class PiecewiseGrid1D {
SP5::H1D::GRID_FORMAT[1];
}

RegularGrid1D<T> grids_[NGRIDSMAX];
RegularGrid1D<T, Transform> grids_[NGRIDSMAX];
int pointTotals_[NGRIDSMAX];
int NGRIDS_;
};
Expand Down
63 changes: 37 additions & 26 deletions spiner/regular_grid_1d.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "ports-of-call/portable_errors.hpp"
#include "sp5.hpp"
#include "spiner_types.hpp"
#include "transformations.hpp"

namespace Spiner {

Expand All @@ -44,7 +45,7 @@ struct weights_t {
}
};

template <typename T = Real,
template <typename T = Real, typename Transform = TransformLinear,
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type =
true>
class RegularGrid1D {
Expand All @@ -55,11 +56,11 @@ class RegularGrid1D {

// Constructors
PORTABLE_INLINE_FUNCTION RegularGrid1D()
: min_(rNaN), max_(rNaN), dx_(rNaN), idx_(rNaN), N_(iNaN) {}
PORTABLE_INLINE_FUNCTION RegularGrid1D(T min, T max, size_t N)
: min_(min), max_(max), dx_((max - min) / ((T)(N - 1))), idx_(1 / dx_),
N_(N) {
PORTABLE_ALWAYS_REQUIRE(min_ < max_ && N_ > 0, "Valid grid");
: umin_(rNaN), umax_(rNaN), du_(rNaN), inv_du_(rNaN), N_(iNaN) {}
PORTABLE_INLINE_FUNCTION RegularGrid1D(T xmin, T xmax, size_t N)
: umin_(Transform::forward(xmin)), umax_(Transform::forward(xmax)),
du_((umax_ - umin_) / ((T)(N - 1))), inv_du_(1 / du_), N_(N) {
PORTABLE_ALWAYS_REQUIRE(umin_ < umax_ && N_ > 0, "Valid grid");
}

// Forces x in the interval
Expand All @@ -71,18 +72,27 @@ class RegularGrid1D {
return ix;
}

// Gets real value at index
PORTABLE_INLINE_FUNCTION T x(const int i) const { return i * dx_ + min_; }
// Translate between u (transformed variable) coordinate and index
PORTABLE_INLINE_FUNCTION T u(const int i) const { return i * du_ + umin_; }
PORTABLE_INLINE_FUNCTION int index_u(const T u) const {
return bound(inv_du_ * (u - umin_));
}

// Translate between x coordinate and index
PORTABLE_INLINE_FUNCTION T x(const int i) const {
return Transform::reverse(u(i));
}
PORTABLE_INLINE_FUNCTION int index(const T x) const {
return bound(idx_ * (x - min_));
return index_u(Transform::forward(x));
}

// Returns closest index and weights for interpolation
PORTABLE_INLINE_FUNCTION void weights(const T &x, int &ix,
weights_t<T> &w) const {
ix = index(x);
const auto floor = static_cast<T>(ix) * dx_ + min_;
w[1] = idx_ * (x - floor);
const T u = Transform::forward(x);
ix = index_u(u);
const auto floor = static_cast<T>(ix) * du_ + umin_;
w[1] = inv_du_ * (u - floor);
w[0] = (1. - w[1]);
}

Expand All @@ -98,20 +108,21 @@ class RegularGrid1D {
// utitilies
PORTABLE_INLINE_FUNCTION bool
operator==(const RegularGrid1D<T> &other) const {
return (min_ == other.min_ && max_ == other.max_ && dx_ == other.dx_ &&
idx_ == other.idx_ && N_ == other.N_);
return (umin_ == other.umin_ && umax_ == other.umax_ && du_ == other.du_ &&
inv_du_ == other.inv_du_ && N_ == other.N_);
}
PORTABLE_INLINE_FUNCTION bool
operator!=(const RegularGrid1D<T> &other) const {
return !(*this == other);
}
PORTABLE_INLINE_FUNCTION T min() const { return min_; }
PORTABLE_INLINE_FUNCTION T max() const { return max_; }
PORTABLE_INLINE_FUNCTION T dx() const { return dx_; }
PORTABLE_INLINE_FUNCTION T umin() const { return umin_; }
PORTABLE_INLINE_FUNCTION T umax() const { return umax_; }
PORTABLE_INLINE_FUNCTION T min() const { return Transform::reverse(umin_); }
PORTABLE_INLINE_FUNCTION T max() const { return Transform::reverse(umax_); }
PORTABLE_INLINE_FUNCTION size_t nPoints() const { return N_; }
PORTABLE_INLINE_FUNCTION bool isnan() const {
return (std::isnan(min_) || std::isnan(max_) || std::isnan(dx_) ||
std::isnan(idx_) || std::isnan((T)N_));
return (std::isnan(umin_) || std::isnan(umax_) || std::isnan(du_) ||
std::isnan(inv_du_) || std::isnan((T)N_));
}
PORTABLE_INLINE_FUNCTION bool isWellFormed() const { return !isnan(); }

Expand All @@ -123,7 +134,7 @@ class RegularGrid1D {
auto H5T_T =
std::is_same<T, double>::value ? H5T_NATIVE_DOUBLE : H5T_NATIVE_FLOAT;
herr_t status;
T range[] = {min_, max_, dx_};
T range[] = {umin_, umax_, du_};
hsize_t range_dims[] = {3};
int n = static_cast<int>(N_);
status = H5LTmake_dataset(loc, name.c_str(), SP5::RG1D::RANGE_RANK,
Expand All @@ -144,19 +155,19 @@ class RegularGrid1D {
T range[3];
int n;
status = H5LTread_dataset(loc, name.c_str(), H5T_T, range);
min_ = range[0];
max_ = range[1];
dx_ = range[2];
idx_ = 1. / dx_;
umin_ = range[0];
umax_ = range[1];
du_ = range[2];
inv_du_ = 1. / du_;
status += H5LTget_attribute_int(loc, name.c_str(), SP5::RG1D::N, &n);
N_ = n;
return status;
}
#endif

private:
T min_, max_;
T dx_, idx_;
T umin_, umax_;
T du_, inv_du_;
size_t N_;
};

Expand Down
60 changes: 60 additions & 0 deletions spiner/transformations.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef _SPINER_TRANSFORM_HPP_
#define _SPINER_TRANSFORM_HPP_
//======================================================================
// © (or copyright) 2019-2021. Triad National Security, LLC. All rights
// reserved. This program was produced under U.S. Government contract
// 89233218CNA000001 for Los Alamos National Laboratory (LANL), which is
// operated by Triad National Security, LLC for the U.S. Department of
// Energy/National Nuclear Security Administration. All rights in the
// program are reserved by Triad National Security, LLC, and the
// U.S. Department of Energy/National Nuclear Security
// Administration. The Government is granted for itself and others acting
// on its behalf a nonexclusive, paid-up, irrevocable worldwide license
// in this material to reproduce, prepare derivative works, distribute
// copies to the public, perform publicly and display publicly, and to
// permit others to do so.
//======================================================================

#include "ports-of-call/portability.hpp"

#include <cmath>
#include <limits>

namespace Spiner {

// Note on notation:
// -- "real" space is called x
// -- "transformed" space is called u
// -- u = forward(x)
// -- x = reverse(u)
BrendanKKrueger marked this conversation as resolved.
Show resolved Hide resolved

// linear transformation (aka no-op): y = x
struct TransformLinear {
BrendanKKrueger marked this conversation as resolved.
Show resolved Hide resolved
template <typename T>
PORTABLE_INLINE_FUNCTION static T forward(const T x) {
BrendanKKrueger marked this conversation as resolved.
Show resolved Hide resolved
return x;
}
template <typename T>
PORTABLE_INLINE_FUNCTION static T reverse(const T u) {
return u;
}
};

// logarithmic transformation: y = log(x + small)
struct TransformLogarithmic {
template <typename T>
PORTABLE_INLINE_FUNCTION static T forward(const T x) {
return std::log(x + std::numeric_limits<T>::denorm_min());
BrendanKKrueger marked this conversation as resolved.
Show resolved Hide resolved
}
template <typename T>
PORTABLE_INLINE_FUNCTION static T reverse(const T u) {
return std::exp(u) - std::numeric_limits<T>::denorm_min();
}
};

// TODO: log_NQT and arcsinh_NQT, but these require adding a dependency on
// https://github.com/lanl/not-quite-transcendental. I may leave this for
// Jonah ;-)
BrendanKKrueger marked this conversation as resolved.
Show resolved Hide resolved

} // namespace Spiner
#endif // _SPINER_TRANSFORM_HPP_
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ target_link_libraries(spiner_test
${spinerTest_POPULATED_TARGETS}
)
# add unit tests
add_executable(test.bin test.cpp)
add_executable(test.bin test.cpp regular_grid_1d.cpp transformations.cpp)
target_link_libraries(test.bin
PRIVATE
spiner::spiner
Expand Down
5 changes: 4 additions & 1 deletion test/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ int main(int argc, char *argv[]) {

RegularGrid1D gcoarse(xmin, xmax, ncoarse);
std::vector<RegularGrid1D> gfine;
std::vector<Real> dxfine;
for (const auto &n : nfine) {
gfine.push_back(RegularGrid1D(xmin, xmax, n));
dxfine.push_back((xmax - xmin) / n);
}

std::cout << "# ncoarse = " << ncoarse << std::endl;
Expand All @@ -98,7 +100,8 @@ int main(int argc, char *argv[]) {
for (int ifine = 0; ifine < nfine.size(); ++ifine) {
auto n = nfine[ifine];
auto g = gfine[ifine];
Real d3x = g.dx() * g.dx() * g.dx();
auto dx = dxfine[ifine];
Real d3x = dx * dx * dx;
Real L2_error;
#ifdef PORTABILITY_STRATEGY_KOKKOS
Kokkos::fence();
Expand Down
88 changes: 88 additions & 0 deletions test/regular_grid_1d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// © (or copyright) 2019-2021. Triad National Security, LLC. All rights
// reserved. This program was produced under U.S. Government contract
// 89233218CNA000001 for Los Alamos National Laboratory (LANL), which is
// operated by Triad National Security, LLC for the U.S. Department of
// Energy/National Nuclear Security Administration. All rights in the
// program are reserved by Triad National Security, LLC, and the
// U.S. Department of Energy/National Nuclear Security
// Administration. The Government is granted for itself and others acting
// on its behalf a nonexclusive, paid-up, irrevocable worldwide license
// in this material to reproduce, prepare derivative works, distribute
// copies to the public, perform publicly and display publicly, and to
// permit others to do so.

#include <ports-of-call/portability.hpp>
#include <spiner/regular_grid_1d.hpp>

#include <catch2/catch_session.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>

#include <cmath>

using Catch::Matchers::WithinRel;

TEST_CASE("RegularGrid1D", "[RegularGrid1D]") {
SECTION("A regular grid 1d emits appropriate metadata") {
constexpr Real min = -1;
constexpr Real max = 1;
constexpr size_t N = 10;
Spiner::RegularGrid1D<Real> g(min, max, N);
REQUIRE(g.min() == min);
REQUIRE(g.max() == max);
REQUIRE(g.nPoints() == N);
}
}

TEST_CASE("RegularGrid1D with transformations",
"[RegularGrid1D][transformations]") {
constexpr double min = 1;
constexpr double max = 1024;
constexpr size_t N = 11;
Spiner::RegularGrid1D<double, Spiner::TransformLinear> glin(min, max, N);
Spiner::RegularGrid1D<double, Spiner::TransformLogarithmic> glog(min, max, N);
REQUIRE(glin.min() == min);
REQUIRE(glog.min() == min);
REQUIRE(glin.max() == max);
REQUIRE(glog.max() == max);
REQUIRE(glin.nPoints() == N);
REQUIRE(glog.nPoints() == N);

// Check all fixed points (lin)
for (std::size_t n = 0; n < N; ++n) {
const double xx = 102.3 * double(n) + 1;
const double uu = xx;
CHECK_THAT(glin.u(n), WithinRel(uu, 1.0e-12));
CHECK_THAT(glin.x(n), WithinRel(xx, 1.0e-12));
}

// Check all fixed points (log)
for (std::size_t n = 0; n < N; ++n) {
const double xx = std::pow(double(2), n);
const double uu = std::log(xx);
CHECK_THAT(glog.u(n), WithinRel(uu, 1.0e-12));
CHECK_THAT(glog.x(n), WithinRel(xx, 1.0e-12));
}

// Check weights (lin)
for (std::size_t n = 1; n < N; ++n) {
const double xlin = 0.5 * (glin.x(n - 1) + glin.x(n));
int ilin;
Spiner::weights_t<double> wlin;
glin.weights(xlin, ilin, wlin);
CHECK(ilin == n - 1);
CHECK_THAT(wlin.first, WithinRel(0.5));
CHECK_THAT(wlin.second, WithinRel(0.5));
}

// Check weights (log)
for (std::size_t n = 1; n < N; ++n) {
const double xlog = std::sqrt(glog.x(n - 1) * glog.x(n));
int ilog;
Spiner::weights_t<double> wlog;
glog.weights(xlog, ilog, wlog);
CHECK(ilog == n - 1);
CHECK_THAT(wlog.first, WithinRel(0.5));
CHECK_THAT(wlog.second, WithinRel(0.5));
}
}
Loading
Loading