6#include "nlohmann/json.hpp"
11#include <boost/asio/thread_pool.hpp>
12#include <boost/asio/post.hpp>
19 template<
typename Model>
26#define stdstringify(s) std::string(#s)
28#define SatRhoLPPoint_optionalfields X(T) X(p_exp) X(rhoL_exp) X(rhoL_guess) X(rhoV_guess)
30 #define X(field) std::optional<double> field;
34 Eigen::ArrayXd
z = (Eigen::ArrayXd(1) << 1.0).finished();
37 #define X(field) if (!field){ throw teqp::InvalidArgument("A field [" + stdstringify(field) + "] has not been initialized"); }
42 template<
typename Model>
45 auto rhoL = rhoLrhoV[0];
46 auto p = rhoL*
R*
T.value()*(1+model->get_Ar01(
T.value(), rhoL,
z));
52#define SatRhoLPWPoint_optionalfields X(T) X(p_exp) X(rhoL_exp) X(w_exp) X(rhoL_guess) X(rhoV_guess) X(Ao20) X(M) X(R)
55 #define X(field) std::optional<double> field;
59 Eigen::ArrayXd
z = (Eigen::ArrayXd(1) << 1.0).finished();
62 #define X(field) if (!field){ throw teqp::InvalidArgument("A field [" + stdstringify(field) + "] has not been initialized"); }
67 template<
typename Model>
73 auto rhoL = rhoLrhoV[0];
75 auto Ar0n = model->get_Ar02n(
T.value(), rhoL,
z);
76 double Ar01 = Ar0n[1], Ar02 = Ar0n[2];
77 auto Ar11 = model->get_Ar11(
T.value(), rhoL,
z);
78 auto Ar20 = model->get_Ar20(
T.value(), rhoL,
z);
81 auto p = rhoL*
R.value()*
T.value()*(1+Ar01);
87 double Mw2RT = 1 + 2*Ar01 + Ar02 -
POW2(1.0 + Ar01 - Ar11)/(
Ao20.value() + Ar20);
88 double w = sqrt(Mw2RT*
R.value()*
T.value()/
M.value());
98#define SOSPoint_fields X(T) X(p_exp) X(rho_guess) X(w_exp) X(Ao20) X(M) X(R)
101 #define X(field) std::optional<double> field;
106 Eigen::ArrayXd
z = (Eigen::ArrayXd(1) << 1.0).finished();
109 #define X(field) if (!field){ throw teqp::InvalidArgument("A field [" + stdstringify(field) + "] has not been initialized"); }
114 template<
typename Model>
118 double R_ =
R.value();
119 double T_K_ =
T.value();
123 for (
auto step = 0; step < 10; ++step){
124 auto Ar0n = model->get_Ar02n(T_K_, rho,
z);
125 double Ar01 = Ar0n[1], Ar02 = Ar0n[2];
126 double pEOS = rho*R_*T_K_*(1+Ar01);
127 double dpdrho = R_*T_K_*(1 + 2*Ar0n[1] + Ar0n[2]);
128 double res = (pEOS-
p_exp.value())/
p_exp.value();
129 double dresdrho = dpdrho/
p_exp.value();
130 double change = -res/dresdrho;
131 if (std::abs(change/rho-1) < 1e-10 || abs(res) < 1e-12){
139 auto Ar0n = model->get_Ar02n(T_K_, rho,
z);
140 double Ar01 = Ar0n[1], Ar02 = Ar0n[2];
141 auto Ar11 = model->get_Ar11(T_K_, rho,
z);
142 auto Ar20 = model->get_Ar20(T_K_, rho,
z);
146 double Mw2RT = 1.0 + 2.0*Ar01 + Ar02 -
POW2(1.0 + Ar01 - Ar11)/(
Ao20.value() + Ar20);
147 double w = sqrt(Mw2RT*R_*T_K_/
M.value());
157 auto make_pointers(
const std::vector<std::variant<std::string, std::vector<std::string>>>& pointerstrs){
158 std::vector<std::vector<nlohmann::json::json_pointer>> pointers_;
159 for (
auto & pointer: pointerstrs){
160 if (std::holds_alternative<std::string>(pointer)){
161 const std::string& s= std::get<std::string>(pointer);
162 pointers_.emplace_back(1, nlohmann::json::json_pointer(s));
165 std::vector<nlohmann::json::json_pointer> buffer;
166 for (
const auto& s : std::get<std::vector<std::string>>(pointer)){
167 buffer.emplace_back(s);
169 pointers_.push_back(buffer);
176 std::vector<std::vector<nlohmann::json::json_pointer>>
pointers;
182 std::visit([](
const auto&c){c.check_fields();}, cont);
187 return std::vector<double>{1, 3};
196 nlohmann::json j =
jbase;
197 for (
auto i = 0; i < x.size(); ++i){
198 for (
const auto& ptr :
pointers[i]){
210 return std::make_tuple(std::move(model), helpers);
215 const auto [_model, _helpers] =
prepare(x);
216 const auto& model = _model;
217 const auto& helpers = _helpers;
220 cost += std::visit([&model](
const auto& c){
return c.calculate_contribution(model); }, contrib);
222 if (!std::isfinite(cost)){
230 boost::asio::thread_pool pool{Nthreads};
231 const auto [_model, _helpers] =
prepare(x);
232 const auto& model = _model;
233 const auto& helpers = _helpers;
237 auto& dest = buffer[i];
238 auto payload = [&model, &dest, contrib] (){
239 dest = std::visit([&model](
const auto& c){
return c.calculate_contribution(model); }, contrib);
240 if (!std::isfinite(dest)){ dest = 1e30; }
242 boost::asio::post(pool, payload);
std::vector< PureOptimizationContribution > contributions
const nlohmann::json jbase
auto prepare(const T &x) const
auto cost_function(const T &x) const
auto cost_function_threaded(const T &x, std::size_t Nthreads)
void add_one_contribution(const PureOptimizationContribution &cont)
nlohmann::json build_JSON(const T &x) const
auto prepare_helper_models(const auto &model) const
PureParameterOptimizer(const nlohmann::json jbase, const std::vector< std::variant< std::string, std::vector< std::string > > > &pointerstrs)
std::vector< std::vector< nlohmann::json::json_pointer > > pointers
std::variant< SatRhoLPoint, SatRhoLPPoint, SatRhoLPWPoint, SOSPoint > PureOptimizationContribution
std::unique_ptr< AbstractModel > make_model(const nlohmann::json &, bool validate=true)
#define SatRhoLPWPoint_optionalfields
#define SatRhoLPPoint_optionalfields
std::optional< double > T
std::optional< double > M
auto calculate_contribution(const Model &model) const
std::optional< double > w_exp
std::optional< double > R
std::optional< double > rho_guess
auto check_fields() const
std::optional< double > Ao20
std::optional< double > p_exp
std::optional< double > T
std::optional< double > rhoL_exp
std::optional< double > rhoL_guess
auto check_fields() const
std::optional< double > rhoV_guess
auto calculate_contribution(const Model &model) const
std::optional< double > p_exp
std::optional< double > M
std::optional< double > rhoL_exp
std::optional< double > rhoL_guess
std::optional< double > T
auto check_fields() const
std::optional< double > rhoV_guess
std::optional< double > p_exp
std::optional< double > R
std::optional< double > w_exp
std::optional< double > Ao20
auto calculate_contribution(const Model &model) const
auto check_fields() const
auto calculate_contribution(const Model &model) const