CoolProp
8.0.0
An open-source fluid property and humid air property database
include
CoolProp
svd
SVDDecomposition.h
Go to the documentation of this file.
1
#ifndef COOLPROP_SVD_SVD_DECOMPOSITION_H
2
#define COOLPROP_SVD_SVD_DECOMPOSITION_H
3
4
#include <cstdint>
5
#include <vector>
6
7
namespace
CoolProp
{
8
namespace
svd {
9
10
// Output transform applied to the SVD result. We store the SVD of a
11
// matrix in some transformed space (typically log of a strictly positive
12
// property), and undo the transform at evaluation time.
13
enum class
OutputTransform
: std::uint8_t
14
{
15
IDENTITY
,
// value = sum_k S_k u_k v_k (no wrap)
16
EXP
// value = exp(sum_k S_k u_k v_k) (matrix was log of property)
17
};
18
19
// Slope source used to build the per-mode 1D slopes (dU_dx, dV_S_dy).
20
// Affects build only — the eval kernel reads slopes from arrays and is
21
// agnostic to how they were computed.
22
enum class
SlopeSource
: std::uint8_t
23
{
24
NATURAL_CUBIC_SPLINE
,
// default; C^2 continuous interpolant of each mode
25
HERMITE_FD
,
// central finite difference (svd_bench.cpp parity)
26
PCHIP
// monotone cubic; useful when monotonicity matters
27
};
28
29
// Plain-old-data container ferrying a 2D rank-r SVD from the offline
30
// builder to the runtime evaluator.
31
//
32
// Layout choices deliberately diverge from `dev/svd_bench.cpp` for
33
// performance:
34
// - V is stored transposed relative to svd_bench.cpp's Vt: here
35
// `V_S[j*rank + k]` is the k-th mode at y-index j, so the per-mode
36
// scan in eval is unit-stride.
37
// - The singular values S are *folded into* V_S — V_S[j,k] = V[j,k] * S[k].
38
// The eval kernel becomes a plain dot product. Storage saving:
39
// rank doubles (negligible). CPU saving: one multiply per mode per
40
// call (small but free).
41
// - dU_dx and dV_S_dy carry the precomputed slopes used by the cubic
42
// Hermite kernel; one slope per (axis grid point, mode).
43
//
44
// This struct is NOT trivially copyable — the std::vector members own
45
// heap storage, so a memcpy of the SVDDecomposition object itself
46
// produces garbage. Callers wanting GPU portability should `cudaMemcpy`
47
// the underlying contiguous buffers (U.data(), V_S.data(), dU_dx.data(),
48
// dV_S_dy.data(), x_grid.data(), y_grid.data()) into device buffers
49
// individually and read them with an Eigen::Map on the device side.
50
// Device-side evaluation will agree with host evaluation within a few
51
// ulp — not byte-exact — because nvcc fuses multiply-and-accumulate by
52
// default (`--fmad=true`) and the slopes themselves were computed on
53
// the host with whatever rounding the spline solver chose.
54
struct
SVDDecomposition
55
{
56
std::int32_t
NX
= 0;
// number of grid points on x axis
57
std::int32_t
NY
= 0;
// number of grid points on y axis
58
std::int32_t
rank
= 0;
// truncation rank r (rank <= min(NX, NY))
59
60
OutputTransform
out_transform
=
OutputTransform::IDENTITY
;
61
// Provenance only — the eval kernel reads slopes from dU_dx /
62
// dV_S_dy and is agnostic to which strategy filled them. Kept on
63
// the struct so a deserialised decomposition is self-describing.
64
SlopeSource
slope_source
=
SlopeSource::NATURAL_CUBIC_SPLINE
;
65
66
std::vector<double>
x_grid
;
// size NX
67
std::vector<double>
y_grid
;
// size NY
68
69
// U: NX rows, rank columns, row-major. U[i*rank + k] is mode k at x_i.
70
std::vector<double>
U
;
71
// dU/dx slopes co-located with U.
72
std::vector<double>
dU_dx
;
73
74
// V with S folded in: NY rows, rank columns, row-major.
75
// V_S[j*rank + k] is sigma_k * V[j, k].
76
std::vector<double>
V_S
;
77
// dV_S/dy slopes co-located with V_S.
78
std::vector<double>
dV_S_dy
;
79
80
// Raw singular values kept for diagnostics / debug output. Not used
81
// by the hot path; the values are already folded into V_S.
82
std::vector<double>
S
;
83
};
84
85
}
// namespace svd
86
}
// namespace CoolProp
87
88
#endif
// COOLPROP_SVD_SVD_DECOMPOSITION_H
Generated by
1.9.4