Nothing
# Tests against the worked examples in Annex D of ISO 6976:2016
# All expected values are taken directly from the standard.
library(ISO6976.2016)
################################################################################
# Example 1 (Annex D.2): 5-component mixture, 15/15 °C
################################################################################
test_that("Example 1 — 15/15 °C: molar mass, Z, molar GCV, mass GCV, vol. GCV", {
data("example1", envir = environment())
res <- calculateProperties(example1$fractionArray, example1$uncertaintyArray, example1$correlationMatrix,
combustionTemperature = 15,
volumeTemperature = 15,
coverage = 1)
expect_equal(res$M, 17.3884301, tolerance = 1e-7) # molar mass
expect_equal(res$Z, 0.99776224, tolerance = 1e-8) # compression factor
expect_equal(res$Hcg, 906.1799588, tolerance = 1e-7) # molar gross CV
expect_equal(res$u_Hcg, 0.615609872, tolerance = 1e-9) # u(molar GCV)
expect_equal(res$Hmg, 52.113961, tolerance = 1e-6) # mass gross CV
expect_equal(res$u_Hmg, 0.024301, tolerance = 1e-6) # u(mass GCV)
expect_equal(res$Hvg, 38.410611, tolerance = 1e-6) # real-gas vol. GCV
expect_equal(res$u_Hvg, 0.026267, tolerance = 1e-6) # u(vol. GCV)
})
################################################################################
# Example 2 (Annex D.3): mixture with water vapour, 15.55/15.55 °C
# Known mismatch vs. standard for Z: -1.78e-5
################################################################################
test_that("Example 2 — 15.55/15.55 °C (water vapour)", {
data("example2", envir = environment())
res <- calculateProperties(example2$fractionArray, example2$uncertaintyArray, example2$correlationMatrix,
combustionTemperature = 15.55,
volumeTemperature = 15.55,
coverage = 1)
expect_equal(res$M, 16.9891697, tolerance = 1e-7)
expect_equal(res$Z, 0.9975690, tolerance = 1e-7) # mismatch -1.78e-5
expect_equal(res$Hcg, 871.443916, tolerance = 1e-7)
expect_equal(res$u_Hcg, 0.522493911, tolerance = 1e-9)
expect_equal(res$Hmg, 51.294085, tolerance = 1e-6)
expect_equal(res$u_Hmg, 0.025938, tolerance = 1e-6)
expect_equal(res$Hvg, 36.874304, tolerance = 1e-3)
expect_equal(res$u_Hvg, 0.022289, tolerance = 1e-6)
})
################################################################################
# Example 3 (Annex D): 11-component mixture, identity matrix, 15/15 °C
################################################################################
test_that("Example 3 — identity matrix, 15/15 °C", {
data("example3", envir = environment())
res <- calculateProperties(example3$fractionArray, example3$uncertaintyArray, example3$correlationMatrix,
combustionTemperature = 15,
volumeTemperature = 15,
coverage = 1)
expect_equal(res$Hvg, 39.73351, tolerance = 1e-5)
expect_equal(res$u_Hvg, 0.026917, tolerance = 1e-6)
expect_equal(res$Hvn, 35.86811, tolerance = 1e-5)
expect_equal(res$u_Hvn, 0.024757, tolerance = 1e-6)
expect_equal(res$D, 0.76462, tolerance = 1e-5)
expect_equal(res$u_D, 0.000586, tolerance = 1e-6)
expect_equal(res$G, 0.62391, tolerance = 1e-5)
expect_equal(res$u_G, 0.000478, tolerance = 1e-6)
expect_equal(res$Wg, 50.30318, tolerance = 1e-5)
expect_equal(res$u_Wg, 0.021588, tolerance = 1e-6)
expect_equal(res$Wn, 45.40954, tolerance = 1e-5)
expect_equal(res$u_Wn, 0.020151, tolerance = 1e-6)
})
################################################################################
# Example 3, identity matrix, 25/0 °C
################################################################################
test_that("Example 3 — identity matrix, 25/0 °C", {
data("example3", envir = environment())
res <- calculateProperties(example3$fractionArray, example3$uncertaintyArray, example3$correlationMatrix,
combustionTemperature = 25,
volumeTemperature = 0,
coverage = 1)
expect_equal(res$Hvg, 41.89360, tolerance = 1e-5)
expect_equal(res$u_Hvg, 0.028425, tolerance = 1e-6)
expect_equal(res$Hvn, 37.85228, tolerance = 1e-5)
expect_equal(res$u_Hvn, 0.026164, tolerance = 1e-6)
expect_equal(res$D, 0.80701, tolerance = 1e-5)
expect_equal(res$u_D, 0.000619, tolerance = 1e-6)
expect_equal(res$G, 0.62411, tolerance = 1e-5)
expect_equal(res$u_G, 0.000479, tolerance = 1e-6)
expect_equal(res$Wg, 53.02930, tolerance = 1e-5)
expect_equal(res$u_Wg, 0.022783, tolerance = 1e-6)
expect_equal(res$Wn, 47.91376, tolerance = 1e-5)
expect_equal(res$u_Wn, 0.021278, tolerance = 1e-6)
})
################################################################################
# Example 3, full correlation matrix, 15/15 °C
#
# NOTE — error in ISO 6976:2016 Annex D:
# The published standard shows uncertainty values for this example that are
# approximately twice the correct standard uncertainties (k = 1). The root
# cause is an error in the normalisation of the composition: the raw GC
# fractions sum to 99.83 mol% (not 100 mol%), and the normalisation Jacobian
# correction was not correctly propagated into the covariance matrix of the
# mol-fractions before uncertainty propagation was applied. The values tested
# below are the correct standard uncertainties (k = 1) as produced by this
# package. (Verified independently against ISO 6976:2016 Annex D.)
################################################################################
test_that("Example 3 — full correlation matrix, 15/15 °C", {
data("example3_ex", envir = environment())
res <- calculateProperties(example3_ex$fractionArray, example3_ex$uncertaintyArray, example3_ex$correlationMatrix,
combustionTemperature = 15,
volumeTemperature = 15)
expect_equal(res$Hvg, 39.73351, tolerance = 1e-5)
expect_equal(res$u_Hvg, 0.016316, tolerance = 1e-6)
expect_equal(res$Hvn, 35.86811, tolerance = 1e-5)
expect_equal(res$u_Hvn, 0.015305, tolerance = 1e-6)
expect_equal(res$D, 0.76462, tolerance = 1e-5)
expect_equal(res$u_D, 0.000277, tolerance = 1e-6)
expect_equal(res$G, 0.62391, tolerance = 1e-5)
expect_equal(res$u_G, 0.000226, tolerance = 1e-6)
expect_equal(res$Wg, 50.30318, tolerance = 1e-5)
expect_equal(res$u_Wg, 0.019823, tolerance = 1e-6)
expect_equal(res$Wn, 45.40954, tolerance = 1e-5)
expect_equal(res$u_Wn, 0.018498, tolerance = 1e-6)
})
################################################################################
# Example 3, full correlation matrix, 25/0 °C
#
# EASTER EGG — ISO 6976:2016 Annex D:
# u(Hvn) = 0.016181 MJ/m³ ≈ φ/100, where φ = 1.6180339887… is the golden
# ratio. Our full-precision value is 0.016180543…, which rounds to 0.016181
# at the precision published in the standard. The coincidence arises from the
# normalisation of the raw 8-component GC composition (sum = 99.83 mol%) via
# factor normalisation: the Jacobian correction introduces specific negative
# inter-component correlations that happen to drive u(Hvn) to within 2 × 10⁻⁶
# of φ/100 at the 25 °C / 0 °C reference condition.
# (Verified independently against ISO 6976:2016 Annex D.)
################################################################################
test_that("Example 3 — full correlation matrix, 25/0 °C", {
data("example3_ex", envir = environment())
res <- calculateProperties(example3_ex$fractionArray, example3_ex$uncertaintyArray, example3_ex$correlationMatrix,
combustionTemperature = 25,
volumeTemperature = 0,
coverage = 1)
expect_equal(res$Hvg, 41.89360, tolerance = 1e-5)
expect_equal(res$u_Hvg, 0.017241, tolerance = 1e-6)
expect_equal(res$Hvn, 37.85228, tolerance = 1e-5)
expect_equal(res$u_Hvn, 0.016181, tolerance = 1e-6)
expect_equal(res$D, 0.80701, tolerance = 1e-5)
expect_equal(res$u_D, 0.000293, tolerance = 1e-6)
expect_equal(res$G, 0.62411, tolerance = 1e-5)
expect_equal(res$u_G, 0.000227, tolerance = 1e-6)
expect_equal(res$Wg, 53.02930, tolerance = 1e-5)
expect_equal(res$u_Wg, 0.020914, tolerance = 1e-6)
expect_equal(res$Wn, 47.91376, tolerance = 1e-5)
expect_equal(res$u_Wn, 0.019528, tolerance = 1e-6)
})
################################################################################
# Ideal-gas relational checks (Example 3, identity matrix, 15/15 °C)
# Verifies internal consistency of the ideal-gas properties.
################################################################################
test_that("Example 3 — ideal-gas property relationships", {
data("example3", envir = environment())
res <- calculateProperties(example3$fractionArray, example3$uncertaintyArray, example3$correlationMatrix,
combustionTemperature = 15,
volumeTemperature = 15,
coverage = 1)
expect_equal(res$G_o, res$M / 28.96546, tolerance = 1e-9) # G_o = M/M_air
expect_equal(res$D_o, res$D * res$Z, tolerance = 1e-6) # D_o = D * Z
expect_equal(res$Hvg_o, res$Hvg * res$Z, tolerance = 1e-6) # Hv_o = Hv * Z
expect_equal(res$Hvn_o, res$Hvn * res$Z, tolerance = 1e-6)
expect_equal(res$Wg_o, res$Hvg_o / sqrt(res$G_o), tolerance = 1e-6)
expect_equal(res$Wn_o, res$Hvn_o / sqrt(res$G_o), tolerance = 1e-6)
})
################################################################################
# Ideal-gas uncertainty checks (Example 1, 15/15 °C)
# u_Hvg_o and u_Hvn_o are not tabulated in ISO 6976:2016 Annex D.
# The standard states Hv = Hv_o / Z, so u(Hv) = u(Hv_o) / Z, giving
# u(Hv_o) = u(Hv) * Z. We verify this structural identity and that the
# values are positive.
################################################################################
test_that("Example 1 — ideal-gas CV uncertainty structural identity", {
data("example1", envir = environment())
res <- calculateProperties(example1$fractionArray, example1$uncertaintyArray,
example1$correlationMatrix,
combustionTemperature = 15, volumeTemperature = 15,
coverage = 1)
expect_equal(res$u_Hvg_o, res$u_Hvg * res$Z, tolerance = 1e-9)
expect_equal(res$u_Hvn_o, res$u_Hvn * res$Z, tolerance = 1e-9)
expect_true(res$u_Hvg_o > 0)
expect_true(res$u_Hvn_o > 0)
})
################################################################################
# NCV sanity checks (Example 1, 15/15 °C)
################################################################################
test_that("Example 1 — NCV values finite, positive, and below GCV", {
data("example1", envir = environment())
res <- calculateProperties(example1$fractionArray, example1$uncertaintyArray, example1$correlationMatrix,
combustionTemperature = 15,
volumeTemperature = 15,
coverage = 1)
expect_true(is.finite(res$Hcn) && res$Hcn > 0)
expect_true(is.finite(res$Hmn) && res$Hmn > 0)
expect_true(is.finite(res$u_Hcn) && res$u_Hcn > 0)
expect_true(is.finite(res$u_Hmn) && res$u_Hmn > 0)
expect_lt(res$Hcn, res$Hcg)
expect_lt(res$Hmn, res$Hmg)
})
################################################################################
# componentIndex / componentName / componentNames
################################################################################
test_that("componentNames() returns length-60 character vector", {
nm <- componentNames()
expect_type(nm, "character")
expect_length(nm, 60)
})
test_that("componentIndex returns correct indices for boundary components", {
expect_equal(componentIndex("methane"), 1L)
expect_equal(componentIndex("ethane"), 2L)
expect_equal(componentIndex("nitrogen"), 52L)
expect_equal(componentIndex("carbon dioxide"), 54L)
expect_equal(componentIndex("n-pentadecane"), 60L)
})
test_that("componentName returns correct names for boundary indices", {
expect_equal(componentName(1L), "methane")
expect_equal(componentName(52L), "nitrogen")
expect_equal(componentName(54L), "carbon dioxide")
expect_equal(componentName(60L), "n-pentadecane")
})
test_that("componentIndex / componentName round-trip", {
for (i in c(1L, 10L, 30L, 54L, 60L)) {
expect_equal(componentIndex(componentName(i)), i)
}
})
test_that("componentIndex errors on unknown name", {
expect_error(componentIndex("unobtainium"), "Unknown component")
})
test_that("componentName errors on out-of-range index", {
expect_error(componentName(0L), "index must be between 1 and 60")
expect_error(componentName(61L), "index must be between 1 and 60")
})
################################################################################
# GasComponents R6 class — construction and defaults
################################################################################
test_that("GasComponents initialises with zeros and identity matrix", {
gc <- GasComponents$new()
expect_equal(gc$fractions, numeric(60))
expect_equal(gc$uncertainties, numeric(60))
expect_equal(gc$correlations, diag(60))
})
################################################################################
# GasComponents — single-component getters/setters by index and by name
################################################################################
test_that("setFraction / getFraction work by index and by name", {
gc <- GasComponents$new()
gc$setFraction(1L, 0.9)
expect_equal(gc$getFraction(1L), 0.9)
expect_equal(gc$getFraction("methane"), 0.9)
gc$setFraction("nitrogen", 0.05)
expect_equal(gc$getFraction(52L), 0.05)
expect_equal(gc$getFraction("nitrogen"), 0.05)
})
test_that("setUncertainty / getUncertainty work by index and by name", {
gc <- GasComponents$new()
gc$setUncertainty(1L, 0.001)
expect_equal(gc$getUncertainty(1L), 0.001)
expect_equal(gc$getUncertainty("methane"), 0.001)
gc$setUncertainty("carbon dioxide", 0.0005)
expect_equal(gc$getUncertainty(54L), 0.0005)
})
test_that("setCorrelation / getCorrelation are symmetric", {
gc <- GasComponents$new()
gc$setCorrelation(1L, 2L, 0.3)
expect_equal(gc$getCorrelation(1L, 2L), 0.3)
expect_equal(gc$getCorrelation(2L, 1L), 0.3) # symmetry
expect_equal(gc$correlations[1, 2], 0.3)
expect_equal(gc$correlations[2, 1], 0.3)
})
################################################################################
# GasComponents — array setters
################################################################################
test_that("setFractionArray accepts length-60 vector", {
gc <- GasComponents$new()
x <- rep(0, 60)
x[1] <- 0.85
x[52] <- 0.15
gc$setFractionArray(x)
expect_equal(gc$fractions, x)
})
test_that("setUncertaintyArray accepts length-60 vector", {
gc <- GasComponents$new()
u <- rep(0.001, 60)
gc$setUncertaintyArray(u)
expect_equal(gc$uncertainties, u)
})
test_that("setCorrelationMatrix accepts valid 60x60 matrix", {
gc <- GasComponents$new()
r <- diag(60)
r[1, 2] <- r[2, 1] <- -0.5
gc$setCorrelationMatrix(r)
expect_equal(gc$correlations[1, 2], -0.5)
expect_equal(gc$correlations[2, 1], -0.5)
})
################################################################################
# GasComponents — input validation errors
################################################################################
test_that("setFractionArray rejects wrong-length input", {
gc <- GasComponents$new()
expect_error(gc$setFractionArray(numeric(59)), "length 60")
expect_error(gc$setFractionArray(numeric(61)), "length 60")
})
test_that("setUncertaintyArray rejects wrong-length input", {
gc <- GasComponents$new()
expect_error(gc$setUncertaintyArray(numeric(1)), "length 60")
})
test_that("setCorrelationMatrix rejects non-matrix and wrong-size inputs", {
gc <- GasComponents$new()
expect_error(gc$setCorrelationMatrix(numeric(3600)), "60x60 matrix")
expect_error(gc$setCorrelationMatrix(matrix(0, 59, 60)), "60x60 matrix")
})
test_that("setCorrelationMatrix rejects out-of-range coefficients", {
gc <- GasComponents$new()
bad <- diag(60)
bad[1, 2] <- 1.1
expect_error(gc$setCorrelationMatrix(bad), "\\[-1, 1\\]")
})
test_that(".resolve errors on index out of range", {
gc <- GasComponents$new()
expect_error(gc$getFraction(0L), "between 1 and 60")
expect_error(gc$getFraction(61L), "between 1 and 60")
})
test_that(".resolve errors on unknown name", {
gc <- GasComponents$new()
expect_error(gc$getFraction("unobtainium"), "Unknown component")
})
################################################################################
# calculateProperties() — input validation
################################################################################
test_that("calculateProperties errors on wrong-length compositionArray", {
expect_error(
calculateProperties(numeric(59), numeric(60), diag(60)),
"length 60"
)
})
test_that("calculateProperties errors on wrong-length uncertaintyArray", {
expect_error(
calculateProperties(numeric(60), numeric(61), diag(60)),
"length 60"
)
})
test_that("calculateProperties errors on non-matrix correlationMatrix", {
expect_error(
calculateProperties(numeric(60), numeric(60), numeric(3600)),
"60x60 matrix"
)
})
test_that("calculateProperties errors on wrong-size correlationMatrix", {
expect_error(
calculateProperties(numeric(60), numeric(60), matrix(0, 59, 60)),
"60x60 matrix"
)
})
test_that("calculateProperties errors on invalid combustionTemperature", {
expect_error(
calculateProperties(numeric(60), numeric(60), diag(60),
combustionTemperature = 30),
"combustionTemperature"
)
})
test_that("calculateProperties errors on invalid volumeTemperature", {
expect_error(
calculateProperties(numeric(60), numeric(60), diag(60),
volumeTemperature = 10),
"volumeTemperature"
)
})
test_that("calculateProperties errors on out-of-range pressure", {
expect_error(
calculateProperties(numeric(60), numeric(60), diag(60), pressure = 50),
"pressure"
)
expect_error(
calculateProperties(numeric(60), numeric(60), diag(60), pressure = 200),
"pressure"
)
})
################################################################################
# calculateProperties() — coverage factor scaling
################################################################################
test_that("coverage factor k doubles all uncertainty outputs", {
data("example1", envir = environment())
r1 <- calculateProperties(example1$fractionArray, example1$uncertaintyArray, example1$correlationMatrix,
combustionTemperature = 15, volumeTemperature = 15,
coverage = 1)
r2 <- calculateProperties(example1$fractionArray, example1$uncertaintyArray, example1$correlationMatrix,
combustionTemperature = 15, volumeTemperature = 15,
coverage = 2)
u_names <- c("u_G", "u_D", "u_Hcg", "u_Hcn", "u_Hmg", "u_Hmn",
"u_Hvg_o", "u_Hvn_o", "u_Hvg", "u_Hvn", "u_Wg", "u_Wn")
for (nm in u_names) {
expect_equal(r2[[nm]], 2 * r1[[nm]], tolerance = 1e-12,
label = paste0("2 * u (k=1) == u (k=2) for ", nm))
}
})
test_that("coverage factor does not affect non-uncertainty outputs", {
data("example1", envir = environment())
r1 <- calculateProperties(example1$fractionArray, example1$uncertaintyArray, example1$correlationMatrix,
combustionTemperature = 15, volumeTemperature = 15,
coverage = 1)
r5 <- calculateProperties(example1$fractionArray, example1$uncertaintyArray, example1$correlationMatrix,
combustionTemperature = 15, volumeTemperature = 15,
coverage = 5)
det_names <- c("M", "Z", "G_o", "D_o", "G", "D",
"Hcg", "Hcn", "Hmg", "Hmn",
"Hvg_o", "Hvn_o", "Hvg", "Hvn",
"Wg_o", "Wn_o", "Wg", "Wn")
for (nm in det_names) {
expect_equal(r5[[nm]], r1[[nm]], tolerance = 1e-12,
label = paste0(nm, " unchanged by coverage factor"))
}
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.