NeqSim’s Standard_ISO15403 class calculates a motor octane number (MON) and a
methane-number result for compressed-natural-gas compositions. The class is a
calculation helper; it does not perform a complete conformity assessment against
ISO 15403-1:2006.
Implemented correlation
The current implementation evaluates
\[MON=137.78x_{CH_4}+29.948x_{C_2H_6}-18.193x_{C_3H_8}-167.062(x_{nC_4}+x_{iC_4})+181.233x_{CO_2}+26.944x_{N_2}\]and then
\[NM=1.445MON-103.42\]where each $x_i$ is the overall mole fraction stored by the thermodynamic
system. Call calculate() before reading a result. The supported result keys
are "MON" and "NM"; the usual methane-number abbreviation is not an
accepted getter key.
The six terms above are the complete component coverage of the current class. Hydrogen, C5+ hydrocarbons, and other unlisted components contribute zero to the implemented sum, so mixtures containing material amounts of those components require a method whose validity range covers them.
Pure methane is a useful implementation anchor, not a definition of the methane-number scale: this correlation returns MON = 137.78 and NM = 95.6721. A hydrogen-only system would produce NM = -103.42 because hydrogen has no term; that extrapolation is outside the implemented component coverage and must not be interpreted as a hydrogen-fuel rating.
Complete Java example
This example keeps every case on the same one-mole composition basis. The sensitivity cases replace two mole percentage points of methane with either carbon dioxide or nitrogen instead of adding material to an existing system.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import neqsim.standards.gasquality.Standard_ISO15403;
import neqsim.thermo.system.SystemInterface;
import neqsim.thermo.system.SystemSrkEos;
public final class Iso15403Example {
private static final Logger logger = LogManager.getLogger(Iso15403Example.class);
private Iso15403Example() {}
public static void main(String[] args) {
Standard_ISO15403 base = new Standard_ISO15403(createCng(0.92, 0.01, 0.01));
base.calculate();
double baseMon = base.getValue("MON");
double baseNm = base.getValue("NM");
Standard_ISO15403 carbonDioxideCase =
new Standard_ISO15403(createCng(0.90, 0.03, 0.01));
carbonDioxideCase.calculate();
double carbonDioxideNm = carbonDioxideCase.getValue("NM");
Standard_ISO15403 nitrogenCase =
new Standard_ISO15403(createCng(0.90, 0.01, 0.03));
nitrogenCase.calculate();
double nitrogenNm = nitrogenCase.getValue("NM");
if (!Double.isFinite(baseMon) || !Double.isFinite(baseNm)) {
throw new IllegalStateException("ISO 15403 correlation returned a non-finite result");
}
if (!(carbonDioxideNm > baseNm && nitrogenNm < baseNm)) {
throw new IllegalStateException("Unexpected composition-sensitivity result");
}
logger.info("Base MON={}, base NM={}", baseMon, baseNm);
logger.info("NM after replacing methane with CO2={}", carbonDioxideNm);
logger.info("NM after replacing methane with N2={}", nitrogenNm);
}
private static SystemInterface createCng(
double methane, double carbonDioxide, double nitrogen) {
SystemInterface gas = new SystemSrkEos(288.15, 200.0);
gas.addComponent("methane", methane);
gas.addComponent("ethane", 0.04);
gas.addComponent("propane", 0.01);
gas.addComponent("n-butane", 0.005);
gas.addComponent("i-butane", 0.005);
gas.addComponent("CO2", carbonDioxide);
gas.addComponent("nitrogen", nitrogen);
gas.init(0);
return gas;
}
}
For these three normalized compositions, the current source correlation gives:
| Case | MON | NM | Engineering interpretation |
|---|---|---|---|
| Base composition | 128.18474 | 81.8069493 | Reference case |
| Replace 2 mol% methane with CO2 | 129.05380 | 83.0627410 | Increases this correlation result |
| Replace 2 mol% methane with N2 | 125.96802 | 78.6037889 | Decreases this correlation result |
These trends are properties of the implemented coefficients and the stated replacement experiment. They are not universal claims about engine knock or arbitrary dilution paths.
API and engineering boundaries
| API | Current behavior |
|---|---|
new Standard_ISO15403(system) |
Uses the system’s overall composition |
calculate() |
Updates the stored MON and NM results |
getValue("MON") |
Returns the dimensionless motor octane number |
getValue("NM") |
Returns the dimensionless methane-number result |
getUnit(...) |
Returns an empty string |
isOnSpec() |
Always returns true; no acceptance limits are evaluated |
Do not use isOnSpec() as evidence that a fuel complies with ISO 15403, a
national fuel specification, or an engine manufacturer’s limits. A conformity
assessment also needs the applicable standard edition, sampling and analysis
requirements, validated composition range, contractual limits, and any other
required fuel properties.