CoolProp 8.0.0
An open-source fluid property and humid air property database
BoundaryCurve.h
Go to the documentation of this file.
1#ifndef COOLPROP_REGION_BOUNDARY_CURVE_H
2#define COOLPROP_REGION_BOUNDARY_CURVE_H
3
4#include <utility>
5
6namespace CoolProp {
7namespace region {
8
9// 1D curve b = f(a) over a closed interval [a_lo, a_hi]. The primary
10// axis variable a is the independent input; the secondary axis variable
11// b is what the curve produces.
12//
13// Used as a building block for Region — two BoundaryCurves (lower and
14// upper) plus an AxisTransform define a curved 2D region in (a, b) space
15// that maps to the (xi, eta) unit square.
16//
17// All concrete subclasses are required to provide *analytic* eval_da
18// (never a finite-difference shim). Each subclass differentiates its
19// own internal representation symbolically.
20//
21// Lifetime: instances are owned by Region via std::unique_ptr; the
22// interface lives behind a virtual call but is only invoked inside the
23// AABB-hit branch of region dispatch, so the indirection is off the
24// inner SVD-eval hot path.
26{
27 public:
28 BoundaryCurve() = default;
29 BoundaryCurve(const BoundaryCurve&) = default;
33 virtual ~BoundaryCurve() = default;
34
35 // Value of the curve at a. Behaviour outside [a_lo, a_hi] is
36 // implementation-defined (typically extrapolated by the underlying
37 // basis); callers should normally not query outside the build range.
38 [[nodiscard]] virtual double eval(double a) const noexcept = 0;
39
40 // First derivative db/da at a — analytic, not finite-difference.
41 [[nodiscard]] virtual double eval_da(double a) const noexcept = 0;
42
43 // Fast approximate variant of eval(a) — opt-in surrogate for
44 // sign-only callers (e.g. RegionAtlas curve_contains, which only
45 // needs to decide which side of the curve the probe is on).
46 //
47 // Default forwards to eval() so non-SA curves are unaffected.
48 // Subclasses backed by an expensive analytic representation (e.g.
49 // SuperancillaryBoundaryCurve, which composes get_T_from_p with
50 // eval_sat — ~80 ns per call) override this with a precomputed
51 // linear-interp table that runs in single-digit ns and is accurate
52 // to ~1e-6 over the curve's build range. Use of eval_fast is
53 // confined to callers where boundary-value noise doesn't
54 // contaminate downstream numerics; precision-critical callers
55 // (Region::to_normalized / from_normalized, which compute the eta
56 // normalization the SVD consumes) continue to use eval().
57 [[nodiscard]] virtual double eval_fast(double a) const noexcept {
58 return eval(a);
59 }
60
61 // Min and max of b achieved on the build interval [a_lo, a_hi].
62 // Precomputed at build; used to populate the parent Region's
63 // axis-aligned bounding box for cheap region-dispatch filtering.
64 [[nodiscard]] virtual std::pair<double, double> bounds() const noexcept = 0;
65
66 // Build interval [a_lo, a_hi] on the primary axis.
67 [[nodiscard]] virtual std::pair<double, double> a_range() const noexcept = 0;
68};
69
70} // namespace region
71} // namespace CoolProp
72
73#endif // COOLPROP_REGION_BOUNDARY_CURVE_H