1 |
#include "ammonia.h" |
2 |
|
3 |
|
4 |
/** |
5 |
Ideal gas data for Ammonia, from Tillner-Roth, Harms-Watzenberg and |
6 |
Baehr, 'Eine neue Fundamentalgleichung f端r Ammoniak', DKV-Tagungsbericht, |
7 |
20:167-181, 1993. This is the ammmonia property correlation recommended |
8 |
by NIST in its program REFPROP 7.0. |
9 |
*/ |
10 |
const IdealData ideal_data_ammonia = { |
11 |
-15.815020 /* const */ |
12 |
, 4.255726 /* linear */ |
13 |
, 3 /* power terms */ |
14 |
, (const IdealPowTerm[]){ |
15 |
{11.474340, 1./3 } |
16 |
,{-1.296211, -3./2.} |
17 |
,{0.5706757, -7./4.} |
18 |
} |
19 |
, 0, (const IdealExpTerm *)0 /* no exponential terms */ |
20 |
}; |
21 |
|
22 |
|
23 |
/** |
24 |
Residual (non-ideal) property data for Ammonia, from Tillner-Roth, |
25 |
Harms-Watzenberg and Baehr, 'Eine neue Fundamentalgleichung f端r Ammoniak', |
26 |
DKV-Tagungsbericht, 20:167-181, 1993. This is the ammmonia property correlation |
27 |
recommended by NIST in its program REFPROP 7.0. |
28 |
*/ |
29 |
const HelmholtzData helmholtz_data_ammonia = { |
30 |
/* R */ 488.189 /* J/kg/K */ |
31 |
, /* M */ 17.03026 /* kg/kmol */ |
32 |
, /* rho_star */225. /* kg/m続 */ |
33 |
, /* T_star */ 405.40 /* K */ |
34 |
, &ideal_data_ammonia |
35 |
, 21 /* np */ |
36 |
, (const HelmholtzPowTerm[]){ |
37 |
/* a_i, t_i, d_i, l_i */ |
38 |
{0.4554431E-1, -0.5 , 2, 0}/* 1 */ |
39 |
,{0.7238548E+0, 0.5 , 1, 0 } |
40 |
,{0.1229470E-1, 1 , 4, 0 } |
41 |
,{-0.1858814E+1, 1.5 , 1, 0 } |
42 |
,{0.2141882E-10, 3 , 15, 0 }/* 5 */ |
43 |
,{-0.1430020E-1, 0 , 3, 1 } |
44 |
,{0.3441324E+0, 3 , 3, 1 } |
45 |
,{-0.2873571E+0, 4 , 1, 1 } |
46 |
,{0.2352589E-4, 4 , 8, 1 } |
47 |
,{-0.3497111E-1, 5 , 2, 1}/* 10 */ |
48 |
,{0.2397852E-1, 3 , 1, 2} |
49 |
,{0.1831117E-2, 5 , 8, 2} |
50 |
,{-0.4085375E-1, 6 , 1, 2} |
51 |
,{0.2379275E+0, 8 , 2, 2} |
52 |
,{-0.3548972E-1, 8 , 3, 2}/* 15 */ |
53 |
,{-0.1823729E+0, 10, 2, 2} |
54 |
,{0.2281556E-1, 10 , 4, 2} |
55 |
,{-0.6663444E-2, 5 , 3, 3} |
56 |
,{-0.8847486E-2, 7.5, 1, 3} |
57 |
,{0.2272635E-2 , 15 , 2, 3}/* 20 */ |
58 |
,{-0.5588655E-3, 30, 4, 3} |
59 |
} |
60 |
, 0, 0 /* no exponential terms */ |
61 |
}; |
62 |
|
63 |
|
64 |
/* |
65 |
Test suite. These tests attempt to validate the current code using |
66 |
a few sample figures output by REFPROP 7.0. |
67 |
|
68 |
To run the test, compile and run as follows: |
69 |
|
70 |
gcc helmholtz.c ammonia.c -DTEST -o ammonia -lm && ./ammonia |
71 |
|
72 |
These tests all currently pass with a maximum error of 2%. The error |
73 |
seems to arise in the enthalpy data for low temperatures. Haven't been |
74 |
able to determine where the problem comes from. |
75 |
*/ |
76 |
#ifdef TEST |
77 |
|
78 |
#include <assert.h> |
79 |
#include <stdlib.h> |
80 |
#include <stdio.h> |
81 |
#include <math.h> |
82 |
|
83 |
typedef struct{double T,p,rho,h,s;} TestData; |
84 |
const TestData td[]; const unsigned ntd; |
85 |
|
86 |
int main(void){ |
87 |
unsigned n, i; |
88 |
double rho, T, p, h, s; |
89 |
const HelmholtzData *d; |
90 |
|
91 |
d = &helmholtz_data_ammonia; |
92 |
double maxerr = 0; |
93 |
|
94 |
n = ntd; |
95 |
fprintf(stderr,"Running through %d test points...\n",n); |
96 |
|
97 |
/* enthalpy offset is required to attain agreement with values from REFPROP */ |
98 |
double Z = -1.4314814207e+05; |
99 |
|
100 |
/* entropy offset required to attain agreement with REFPROP */ |
101 |
double Y = -4.7157087586e+02; |
102 |
|
103 |
/* a simple macro to actually do the testing */ |
104 |
#define ASSERT_TOL(FN,PARAM1,PARAM2,PARAM3,VAL,TOL) {\ |
105 |
double cval; cval = FN(PARAM1,PARAM2,PARAM3);\ |
106 |
double err; err = cval - (double)(VAL);\ |
107 |
double relerrpc = (cval-(VAL))/(VAL)*100;\ |
108 |
if(fabs(relerrpc)>maxerr)maxerr=fabs(relerrpc);\ |
109 |
if(fabs(err)>fabs(TOL)){\ |
110 |
fprintf(stderr,"ERROR in line %d: value of '%s(%f,%f,%s)' = %f,"\ |
111 |
" should be %f, error is %.10e (%.2f%%)!\n"\ |
112 |
, __LINE__, #FN,PARAM1,PARAM2,#PARAM3, cval, VAL,cval-(VAL)\ |
113 |
,relerrpc\ |
114 |
);\ |
115 |
exit(1);\ |
116 |
}else{\ |
117 |
fprintf(stderr," OK, %s(%f,%f,%s) = %8.2e with %.2f%% err.\n"\ |
118 |
,#FN,PARAM1,PARAM2,#PARAM3,VAL,relerrpc\ |
119 |
);\ |
120 |
}\ |
121 |
} |
122 |
|
123 |
fprintf(stderr,"PRESSURE TESTS\n"); |
124 |
for(i=0; i<n;++i){ |
125 |
p = td[i].p*1e6; |
126 |
ASSERT_TOL(helmholtz_p, td[i].T+273.15, td[i].rho, d, p, p*2e-4); |
127 |
} |
128 |
|
129 |
fprintf(stderr,"ENTROPY TESTS\n"); |
130 |
for(i=0; i<n;++i){ |
131 |
s = td[i].s*1e3 + Y; |
132 |
ASSERT_TOL(helmholtz_s, td[i].T+273.15, td[i].rho, d, s, 100*s); |
133 |
} |
134 |
|
135 |
fprintf(stderr,"ENTHALPY TESTS\n"); |
136 |
for(i=0; i<n;++i){ |
137 |
ASSERT_TOL(helmholtz_h, td[i].T+273.15, td[i].rho, d, td[i].h*1e3 + Z, 1E3); |
138 |
} |
139 |
|
140 |
fprintf(stderr,"Tests completed OK (maximum error = %0.2f%%)\n",maxerr); |
141 |
exit(0); |
142 |
} |
143 |
|
144 |
/* |
145 |
Some test data generated by REFPROP 7.0 for p=0.1, 1, 10, 20, 100 MPa. |
146 |
*/ |
147 |
const TestData td[] = { |
148 |
/* {T/属C , p/MPa rho/(kg/m続) , h/(kJ/kg) , s/(kJ/kgK)} */ |
149 |
{-7.0E+1, 1.E-1, 7.247478262E+2, 3.24282714E+1, 1.620191045E-1} |
150 |
, {-3.358834071E+1, 1.E-1, 6.822948922E+2, 1.90753355E+2, 8.784304761E-1} |
151 |
, {-3.358834071E+1, 1.E-1, 8.786678914E-1, 1.561014597E+3, 6.5982992E+0} |
152 |
, {-2.0E+1, 1.E-1, 8.263382177E-1, 1.591688059E+3, 6.722856799E+0} |
153 |
, {3.0E+1, 1.E-1, 6.82304266E-1, 1.700664077E+3, 7.115863679E+0} |
154 |
, {8.0E+1, 1.E-1, 5.831571413E-1, 1.80978242E+3, 7.448946867E+0} |
155 |
, {1.30E+2, 1.E-1, 5.097610128E-1, 1.922139191E+3, 7.746386561E+0} |
156 |
, {1.80E+2, 1.E-1, 4.5299046E-1, 2.038924538E+3, 8.019355389E+0} |
157 |
, {2.30E+2, 1.E-1, 4.076912096E-1, 2.160745608E+3, 8.274268056E+0} |
158 |
, {2.80E+2, 1.E-1, 3.706742442E-1, 2.287955598E+3, 8.515225293E+0} |
159 |
, {3.30E+2, 1.E-1, 3.398445366E-1, 2.420766836E+3, 8.745015419E+0} |
160 |
, {3.80E+2, 1.E-1, 3.137636628E-1, 2.559300504E+3, 8.965613422E+0} |
161 |
, {-7.0E+1, 1.E+0, 7.250581532E+2, 3.329212774E+1, 1.601599414E-1} |
162 |
, {-2.0E+1, 1.E+0, 6.655956817E+2, 2.523244796E+2, 1.122985212E+0} |
163 |
, {2.489509207E+1, 1.E+0, 6.029210949E+2, 4.603181705E+2, 1.878768996E+0} |
164 |
, {2.489509207E+1, 1.E+0, 7.782283811E+0, 1.626522182E+3, 5.791613203E+0} |
165 |
, {3.0E+1, 1.E+0, 7.573646544E+0, 1.64218808E+3, 5.843733285E+0} |
166 |
, {8.0E+1, 1.E+0, 6.146734558E+0, 1.776840309E+3, 6.255779773E+0} |
167 |
, {1.30E+2, 1.E+0, 5.259177246E+0, 1.900135075E+3, 6.582405217E+0} |
168 |
, {1.80E+2, 1.E+0, 4.621587996E+0, 2.022912586E+3, 6.869456377E+0} |
169 |
, {2.30E+2, 1.E+0, 4.132311779E+0, 2.148479127E+3, 7.132238182E+0} |
170 |
, {2.80E+2, 1.E+0, 3.741648311E+0, 2.278233212E+3, 7.378029463E+0} |
171 |
, {3.30E+2, 1.E+0, 3.421067224E+0, 2.412874791E+3, 7.610994396E+0} |
172 |
, {3.80E+2, 1.E+0, 3.152561727E+0, 2.552781957E+3, 7.833784037E+0} |
173 |
, {-7.0E+1, 1.E+1, 7.281133559E+2, 4.198085991E+1, 1.41957312E-1} |
174 |
, {-2.0E+1, 1.E+1, 6.705474103E+2, 2.593441153E+2, 1.097500056E+0} |
175 |
, {3.0E+1, 1.0E+1, 6.036532714E+2, 4.883773339E+2, 1.922486043E+0} |
176 |
, {8.0E+1, 1.E+1, 5.191766069E+2, 7.375493941E+2, 2.682019021E+0} |
177 |
, {1.251668991E+2, 1.0E+1, 3.566957919E+2, 1.064721249E+3, 3.546261425E+0} |
178 |
, {1.251668991E+2, 1.0E+1, 1.215794756E+2, 1.450595358E+3, 4.515023005E+0} |
179 |
, {1.30E+2, 1.0E+1, 1.006607688E+2, 1.533108854E+3, 4.721093813E+0} |
180 |
, {1.80E+2, 1.0E+1, 6.013676382E+1, 1.830511847E+3, 5.423234397E+0} |
181 |
, {2.30E+2, 1.E+1, 4.825185325E+1, 2.013315037E+3, 5.806541293E+0} |
182 |
, {2.80E+2, 1.0E+1, 4.136336686E+1, 2.175462144E+3, 6.11393854E+0} |
183 |
, {3.30E+2, 1.0E+1, 3.661170108E+1, 2.331445154E+3, 6.383938033E+0} |
184 |
, {3.80E+2, 1.0E+1, 3.303984101E+1, 2.486570677E+3, 6.631017385E+0} |
185 |
// we seem to have problems at low temperatures for 20 MPa, not sure why... |
186 |
, {-7.0E+1, 2.E+1, 7.314110284E+2, 5.173429903E+1, 1.225158918E-1} |
187 |
, {-6.0E+1, 2.E+1, 7.21003185E+2, 9.387141936E+1, 3.249807774E-1} |
188 |
, {-5.0E+1, 2.E+1, 7.101928923E+2, 1.365435121E+2, 5.206147995E-1} |
189 |
, {-4.0E+1, 2.E+1, 6.990247179E+2, 1.797203029E+2, 7.0988476E-1} |
190 |
, {-3.0E+1, 2.E+1, 6.875346255E+2, 2.233556145E+2, 8.93131467E-1} |
191 |
, {-2.0E+1, 2.E+1, 6.757461174E+2, 2.674043891E+2, 1.070658825E+0} |
192 |
, {-1.0E+1, 2.E+1, 6.636692193E+2, 3.11832692E+2, 1.24277842E+0} |
193 |
, {0.E+0, 2.0E+1, 6.513006059E+2, 3.566229991E+2, 1.409828141E+0} |
194 |
, {1.0E+1, 2.E+1, 6.386239377E+2, 4.017767906E+2, 1.572177757E+0} |
195 |
, {-2.0E+1, 1.E+2, 7.097079501E+2, 3.380654271E+2, 8.941118487E-1} |
196 |
, {3.0E+1, 1.00E+2, 6.609898909E+2, 5.505822381E+2, 1.660051479E+0} |
197 |
, {8.0E+1, 1.00E+2, 6.112193023E+2, 7.645876046E+2, 2.313447447E+0} |
198 |
, {1.30E+2, 1.E+2, 5.605676047E+2, 9.797127692E+2, 2.88311668E+0} |
199 |
, {1.80E+2, 1.00E+2, 5.091016945E+2, 1.197234461E+3, 3.391678155E+0} |
200 |
, {2.30E+2, 1.00E+2, 4.577648376E+2, 1.417741767E+3, 3.853216148E+0} |
201 |
, {2.80E+2, 1.00E+2, 4.085537409E+2, 1.640134431E+3, 4.274597549E+0} |
202 |
, {3.30E+2, 1.00E+2, 3.638085408E+2, 1.86192272E+3, 4.658479239E+0} |
203 |
, {3.80E+2, 1.00E+2, 3.251311703E+2, 2.080565949E+3, 5.006781049E+0} |
204 |
}; |
205 |
|
206 |
const unsigned ntd = sizeof(td)/sizeof(TestData); |
207 |
|
208 |
#endif |