# Natural Gas Properties with ISO6976.2016

## Overview

`ISO6976.2016` implements the calculation method of ISO 6976:2016 “Natural Gas — Calculation of calorific values, density, relative density and Wobbe indices from composition”. Given a gas composition as mole fractions, it returns all combustion and volumetric properties together with their standard uncertainties, propagated according to Annex B of the standard.

### Properties returned

Symbol | Description | Unit
--- | --- | ---
`M` | Molar mass | kg/kmol
`Z` | Compression factor | —
`G_o`, `D_o` | Ideal-gas relative density and density | —, kg/m³
`G`, `u_G` | Real-gas relative density | —
`D`, `u_D` | Real-gas density | kg/m³
`Hcg`, `u_Hcg` | Molar gross calorific value | kJ/mol
`Hcn`, `u_Hcn` | Molar net calorific value | kJ/mol
`Hmg`, `u_Hmg` | Mass-basis gross calorific value | MJ/kg
`Hmn`, `u_Hmn` | Mass-basis net calorific value | MJ/kg
`Hvg`, `u_Hvg` | Volumetric gross calorific value (real gas) | MJ/m³
`Hvn`, `u_Hvn` | Volumetric net calorific value (real gas) | MJ/m³
`Hvg_o`, `Hvn_o` | Ideal-gas volumetric calorific values | MJ/m³
`Wg`, `u_Wg` | Gross Wobbe index | MJ/m³
`Wn`, `u_Wn` | Net Wobbe index | MJ/m³
`Wg_o`, `Wn_o` | Ideal-gas Wobbe indices | MJ/m³

Properties with a `u_` prefix are standard uncertainties (k = 1) unless the `coverage` argument is set to a value other than 1.

## Application limits

The calculation is valid only within the limits defined in ISO 6976:2016 §5:

- Combustion temperature (`combustionTemperature`): 0, 15, 15.55, 20, or 25 °C
- Volume reference temperature (`volumeTemperature`): 0, 15, 15.55, or 20 °C
- Reference pressure (`pressure`): 90–110 kPa (default 101.325 kPa)
- The compression factor Z must exceed 0.9

## Quick start

The simplest way to provide a composition is to construct a numeric vector of length 60 in the component order of ISO 6976:2016 Table A.2 (use `componentNames()` to see the full list):

    x   <- numeric(60)   # all zeros
    u_x <- numeric(60)   # all zero uncertainties
    r_x <- diag(60)      # identity correlation matrix (no correlations)

    # Fill in a simple two-component mixture: 95 % methane, 5 % nitrogen
    x[componentIndex("methane")]  <- 0.95
    x[componentIndex("nitrogen")] <- 0.05

    # Assign standard uncertainties (0.05 mol/mol each)
    u_x[componentIndex("methane")]  <- 0.0005
    u_x[componentIndex("nitrogen")] <- 0.0005

    res <- calculateProperties(x, u_x, r_x,
                               combustionTemperature = 25,
                               volumeTemperature     = 15)

    cat("Molar mass              :", round(res$M,   4), "kg/kmol\n")
    #> Molar mass              : 16.641 kg/kmol
    cat("Compression factor Z    :", round(res$Z,   6), "\n")
    #> Compression factor Z    : 0.998139
    cat("Gross CV (volumetric)   :", round(res$Hvg, 4), "MJ/m³\n")
    #> Gross CV (volumetric)   : 35.8484 MJ/m³
    cat("  standard uncertainty  :", round(res$u_Hvg, 6), "MJ/m³\n")
    #>   standard uncertainty  : 0.020476 MJ/m³
    cat("Gross Wobbe index       :", round(res$Wg,  4), "MJ/m³\n")
    #> Gross Wobbe index       : 47.261 MJ/m³
    cat("  standard uncertainty  :", round(res$u_Wg, 6), "MJ/m³\n")
    #>   standard uncertainty  : 0.026097 MJ/m³

## Using the GasComponents class

For applications that build a composition incrementally — for example when reading chromatograph results component by component — the `GasComponents` R6 class provides named getters and setters:

    gc <- GasComponents$new()

    # Set fractions by name or by index
    gc$setFraction("methane",  0.9234)
    gc$setFraction("ethane",   0.0254)
    gc$setFraction("propane",  0.0152)
    gc$setFraction("nitrogen", 0.0103)
    gc$setFraction("carbon dioxide", 0.0154)
    gc$setFraction(1L, 0.9234)   # same as "methane"

    # Set uncertainties
    gc$setUncertainty("methane",        0.000332)
    gc$setUncertainty("ethane",         0.000243)
    gc$setUncertainty("propane",        0.000148)
    gc$setUncertainty("nitrogen",       0.000195)
    gc$setUncertainty("carbon dioxide", 0.000111)

    # Retrieve a value
    gc$getFraction("methane")
    #> [1] 0.9234

    # Pass directly to calculateProperties
    res <- calculateProperties(gc$fractions, gc$uncertainties, gc$correlations,
                               combustionTemperature = 15,
                               volumeTemperature     = 15)
    round(res$Hvg, 4)   # real-gas vol. gross CV [MJ/m³]
    #> [1] 38.0053

### Setting correlations

When a GC calibration provides a full covariance matrix, use `setCorrelationMatrix()` or `setCorrelation()` for individual pairs:

    gc2 <- GasComponents$new()
    gc2$setFractionArray(gc$fractions)
    gc2$setUncertaintyArray(gc$uncertainties)

    # Negative correlation between methane and ethane (typical for GC)
    gc2$setCorrelation("methane", "ethane", -0.65)
    gc2$getCorrelation("methane", "ethane")
    #> [1] -0.65
    gc2$getCorrelation("ethane", "methane")   # automatically symmetric
    #> [1] -0.65

## Reference conditions

ISO 6976:2016 defines properties at specified reference temperatures and a reference pressure. The package supports all temperature combinations in the standard:

    data("example3", envir = environment())

    # German/European standard: 25 °C combustion, 0 °C metering
    r25_0 <- calculateProperties(example3$fractionArray, example3$uncertaintyArray,
                                 example3$correlationMatrix,
                                 combustionTemperature = 25,
                                 volumeTemperature     = 0)

    # UK/legacy standard: 15 °C / 15 °C
    r15_15 <- calculateProperties(example3$fractionArray, example3$uncertaintyArray,
                                  example3$correlationMatrix,
                                  combustionTemperature = 15,
                                  volumeTemperature     = 15)

    cat("Hvg at 25/0 °C  :", round(r25_0$Hvg,  5), "MJ/m³\n")
    #> Hvg at 25/0 °C  : 41.8936 MJ/m³
    cat("Hvg at 15/15 °C :", round(r15_15$Hvg, 5), "MJ/m³\n")
    #> Hvg at 15/15 °C : 39.73351 MJ/m³

## Uncertainty and coverage factor

All `u_` outputs are standard uncertainties (k = 1) by default. For expanded uncertainties at a given confidence level, set `coverage = 2` (approximately 95 % for a normal distribution):

    data("example1", envir = environment())

    r_k1 <- calculateProperties(example1$fractionArray, example1$uncertaintyArray,
                                 example1$correlationMatrix,
                                 combustionTemperature = 15, volumeTemperature = 15,
                                 coverage = 1)
    r_k2 <- calculateProperties(example1$fractionArray, example1$uncertaintyArray,
                                 example1$correlationMatrix,
                                 combustionTemperature = 15, volumeTemperature = 15,
                                 coverage = 2)

    cat("Gross Wobbe index :", round(r_k1$Wg, 5), "MJ/m³\n")
    #> Gross Wobbe index : 49.52936 MJ/m³
    cat("  u (k=1)         :", round(r_k1$u_Wg, 6), "MJ/m³\n")
    #>   u (k=1)         : 0.021675 MJ/m³
    cat("  U (k=2, ~95%)   :", round(r_k2$u_Wg, 6), "MJ/m³\n")
    #>   U (k=2, ~95%)   : 0.04335 MJ/m³

## Verification against ISO 6976:2016 Annex D

The package ships with the four reference datasets from Annex D of the standard. The results below reproduce Table D.2 of ISO 6976:2016.

    data("example1", envir = environment())
    res <- calculateProperties(example1$fractionArray, example1$uncertaintyArray,
                               example1$correlationMatrix,
                               combustionTemperature = 15,
                               volumeTemperature     = 15,
                               coverage              = 1)

    tab <- data.frame(
      Property = c("M [kg/kmol]", "Z", "Hcg [kJ/mol]", "u(Hcg)",
                   "Hmg [MJ/kg]", "u(Hmg)", "Hvg [MJ/m\u00b3]", "u(Hvg)"),
      Computed = round(c(res$M,     res$Z,     res$Hcg,   res$u_Hcg,
                         res$Hmg,   res$u_Hmg, res$Hvg,   res$u_Hvg), 7),
      ISO_6976 = c(17.3884301, 0.99776224, 906.1799588, 0.615609872,
                   52.113961,  0.024301,   38.410611,   0.026267)
    )
    knitr::kable(tab, align = "lrr")

Property | Computed | ISO_6976
--- | --- | ---
M [kg/kmol] | 17.3884301 | 17.3884301
Z | 0.9977622 | 0.9977622
Hcg [kJ/mol] | 906.1799588 | 906.1799588
u(Hcg) | 0.6156099 | 0.6156099
Hmg [MJ/kg] | 52.1139605 | 52.1139610
u(Hmg) | 0.0243009 | 0.0243010
Hvg [MJ/m³] | 38.4106112 | 38.4106110
u(Hvg) | 0.0262668 | 0.0262670

## Component reference

    # All 60 components in table order
    nms <- componentNames()
    cat(paste(sprintf("%2d  %s", seq_along(nms), nms), collapse = "\n"), "\n")
    #>  1  methane
    #>  2  ethane
    #>  3  propane
    #>  4  n-butane
    #>  5  isobutane
    #>  6  n-pentane
    #>  7  isopentane
    #>  8  neopentane
    #>  9  n-hexane
    #> 10  2-methylpentane
    #> 11  3-methylpentane
    #> 12  2,2-dimethylbutane
    #> 13  2,3-dimethylbutane
    #> 14  n-heptane
    #> 15  n-octane
    #> 16  n-nonane
    #> 17  n-decane
    #> 18  ethylene
    #> 19  propylene
    #> 20  1-butene
    #> 21  cis-2-butene
    #> 22  trans-2-butene
    #> 23  isobutylene
    #> 24  1-pentene
    #> 25  propadiene
    #> 26  1,2-butadiene
    #> 27  1,3-butadiene
    #> 28  acetylene
    #> 29  cyclopentane
    #> 30  methylcyclopentane
    #> 31  ethylcyclopentane
    #> 32  cyclohexane
    #> 33  methylcyclohexane
    #> 34  ethylcyclohexane
    #> 35  benzene
    #> 36  toluene
    #> 37  ethylbenzene
    #> 38  o-xylene
    #> 39  methanol
    #> 40  methanethiol
    #> 41  hydrogen
    #> 42  water
    #> 43  hydrogen sulphide
    #> 44  ammonia
    #> 45  hydrogen cyanide
    #> 46  carbon monoxide
    #> 47  carbonyl sulphide
    #> 48  carbon disulphide
    #> 49  helium
    #> 50  neon
    #> 51  argon
    #> 52  nitrogen
    #> 53  oxygen
    #> 54  carbon dioxide
    #> 55  sulphur dioxide
    #> 56  n-undecane
    #> 57  n-dodecane
    #> 58  n-tridecane
    #> 59  n-tetradecane
    #> 60  n-pentadecane

## Further reading

- ISO 6976:2016 — the primary reference for all formulas, constants, and application limits.
- `?calculateProperties` — full parameter documentation and output table.
- `?GasComponents` — R6 class reference.
- `?example1` through `?example3_ex` — dataset documentation.