Black Oil Package
The blackoil package provides black oil model capabilities for reservoir engineering applications, including PVT table handling and flash calculations.
Table of Contents
Overview
Location: neqsim.blackoil
Purpose:
- Black oil PVT modeling
- Generate PVT tables from compositional models
- Black oil flash calculations
- Export to reservoir simulators
Package Structure
blackoil/
├── BlackOilFlash.java # Black oil flash calculator
├── BlackOilFlashResult.java # Flash results container
├── BlackOilPVTTable.java # PVT table storage
├── BlackOilConverter.java # Compositional to black oil conversion
├── SystemBlackOil.java # Black oil system representation
│
└── io/ # I/O utilities
└── BlackOilTableExporter.java
Black Oil Model
Theory
The black oil model describes reservoir fluids using three pseudo-components:
- Oil (stock tank oil)
- Gas (separator gas)
- Water
Key Properties
| Property | Symbol | Description |
|---|---|---|
| Solution GOR | Rs | Gas dissolved in oil (Sm³/Sm³) |
| Oil FVF | Bo | Oil formation volume factor |
| Gas FVF | Bg | Gas formation volume factor |
| Water FVF | Bw | Water formation volume factor |
| Oil-in-Gas ratio | Rv | Oil vaporized in gas (Sm³/Sm³) |
| Oil viscosity | μo | Dynamic viscosity of oil |
| Gas viscosity | μg | Dynamic viscosity of gas |
| Water viscosity | μw | Dynamic viscosity of water |
Correlations
Standing Correlation for Rs
\[R_s = \gamma_g \left( \frac{P}{18.2} \cdot 10^{0.0125 \cdot API - 0.00091 \cdot T} \right)^{1.2048}\]Vasquez-Beggs for Bo
\[B_o = 1 + C_1 R_s + C_2 (T - 60) \left( \frac{API}{\gamma_{g,100}} \right) + C_3 R_s (T - 60) \left( \frac{API}{\gamma_{g,100}} \right)\]PVT Tables
BlackOilPVTTable
import neqsim.blackoil.BlackOilPVTTable;
// Create PVT table
BlackOilPVTTable pvtTable = new BlackOilPVTTable();
// Set pressure points
double[] pressures = {50, 100, 150, 200, 250, 300};
pvtTable.setPressures(pressures);
// Set properties at each pressure
pvtTable.setRs(new double[]{80, 100, 120, 140, 160, 180});
pvtTable.setBo(new double[]{1.25, 1.30, 1.35, 1.40, 1.45, 1.50});
pvtTable.setBg(new double[]{0.010, 0.008, 0.006, 0.005, 0.004, 0.003});
pvtTable.setMuO(new double[]{1.5, 1.2, 1.0, 0.9, 0.8, 0.7});
pvtTable.setMuG(new double[]{0.015, 0.016, 0.017, 0.018, 0.019, 0.020});
Interpolation
// Get properties at any pressure
double P = 175.0; // bar
double Rs = pvtTable.Rs(P);
double Bo = pvtTable.Bo(P);
double Bg = pvtTable.Bg(P);
double muO = pvtTable.mu_o(P);
double muG = pvtTable.mu_g(P);
BlackOilFlash
Flash Calculator
import neqsim.blackoil.BlackOilFlash;
import neqsim.blackoil.BlackOilFlashResult;
// Create flash calculator
double rho_o_sc = 850.0; // Oil density at SC, kg/m³
double rho_g_sc = 0.85; // Gas density at SC, kg/m³
double rho_w_sc = 1000.0; // Water density at SC, kg/m³
BlackOilFlash flash = new BlackOilFlash(pvtTable, rho_o_sc, rho_g_sc, rho_w_sc);
// Perform flash at reservoir conditions
double P = 200.0; // bar
double T = 373.15; // K (not used in simple model)
double Otot_std = 1000.0; // Stock tank oil, Sm³
double Gtot_std = 150000.0; // Total gas, Sm³
double W_std = 500.0; // Water, Sm³
BlackOilFlashResult result = flash.flash(P, T, Otot_std, Gtot_std, W_std);
Flash Results
// Phase volumes at reservoir conditions
double V_oil = result.V_o; // Oil volume, m³
double V_gas = result.V_g; // Gas volume, m³
double V_water = result.V_w; // Water volume, m³
// Phase properties
double rho_oil = result.rho_o; // Oil density, kg/m³
double rho_gas = result.rho_g; // Gas density, kg/m³
double rho_water = result.rho_w; // Water density, kg/m³
double mu_oil = result.mu_o; // Oil viscosity, cP
double mu_gas = result.mu_g; // Gas viscosity, cP
double mu_water = result.mu_w; // Water viscosity, cP
// PVT properties used
double Rs = result.Rs; // Solution GOR
double Bo = result.Bo; // Oil FVF
double Bg = result.Bg; // Gas FVF
double Bw = result.Bw; // Water FVF
Compositional to Black Oil Conversion
BlackOilConverter
Generate black oil tables from compositional EoS model.
import neqsim.blackoil.BlackOilConverter;
// Create compositional oil
SystemInterface oil = new SystemPrEos(373.15, 300.0);
oil.addComponent("nitrogen", 0.5);
oil.addComponent("CO2", 2.0);
oil.addComponent("methane", 35.0);
oil.addComponent("ethane", 8.0);
oil.addComponent("propane", 5.0);
oil.addComponent("n-butane", 3.0);
oil.addComponent("n-pentane", 2.5);
oil.addComponent("n-hexane", 3.0);
oil.addTBPfraction("C7+", 41.0, 220.0/1000.0, 0.85);
oil.setMixingRule("classic");
oil.useVolumeCorrection(true);
// Convert to black oil
BlackOilConverter converter = new BlackOilConverter(oil);
converter.setTemperature(373.15, "K");
// Define separator conditions
converter.setSeparatorTemperature(288.15, "K");
converter.setSeparatorPressure(1.01325, "bara");
// Generate table
double[] pressures = {1, 50, 100, 150, 200, 250, 300};
converter.setPressures(pressures, "bara");
converter.run();
// Get black oil table
BlackOilPVTTable boTable = converter.getBlackOilTable();
Export to Simulators
Eclipse Format
import neqsim.blackoil.io.BlackOilTableExporter;
BlackOilTableExporter exporter = new BlackOilTableExporter(boTable);
exporter.setFormat("ECLIPSE");
exporter.exportToFile("PVTO.inc");
Example PVTO Output
PVTO
-- Rs P Bo viscosity
50.0 50.0 1.250 1.50
100.0 1.248 1.55
150.0 1.246 1.60 /
100.0 100.0 1.350 1.20
150.0 1.347 1.25
200.0 1.345 1.30 /
/
Complete Example
import neqsim.blackoil.*;
import neqsim.pvtsimulation.simulation.*;
// Step 1: Create compositional model
SystemInterface oil = new SystemPrEos(373.15, 250.0);
oil.addComponent("nitrogen", 0.3);
oil.addComponent("CO2", 1.5);
oil.addComponent("methane", 40.0);
oil.addComponent("ethane", 7.0);
oil.addComponent("propane", 4.5);
oil.addComponent("i-butane", 1.0);
oil.addComponent("n-butane", 2.5);
oil.addComponent("i-pentane", 1.2);
oil.addComponent("n-pentane", 1.8);
oil.addComponent("n-hexane", 2.5);
oil.addTBPfraction("C7-C10", 15.0, 120.0/1000.0, 0.78);
oil.addTBPfraction("C11-C15", 10.0, 180.0/1000.0, 0.82);
oil.addTBPfraction("C16+", 12.7, 350.0/1000.0, 0.90);
oil.setMixingRule("classic");
oil.useVolumeCorrection(true);
// Step 2: Run differential liberation
DifferentialLiberation dl = new DifferentialLiberation(oil);
dl.setTemperature(373.15, "K");
double[] pressures = {250, 200, 150, 100, 75, 50, 25, 1.01325};
dl.setPressures(pressures, "bara");
dl.run();
// Step 3: Create black oil table
BlackOilPVTTable boTable = new BlackOilPVTTable();
boTable.setPressures(pressures);
boTable.setRs(dl.getRs());
boTable.setBo(dl.getBo());
boTable.setMuO(dl.getOilViscosity());
// Add gas properties
boTable.setBg(dl.getBg());
boTable.setMuG(dl.getGasViscosity());
// Step 4: Separator test for stock tank conditions
SeparatorTest sep = new SeparatorTest(oil.clone());
sep.setSeparatorConditions(
new double[]{323.15, 288.15},
new double[]{30.0, 1.01325}
);
sep.run();
double rho_o_sc = sep.getOilDensity();
// Step 5: Create flash calculator
BlackOilFlash boFlash = new BlackOilFlash(boTable, rho_o_sc, 0.85, 1000.0);
// Step 6: Calculate at different conditions
System.out.println("P (bar)\tRs\tBo\tρ_oil\tμ_oil");
for (double P : new double[]{50, 100, 150, 200}) {
BlackOilFlashResult r = boFlash.flash(P, 373.15, 1000.0, 150000.0, 0.0);
System.out.printf("%.0f\t%.1f\t%.4f\t%.1f\t%.3f%n",
P, r.Rs, r.Bo, r.rho_o, r.mu_o);
}
Best Practices
- Validate against compositional - Compare black oil results with full EoS
- Use appropriate correlations - Match fluid type (light, medium, heavy oil)
- Check consistency - Ensure Rs and Bo are consistent at bubble point
- Include undersaturated region - Extend table above bubble point
- Document separator conditions - Record conditions used for conversion
Limitations
- Temperature dependence not fully captured
- Compositional grading not modeled
- Gas condensate requires extended model (Rv)
- Near-critical fluids may need compositional treatment
Related Documentation
- PVT Simulation - Laboratory experiments
- PVT Workflow - End-to-end workflow
- Black Oil PVT Export - Export details