Newer
Older
#include <iostream>
#include <algorithm>
#include <numeric>
#include <valarray>
#include "autodiff/forward.hpp"
#include "autodiff/reverse.hpp"
/* A (very) simple implementation of the van der Waals EOS*/
class vdWEOSSimple {
private:
double a, b;
public:
vdWEOSSimple(double a, double b) : a(a), b(b) {};
const double R = 1.380649e-23 * 6.02214076e23; ///< Exact value, given by k_B*N_A
template<typename TType, typename RhoType>
auto alphar(const TType &T, const RhoType& rho) const -> TType{
auto rhotot = std::accumulate(std::begin(rho), std::end(rho), static_cast<typename RhoType::value_type>(0.0));
auto Psiminus = -log(1.0 - b * rhotot);
auto Psiplus = rhotot;
return Psiminus - a / (R * T) * Psiplus;
}
};
void test_vdW_autodiff() {
// Argon + Xenon
std::valarray<double> Tc_K = { 150.687, 289.733 };
std::valarray<double> pc_Pa = { 4863000.0, 5842000.0 };
double T = 298.15;
auto rho = 3.0;
auto R = 1.380649e-23 * 6.02214076e23; ///< Exact value, given by k_B*N_A
auto rhotot = rho;
const std::valarray<double> rhovec = { rhotot / 2, rhotot / 2 };
int i = 0;
double ai = 27.0/64.0*pow(R*Tc_K[i], 2)/pc_Pa[i];
double bi = 1.0/8.0*R*Tc_K[i]/pc_Pa[i];
vdWEOSSimple vdW(ai, bi);
autodiff::dual varT {T};
auto u = vdW.alphar(varT, rhovec);
int rr = 0;
auto dalphardT = derivative([&vdW, &rhovec](auto& T) {return vdW.alphar(T, rhovec); }, wrt(varT), at(varT));
double h = 1e-100;
auto dalphardT_comstep = vdW.alphar(std::complex<double>(T,h), rhovec).imag()/h;
std::cout << dalphardT-dalphardT_comstep << " diff, absolute" << std::endl;