Newer
Older
#pragma once
Ian Bell
committed
#include <string>
Ian Bell
committed
#include <optional>
#include <variant>
Ian Bell
committed
#include "teqp/types.hpp"
Ian Bell
committed
#include "teqp/filesystem.hpp"
#include "teqp/exceptions.hpp"
#include "MultiComplex/MultiComplex.hpp"
#include "multifluid_eosterms.hpp"
#include <boost/algorithm/string/join.hpp>
// See https://eigen.tuxfamily.org/dox/TopicCustomizing_CustomScalar.html
namespace Eigen {
template<typename TN> struct NumTraits<mcx::MultiComplex<TN>> : NumTraits<double> // permits to get the epsilon, dummy_precision, lowest, highest functions
{
enum {
IsComplex = 1,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 1,
AddCost = 3,
MulCost = 3
};
};
}
template<typename EOSCollection>
class CorrespondingStatesContribution {
private:
const EOSCollection EOSs;
public:
CorrespondingStatesContribution(EOSCollection&& EOSs) : EOSs(EOSs) {};
auto size() const { return EOSs.size(); }
template<typename TauType, typename DeltaType, typename MoleFractions>
auto alphar(const TauType& tau, const DeltaType& delta, const MoleFractions& molefracs) const {
using resulttype = std::common_type_t<decltype(tau), decltype(molefracs[0]), decltype(delta)>; // Type promotion, without the const-ness
resulttype alphar = 0.0;
auto N = molefracs.size();
for (auto i = 0; i < N; ++i) {
alphar = alphar + molefracs[i] * EOSs[i].alphar(tau, delta);
}
}
template<typename TauType, typename DeltaType>
auto alphari(const TauType& tau, const DeltaType& delta, std::size_t i) const {
return EOSs[i].alphar(tau, delta);
}
auto get_EOS(std::size_t i) const{
return EOSs[i];
}
};
template<typename FCollection, typename DepartureFunctionCollection>
class DepartureContribution {
private:
const FCollection F;
const DepartureFunctionCollection funcs;
public:
DepartureContribution(FCollection&& F, DepartureFunctionCollection&& funcs) : F(F), funcs(funcs) {};
template<typename TauType, typename DeltaType, typename MoleFractions>
auto alphar(const TauType& tau, const DeltaType& delta, const MoleFractions& molefracs) const {
using resulttype = std::common_type_t<decltype(tau), decltype(molefracs[0]), decltype(delta)>; // Type promotion, without the const-ness
resulttype alphar = 0.0;
auto N = molefracs.size();
for (auto i = 0; i < N; ++i) {
Ian Bell
committed
for (auto j = i+1; j < N; ++j) {
alphar = alphar + molefracs[i] * molefracs[j] * F(i, j) * funcs[i][j].alphar(tau, delta);
}
}
}
/// Call a single departure term at i,j
template<typename TauType, typename DeltaType>
auto get_alpharij(const int i, const int j, const TauType& tau, const DeltaType& delta) const {
int N = funcs.size();
if (i < 0 || j < 0){
throw teqp::InvalidArgument("i or j is negative");
}
if (i >= N || j >= N){
throw teqp::InvalidArgument("i or j is invalid; size is " + std::to_string(N));
}
return forceeval(funcs[i][j].alphar(tau, delta));
}
};
template<typename CorrespondingTerm, typename DepartureTerm>
private:
std::string meta = ""; ///< A string that can be used to store arbitrary metadata as needed
const CorrespondingTerm corr;
const DepartureTerm dep;
template<class VecType>
auto R(const VecType& molefrac) const {
return get_R_gas<decltype(molefrac[0])>();
}
/// Store some sort of metadata in string form (perhaps a JSON representation of the model?)
void set_meta(const std::string& m) { meta = m; }
/// Get the metadata stored in string form
auto get_meta() const { return meta; }
MultiFluid(ReducingFunctions&& redfunc, CorrespondingTerm&& corr, DepartureTerm&& dep) : redfunc(redfunc), corr(corr), dep(dep) {};
template<typename TType, typename RhoType>
auto alphar(TType T,
const RhoType& rhovec,
const std::optional<typename RhoType::value_type> rhotot = std::nullopt) const
{
typename RhoType::value_type rhotot_ = (rhotot.has_value()) ? rhotot.value() : std::accumulate(std::begin(rhovec), std::end(rhovec), (decltype(rhovec[0]))0.0);
auto molefrac = rhovec / rhotot_;
return alphar(T, rhotot_, molefrac);
}
template<typename TType, typename RhoType, typename MoleFracType>
Ian Bell
committed
auto alphar(const TType &T,
const RhoType &rho,
const MoleFracType& molefrac) const
{
if (molefrac.size() != corr.size()){
throw teqp::InvalidArgument("Wrong size of mole fractions; "+std::to_string(corr.size()) + " are loaded but "+std::to_string(molefrac.size()) + " were provided");
}
auto Tred = forceeval(redfunc.get_Tr(molefrac));
auto rhored = forceeval(redfunc.get_rhor(molefrac));
auto delta = forceeval(rho / rhored);
auto tau = forceeval(Tred / T);
auto val = corr.alphar(tau, delta, molefrac) + dep.alphar(tau, delta, molefrac);
return forceeval(val);
}
};
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/***
* \brief Get the JSON data structure for a given departure function
* \param name The name (or alias) of the departure function to be looked up
* \parm path The root path to the fluid data, or alternatively, the path to the json file directly
*/
inline auto get_departure_json(const std::string& name, const std::string& path) {
std::string filepath = std::filesystem::is_regular_file(path) ? path : path + "/dev/mixtures/mixture_departure_functions.json";
nlohmann::json j = load_a_JSON_file(filepath);
std::string js = j.dump(2);
// First pass, direct name lookup
for (auto& el : j) {
if (el.at("Name") == name) {
return el;
}
}
// Second pass, iterate over aliases
for (auto& el : j) {
for (auto &alias : el.at("aliases")) {
if (alias == name) {
return el;
}
}
}
throw std::invalid_argument("Could not match the name: " + name + "when looking up departure function");
}
inline auto build_departure_function(const nlohmann::json& j) {
Ian Bell
committed
auto build_power = [&](auto term, auto& dep) {
std::size_t N = term["n"].size();
// Don't add a departure function if there are no coefficients provided
if (N == 0) {
return;
}
PowerEOSTerm eos;
auto eigorzero = [&term, &N](const std::string& name) -> Eigen::ArrayXd {
Loading
Loading full blame...