CoolProp  4.2.5
An open-source fluid property and humid air property database
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
IncompSolution.cpp
Go to the documentation of this file.
1 
2 #if defined(_MSC_VER)
3 #define _CRTDBG_MAP_ALLOC
4 #define _CRT_SECURE_NO_WARNINGS
5 #include <stdlib.h>
6 #include <crtdbg.h>
7 #else
8 #include <stdlib.h>
9 #endif
10 
11 #include "Units.h"
12 #include "math.h"
13 #include "stdio.h"
14 #include <string.h>
15 #include "Brine.h"
16 #include "CoolPropTools.h"
17 #include "CoolProp.h"
18 #include "IncompBase.h"
19 #include "IncompSolution.h"
20 
21 
23 
26 void IncompressibleSolution::testInputs(double T_K, double p, double x){
27  double result = 0.;
28 
29  printf(" %s \n"," ");
30  printf("Testing %s \n",this->get_name().c_str());
31  printf("Inputs: T = %3.3f degC \t p = %2.4f bar \t x = %1.5f \n",T_K-273.15,p/1e5,x);
32 
33  result = this->rho(T_K,p,x);
34  printf("From object: rho = %4.2f \t kg/m3 \n",result);
35  result = this->cp(T_K,p,x);
36  printf("From object: cp = %1.5f \t kJ/kg-K \n",result/1e3);
37  result = this->h(T_K,p,x);
38  printf("From object: h = %3.3f \t kJ/kg \n",result/1e3);
39  result = this->s(T_K,p,x);
40  printf("From object: s = %1.5f \t kJ/kg-K \n",result/1e3);
41  result = this->visc(T_K,p,x);
42  printf("From object: eta = %1.5f \t 1e-5 Pa-s\n",result*1e5);
43  result = this->cond(T_K,p,x);
44  printf("From object: lambda = %1.5f \t W/m-k \n",result*1e3);
45  result = this->u(T_K,p,x);
46  printf("From object: u = %3.3f \t kJ/kg \n",result/1e3);
47  result = this->psat(T_K,x);
48  printf("From object: psat = %2.4f \t bar \n",result/1e5);
49  result = this->Tfreeze(p,x);
50  printf("From object:Tfreeze = %3.3f \t degC \n\n",result-273.15);
51 }
52 
53 
54 /*
55  * Some more functions to provide a single implementation
56  * of important routines.
57  * We start with the check functions that can validate input
58  * in terms of pressure p, temperature T and composition x.
59  */
60 
62 
66 bool IncompressibleSolution::checkT(double T_K, double p, double x){
67  if( Tmin < 0. ) {
68  throw ValueError("Please specify the minimum temperature.");
69  } else if( Tmax < 0.) {
70  throw ValueError("Please specify the maximum temperature.");
71  } else if ( (Tmin>T_K) || (T_K>Tmax) ) {
72  throw ValueError(format("Your temperature %f is not between %f and %f.",T_K,Tmin,Tmax));
73  } else if (T_K < Tfreeze(p,x)) {
74  throw ValueError(format("Your temperature %f is below the freezing point of %f.",T_K,Tfreeze(p,x)));
75  } else {
76  return true;
77  }
78  return false;
79 }
80 
82 
88 bool IncompressibleSolution::checkP(double T_K, double p, double x) {
89  double ps = psat(T_K,x);
90  if (p<ps) {
91  throw ValueError(format("Equations are valid for solution phase only: %f < %f. ",p,ps));
92  } else {
93  return true;
94  }
95 }
96 
98 
102  if( xmin < 0. ) {
103  throw ValueError("Please specify the minimum concentration.");
104  } else if( xmax < 0.) {
105  throw ValueError("Please specify the maximum concentration.");
106  } else if ( (xmin>x) || (x>xmax) ) {
107  throw ValueError(format("Your composition %f is not between %f and %f.",x,xmin,xmax));
108  } else {
109  return true;
110  }
111  return false;
112 }
113 
115 bool IncompressibleSolution::checkTPX(double T, double p, double x) {
116  return (checkT(T,p,x) && checkP(T,p,x) && checkX(x));
117 }
118 
119 
120 
124  std::vector<IncompressibleSolution*> tmpVector;
125 
126  tmpVector.push_back(new MelinderSolution());
127  tmpVector.push_back(new EGSolution());
128  tmpVector.push_back(new PGSolution());
129  tmpVector.push_back(new EASolution());
130  tmpVector.push_back(new MASolution());
131  tmpVector.push_back(new GLSolution());
132  tmpVector.push_back(new AMSolution());
133  tmpVector.push_back(new KCSolution());
134  tmpVector.push_back(new CASolution());
135  tmpVector.push_back(new MGSolution());
136  tmpVector.push_back(new NASolution());
137  tmpVector.push_back(new KASolution());
138  tmpVector.push_back(new KFSolution());
139  tmpVector.push_back(new LISolution());
140 
141  tmpVector.push_back(new SecCoolSolution());
142  tmpVector.push_back(new ZitrecAC());
143  tmpVector.push_back(new IceSlurryEA());
144  tmpVector.push_back(new IceSlurryPG());
145  tmpVector.push_back(new IceSlurryNA());
146  tmpVector.push_back(new PK2000());
147 
148  tmpVector.push_back(new LiBrSolution());
149 
150  // Now we store the vector in the variable
151  // and overwrite the map.
152  set_solutions(tmpVector);
153 }
154 
156  while (!solution_list.empty()) {
157  delete solution_list.back();
158  solution_list.pop_back();
159  }
160 }
161 
163  return solution_list[index];
164 }
165 
167  std::map<std::string,IncompressibleSolution*>::iterator it;
168  // Try to find using the map if Fluid name is provided
169  it = solution_map.find(name);
170  // If it is found the iterator will not be equal to end
171  if (it != solution_map.end() )
172  {
173  // Return a pointer to the class
174  return (*it).second;
175  }
176  else{
177  return NULL;
178  }
179 }
180 
181 void SolutionsContainer::set_solutions(std::vector<IncompressibleSolution*> list){
182  solution_list = list;
183  // Build the map of fluid names mapping to pointers to the solution class instances
184  for (std::vector<IncompressibleSolution*>::iterator it = solution_list.begin(); it != solution_list.end(); it++)
185  {
186  // Load up entry in map
187  solution_map[(*it)->get_name()] = *it;
188  }
189 }
190 
192 
193 bool IsIncompressibleSolution(std::string name)
194 {
195  IncompressibleSolution *pSolution = Solutions.get_solution(getSolutionName(name));
196  if (pSolution == NULL){ //Not found since NULL pointer returned
197  return false;
198  }
199  else{
200  return true;
201  }
202 }
203 
204 double pIncompSolutionSI(long iOutput, double T, double p_SI, double x, IncompressibleSolution *pSolution)
205 {
206  double out;
207  switch (iOutput)
208  {
209  case iT:
210  out = T; break;
211  case iP:
212  out = p_SI; break;
213  case iD:
214  out = pSolution->rho(T,p_SI,x); break;
215  case iC:
216  out = pSolution->cp(T,p_SI,x); break;
217  case iS:
218  out = pSolution->s(T,p_SI,x); break;
219  case iU:
220  out = pSolution->u(T,p_SI,x); break;
221  case iH:
222  out = pSolution->h(T,p_SI,x); break;
223  case iV:
224  out = pSolution->visc(T,p_SI,x); break;
225  case iL:
226  out = pSolution->cond(T,p_SI,x); break;
227  case iTmax:
228  out = pSolution->getTmax(); break;
229  case iTmin:
230  out = pSolution->getTmin(); break;
231  case iTfreeze:
232  out = pSolution->Tfreeze(p_SI,x); break;
233  case iPsat:
234  out = pSolution->psat(T,x); break;
235  default:
236  throw ValueError(format("Your index [%d] is invalid for the incompressible solution %s",iOutput,pSolution->getName().c_str()));
237  out=0; break;
238  }
239  return out;
240 }
241 
242 double IncompSolutionSI(long iOutput, double T, double p, double x, long iFluid)
243 {
244  return pIncompSolutionSI(iOutput,T,p,x,Solutions.get_solution(iFluid));
245 }
246 
247 double IncompSolutionSI(long iOutput, double T, double p, double x, std::string name)
248 {
249  return pIncompSolutionSI(iOutput,T,p,x,Solutions.get_solution(name));
250 }
251 
255 double IncompSolutionSI(long iOutput, double T, double p, std::string name){ // TODO Solutions: Remove as soon as possible
256  // Split into fluid, concentration pair
257  std::vector<std::string> fluid_concentration = strsplit(std::string(name),'-');
258  // Check it worked
259  if (fluid_concentration.size() != 2){
260  throw ValueError(format("Format of incompressible solution string [%s] is invalid, should be like \"EG-20%\" or \"EG-0.2\" ", name.c_str()) );
261  }
262  // Convert the concentration into a string
263  char* pEnd;
264  double x = strtod(fluid_concentration[1].c_str(), &pEnd);
265  // Check if per cent or fraction syntax is used
266  if (!strcmp(pEnd,"%")){ x *= 0.01;}
267  return IncompSolutionSI(iOutput, T, p, x, fluid_concentration[0]);
268 }
269 std::string getSolutionName(std::string name){ // TODO Solutions: Remove as soon as possible
270  // Split into fluid, concentration pair
271  std::vector<std::string> fluid_concentration = strsplit(std::string(name),'-');
272  return fluid_concentration[0];
273 }
274 double getSolutionConc(std::string name){ // TODO Solutions: Remove as soon as possible
275  // Split into fluid, concentration pair
276  std::vector<std::string> fluid_concentration = strsplit(std::string(name),'-');
277  // Check it worked
278  if (fluid_concentration.size() != 2){
279  throw ValueError(format("Format of incompressible solution string [%s] is invalid, should be like \"EG-20%\" or \"EG-0.2\" ", name.c_str()) );
280  }
281  // Convert the concentration into a string
282  char* pEnd;
283  double x = strtod(fluid_concentration[1].c_str(), &pEnd);
284  // Check if per cent or fraction syntax is used
285  if (!strcmp(pEnd,"%")){ x *= 0.01;}
286  return x;
287 }
288 
289 
291 
300 double BaseSolution::baseFunction(std::vector<double> const& coefficients, double T_K, double p, double x){
302  return (((((
303  coefficients[17])*x
304  +coefficients[16])*x
305  +coefficients[15])*T_K
306  +(((coefficients[14])*x
307  +coefficients[13])*x
308  +coefficients[12])*x
309  +coefficients[11])*T_K
310  +((((coefficients[10])*x
311  +coefficients[9])*x
312  +coefficients[8])*x
313  +coefficients[7])*x
314  +coefficients[6])*T_K
315  +(((((coefficients[5])*x
316  +coefficients[4])*x
317  +coefficients[3])*x
318  +coefficients[2])*x
319  +coefficients[1])*x
320  +coefficients[0];
321 }
322 
323 std::vector< std::vector<double> > BaseSolution::makeMatrix(std::vector<double> const& coefficients){
325  std::vector< std::vector<double> > matrix;
326  std::vector<double> tmpVector;
327 
328  tmpVector.clear();
329  tmpVector.push_back(coefficients[0]);
330  tmpVector.push_back(coefficients[6]);
331  tmpVector.push_back(coefficients[11]);
332  tmpVector.push_back(coefficients[15]);
333  matrix.push_back(tmpVector);
334 
335  tmpVector.clear();
336  tmpVector.push_back(coefficients[1]);
337  tmpVector.push_back(coefficients[7]);
338  tmpVector.push_back(coefficients[12]);
339  tmpVector.push_back(coefficients[16]);
340  matrix.push_back(tmpVector);
341 
342  tmpVector.clear();
343  tmpVector.push_back(coefficients[2]);
344  tmpVector.push_back(coefficients[8]);
345  tmpVector.push_back(coefficients[13]);
346  tmpVector.push_back(coefficients[17]);
347  matrix.push_back(tmpVector);
348 
349  tmpVector.clear();
350  tmpVector.push_back(coefficients[3]);
351  tmpVector.push_back(coefficients[9]);
352  tmpVector.push_back(coefficients[14]);
353  tmpVector.push_back(0.0);
354  matrix.push_back(tmpVector);
355 
356  tmpVector.clear();
357  tmpVector.push_back(coefficients[4]);
358  tmpVector.push_back(coefficients[10]);
359  tmpVector.push_back(0.0);
360  tmpVector.push_back(0.0);
361  matrix.push_back(tmpVector);
362 
363  tmpVector.clear();
364  tmpVector.push_back(coefficients[5]);
365  tmpVector.push_back(0.0);
366  tmpVector.push_back(0.0);
367  tmpVector.push_back(0.0);
368  matrix.push_back(tmpVector);
369 
370  tmpVector.clear();
371  return matrix;
372 }
373 
375 std::vector<std::vector<double> > MelinderSolution::convertCoeffs(double* oldestCoeffs, const int A, const int B) {
376  const int lengthA = 18;
377  const int lengthB = 5;
378  if ((A==lengthA) && (B==lengthB) ){
380  double oldCoeffs[lengthA][lengthB];
381  for (int j = 0; j < lengthB; j++) {
382  oldCoeffs[ 0][j] = oldestCoeffs[( 0 * B) + j ];
383  oldCoeffs[ 1][j] = oldestCoeffs[( 4 * B) + j ];
384  oldCoeffs[ 2][j] = oldestCoeffs[( 8 * B) + j ];
385  oldCoeffs[ 3][j] = oldestCoeffs[(12 * B) + j ];
386  oldCoeffs[ 4][j] = oldestCoeffs[(15 * B) + j ];
387  oldCoeffs[ 5][j] = oldestCoeffs[(17 * B) + j ];
388  oldCoeffs[ 6][j] = oldestCoeffs[( 1 * B) + j ];
389  oldCoeffs[ 7][j] = oldestCoeffs[( 5 * B) + j ];
390  oldCoeffs[ 8][j] = oldestCoeffs[( 9 * B) + j ];
391  oldCoeffs[ 9][j] = oldestCoeffs[(13 * B) + j ];
392  oldCoeffs[10][j] = oldestCoeffs[(16 * B) + j ];
393  oldCoeffs[11][j] = oldestCoeffs[( 2 * B) + j ];
394  oldCoeffs[12][j] = oldestCoeffs[( 6 * B) + j ];
395  oldCoeffs[13][j] = oldestCoeffs[(10 * B) + j ];
396  oldCoeffs[14][j] = oldestCoeffs[(14 * B) + j ];
397  oldCoeffs[15][j] = oldestCoeffs[( 3 * B) + j ];
398  oldCoeffs[16][j] = oldestCoeffs[( 7 * B) + j ];
399  oldCoeffs[17][j] = oldestCoeffs[(11 * B) + j ];
400  }
401  std::vector<std::vector<double> > tmpVector;
402  tmpVector.push_back(std::vector<double>());
403  tmpVector.push_back(std::vector<double>());
404  tmpVector.push_back(std::vector<double>());
405  tmpVector.push_back(std::vector<double>());
406  tmpVector.push_back(std::vector<double>());
407  for (int i = 0; i < lengthA; i++) {
408  for (int j = 0; j < lengthB; j++) {
409  if (i<1) tmpVector[j].clear();
410  tmpVector[j].push_back(oldCoeffs[i][j]);
411  }
412  }
413  return tmpVector;
414  }
415  throw ValueError(format("Your array has the dimensions [%d,%d], but only [%d,%d] arrays are supported.",A,B,lengthA,lengthB));
416 }
417 
418 double const LiBrSolution::M_H2O = 0.018015268; /* kg/mol, molar mass of H2O */
419 double const LiBrSolution::M_LiBr = 0.08685; /* kg/mol, molar mass of LiBr */
420 double const LiBrSolution::T0 = 221; /* K, constant */
421 
422 /* Critical point of H2O */
423 double const LiBrSolution::Tc_H2O = 647.096; /* K, temperature */
424 double const LiBrSolution::pc_H2O = 22.064; /* MPa, pressure */
425 double const LiBrSolution::rhoc_H2O = 17873; /* mol/m^3 (322 kg/m^3), molar density */
426 double const LiBrSolution::hc_H2O = 37548.5; /* J/mol, molar enthalpy */
427 double const LiBrSolution::sc_H2O = 79.3933; /* J/(mol.K) molar entropy*/
428 
429 /*Triple point of H2O */
430 double const LiBrSolution::Tt_H2O = 273.16; /* K, temperature */
431 double const LiBrSolution::cpt_H2O = 76.0226; /* J/(mol.K), molar isobaric heat capacity*/
static double const M_LiBr
virtual double cp(double T_K, double p, double x)
static double const M_H2O
SolutionsContainer Solutions
virtual double s(double T_K, double p, double x)
Entropy as a function of temperature, pressure and composition.
virtual double visc(double T_K, double p, double x)
Viscosity as a function of temperature, pressure and composition.
virtual double cond(double T_K, double p, double x)
Thermal conductivity as a function of temperature, pressure and composition.
bool checkTPX(double T, double p, double x)
Check validity of temperature, pressure and composition input.
virtual double psat(double T_K, double x)
Saturation pressure as a function of temperature and composition.
static double const T0
std::string getName() const
Definition: IncompBase.h:31
virtual double u(double T_K, double p, double x)
Internal energy as a function of temperature, pressure and composition.
std::vector< std::string > strsplit(std::string s, char del)
bool checkT(double T_K, double p, double x)
Check validity of temperature input.
std::string get_name() const
Definition: IncompBase.h:33
double getTmin() const
Definition: IncompBase.h:36
Base class for simplified brine/solution models.
std::string format(const char *fmt,...)
std::vector< std::vector< double > > makeMatrix(std::vector< double > const &coefficients)
virtual double h(double T_K, double p, double x)
Enthalpy as a function of temperature, pressure and composition.
Class to access Lithium-Bromide solutions.
std::vector< double > x(ncmax, 0)
void testInputs(double T_K, double p, double x)
Base class for simplified brine/solution models.
static double const pc_H2O
double baseFunction(std::vector< double > const &coefficients, double T_K, double p, double x)
Some more general purpose functions.
IncompressibleSolution * get_solution(long index)
virtual double rho(double T_K, double p, double x)
Density as a function of temperature, pressure and composition.
std::string getSolutionName(std::string name)
bool checkP(double T_K, double p, double x)
Check validity of pressure input.
std::vector< std::vector< double > > convertCoeffs(double *oldestCoeffs, int A, int B)
Convert pre-v4.0-style coefficient array to new format.
static double const Tt_H2O
static double const Tc_H2O
bool IsIncompressibleSolution(std::string name)
double getSolutionConc(std::string name)
static double const sc_H2O
bool checkCoefficients(std::vector< double > const &coefficients, unsigned int n)
Basic checks for coefficient vectors.
Definition: IncompBase.cpp:16
static double const cpt_H2O
bool checkX(double x)
Check validity of composition input.
static double const rhoc_H2O
void set_solutions(std::vector< IncompressibleSolution * > list)
static double const hc_H2O
double getTmax() const
Definition: IncompBase.h:35
double pIncompSolutionSI(long iOutput, double T, double p_SI, double x, IncompressibleSolution *pSolution)
virtual double Tfreeze(double p, double x)
Freezing temperature as a function of pressure and composition.
double IncompSolutionSI(long iOutput, double T, double p, double x, long iFluid)