public static Dictionary <COMMODITY_GROUP, KCoeffs> GetKCoeffs() { Dictionary <COMMODITY_GROUP, KCoeffs> kCoeffs = new Dictionary <COMMODITY_GROUP, KCoeffs>(); // Crude Oil KCoeffs crude = new KCoeffs() { CommodityGroup = COMMODITY_GROUP.CRUDE_OIL, k0 = 341.0957, k1 = 0.0, k2 = 0.0 }; kCoeffs.Add(crude.CommodityGroup, crude); // Fuel Oils KCoeffs fuel = new KCoeffs() { CommodityGroup = COMMODITY_GROUP.FUEL_OILS, k0 = 103.872, k1 = 0.2701, k2 = 0.0 }; kCoeffs.Add(fuel.CommodityGroup, fuel); // Jet Fuels KCoeffs jet = new KCoeffs() { CommodityGroup = COMMODITY_GROUP.JET_FUELS, k0 = 330.301, k1 = 0.0, k2 = 0.0 }; kCoeffs.Add(jet.CommodityGroup, jet); // Transition zone KCoeffs trans = new KCoeffs() { CommodityGroup = COMMODITY_GROUP.TRANSITION_ZONE, k0 = 1489.0670, k1 = 0.0, k2 = -0.00186840 }; kCoeffs.Add(trans.CommodityGroup, trans); // Gasolines KCoeffs gasol = new KCoeffs() { CommodityGroup = COMMODITY_GROUP.GASOLINES, k0 = 192.4571, k1 = 0.2438, k2 = 0.0 }; kCoeffs.Add(gasol.CommodityGroup, gasol); // Lubricating Oils KCoeffs lube = new KCoeffs() { CommodityGroup = COMMODITY_GROUP.LUBRICATING_OIL, k0 = 0.0, k1 = 0.34878, k2 = 0.0 }; kCoeffs.Add(lube.CommodityGroup, lube); return(kCoeffs); }
// Section 11.1.6.1 Step 3 Ki Table public KCoeffs GetKCoeffs(COMMODITY_GROUP cgroup, double api60 = 0.0) { // If density is passed, try to match commodity group to density if (api60 > 0.0) { cgroup = GetKCoeffsGroup(cgroup, api60); } KCoeffs coeffs = null; if (!kCoeffs.TryGetValue(cgroup, out coeffs)) { throw (new ArgumentException(String.Format("Coefficients for COMMODITY_GROUP {0} not found", cgroup))); } return(coeffs); }
public static double Api60ITS90tokgm3ITPS68(double api60, KCoeffs coeffs) { if (coeffs == null) { throw (new ArgumentNullException(nameof(coeffs), new ArgumentException("Must pass and initialize coffs object"))); } // Get density in kg/m3 double rho60 = Conversions.APItoKgm3(api60); // Section 11.1.6.1 Step 3 double A = (deltaT60 / 2.0) * ((coeffs.k0 / rho60 + coeffs.k1) / rho60 + coeffs.k2); double B = (2 * coeffs.k0 + coeffs.k1 * rho60) / (coeffs.k0 + (coeffs.k1 + coeffs.k2 * rho60) * rho60); double rhoITPS68 = rho60 * (1 + (Math.Exp(A * (1 + 0.8 * A)) - 1) / (1 + A * (1 + 1.6 * A) * B)); return(rhoITPS68); }
// Section 11.1.6.1 CTPL (commonly known as VCF) double GetCTPLFromApiDegFPsigNONLiqGas(COMMODITY_GROUP grp, double api60, double tempF, double presPsig = 0) { // Step 1 - Check range for density,temperature and pressure checkRange(api60, "API", grp); checkRange(tempF, "degF"); if (presPsig < 0) { presPsig = 0; } checkRange(presPsig, "psig"); KCoeffs coeffs = GetKCoeffs(grp, api60); // Step 2 and 3 - Get corrected temp and density at ITP68 basis double tempITPS68 = Conversions.TempITS90toITPS68(tempF, "degF"); double densITSP68 = Conversions.Api60ITS90tokgm3ITPS68(api60, coeffs); // kg/m3 // Step 4 - Compute coefficient of thermal expansion double thermExpCoeff60 = GetThermExpCoeff60(densITSP68, coeffs); // Step 5 - Compute temperature correction factor double CTL = GetCTL(thermExpCoeff60, tempITPS68); double CPL = 1.0; // No compensations // If not ATM pressure correct for pressure if (presPsig > 0) { // Step 6 - Compute compressibility factor double Fp = GetCompressFactor(densITSP68, tempITPS68); // Step 7 - Compute pressure correction CPL = GetCPL(Fp, presPsig); } // Step 8 double CTPL = CTL * CPL; return(RoundUpAPI11_1(CTPL, "CTPL")); }
// Section 11.1.2.2 - Equation 16 public double GetThermExpCoeff60(double densITPS68, KCoeffs coeffs) { double alpha60 = coeffs.k0 / (densITPS68 * densITPS68) + coeffs.k1 / densITPS68 + coeffs.k2; return(alpha60); }