CoolProp 8.0.0
An open-source fluid property and humid air property database
superancillary.cpp
Go to the documentation of this file.
1
8
10#include "nlohmann/json.hpp"
11#include "boost/math/tools/toms748_solve.hpp"
12
13#include <functional>
14#include <string>
15#include <vector>
16
17namespace CoolProp {
18namespace superancillary {
19
20namespace detail {
21
22// Out-of-line definition of the TOMS 748 bracketing rootfinder declared in the
23// installed header. Keeping the boost dependency here (rather than in the
24// header) lets downstream consumers compile against superancillary.h with only
25// Eigen on the include path, not boost (CoolProp-1tbe.14). The callable is
26// type-erased through std::function: this is the inverse (rootfinding) path,
27// NOT the hot eval_sat path, and the std::function is built once per rootfind,
28// so its indirection -- plus a possible one-time small-buffer heap allocation
29// for the larger residual closures (they exceed libc++'s 16-byte SBO) -- is
30// negligible against the tens of Chebyshev evaluations each rootfind performs.
31double toms748(const std::function<double(double)>& f, double a, double b, double fa, double fb, unsigned int bits, std::size_t max_iter) {
32 using namespace boost::math::tools;
33 auto max_iter_ = static_cast<boost::math::uintmax_t>(max_iter);
34 auto [l, r] = toms748_solve(f, a, b, fa, fb, eps_tolerance<double>(bits), max_iter_);
35 return (l + r) / 2.0;
36}
37
38} // namespace detail
39
40namespace {
41
42template <typename ArrayType>
43std::vector<ChebyshevExpansion<ArrayType>> load_expansions(const nlohmann::json& j, const std::string& key) {
44 std::vector<ChebyshevExpansion<ArrayType>> buf;
45 for (auto& block : j.at(key)) {
46 buf.emplace_back(block.at("xmin"), block.at("xmax"), block.at("coef"));
47 }
48 return buf;
49}
50
51template <typename ArrayType>
52typename SuperAncillary<ArrayType>::LoadedData parse_loaded(const std::string& s) {
53 nlohmann::json j = nlohmann::json::parse(s);
54 typename SuperAncillary<ArrayType>::LoadedData d;
55 d.rhoL = load_expansions<ArrayType>(j, "jexpansions_rhoL");
56 d.rhoV = load_expansions<ArrayType>(j, "jexpansions_rhoV");
57 d.p = load_expansions<ArrayType>(j, "jexpansions_p");
58 d.Tcrit_num = j.at("meta").at("Tcrittrue / K");
59 d.rhocrit_num = j.at("meta").at("rhocrittrue / mol/m^3");
60 if (j.contains("check_points")) {
61 for (const auto& pt : j.at("check_points")) {
62 d.check_points.push_back({pt.at("T / K").get<double>(), pt.at("p(mp) / Pa").get<double>(), pt.at("rho'(mp) / mol/m^3").get<double>(),
63 pt.at("rho''(mp) / mol/m^3").get<double>(), pt.at("p(SA)/p(mp)").get<double>(),
64 pt.at("rho'(SA)/rho'(mp)").get<double>(), pt.at("rho''(SA)/rho''(mp)").get<double>()});
65 }
66 }
67 return d;
68}
69
70} // namespace
71
72template <typename ArrayType>
73SuperAncillary<ArrayType>::SuperAncillary(const std::string& s) : SuperAncillary(parse_loaded<ArrayType>(s)) {}
74
75// The one and only ArrayType string-constructed across the codebase. Constructing
76// SuperAncillary<other types> from a string is intentionally not provided.
77template SuperAncillary<std::vector<double>>::SuperAncillary(const std::string&);
78
79} // namespace superancillary
80} // namespace CoolProp