Newer
Older
/// Accessor functions
double get_a() const{ return a; }
double get_b() const{ return b; }
const double Ru = 1.380649e-23 * 6.02214076e23; ///< Exact value, given by k_B*N_A
/// \brief Get the universal gas constant
/// \note Here the real universal gas constant, with no composition dependence
template<class VecType>
auto R(const VecType& molefrac) const { return Ru; }
/// The evaluation of \f$ \alpha^{\rm r}=a/(RT) \f$
/// \param T The temperature
Ian Bell
committed
template<typename TType, typename RhoType, typename VecType>
auto alphar(const TType &T, const RhoType& rhotot, const VecType &molefrac) const {
return forceeval(-log(1.0 - b * rhotot) - (a / (R(molefrac) * T)) * rhotot);
/// \brief For testing, provide the pressure explicit form of the EOS
return Ru*T/(v - b) - a/(v*v);
/// A slightly more involved implementation of van der Waals, this time with mixture properties
std::valarray<NumType> ai, bi;
std::valarray<std::valarray<NumType>> k;
auto get_ai(TType T, IndexType i) const { return ai[i]; }
auto get_bi(TType T, IndexType i) const { return bi[i]; }
/// \brief Initializer, taking the arrays of critical temperatures and pressures
/// \param Tc_K Array of critical temperatures in Kelvin
/// \param pc_Pa Array of critical pressures in Pascal
///
/// \note All interaction parameters are set to default value of zero and cannot currently be tuned
vdWEOS(const std::valarray<NumType>& Tc_K, const std::valarray<NumType>& pc_Pa)
{
throw teqp::InvalidArgument("Sizes of Tc_K " + std::to_string(Tc_K.size()) + " and pc_Pa" + std::to_string(pc_Pa.size()) + " do not agree");
ai.resize(Tc_K.size());
bi.resize(Tc_K.size());
for (auto i = 0; i < Tc_K.size(); ++i) {
ai[i] = 27.0 / 64.0 * pow(Ru * Tc_K[i], 2) / pc_Pa[i];
bi[i] = 1.0 / 8.0 * Ru * Tc_K[i] / pc_Pa[i];
}
k = std::valarray<std::valarray<NumType>>(std::valarray<NumType>(0.0, Tc_K.size()), Tc_K.size());
};
/// \brief Calculate the a parameter, based on quadratic mixing rules
/// \param T Temperature
/// \param molefracs Array of mole fractions
template<typename TType, typename CompType>
auto a(TType T, const CompType& molefracs) const {
auto ai = this->ai;
for (auto i = 0; i < molefracs.size(); ++i) {
for (auto j = 0; j < molefracs.size(); ++j) {
auto aij = (1 - k[i][j]) * sqrt(ai[i] * ai[j]);
/// \brief Calculate the b parameter, based on linear mixing rules
/// \param molefracs Array of mole fractions
template<typename CompType>
auto b(const CompType& molefracs) const {
const NumType Ru = get_R_gas<double>(); ///< Universal gas constant, exact number
/// \brief Get the universal gas constant
/// Here the real universal gas constant, with no composition dependence
/// \note The array of mole fractions are ignored, but required to match other function calls
template<class VecType>
return Ru;
}
/// \brief The evaluation of \f$ \alpha^{\rm r}=a/(RT) \f$
/// \param T The temperature
/// \param rho The molar density
/// \param molefrac The mole fractions of each component
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() != ai.size()) {
throw teqp::InvalidArgument("mole fractions must be of size " + std::to_string(ai.size()) + " but are of size " + std::to_string(molefrac.size()));
}
Ian Bell
committed
auto Psiminus = -log(1.0 - b(molefrac) * rho);
auto Psiplus = rho;
auto val = Psiminus - a(T, molefrac) / (Ru * T) * Psiplus;
return forceeval(val);
}; // namespace teqp