AGA8 WebAssembly  1.0
bindings for AGA8 gas properties calculations
Loading...
Searching...
No Matches
Gross.cpp
Go to the documentation of this file.
1
31/*
32This software was developed by employees of the National Institute of Standards and Technology (NIST),
33an agency of the Federal Government and is being made available as a public service. Pursuant to title 17
34United States Code Section 105, works of NIST employees are not subject to copyright protection in the
35United States. This software may be subject to foreign copyright. Permission in the United States and in
36foreign countries, to the extent that NIST may hold copyright, to use, copy, modify, create derivative works,
37and distribute this software and its documentation without fee is hereby granted on a non-exclusive basis,
38provided that this notice and disclaimer of warranty appears in all copies.
39
40THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY,
41INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED
42WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY
43WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE
44ERROR FREE. IN NO EVENT SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT,
45SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE,
46WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY
47PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF,
48OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
49*/
50// ********** This code is preliminary, and will be updated. **********
51// ********** Use only for beta testing. **********
52// ********** June 7, 2016 **********
53
54#include "Gross.h"
55// We add both math headers to placate some non-standards-compliant compilers
56#include <math.h>
57#include <cmath>
58#include <iostream>
59#include <cstdlib>
60
61// Version 2.0 of routines for the calculation of thermodynamic
62// properties from the AGA 8 Part 1 GROSS equation of state.
63// April, 2017
64
65// Written by Eric W. Lemmon
66// Applied Chemicals and Materials Division
67// National Institute of Standards and Technology (NIST)
68// Boulder, Colorado, USA
69// Eric.Lemmon@nist.gov
70// 303-497-7939
71
72// C++ translation by Ian H. Bell
73// Applied Chemicals and Materials Division
74// National Institute of Standards and Technology (NIST)
75// Boulder, Colorado, USA
76// ian.bell@nist.gov
77
78// Other contributors:
79// Volker Heinemann, RMG Messtechnik GmbH
80// Jason Lu, Thermo Fisher Scientific
81// Ian Bell, NIST
82
83// The publication for the AGA 8 equation of state is available from AGA
84// and the Transmission Measurement Committee.
85
86// Subroutines contained here for property calculations:
87// ***** Subroutine SetupGross must be called once before calling other routines. ******
88// Function prototypes
89void Bmix(const double T, const std::vector<double> &xGrs, const double HCH, double &B, double &C, int &ierr, std::string &herr);
90void MolarMassGross(const std::vector<double> &x, double &Mm);
91void PressureGross(const double T, const double D, const std::vector<double> &xGrs, const double HCH, double &P, double &Z, int &ierr, std::string &herr);
92void DensityGross(const double T, const double P, const std::vector<double> &xGrs, const double HCH, double &D, int &ierr, std::string &herr);
93void GrossHv(const std::vector<double> &x, std::vector<double> &xGrs, double &HN, double &HCH);
94void GrossInputs(const double T, const double P, const std::vector<double> &x, std::vector<double> &xGrs, double &Gr, double &HN, double &HCH, int &ierr, std::string &herr);
95void SetupGross();
96
97// 'The compositions in the x() array use the following order and must be sent as mole fractions:
98// ' 0 - PLACEHOLDER
99// ' 1 - Methane
100// ' 2 - Nitrogen
101// ' 3 - Carbon dioxide
102// ' 4 - Ethane
103// ' 5 - Propane
104// ' 6 - Isobutane
105// ' 7 - n-Butane
106// ' 8 - Isopentane
107// ' 9 - n-Pentane
108// ' 10 - n-Hexane
109// ' 11 - n-Heptane
110// ' 12 - n-Octane
111// ' 13 - n-Nonane
112// ' 14 - n-Decane
113// ' 15 - Hydrogen
114// ' 16 - Oxygen
115// ' 17 - Carbon monoxide
116// ' 18 - Water
117// ' 19 - Hydrogen sulfide
118// ' 20 - Helium
119// ' 21 - Argon
120// '
121// 'For example, a mixture (in moles) of 94% methane, 5% CO2, and 1% helium would be (in mole fractions):
122// 'x(1)=0.94, x(3)=0.05, x(20)=0.01
123
124// Variables containing the common parameters in the GROSS equations
125static double RGross;
126static const int NcGross = 21, MaxFlds = 21;
127static const double epsilon = 1e-15;
128static double mN2, mCO2, dPdDsave;
129static double xHN[MaxFlds+1] , MMiGross[MaxFlds+1]; // +1 since C/C++ is 0-based indexing
130static double b0[4][4], b1[4][4], b2[4][4], bCHx[3][3], cCHx[3][3];
131static double c0[4][4][4], c1[4][4][4], c2[4][4][4];
132
143void MolarMassGross(const std::vector<double> &x, double &Mm)
144{
145// Sub MolarMassGross(x, Mm)
146
147// Calculate molar mass of the mixture with the compositions contained in the x() input array
148
149// Inputs:
150// x() - Composition (mole fraction)
151// Do not send mole percents or mass fractions in the x() array, otherwise the output will be incorrect.
152// The sum of the compositions in the x() array must be equal to one.
153// The order of the fluids in this array is given at the top of this code.
154
155// Outputs:
156// Mm - Molar mass (g/mol)
157
158 Mm = 0;
159 for(std::size_t i = 1; i <= NcGross; ++i){
160 Mm += x[i] * MMiGross[i];
161 }
162}
163
183void PressureGross(const double T, const double D, const std::vector<double> &xGrs, const double HCH, double &P, double &Z, int &ierr, std::string &herr)
184{
185 // Sub PressureGross(T, D, xGrs, HCH, P, Z, ierr, herr)
186 //
187 // Calculate pressure as a function of temperature and density. The derivative d(P)/d(D) is also calculated
188 // for use in the iterative DensityGross subroutine (and is only returned as a common variable).
189 //
190 // Inputs:
191 // T - Temperature (K)
192 // D - Density (mol/l)
193 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
194 // HCH - Molar ideal gross heating value of the equivalent hydrocarbon (kJ/mol) at 298.15 K
195 // *** Call subroutine GrossHv or GrossInputs first to obtain HCH. ***
196 //
197 // Outputs:
198 // P - Pressure (kPa)
199 // Z - Compressibility factor
200 // ierr - Error number (0 indicates no error)
201 // herr - Error message if ierr is not equal to zero
202 // dPdDsave - d(P)/d(D) [kPa/(mol/l)] (at constant temperature)
203 // - This variable is cached in the common variables for use in the iterative density solver, but not returned as an argument.
204
205 double B = 1e30, C = 1e30;
206 Z = 1;
207 P = D*RGross*T;
208 Bmix(T, xGrs, HCH, B, C, ierr, herr);
209 if (ierr > 0) { return; }
210 Z = 1 + B*D + C*pow(D, 2);
211 P = D*RGross*T*Z;
212 dPdDsave = RGross*T*(1 + 2*B*D + 3*C*D*D);
213 if (P < 0){
214 ierr = -1;
215 herr = "Pressure is negative in the GROSS method.";
216 }
217}
218
236void DensityGross(const double T, const double P, const std::vector<double> &xGrs, const double HCH, double &D, int &ierr, std::string &herr)
237{
238 // Sub DensityGross(T, P, xGrs, HCH, D, ierr, herr)
239 //
240 // Calculate density as a function of temperature and pressure. This is an iterative routine that calls PressureGross
241 // to find the correct state point. Generally only 6 iterations at most are required.
242 // If the iteration fails to converge, the ideal gas density and an error message are returned.
243 //
244 // Inputs:
245 // T - Temperature (K)
246 // P - Pressure (kPa)
247 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
248 // HCH - Molar ideal gross heating value of the hydrocarbon components (kJ/mol) at 298.15 K
249 // *** Call subroutine GrossHv or GrossInputs first to obtain HCH. ***
250 //
251 // Outputs:
252 // D - Density (mol/l)
253 // ierr - Error number (0 indicates no error)
254 // herr - Error message if ierr is not equal to zero
255
256 double plog, vlog, P2, Z, dpdlv, vdiff, tolr;
257
258 ierr = 0;
259 herr = "";
260 if (P < epsilon){
261 D = 0; return;
262 }
263 tolr = 0.0000001;
264 D = P / RGross / T; //Ideal gas estimate
265 plog = log(P);
266 vlog = -log(D);
267 for(int it = 1; it <= 20; ++it){
268 if(vlog < -7 || vlog > 100){
269 ierr = 1;
270 herr = "Calculation failed to converge in GROSS method, ideal gas density returned.";
271 D = P/RGross/T;
272 return;
273 }
274 D = exp(-vlog);
275 PressureGross(T, D, xGrs, HCH, P2, Z, ierr, herr);
276 if (ierr > 0){ return; }
277 if(dPdDsave < epsilon || P2 < epsilon){
278 vlog += 0.1;
279 }
280 else{
281 // Find the next density with a first order Newton's type iterative scheme, with
282 // log(P) as the known variable and log(v) as the unknown property.
283 // See AGA 8 publication for further information.
284 dpdlv = -D * dPdDsave; // d(p)/d[log(v)]
285 vdiff = (log(P2) - plog) * P2 / dpdlv;
286 vlog = vlog - vdiff;
287 if (std::abs(vdiff) < tolr){
288 if (P2 < 0){
289 ierr = 10;
290 herr = "Calculation failed to converge in the GROSS method, ideal gas density returned.";
291 D = P/RGross/T;
292 return;
293 }
294 // Iteration converged
295 D = exp(-vlog);
296 return;
297 }
298 }
299 }
300 ierr = 10;
301 herr = "Calculation failed to converge in the GROSS method, ideal gas density returned.";
302 D = P/RGross/T;
303}
304
317void GrossHv(const std::vector<double> &x, std::vector<double> &xGrs, double &HN, double &HCH)
318{
319 // Sub GrossHv(x, xGrs, HN, HCH)
320 //
321 // Calculate ideal heating values based on composition. The mole fractions in the mixture are required in this routine, not
322 // just xCH, xN2, and xCO2.
323 //
324 // Inputs:
325 // x - Molar compositions of all components in the mixture. The order in this array is given at the top of this code.
326 //
327 // Outputs:
328 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
329 // HN - Molar ideal gross heating value of the mixture (kJ/mol) at 298.15 K
330 // HCH - Molar ideal gross heating value of the equivalent hydrocarbon (kJ/mol) at 298.15 K
331 xGrs.resize(4);
332 xGrs[1] = 1 - x[2] - x[3];
333 xGrs[2] = x[2];
334 xGrs[3] = x[3];
335 HN = 0;
336 for(std::size_t i = 1; i <= NcGross; ++i){
337 HN += x[i]*xHN[i];
338 }
339 HCH = 0;
340 if (xGrs[1] > 0){
341 HCH = HN / xGrs[1];
342 }
343}
344
364void GrossInputs(const double T, const double P, const std::vector<double> &x, std::vector<double> &xGrs, double &Gr, double &HN, double &HCH, int &ierr, std::string &herr)
365{
366 // Sub GrossInputs(T, P, x, xGrs, Gr, HN, HCH, ierr, herr)
367
368 // Calculate relative density and heating values based on composition. This routine should only be used to get these
369 // two values for use as inputs to Method 1 or Method 2, and not for the relative density for any T and P.
370 // All of the mole fractions in the mixture are required in this routine, not just xCH, xN2, and xCO2.
371
372 // Inputs:
373 // T - Temperature (K), generally a reference temperature for relative density
374 // P - Pressure (kPa), generally a reference pressure for relative density
375 // x - Molar compositions of all components in the mixture. The order in this array is given at the top of this code.
376
377 // Outputs:
378 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
379 // Gr - Relative density at T and P
380 // HN - Molar ideal gross heating value of the mixture (kJ/mol) at 298.15 K
381 // HCH - Molar ideal gross heating value of the equivalent hydrocarbon (kJ/mol) at 298.15 K
382 // ierr - Error number (0 indicates no error)
383 // herr - Error message if ierr is not equal to zero
384
385 double Bref, Zref, Mref, Z, D, Mm;
386 xGrs.resize(4);
387 ierr = 0;
388 herr = "";
389 GrossHv(x, xGrs, HN, HCH);
390 Bref = -0.12527 + 0.000591*T - 0.000000662*pow(T, 2); // 2nd virial coefficient of the reference fluid at T
391 Zref = 1 + Bref*P/RGross/T; // Z of the reference fluid at T and P
392 Mref = 28.9625;
393 MolarMassGross(x, Mm);
394
395 DensityGross(T, P, xGrs, HCH, D, ierr, herr); // Density of the input fluid at T and D
396 Z = P / T / D / RGross; // Z of the input fluid at T and D
397 Gr = Mm * Zref / Mref / Z;
398}
399
412void Bmix(const double T, const std::vector<double> &xGrs, const double HCH, double &B, double &C, int &ierr, std::string &herr)
413{
414 // Sub Bmix(T, xGrs, HCH, B, C, ierr, herr)
415
416 // Calculate 2nd and 3rd virial coefficients for the mixture at T.
417
418 // Inputs:
419 // T - Temperature (K)
420 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
421 // HCH - Molar ideal gross heating value of the equivalent hydrocarbon (kJ/mol) at 298.15 K
422
423 // Outputs:
424 // B - Second virial coefficient (dm^3/mol)
425 // C - Third virial coefficient (dm^6/mol^2)
426 // ierr - Error number (0 indicates no error)
427 // herr - Error message if ierr is not equal to zero
428
429 double bCH[3], cCH[3], BB[4][4], CC[4][4][4];
430 const double onethrd = 1.0 / 3.0;
431
432 ierr = 0;
433 herr = "";
434 B = 0;
435 C = 0;
436
437 // Temperature dependent Bi and Ci values for obtaining B(CH-CH) and C(CH-CH-CH)
438 for (int i = 0; i <= 2; ++i){
439 bCH[i] = bCHx[0][i] + bCHx[1][i]*T + bCHx[2][i]*pow(T, 2);
440 cCH[i] = cCHx[0][i] + cCHx[1][i]*T + cCHx[2][i]*pow(T, 2);
441 }
442
443 // Bij and Cijk values for nitrogen and CO2
444 for(int i = 2; i <= 3; ++i){
445 for(int j = i; j <= 3; ++j){
446 BB[i][j] = b0[i][j] + b1[i][j] * T + b2[i][j]*pow(T, 2);
447 for(int k = j; k <= 3; ++k){
448 CC[i][j][k] = c0[i][j][k] + c1[i][j][k] * T + c2[i][j][k]*pow(T, 2);
449 }
450 }
451 }
452
453 // Bij values for use in calculating Bmix
454 BB[1][1] = bCH[0] + bCH[1]*HCH + bCH[2]*pow(HCH, 2); // B(CH-CH) for the equivalent hydrocarbon
455 BB[1][2] = (0.72 + 0.00001875 * pow(320 - T, 2))*(BB[1][1] + BB[2][2])/2.0; // B(CH-N2)
456 if (BB[1][1]*BB[3][3] < 0){
457 ierr = 4; herr = "Invalid input in Bmix routine";
458 return;
459 }
460 BB[1][3] = -0.865 * sqrt(BB[1][1] * BB[3][3]); // B(CH-CO2)
461
462 // Cijk values for use in calculating Cmix
463 CC[1][1][1] = cCH[0] + cCH[1] * HCH + cCH[2] * pow(HCH, 2); // C(CH-CH-CH) for the equivalent hydrocarbon
464 if (CC[1][1][1] < 0 || CC[3][3][3] < 0){
465 ierr = 5; herr = "Invalid input in Bmix routine";
466 return;
467 }
468 CC[1][1][2] = (0.92 + 0.0013 * (T - 270)) * pow(pow(CC[1][1][1], 2) * CC[2][2][2], onethrd); // C(CH-CH-N2)
469 CC[1][2][2] = (0.92 + 0.0013 * (T - 270)) * pow(pow(CC[2][2][2], 2) * CC[1][1][1], onethrd); // C(CH-N2-N2)
470 CC[1][1][3] = 0.92 * pow(pow(CC[1][1][1], 2) * CC[3][3][3], onethrd); // C(CH-CH-CO2)
471 CC[1][3][3] = 0.92 * pow(pow(CC[3][3][3], 2) * CC[1][1][1], onethrd); // C(CH-CO2-CO2)
472 CC[1][2][3] = 1.1 * pow(CC[1][1][1] * CC[2][2][2] * CC[3][3][3], onethrd); // C(CH-N2-CO2)
473
474 // Calculate Bmix and Cmix
475 for (std::size_t i = 1; i <= 3; ++i){
476 for(std::size_t j = i; j <= 3; ++j){
477 if (i == j){
478 B += BB[i][i]*pow(xGrs[i], 2);
479 }
480 else{
481 B += 2*BB[i][j]*xGrs[i]*xGrs[j];
482 }
483 for(std::size_t k = j; k <= 3; ++k){
484 if (i == j && j == k) {
485 C += CC[i][i][i]*pow(xGrs[i], 3);
486 }
487 else if (i != j && j != k && i != k){
488 C += 6*CC[i][j][k]*xGrs[i]*xGrs[j]*xGrs[k];
489 }
490 else{
491 C += 3*CC[i][j][k]*xGrs[i]*xGrs[j]*xGrs[k];
492 }
493 }
494 }
495 }
496}
497
517void GrossMethod1(const double Th, const double Td, const double Pd, std::vector<double> &xGrs, const double Gr, const double Hv, double & Mm, double &HCH, double &HN, int &ierr, std::string &herr)
518{
519 // Sub GrossMethod1(Th, Td, Pd, xGrs, Gr, Hv, Mm, HCH, HN, ierr, herr)
520
521 // Initialize variables required in the GROSS equation with Method 1 of the AGA 8 Part 1 publication.
522 // Method 1 requires inputs of volumetric gross heating value, relative density, and mole fraction of CO2.
523 //
524 // Inputs:
525 // Th - Reference temperature for heating value (K)
526 // Td - Reference temperature for density (K)
527 // Pd - Reference pressure for density (kPa)
528 // xGrs - Array of size 3 with the molar composition of CO2 in the 3rd position. xCH and xN2 are returned in this array.
529 // Gr - Relative density at Td and Pd
530 // Hv - Volumetric ideal gross heating value (MJ/m^3) at Th
531 //
532 // Outputs:
533 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
534 // Mm - Molar mass (g/mol)
535 // HCH - Molar ideal gross heating value of the equivalent hydrocarbon (kJ/mol) at 298.15 K
536 // HN - Molar ideal gross heating value of the mixture (kJ/mol) at 298.15 K
537 // ierr - Error number (0 indicates no error)
538 // herr - Error message if ierr is not equal to zero
539
540 double xCH, xN2, xCO2, Zd, Zold, G1, G2, Bref, Zref, B, C;
541
542 ierr = 0;
543 herr = "";
544 if (Gr < epsilon){ierr = 1; herr = "Invalid input for relative density"; return;}
545 if (Hv < epsilon){ierr = 2; herr = "Invalid input for heating value"; return;}
546
547 xCO2 = xGrs[3];
548 Zd = 1;
549 G1 = -2.709328;
550 G2 = 0.021062199;
551 Bref = -0.12527 + 0.000591*Td - 0.000000662*pow(Td, 2); // [dm^3/mol]
552 Zref = (1 + Pd / RGross / Td * Bref);
553 for (int i = 0; i < 20; ++i){
554 Zold = Zd;
555 HN = Zd*RGross*Td/Pd*Hv*(1 + 0.0001027*(Th - 298.15)); // [kJ/mol] at 25 C
556 Mm = Gr*Zd*28.9625 / Zref; // [g/mol]
557 xCH = (Mm + (xCO2 - 1) * mN2 - xCO2 * mCO2 - G2 * HN) / (G1 - mN2);
558 xN2 = 1 - xCH - xCO2;
559 if (xN2 < 0){
560 ierr = 3; herr = "Negative nitrogen value in GROSS method 1 setup";
561 return;
562 }
563 HCH = HN / xCH;
564 xGrs[1] = xCH;
565 xGrs[2] = xN2;
566 Bmix(Td, xGrs, HCH, B, C, ierr, herr);
567 if (ierr > 0){
568 return;
569 }
570 Zd = 1 + B*Pd/RGross/Td;
571 if(std::abs(Zold - Zd) < 0.0000001) { break; }
572 }
573}
574
594void GrossMethod2(const double Th, const double Td, const double Pd, std::vector<double> &xGrs, const double Gr, double &Hv, double &Mm, double &HCH, double &HN, int &ierr, std::string &herr)
595{
596 // Sub GrossMethod2(Th, Td, Pd, xGrs, Gr, Hv, Mm, HCH, HN, ierr, herr)
597
598 // Initialize variables required in the GROSS equation with Method 2 of the AGA 8 Part 1 publication.
599 // Method 2 requires inputs of relative density and mole fractions of nitrogen and CO2.
600 //
601 // Inputs:
602 // Th - Reference temperature for heating value (K)
603 // Td - Reference temperature for density (K)
604 // Pd - Reference pressure for density (kPa)
605 // xGrs - Array of size 3 with the molar composition of N2 in the 2nd position and CO2 in the 3rd position. xCH is returned in this array.
606 // Gr - Relative density at Td and Pd
607 //
608 // Outputs:
609 // xGrs - Compositions of the equivalent hydrocarbon, nitrogen, and CO2 (mole fractions)
610 // Hv - Volumetric ideal gross heating value (MJ/m^3) at Th
611 // Mm - Molar mass (g/mol)
612 // HCH - Molar ideal gross heating value of the equivalent hydrocarbon (kJ/mol) at 298.15 K
613 // HN - Molar ideal gross heating value of the mixture (kJ/mol) at 298.15 K
614 // ierr - Error number (0 indicates no error)
615 // herr - Error message if ierr is not equal to zero
616
617 double xCH, Z, Zold, Bref, Zref, MrCH, G1, G2, B, C, xN2, xCO2;
618 ierr = 0;
619 herr = "";
620 if (Gr < epsilon){ ierr = 1; herr = "Invalid input for relative density"; return; }
621
622 xN2 = xGrs[2];
623 xCO2 = xGrs[3];
624 xCH = 1 - xN2 - xCO2;
625 xGrs[1] = xCH;
626 Z = 1;
627 G1 = -2.709328;
628 G2 = 0.021062199;
629 Bref = -0.12527 + 0.000591*Td - 0.000000662*pow(Td, 2);
630 Zref = (1 + Pd / RGross / Td * Bref);
631 for (int i = 0; i < 20; ++i){
632 Zold = Z;
633 Mm = Gr*Z*28.9625/Zref;
634 MrCH = (Mm - xN2 * mN2 - xCO2 * mCO2)/xCH;
635 HCH = (MrCH - G1) / G2;
636 Bmix(Td, xGrs, HCH, B, C, ierr, herr);
637 if (ierr > 0){ return; }
638 Z = 1 + B * Pd / RGross / Td;
639 if (std::abs(Zold - Z) < 0.0000001){ break; };
640 }
641 HN = HCH * xCH;
642 Hv = HN / Z / RGross / Td * Pd / (1 + 0.0001027 * (Th - 298.15));
643}
644
652{
653 // Initialize all the constants and parameters in the GROSS model.
654 RGross = 8.31451;
655
656 // Molar masses (g/mol). These are the same as those in the DETAIL method.
657 MMiGross[1] = 16.043; // Methane
658 MMiGross[2] = 28.0135; // Nitrogen
659 MMiGross[3] = 44.01; // Carbon dioxide
660 MMiGross[4] = 30.07; // Ethane
661 MMiGross[5] = 44.097; // Propane
662 MMiGross[6] = 58.123; // Isobutane
663 MMiGross[7] = 58.123; // n-Butane
664 MMiGross[8] = 72.15; // Isopentane
665 MMiGross[9] = 72.15; // n-Pentane
666 MMiGross[10] = 86.177; // Hexane
667 MMiGross[11] = 100.204; // Heptane
668 MMiGross[12] = 114.231; // Octane
669 MMiGross[13] = 128.258; // Nonane
670 MMiGross[14] = 142.285; // Decane
671 MMiGross[15] = 2.0159; // Hydrogen
672 MMiGross[16] = 31.9988; // Oxygen
673 MMiGross[17] = 28.01; // Carbon monoxide
674 MMiGross[18] = 18.0153; // Water
675 MMiGross[19] = 34.082; // Hydrogen sulfide
676 MMiGross[20] = 4.0026; // Helium
677 MMiGross[21] = 39.948; // Argon
678
679 //Initialize constants
680 b0[2][2] = -0.1446; b1[2][2] = 0.00074091; b2[2][2] = -0.00000091195;
681 b0[2][3] = -0.339693; b1[2][3] = 0.00161176; b2[2][3] = -0.00000204429;
682 b0[3][3] = -0.86834; b1[3][3] = 0.0040376; b2[3][3] = -0.0000051657;
683 c0[2][2][2] = 0.0078498; c1[2][2][2] = -0.000039895; c2[2][2][2] = 0.000000061187;
684 c0[2][2][3] = 0.00552066; c1[2][2][3] = -0.0000168609; c2[2][2][3] = 0.0000000157169;
685 c0[2][3][3] = 0.00358783; c1[2][3][3] = 0.00000806674; c2[2][3][3] = -0.0000000325798;
686 c0[3][3][3] = 0.0020513; c1[3][3][3] = 0.000034888; c2[3][3][3] = -0.000000083703;
687 bCHx[0][0] = -0.425468; bCHx[1][0] = 0.002865; bCHx[2][0] = -0.00000462073;
688 bCHx[0][1] = 0.000877118; bCHx[1][1] = -0.00000556281; bCHx[2][1] = 0.0000000088151;
689 bCHx[0][2] = -0.000000824747; bCHx[1][2] = 0.00000000431436; bCHx[2][2] = -6.08319E-12;
690 cCHx[0][0] = -0.302488; cCHx[1][0] = 0.00195861; cCHx[2][0] = -0.00000316302;
691 cCHx[0][1] = 0.000646422; cCHx[1][1] = -0.00000422876; cCHx[2][1] = 0.00000000688157;
692 cCHx[0][2] = -0.000000332805; cCHx[1][2] = 0.0000000022316; cCHx[2][2] = -3.67713E-12;
693
694 // //Heating values from ISO 6976 at 25 C (kJ/mol)
695 // 'xHN(1) = 890.58 'Methane
696 // 'xHN(2) = 0 'Nitrogen
697 // 'xHN(3) = 0 'Carbon dioxide
698 // 'xHN(4) = 1560.69 'Ethane
699 // 'xHN(5) = 2219.17 'Propane
700 // 'xHN(6) = 2868.2 'Isobutane
701 // 'xHN(7) = 2877.4 'n-Butane
702 // 'xHN(8) = 3528.83 'Isopentane
703 // 'xHN(9) = 3535.77 'n-Pentane
704 // 'xHN(10) = 4194.95 'Hexane
705 // 'xHN(11) = 4853.43 'Heptane
706 // 'xHN(12) = 5511.8 'Octane
707 // 'xHN(13) = 6171.15 'Nonane
708 // 'xHN(14) = 6829.77 'Decane
709 // 'xHN(15) = 285.83 'Hydrogen
710 // 'xHN(16) = 0 'Oxygen
711 // 'xHN(17) = 282.98 'Carbon monoxide
712 // 'xHN(18) = 44.013 'Water
713 // 'xHN(19) = 562.01 'Hydrogen sulfide
714 // 'xHN(20) = 0 'Helium
715 // 'xHN(21) = 0 'Argon
716
717 // Heating values from AGA-5, 2009 at 25 C (kJ/mol)
718 xHN[1] = 890.63; // Methane
719 xHN[2] = 0; // Nitrogen
720 xHN[3] = 0; // Carbon dioxide
721 xHN[4] = 1560.69; // Ethane
722 xHN[5] = 2219.17; // Propane
723 xHN[6] = 2868.2; // Isobutane
724 xHN[7] = 2877.4; // n-Butane
725 xHN[8] = 3528.83; // Isopentane
726 xHN[9] = 3535.77; // n-Pentane
727 xHN[10] = 4194.95; // Hexane
728 xHN[11] = 4853.43; // Heptane
729 xHN[12] = 5511.8; // Octane
730 xHN[13] = 6171.15; // Nonane
731 xHN[14] = 6829.77; // Decane
732 xHN[15] = 285.83; // Hydrogen
733 xHN[16] = 0; // Oxygen
734 xHN[17] = 282.98; // Carbon monoxide
735 xHN[18] = 44.016; // Water
736 xHN[19] = 562.01; // Hydrogen sulfide
737 xHN[20] = 0; // Helium
738 xHN[21] = 0; // Argon
739
740 mN2 = MMiGross[2];
741 mCO2 = MMiGross[3];
742
743}
744
745
746
747#ifdef TEST_GROSS
748int main(){
749 SetupGross();
750 double _x[] = {0.77824, 0.02, 0.06, 0.08, 0.03, 0.0015, 0.003, 0.0005, 0.00165, 0.00215, 0.00088, 0.00024, 0.00015, 0.00009, 0.004, 0.005, 0.002, 0.0001, 0.0025, 0.007, 0.001};
751 std::vector<double> x(_x, _x+NcGross), xGrs(4,0);
752 x.insert(x.begin(), 0.0);
753
754 double mm = 0;
755 MolarMassGross(x, mm);
756
757 int ierr = 0;
758 std::string herr;
759
760 double T = 300, P = 10000, Td = 273.15, Th = 298.15, Pd = 101.325, D = 6.35826, pp = -1, Hv = -1, Hv2 = -1, Gr, HN, HCH, Z=-1;
761 printf("Inputs-----\n");
762 printf("Temperature [K]: 300.0000000000000 != %0.16g\n",T);
763 printf("Pressure [kPa]: 10000.00000000000 != %0.16g\n",P);
764 printf("Th [K]: 298.1500000000000 != %0.16g\n",Th);
765 printf("Td [K]: 273.1500000000000 != %0.16g\n",Td);
766 printf("Pd [kPa]: 101.3250000000000 != %0.16g\n",Pd);
767
768 GrossHv(x,xGrs,HN,HCH);
769 DensityGross(T,P,xGrs,HCH,D,ierr,herr);
770 PressureGross(T,D,xGrs,HCH,pp,Z,ierr,herr);
771 printf("Outputs-----\n");
772 printf("Molar mass [g/mol]: 20.54333051000000 != %0.16g\n",mm);
773 printf("Molar density [mol/l]: 5.117641317088482 != %0.16g\n",D);
774 printf("Pressure [kPa]: 9999.999999999998 != %0.16g\n",P);
775 printf("Compressibility factor: 0.7833795701012788 != %0.16g\n",Z);
776
777 GrossInputs(Td, Pd, x, xGrs, Gr, HN, HCH, ierr, herr);
778 GrossHv(x,xGrs,HN,HCH);
779 DensityGross(Td,Pd,xGrs,HCH,D,ierr,herr);
780 Hv = HN*D;
781 printf("Relative density: 0.7112387718599272 != %0.16g\n",Gr);
782 printf("Molar heating value (kJ/mol, 25 C): 924.3591780000000 != %0.16g\n", HN);
783 printf("HCH (kJ/mol, 25 C): 1004.738236956522 != %0.16g\n",HCH);
784 printf("Equivalent hydrocarbon fraction: 0.9199999999999999 != %0.16g\n",xGrs[1]);
785 printf("nitrogen mole fraction: 2.000000000000000E-02 != %0.16g\n",xGrs[2]);
786 printf("CO2 mole fraction: 6.000000000000000E-02 != %0.16g\n",xGrs[3]);
787 printf("Volumetric heating value at Td,Pd: 41.37676728724603 != %0.16g\n",Hv);
788
789 xGrs[2] = x[2];
790 xGrs[3] = x[3];
791 GrossMethod2(Th, Td, Pd, xGrs, Gr, Hv2, mm, HCH, HN, ierr, herr);
792 DensityGross(T,P,xGrs,HCH,D,ierr,herr);
793 printf("Gross method 2-----\n");
794 printf("Molar density [mol/l]: 5.197833636353455 != %0.16g\n", D);
795 printf("Volumetric heating value at Td,Pd: 42.15440903329388 != %0.16g\n", Hv2);
796
797 xGrs[2] = x[2];
798 xGrs[3] = x[3];
799 GrossMethod1(Th,Td,Pd,xGrs,Gr,Hv,mm,HCH,HN,ierr,herr);
800 DensityGross(T,P,xGrs,HCH,D,ierr,herr);
801 printf("Gross method 1-----\n");
802 printf("Molar density [mol/l]: 5.144374668159809 != %0.16g\n", D);
803}
804#endif
static const int MaxFlds
Definition Detail.cpp:128
static const double epsilon
Definition Detail.cpp:129
static double dPdDsave
Definition Detail.cpp:140
void GrossHv(const std::vector< double > &x, std::vector< double > &xGrs, double &HN, double &HCH)
Calculate ideal heating values based on composition.
Definition Gross.cpp:317
static double RGross
Definition Gross.cpp:125
static double mN2
Definition Gross.cpp:128
static double b0[4][4]
Definition Gross.cpp:130
static double c1[4][4][4]
Definition Gross.cpp:131
static double c0[4][4][4]
Definition Gross.cpp:131
static double bCHx[3][3]
Definition Gross.cpp:130
static double c2[4][4][4]
Definition Gross.cpp:131
void GrossMethod2(const double Th, const double Td, const double Pd, std::vector< double > &xGrs, const double Gr, double &Hv, double &Mm, double &HCH, double &HN, int &ierr, std::string &herr)
Initialize variables required in the GROSS equation with Method 2 of the AGA 8 Part 1 publication.
Definition Gross.cpp:594
static double xHN[MaxFlds+1]
Definition Gross.cpp:129
void DensityGross(const double T, const double P, const std::vector< double > &xGrs, const double HCH, double &D, int &ierr, std::string &herr)
Calculate density as a function of temperature and pressure.
Definition Gross.cpp:236
void PressureGross(const double T, const double D, const std::vector< double > &xGrs, const double HCH, double &P, double &Z, int &ierr, std::string &herr)
Calculate pressure as a function of temperature and density.
Definition Gross.cpp:183
void GrossMethod1(const double Th, const double Td, const double Pd, std::vector< double > &xGrs, const double Gr, const double Hv, double &Mm, double &HCH, double &HN, int &ierr, std::string &herr)
Initialize variables required in the GROSS equation with Method 1 of the AGA 8 Part 1 publication.
Definition Gross.cpp:517
static double b1[4][4]
Definition Gross.cpp:130
void SetupGross()
Initialize all the constants and parameters in the GROSS model.
Definition Gross.cpp:651
static double b2[4][4]
Definition Gross.cpp:130
static double mCO2
Definition Gross.cpp:128
static double MMiGross[MaxFlds+1]
Definition Gross.cpp:129
void Bmix(const double T, const std::vector< double > &xGrs, const double HCH, double &B, double &C, int &ierr, std::string &herr)
Calculate 2nd and 3rd virial coefficients for the mixture at T.
Definition Gross.cpp:412
static const int NcGross
Definition Gross.cpp:126
void GrossInputs(const double T, const double P, const std::vector< double > &x, std::vector< double > &xGrs, double &Gr, double &HN, double &HCH, int &ierr, std::string &herr)
Calculate relative density and heating values based on composition.
Definition Gross.cpp:364
static double cCHx[3][3]
Definition Gross.cpp:130
void MolarMassGross(const std::vector< double > &x, double &Mm)
Calculate molar mass of the mixture with the compositions contained in the x() input array.
Definition Gross.cpp:143