Added the first incompressible test cases and it seems to work...

This commit is contained in:
jowr
2014-06-23 17:34:37 +02:00
parent 864df6d590
commit de03057f48
7 changed files with 920 additions and 516 deletions

View File

@@ -1,120 +0,0 @@
///*
// * Incompressible.cpp
// *
// * Created on: 20 Dec 2013
// * Author: jowr
// */
//
//#include "Incompressible.h"
//
//
//namespace CoolProp {
//
//
//
//// /* All functions need T and p as input. Might not
//// * be necessary, but gives a clearer structure.
//// */
//// /// Density as a function of temperature, pressure and composition.
//// double Incompressible::rho(double T_K, double p) {
//// return poly.polyval(cRho, getxInput(x), getTInput(T_K));
//// }
//// /// Heat capacities as a function of temperature, pressure and composition.
//// double Incompressible::c(double T_K, double p) {
//// return poly.polyval(cHeat, getxInput(x), getTInput(T_K));
//// }
//// /// Enthalpy as a function of temperature, pressure and composition.
//// double Incompressible::h(double T_K, double p) {
//// return h_u(T_K, p);
//// }
//// /// Entropy as a function of temperature, pressure and composition.
//// double Incompressible::s(double T_K, double p) {
//// return poly.polyfracintcentral(cHeat, getxInput(x), T_K, Tbase)
//// - poly.polyfracintcentral(cHeat, getxInput(x), Tref, Tbase);
//// }
//// /// Viscosity as a function of temperature, pressure and composition.
//// double Incompressible::visc(double T_K, double p) {
//// return expo.expval(cVisc, getxInput(x), getTInput(T_K), 2) / 1e3;
//// }
//// /// Thermal conductivity as a function of temperature, pressure and composition.
//// double Incompressible::cond(double T_K, double p) {
//// return poly.polyval(cCond, getxInput(x), getTInput(T_K));
//// }
//// /// Internal energy as a function of temperature, pressure and composition.
//// double Incompressible::u(double T_K, double p) {
//// return poly.polyint(cHeat, getxInput(x), getTInput(T_K))
//// - poly.polyint(cHeat, getxInput(x), getTInput(Tref));
//// }
//
///// Saturation pressure as a function of temperature and composition.
//double Incompressible::psat(double T_K ){throw NotImplementedError("Psat is not available");};
///// Freezing temperature as a function of pressure and composition.
//double Incompressible::Tfreeze( double p){throw NotImplementedError("Tfreeze is not available");};
//
//
///*
// * Some more functions to provide a single implementation
// * of important routines.
// * We start with the check functions that can validate input
// * in terms of pressure p, temperature T and composition x.
// */
//
///// Check validity of temperature input.
///** Compares the given temperature T to the result of a
// * freezing point calculation. This is not necessarily
// * defined for all fluids, default values do not
// * cause errors. */
//bool Incompressible::checkT(double T_K, double p){
// if( Tmin < 0. ) {
// throw ValueError("Please specify the minimum temperature.");
// } else if( Tmax < 0.) {
// throw ValueError("Please specify the maximum temperature.");
// } else if ( (Tmin>T_K) || (T_K>Tmax) ) {
// throw ValueError(format("Your temperature %f is not between %f and %f.",T_K,Tmin,Tmax));
// } else if (T_K < Tfreeze(p)) {
// throw ValueError(format("Your temperature %f is below the freezing point of %f.",T_K,Tfreeze(p)));
// } else {
// return true;
// }
// return false;
//}
//
///// Check validity of pressure input.
///** Compares the given pressure p to the saturation pressure at
// * temperature T and throws and exception if p is lower than
// * the saturation conditions.
// * The default value for psat is -1 yielding true if psat
// * is not redefined in the subclass.
// * */
//bool Incompressible::checkP(double T_K, double p) {
// double ps = psat(T_K);
// if (p<ps) {
// throw ValueError(format("Equations are valid for solution phase only: %f < %f. ",p,ps));
// } else {
// return true;
// }
//}
//
///// Check validity of composition input.
///** Compares the given composition x to a stored minimum and
// * maximum value. Enforces the redefinition of xmin and
// * xmax since the default values cause an error. */
//bool Incompressible::checkX(double x){
// if( xmin < 0. ) {
// throw ValueError("Please specify the minimum concentration.");
// } else if( xmax < 0.) {
// throw ValueError("Please specify the maximum concentration.");
// } else if ( (xmin>x) || (x>xmax) ) {
// throw ValueError(format("Your composition %f is not between %f and %f.",x,xmin,xmax));
// } else {
// return true;
// }
// return false;
//}
//
///// Check validity of temperature, pressure and composition input.
//bool Incompressible::checkTPX(double T, double p, double x) {
// return (checkT(T,p) && checkP(T,p) && checkX(x));
//}
//
//} /* namespace CoolProp */

View File

@@ -1,169 +0,0 @@
/*
* Incompressible.h
*
* Created on: 20 Dec 2013
* Author: jowr
*/
#ifndef INCOMPRESSIBLE_H_
#define INCOMPRESSIBLE_H_
#include <Eigen/Core>
#include "PolyMath.h"
#include "MatrixMath.h"
namespace CoolProp {
class Incompressible{
protected:
std::string name;
std::string description;
std::string reference;
double Tmin, Tmax;
double xmin, xmax;
double TminPsat;
double xref, Tref;
double xbase, Tbase;
Eigen::MatrixXd cRho;
Eigen::MatrixXd cHeat;
Eigen::MatrixXd cVisc;
Eigen::MatrixXd cCond;
Eigen::MatrixXd cPsat;
Eigen::MatrixXd cTfreeze;
Eigen::MatrixXd cV2M;
Polynomial2DFrac poly;
public:
Incompressible();
virtual ~Incompressible();
std::string getName() const {return name;}
std::string get_name() const {return getName();}// For backwards-compatibility.
std::string getDescription() const {return description;}
std::string getReference() const {return reference;}
double getTmax() const {return Tmax;}
double getTmin() const {return Tmin;}
double getxmax() const {return xmax;}
double getxmin() const {return xmin;}
double getTminPsat() const {return TminPsat;}
double getTref() const {return Tref;}
double getxref() const {return xref;}
double getTbase() const {return Tbase;}
double getxbase() const {return xbase;}
void setName(std::string name) {this->name = name;}
void setDescription(std::string description) {this->description = description;}
void setReference(std::string reference) {this->reference = reference;}
void setTmax(double Tmax) {this->Tmax = Tmax;}
void setTmin(double Tmin) {this->Tmin = Tmin;}
void setxmax(double xmax) {this->xmax = xmax;}
void setxmin(double xmin) {this->xmin = xmin;}
void setTminPsat(double TminPsat) {this->TminPsat = TminPsat;}
void setTref(double Tref) {this->Tref = Tref;}
void setxref(double xref) {this->xref = xref;}
void setTbase(double Tbase) {this->Tbase = Tbase;}
void setxbase(double xbase) {this->xbase = xbase;}
// Setters for the coefficients
void setcRho(Eigen::MatrixXd cRho){this->cRho = cRho;}
void setcHeat(Eigen::MatrixXd cHeat){this->cHeat = cHeat;}
void setcVisc(Eigen::MatrixXd cVisc){this->cVisc = cVisc;}
void setcCond(Eigen::MatrixXd cCond){this->cCond = cCond;}
void setcPsat(Eigen::MatrixXd cPsat){this->cPsat = cPsat;}
void setcTfreeze(Eigen::MatrixXd cTfreeze){this->cTfreeze = cTfreeze;}
void setcV2M(Eigen::MatrixXd cV2M){this->cV2M = cV2M;}
double getTInput(double curTValue){return curTValue-Tbase;}
double getxInput(double curxValue){return (curxValue-xbase)*100.0;}
/* All functions need T and p as input. Might not
* be necessary, but gives a clearer structure.
*/
/// Density as a function of temperature, pressure and composition.
virtual double rho (double T_K, double p, double x);
/// Heat capacities as a function of temperature, pressure and composition.
virtual double c (double T_K, double p, double x);
virtual double cp (double T_K, double p, double x){return c(T_K,p,x);};
virtual double cv (double T_K, double p, double x){return c(T_K,p,x);};
/// Entropy as a function of temperature, pressure and composition.
virtual double s (double T_K, double p, double x);
/// Internal energy as a function of temperature, pressure and composition.
virtual double u (double T_K, double p, double x);
/// Enthalpy as a function of temperature, pressure and composition.
virtual double h (double T_K, double p, double x);
/// Viscosity as a function of temperature, pressure and composition.
virtual double visc(double T_K, double p, double x);
/// Thermal conductivity as a function of temperature, pressure and composition.
virtual double cond(double T_K, double p, double x);
/// Saturation pressure as a function of temperature and composition.
virtual double psat(double T_K, double x );
/// Freezing temperature as a function of pressure and composition.
virtual double Tfreeze( double p, double x);
/// Conversion from volume-based to mass-based composition.
virtual double V2M( double x);
protected:
/* Define internal energy and enthalpy as functions of the
* other properties to provide data in case there are no
* coefficients.
*/
/// Enthalpy from u, p and rho.
/** Calculate enthalpy as a function of temperature and
* pressure employing functions for internal energy and
* density. Provides consistent formulations. */
double h_u(double T_K, double p, double x) {
return u(T_K,p,x)+p/rho(T_K,p,x);
};
/// Internal energy from h, p and rho.
/** Calculate internal energy as a function of temperature
* and pressure employing functions for enthalpy and
* density. Provides consistent formulations. */
double u_h(double T_K, double p, double x) {
return h(T_K,p,x)-p/rho(T_K,p,x);
};
/*
* Some more functions to provide a single implementation
* of important routines.
* We start with the check functions that can validate input
* in terms of pressure p, temperature T and composition x.
*/
/// Check validity of temperature input.
/** Compares the given temperature T to the result of a
* freezing point calculation. This is not necessarily
* defined for all fluids, default values do not cause errors. */
bool checkT(double T_K, double p, double x);
/// Check validity of pressure input.
/** Compares the given pressure p to the saturation pressure at
* temperature T and throws and exception if p is lower than
* the saturation conditions.
* The default value for psat is -1 yielding true if psat
* is not redefined in the subclass.
* */
bool checkP(double T_K, double p, double x);
/// Check validity of composition input.
/** Compares the given composition x to a stored minimum and
* maximum value. Enforces the redefinition of xmin and
* xmax since the default values cause an error. */
bool checkX(double x);
/// Check validity of temperature, pressure and composition input.
bool checkTPX(double T, double p, double x);
};
} /* namespace CoolProp */
#endif /* INCOMPRESSIBLE_H_ */

View File

@@ -1,7 +1,181 @@
#include "IncompressibleLibrary.h"
#include "MatrixMath.h"
#include "rapidjson/rapidjson_include.h"
#include "all_incompressibles_JSON.h" // Makes a std::string variable called all_fluids_JSON
namespace CoolProp{
/// A general function to parse the json files that hold the coefficient matrices
IncompressibleData JSONIncompressibleLibrary::parse_coefficients(rapidjson::Value &obj, std::string id, bool vital){
IncompressibleData fluidData;
if (obj.HasMember(id.c_str())) {
//rapidjson::Value value = obj[id.c_str()];
if (obj[id.c_str()].HasMember("type")){
std::string type = cpjson::get_string(obj[id.c_str()], "type");
if (!type.compare("polynomial")){
fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL;
fluidData.coeffs = vec_to_eigen(cpjson::get_double_array(obj[id.c_str()]["coeffs"]));
return fluidData;
}
else if (!type.compare("exponential")){
fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_EXPONENTIAL;
fluidData.coeffs = vec_to_eigen(cpjson::get_double_array(obj[id.c_str()]["coeffs"]));
return fluidData;
}
else if (!type.compare("exppolynomial")){
fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_EXPPOLYNOMIAL;
fluidData.coeffs = vec_to_eigen(cpjson::get_double_array(obj[id.c_str()]["coeffs"]));
return fluidData;
}
else{
throw ValueError(format("The type [%s] is not understood for [%s] of incompressible fluids. Please check your JSON file.", type.c_str(), id.c_str()));
}
}
else{
throw ValueError(format("Your file does not have an entry for \"type\" of [%s], which is vital for this function.", id.c_str()));
}
}
else{
if (vital) {
throw ValueError(format("Your file does not have information for [%s], which is vital for an incompressible fluid.", id.c_str()));
}
}
return fluidData;
}
/// Get a double from the JSON storage if it is defined, otherwise return def
double JSONIncompressibleLibrary::parse_value(rapidjson::Value &obj, std::string id, bool vital, double def=0.0){
if (obj.HasMember(id.c_str())) {return cpjson::get_double(obj, id);}
else{
if (vital) {
throw ValueError(format("Your file does not have information for [%s], which is vital for an incompressible fluid.", id.c_str()));
}
else{
return def;
}
}
}
/// Add all the fluid entries in the rapidjson::Value instance passed in
void JSONIncompressibleLibrary::add_many(rapidjson::Value &listing) {
for (rapidjson::Value::ValueIterator itr = listing.Begin();
itr != listing.End(); ++itr) {
add_one(*itr);
}
};
void JSONIncompressibleLibrary::add_one(rapidjson::Value &fluid_json) {
_is_empty = false;
// Get the next index for this fluid
std::size_t index = fluid_map.size();
// Add index->fluid mapping
fluid_map[index] = IncompressibleFluid();
// Create an instance of the fluid
IncompressibleFluid &fluid = fluid_map[index];
fluid.setName(cpjson::get_string(fluid_json, "name"));
fluid.setDescription(cpjson::get_string(fluid_json, "description"));
fluid.setReference(cpjson::get_string(fluid_json, "reference"));
fluid.setTmax(parse_value(fluid_json, "Tmax", true, 0.0));
fluid.setTmin(parse_value(fluid_json, "Tmin", true, 0.0));
fluid.setxmax(parse_value(fluid_json, "xmax", false, 1.0));
fluid.setxmin(parse_value(fluid_json, "xmin", false, 0.0));
fluid.setTminPsat(parse_value(fluid_json, "TminPsat", false, 0.0));
fluid.setTbase(parse_value(fluid_json, "Tbase", false, 0.0));
fluid.setxbase(parse_value(fluid_json, "xbase", false, 0.0));
/// Setters for the coefficients
fluid.setDensity(parse_coefficients(fluid_json, "density", true));
fluid.setSpecificHeat(parse_coefficients(fluid_json, "specific_heat", true));
fluid.setViscosity(parse_coefficients(fluid_json, "viscosity", false));
fluid.setConductivity(parse_coefficients(fluid_json, "conductivity", false));
fluid.setPsat(parse_coefficients(fluid_json, "saturation_pressure", false));
fluid.setTfreeze(parse_coefficients(fluid_json, "T_freeze", false));
fluid.setVolToMass(parse_coefficients(fluid_json, "volume2mass", false));
fluid.setMassToMole(parse_coefficients(fluid_json, "mass2mole", false));
fluid.set_reference_state(
parse_value(fluid_json, "Tref", false, 25+273.15) ,
parse_value(fluid_json, "pref", false, 1.01325e5) ,
parse_value(fluid_json, "xref", false, 0.0) ,
parse_value(fluid_json, "href", false, 0.0) ,
parse_value(fluid_json, "sref", false, 0.0)
);
/// A function to check coefficients and equation types.
fluid.validate();
// Add name->index mapping
string_to_index_map[fluid.getName()] = index;
};
/// Get an IncompressibleFluid instance stored in this library
/**
@param name Name of the fluid
*/
IncompressibleFluid& JSONIncompressibleLibrary::get(std::string key) {
std::map<std::string, std::size_t>::iterator it;
// Try to find it
it = string_to_index_map.find(key);
// If it is found
if (it != string_to_index_map.end()) {
return get(it->second);
} else {
throw ValueError(
format(
"key [%s] was not found in string_to_index_map in JSONIncompressibleLibrary",
key.c_str()
)
);
}
};
/// Get a CoolPropFluid instance stored in this library
/**
@param key The index of the fluid in the map
*/
IncompressibleFluid& JSONIncompressibleLibrary::get(std::size_t key) {
std::map<std::size_t, IncompressibleFluid>::iterator it;
// Try to find it
it = fluid_map.find(key);
// If it is found
if (it != fluid_map.end()) {
return it->second;
} else {
throw ValueError(
format("key [%d] was not found in JSONIncompressibleLibrary",key));
}
};
static JSONIncompressibleLibrary library;

View File

@@ -22,172 +22,44 @@ a rapidjson array of fluids to the add_many function.
*/
class JSONIncompressibleLibrary
{
/// Map from CAS code to JSON instance. For pseudo-pure fluids, use name in place of CAS code since no CASE number is defined for mixtures
/// Map from CAS code to JSON instance.
/** This is not practical for the incomressibles, the CAS may not be
* defined for blends of heat transfer fluids and solutions.
*/
std::map<std::size_t, IncompressibleFluid> fluid_map;
std::vector<std::string> name_vector;
std::map<std::string, std::size_t> string_to_index_map;
bool _is_empty;
protected:
/// A general function to parse the json files that hold the coefficient matrices
IncompressibleData parse_coefficients(rapidjson::Value &obj, std::string id, bool vital);
double parse_value(rapidjson::Value &obj, std::string id, bool vital, double def);
/// Parse the viscosity
void parse_viscosity(rapidjson::Value &viscosity, IncompressibleFluid & fluid)
{
if (viscosity.HasMember("type")){
std::string type = cpjson::get_string(viscosity, "type");
if (!type.compare("polynomial")){
fluid.viscosity.type = CoolProp::IncompressibleViscosityVariables::INCOMPRESSIBLE_VISCOSITY_POLYNOMIAL;
fluid.viscosity.poly.coeffs = cpjson::get_double_array(viscosity["coeffs"]);
return;
}
else{
throw ValueError(format("viscosity type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
}
}
else{
throw ValueError(format("viscosity does not have \"type\" for fluid %s", fluid.name.c_str()));
}
};
/// Parse the conductivity
void parse_conductivity(rapidjson::Value &conductivity, IncompressibleFluid & fluid)
{
if (conductivity.HasMember("type")){
std::string type = cpjson::get_string(conductivity, "type");
if (!type.compare("polynomial")){
fluid.conductivity.type = CoolProp::IncompressibleConductivityVariables::INCOMPRESSIBLE_CONDUCTIVITY_POLYNOMIAL;
fluid.conductivity.poly.coeffs = cpjson::get_double_array(conductivity["coeffs"]);
return;
}
else{
throw ValueError(format("conductivity type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
}
}
else{
throw ValueError(format("conductivity does not have \"type\" for fluid %s", fluid.name.c_str()));
}
};
/// Parse the specific_heat
void parse_specific_heat(rapidjson::Value &specific_heat, IncompressibleFluid & fluid)
{
if (specific_heat.HasMember("type")){
std::string type = cpjson::get_string(specific_heat, "type");
if (!type.compare("polynomial")){
fluid.specific_heat.type = CoolProp::IncompressibleSpecificHeatVariables::INCOMPRESSIBLE_SPECIFIC_HEAT_POLYNOMIAL; return;
fluid.specific_heat.poly.coeffs = cpjson::get_double_array(specific_heat["coeffs"]);
}
else{
throw ValueError(format("specific_heat type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
}
}
else{
throw ValueError(format("specific_heat does not have \"type\" for fluid %s", fluid.name.c_str()));
}
};
/// Parse the density
void parse_density(rapidjson::Value &density, IncompressibleFluid & fluid)
{
if (density.HasMember("type")){
std::string type = cpjson::get_string(density, "type");
if (!type.compare("polynomial")){
fluid.density.type = CoolProp::IncompressibleDensityVariables::INCOMPRESSIBLE_DENSITY_POLYNOMIAL; return;
fluid.density.poly.coeffs = cpjson::get_double_array(density["coeffs"]);
}
else{
throw ValueError(format("density type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
}
}
else{
throw ValueError(format("density does not have \"type\" for fluid %s", fluid.name.c_str()));
}
};
/// Validate the fluid file that was just constructed
void validate(IncompressibleFluid & fluid)
{
}
public:
// Default constructor;
JSONIncompressibleLibrary(){
_is_empty = true;
};
JSONIncompressibleLibrary(){ _is_empty = true;};
bool is_empty(void){ return _is_empty;};
/// Add all the fluid entries in the rapidjson::Value instance passed in
void add_many(rapidjson::Value &listing)
{
for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr)
{
add_one(*itr);
}
};
void add_one(rapidjson::Value &fluid_json)
{
_is_empty = false;
void add_many(rapidjson::Value &listing);
void add_one(rapidjson::Value &fluid_json);
// Get the next index for this fluid
std::size_t index = fluid_map.size();
// Add index->fluid mapping
fluid_map[index] = IncompressibleFluid();
// Create an instance of the fluid
IncompressibleFluid &fluid = fluid_map[index];
fluid.name = cpjson::get_string(fluid_json, "name");
fluid.Tmin = cpjson::get_double(fluid_json, "Tmin");
fluid.Tmax = cpjson::get_double(fluid_json, "Tmax");
parse_conductivity(fluid_json["conductivity"], fluid);
parse_density(fluid_json["density"], fluid);
parse_viscosity(fluid_json["viscosity"], fluid);
parse_specific_heat(fluid_json["specific_heat"], fluid);
// Add name->index mapping
string_to_index_map[fluid.name] = index;
};
/// Get an IncompressibleFluid instance stored in this library
/**
@param name Name of the fluid
*/
IncompressibleFluid& get(std::string key)
{
std::map<std::string, std::size_t>::iterator it;
// Try to find it
it = string_to_index_map.find(key);
// If it is found
if (it != string_to_index_map.end()){
return get(it->second);
}
else{
throw ValueError(format("key [%s] was not found in string_to_index_map in JSONIncompressibleLibrary",key.c_str()));
}
};
IncompressibleFluid& get(std::string key);
/// Get a CoolPropFluid instance stored in this library
/**
@param key The index of the fluid in the map
*/
IncompressibleFluid& get(std::size_t key)
{
std::map<std::size_t, IncompressibleFluid>::iterator it;
// Try to find it
it = fluid_map.find(key);
// If it is found
if (it != fluid_map.end()){
return it->second;
}
else{
throw ValueError(format("key [%d] was not found in JSONIncompressibleLibrary",key));
}
};
IncompressibleFluid& get(std::size_t key);
/// Return a comma-separated list of fluid names
std::string get_fluid_list(void)
{
return strjoin(name_vector, ",");
};
std::string get_fluid_list(void){ return strjoin(name_vector, ",");};
};
/// Get a reference to the library instance