Best for
- USE WHEN: writing Java or Python code that uses NeqSim for thermodynamic calculations, process simulation, or property retrieval.
equinor/neqsim/.github/skills/neqsim-api-patterns/SKILL.md
NeqSim API patterns and code recipes. USE WHEN: writing Java or Python code that uses NeqSim for thermodynamic calculations, process simulation, or property retrieval. Covers EOS selection, fluid creation, flash calculations, property access, equipment patterns, and unit conventions.
Decision brief
Copy-paste reference for common NeqSim operations. All Java code must be Java 8 compatible.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/equinor/neqsim --skill ".github/skills/neqsim-api-patterns"Inspect the Agent Skill "neqsim-api-patterns" from https://github.com/equinor/neqsim/blob/9e8d44a141bba600026d2229969b49af50f34237/.github/skills/neqsim-api-patterns/SKILL.md at commit 9e8d44a141bba600026d2229969b49af50f34237. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
from neqsim import jneqsim EclipseFluidReadWrite = jneqsim.thermo.util.readwrite.EclipseFluidReadWrite fluid = EclipseFluidReadWrite.read("path/to/fluid.e300")
Separator class ↔ orientation (affects gas-capacity results):
For large process plants (platforms, refineries, gas plants), split the model into separate ProcessSystem objects per process area, then combine them into a single ProcessModel. NEVER try to add a ProcessModule or ProcessSystem to another ProcessSystem — use ProcessModel as the…
Review the “Setup and Discovery” section in the pinned source before continuing.
For phase-envelope generation, plotting, physical branch classification, zero/trace-component handling, or Michelsen solver changes, load neqsim-phase-envelope. This section is the compact API reference; the dedicated skill owns the end-to-end workflow and regression rules.
Permission review
The documentation asks the agent to read local files, directories, or repositories.
// Load fluid from E300 file (returns SystemInterface with PR-EOS)The documentation asks the agent to read local files, directories, or repositories.
| Save/load model | `saveToNeqsim("file.neqsim")`, `loadFromNeqsim("file.neqsim")` |The documentation asks the agent to create, modify, or delete local files.
| Save/load model | `saveToNeqsim("file.neqsim")`, `loadFromNeqsim("file.neqsim")` |Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 92/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 136 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Copy-paste reference for common NeqSim operations. All Java code must be Java 8 compatible.
| Fluid Type | Java Class | Mixing Rule |
|---|---|---|
| Dry/lean gas, simple HC | SystemSrkEos | "classic" |
| General hydrocarbons, oil | SystemPrEos | "classic" |
| Matched to commercial simulator PR-LK | SystemPrLeeKeslerEos | "classic" |
| Water, MEG, methanol, polar | SystemSrkCPAstatoil | 10 (numeric) |
| Custody transfer, fiscal metering | SystemGERG2008Eos | (none needed) |
| Electrolyte systems, hydrate with salt brine | SystemElectrolyteCPAstatoil | 10 |
| Volume-corrected SRK | SystemSrkEosvolcor | "classic" |
PR-LK vs PR78: SystemPrLeeKeslerEos uses PR76 alpha for ALL ω:
m = 0.37464 + 1.54226ω − 0.26992ω². Standard SystemPrEos1978 uses a modified
cubic for ω > 0.49. Use PR-LK when matching commercial simulator models that use
this EOS label.
// 1. Create: temperature in KELVIN, pressure in bara
SystemInterface fluid = new SystemSrkEos(273.15 + 25.0, 60.0);
// 2. Add components (name, mole fraction)
fluid.addComponent("methane", 0.85);
fluid.addComponent("ethane", 0.10);
fluid.addComponent("propane", 0.05);
// 3. MANDATORY: set mixing rule — NEVER skip
fluid.setMixingRule("classic");
// 4. Optional: multi-phase check for water/heavy systems
fluid.setMultiPhaseCheck(true);
fluid.addTBPfraction("C7", 0.05, 92.0 / 1000, 0.727); // name, moleFrac, MW_kg/mol, density
fluid.addTBPfraction("C8", 0.04, 104.0 / 1000, 0.749);
fluid.addPlusFraction("C20+", 0.02, 350.0 / 1000, 0.88);
fluid.getCharacterization().getLumpingModel().setNumberOfLumpedComponents(6);
fluid.getCharacterization().characterisePlusFraction();
NeqSim can read Eclipse E300-format fluid files with full component properties and binary interaction parameters:
// Load fluid from E300 file (returns SystemInterface with PR-EOS)
SystemInterface fluid = EclipseFluidReadWrite.read("path/to/fluid.e300");
// Returns a PR-EOS fluid with all components, properties, and BIPs set
Required E300 sections: CNAMES, TCRIT, PCRIT, ACF, MW, TBOIL,
VCRIT, PARACHOR, SSHIFT, BIC, ZI.
Optional E300 sections (NeqSim parses and applies these):
OMEGAA / OMEGAB — per-component OmegaA/B overrides (applied after init(0))BICS — surface-condition BICs (parsed, same lower-triangular format as BIC)SSHIFTS — surface-condition volume shiftPEDERSEN — activates Pedersen viscosity modelEOS keyword determines fluid class:
EOS\nSRK / → SystemSrkEosEOS\nPR /\nPRCORR → SystemPrEos1978EOS\nPR /\nPRLKCORR → SystemPrLeeKeslerEos ← use for PR-LK matchingEOS\nPR / → SystemPrEosCRITICAL: The BIC section must ALWAYS be present. If omitted, NeqSim
defaults to zero BIPs (no crash, but results may differ significantly from the
source simulator). The PARACHOR section is also required — estimate unknown
values with 4.0 * MW^0.77.
Component name mapping: C1→methane, C2→ethane, C3→propane,
iC4→i-butane, C4→n-butane, iC5→i-pentane, C5→n-pentane,
C6→n-hexane, N2→nitrogen, CO2→CO2, H2O→water. All other names are
treated as TBP pseudo-fractions via addTBPfraction() — including aromatics
(Benzene, Toluene, etc.).
# Python usage — auto-detects EOS from file
from neqsim import jneqsim
EclipseFluidReadWrite = jneqsim.thermo.util.readwrite.EclipseFluidReadWrite
fluid = EclipseFluidReadWrite.read("path/to/fluid.e300")
# Force a specific EOS regardless of what's in the file
SystemPrLeeKeslerEos = jneqsim.thermo.system.SystemPrLeeKeslerEos
target_fluid = SystemPrLeeKeslerEos(288.15, 1.01325)
fluid = EclipseFluidReadWrite.read("path/to/fluid.e300", target_fluid)
JSON process builder also supports PR-LK via "model": "PR_LK":
{ "fluid": { "model": "PR_LK", "temperature": 288.15, "pressure": 50.0, ... } }
ThermodynamicOperations ops = new ThermodynamicOperations(fluid);
ops.TPflash();
// CRITICAL: call initProperties() AFTER flash, BEFORE reading properties
// init(3) alone does NOT initialize transport properties — they return ZERO
fluid.initProperties();
// Bulk properties
double density = fluid.getDensity("kg/m3");
double molarMass = fluid.getMolarMass("kg/mol");
double Z = fluid.getZ();
// Phase properties
double gasDensity = fluid.getPhase("gas").getDensity("kg/m3");
double gasViscosity = fluid.getPhase("gas").getViscosity("kg/msec");
double gasThermalCond = fluid.getPhase("gas").getThermalConductivity("W/mK");
double gasCp = fluid.getPhase("gas").getCp("J/kgK");
// Phase checks
int numPhases = fluid.getNumberOfPhases();
boolean hasGas = fluid.hasPhaseType("gas");
ops.PHflash(enthalpy); // Pressure-Enthalpy
ops.PSflash(entropy); // Pressure-Entropy
ops.dewPointTemperatureFlash(); // Dew point temperature
ops.bubblePointPressureFlash(); // Bubble point pressure
ops.hydrateFormationTemperature(); // Hydrate T at given P
ops.calcPTphaseEnvelope(); // Phase envelope
| Quantity | Constructor default | Setter pattern |
|---|---|---|
| Temperature | Kelvin | setTemperature(25.0, "C") |
| Pressure | bara | setPressure(50.0, "bara") |
| Flow rate | — | setFlowRate(50000.0, "kg/hr") |
| Getting temp | Returns Kelvin | getTemperature() - 273.15 for °C |
Stream feed = new Stream("feed", fluid);
feed.setFlowRate(100.0, "kg/hr");
feed.setPressure(50.0, "bara");
feed.setTemperature(30.0, "C");
Separator sep = new Separator("HP Sep", feedStream);
Stream gasOut = sep.getGasOutStream();
Stream liqOut = sep.getLiquidOutStream();
Separator class ↔ orientation (affects gas-capacity results):
| Class | Default orientation | Use for |
|---|---|---|
Separator, ThreePhaseSeparator | horizontal | horizontal separators (VA-tag) |
GasScrubber, GasScrubberSimple, NeqGasScrubber (2-phase) | vertical | vertical scrubbers (VG-tag) |
ThreePhaseGasScrubber (3-phase) | vertical | vertical 3-phase scrubbers |
A horizontal vessel derates the gas area by the design liquid level (default 80% →
gas area (1−0.8)=0.2×), so using a horizontal Separator/ThreePhaseSeparator
for a physically vertical scrubber over-reads getGasLoadFactor() /
getGasSuperficialVelocity() by ~5×. Prefer the *GasScrubber classes for vertical
scrubbers, or override with sep.setOrientation("vertical"). setInternalDiameter()
propagates correctly through run() — the trap is orientation, not diameter.
Physical dimensions, internals, and design parameters are configured through
SeparatorMechanicalDesign — NOT directly on Separator. The Separator
class handles process simulation (flash, entrainment); SeparatorMechanicalDesign
owns the physical vessel design.
// After process.run():
sep.initMechanicalDesign();
SeparatorMechanicalDesign design =
(SeparatorMechanicalDesign) sep.getMechanicalDesign();
// Design envelope
design.setMaxOperationPressure(85.0); // bara
design.setMaxOperationTemperature(273.15 + 80); // K
// Vessel sizing parameters (configured via MechanicalDesign)
design.setGasLoadFactor(0.107); // K-factor [m/s]
design.setRetentionTime(120.0); // Liquid retention [s]
design.setFg(0.5); // Gas area fraction
// Nozzle diameters (set via MechanicalDesign, NOT on Separator)
design.setInletNozzleID(0.254); // 10-inch inlet nozzle [m]
design.setGasOutletNozzleID(0.20); // Gas outlet [m]
design.setOilOutletNozzleID(0.15); // Oil outlet [m]
// Demister/mist eliminator parameters
design.setDemisterType("wire_mesh"); // "wire_mesh", "vane_pack", "cyclone"
design.setDemisterPressureDrop(1.5); // [mbar]
design.setDemisterThickness(150.0); // [mm]
design.setFoamAllowanceFactor(1.0); // 1.0 = no foam
// Bridge methods — entrainment internals (delegate to Separator)
design.setInletPipeDiameter(0.254); // Inlet pipe ID for DSD generation [m]
design.setInletDeviceType(InletDeviceModel.InletDeviceType.INLET_VANE);
design.setGasLiquidSurfaceTension(0.020); // Interfacial tension [N/m]
design.addSeparatorSection("Demister", "meshpad");
// Bridge methods — dynamic internals (delegate to Separator)
design.setWeirHeightAbsolute(0.30); // Weir height [m] (syncs weirFraction)
design.setWeirLength(1.5); // Weir crest length [m]
design.setBootVolume(2.0); // Boot/sump volume [m3]
design.setMistEliminatorDpCoeff(150.0); // Euler number for dP calc
design.setMistEliminatorThickness(0.15); // Demister pad thickness [m]
// Run design calculation
design.readDesignSpecifications();
design.calcDesign();
String report = design.toJson();
// Results: design.getInnerDiameter(), design.getTantanLength(),
// design.getWallThickness(), design.getInletNozzleID(), etc.
Imperfect separation is modelled with setEntrainment() on the Separator /
ThreePhaseSeparator itself (not the mechanical design). It transfers a fraction
of one phase into another outlet stream.
// setEntrainment(double val, String specType, String specifiedStream,
// String phaseFrom, String phaseTo)
// specType : "mole" | "mass" | "volume"
// specifiedStream : "feed" (fraction of feed) | "product" (fraction of receiving outlet)
// phaseFrom/To : "gas" | "oil" | "aqueous" (base Separator also accepts "liquid")
ThreePhaseSeparator sep = new ThreePhaseSeparator("1st Stage", feed);
// Liquid carry-over into gas (feed basis)
sep.setEntrainment(0.001, "mole", "feed", "oil", "gas"); // oil-in-gas
sep.setEntrainment(0.001, "mole", "feed", "aqueous", "gas"); // water-in-gas
// Cross-contamination expressed on the receiving product stream
sep.setEntrainment(0.005, "mass", "product", "aqueous", "oil"); // 0.5 mass% BS&W in oil
sep.setEntrainment(500e-6, "mass", "product", "oil", "aqueous"); // 500 ppm oil-in-water
sep.run();
Separator supports 3 paths: oil→gas, aqueous→gas, gas→liquid.ThreePhaseSeparator supports all 6 paths: oil→gas, aqueous→gas,
gas→oil, gas→aqueous, oil→aqueous, aqueous→oil.specifiedStream="product", val is clamped: ≤0 transfers nothing,
≥1 transfers the entire source phase.Typical screening values (indicative only — always defer to the project
separation spec / datasheet; for rigorous physics use the enhanced entrainment
model and SeparatorMechanicalDesign):
| Carry-over path | Typical range | Basis | Notes |
|---|---|---|---|
| Liquid-in-gas (oil or water → gas) | 0.01 – 0.5 % | mole/mass, feed | Well-designed mist extractor; tighter (<0.01%) with high-efficiency internals |
| Gas carry-under (gas → liquid) | 0.1 – 2 % | mole, feed | Higher with foaming / short retention |
| Water-in-oil (BS&W, aqueous → oil) | 0.5 – 5 vol% | volume, product | Export crude spec often ≤ 0.5 vol%; inter-stage higher |
| Oil-in-water (oil → aqueous) | 100 – 1000 ppm | mass, product | Produced-water inlet; overboard discharge typically ≤ 30 ppm (OSPAR) |
SeparatorMechanicalDesign.calculateSeparationEfficiency() returns a
SeparatorEfficiencyReport that combines the physics-based entrainment /
carry-under fractions with a per-internal Souders-Brown K-factor operating
window check (from the internals database MinKFactor/MaxKFactor). It answers
"is this mist mat / vane pack / cyclone inside its good performance band, below
turndown, or into flooding?" and works for two-phase AND three-phase separators
and gas scrubbers (GasScrubberMechanicalDesign inherits it).
It is read-only — it does not change what run() does. Whether the physics
entrainment model is applied at run time is a separate opt-in toggle
(setEfficiencyModelEnabled). Default behaviour (no entrainment, or manual
setEntrainment(...)) is unchanged.
sep.run(); // flash
SeparatorMechanicalDesign design =
(SeparatorMechanicalDesign) sep.getMechanicalDesign();
design.calcDesign();
design.setDesign(); // push sized diameter to the separator
// Optional: pick a specific database sub-type for the mist mat
design.setDemisterType("wire_mesh"); // "wire_mesh" | "vane_pack" | "cyclone"
design.setDemisterSubType("High Efficiency"); // sub-type from SeparatorInternals.csv
// Read-only assessment (2-phase or 3-phase, auto-detected)
SeparatorEfficiencyReport report = design.calculateSeparationEfficiency();
double opK = report.getOperatingKFactor(); // m/s
double effGL = report.getOverallGasLiquidEfficiency(); // 0-1
String verdict = report.getVerdict(); // GOOD_PERFORMANCE | BELOW_TURNDOWN | FLOODING_RISK | MARGINAL_EFFICIENCY
for (InternalOperatingWindow w : report.getWindows()) {
// w.getStatus(): BELOW_MIN_TURNDOWN | IN_RANGE | ABOVE_MAX_FLOODING
// w.getMinKFactor(), w.getMaxKFactor(), w.getUtilization(), w.getTurndownRatio()
}
String json = report.toJson(); // full report incl. per-internal windows
// Apply the physics entrainment/carry-under model during run() (opt-in):
design.setEfficiencyModelEnabled(true); // delegates to setDetailedEntrainmentCalculation(true)
sep.run(); // gas/liquid outlets now reflect computed carry-over
design.setEfficiencyModelEnabled(false); // back to no-entrainment / manual setEntrainment
K-factor window meaning (limits from SeparatorInternals.csv):
K < Kmin → below turndown (poor coalescence, droplets slip through);
Kmin ≤ K ≤ Kmax → good performance band; K > Kmax → flooding / re-entrainment.
Compressor comp = new Compressor("Comp", gasStream);
comp.setOutletPressure(120.0);
// comp.setIsentropicEfficiency(0.75);
Stream out = comp.getOutletStream();
// After run: comp.getPower("kW")
A Compressor can hold several performance maps at once via a
CompressorChartLibrary and switch the active chart by name — the professional
way to keep vendor-expected, as-tested and field-fitted curves for the same
machine side by side (revamp studies, digital twins, design-vs-tested checks).
See the Compressor Chart Library doc.
comp.addChart("BCL405B-design", expectedChart);
comp.addChart("BCL405B-tested", asTestedChart,
new CompressorChartMetadata("BCL 405/B", "gas export", "27-KA01",
"8300199-CA-001", CompressorChartMetadata.CurveType.AS_TESTED));
comp.selectChart("BCL405B-tested"); // sets + enables the chart, turns on polytropic calc
comp.run();
List<String> charts = comp.getAvailableCharts(); // ["BCL405B-design", "BCL405B-tested"]
String active = comp.getSelectedChartName(); // "BCL405B-tested"
// Persist / reload a shared vendor-curve database (all curves + metadata):
comp.getChartLibrary().saveToFile("BCL405B_charts.json");
comp.setChartLibrary(CompressorChartLibrary.loadFromFile("BCL405B_charts.json"));
Model deposit (fouling) mass from process thermodynamics, its effect on
performance, where it lands per impeller, the degraded chart after N hours, and
online washing. Package neqsim.process.equipment.compressor. See the
Compressor Deposit and Performance Degradation
doc.
// 1) Deposit mass -> performance effect (combine several mechanisms)
CompressorDeposit dep = CompressorDeposit.fromCompressor(comp); // sizes foulable geometry
dep.addDeposit(DepositMechanism.SULFUR_S8, 1.2); // kg (S8 study)
dep.addDeposit(DepositMechanism.SALT_NACL, 0.4); // kg (salt study)
comp.setDepositModel(dep); // run() now degrades efficiency/power
comp.run();
double effLoss = 1.0 - dep.getEfficiencyMultiplier();
// 2) Deposit mass FROM the process (precipitation bridge)
SolidFlashDepositSource s8 =
new SolidFlashDepositSource(feed, "S8", DepositMechanism.SULFUR_S8, 0.3); // TPSolidflash
EntrainedSaltDepositSource salt =
new EntrainedSaltDepositSource(10.0, 0.05); // 10 kg/hr entrained water, 5 wt% salt
dep.accumulate(s8, 500.0); // deposit after 500 operating hours
dep.accumulate(salt, 500.0);
// 3) Degraded performance chart after N hours (chart-based machines)
CompressorChart chart500 = comp.buildDegradedChart();
// 4) Where deposits form (per impeller). Rigorous = real per-step flashed states:
comp.setPolytropicMethod("detailed");
comp.getPropertyProfile().setActive(true);
comp.run();
List<CompressorDepositProfile.StageDeposit> profile =
CompressorDepositProfile.computeFromPropertyProfile(comp, 5, "S8");
int worst = CompressorDepositProfile.worstStage(profile); // 1 = cold first impeller
// 5) Online washing: recommend fluid, plan rate, simulate removal
WashFluid fluid = CompressorDepositWash.recommend(dep); // salt->WATER, S8->XYLENE
CompressorDepositWash washer = new CompressorDepositWash();
washer.setContactEfficiency(0.7);
double rateKgHr = washer.requiredFluidRateKgHr(dep, fluid, 2.0, 3.0); // remove 2 kg in 3 h
CompressorDepositWash.WashResult r = comp.washOnline(fluid, rateKgHr, 3.0);
comp.run(); // performance recovers
Wash-fluid → deposit matching (screening solubilities): water dissolves salt/scale;
xylene/toluene dissolve S8 and wax; condensate dissolves wax; methanol moderate salt.
recommend() returns the fluid that removes the most mass — for mixed salt+S8 fouling,
wash in sequence (water, then xylene).
Cooler cooler = new Cooler("Cooler", hotStream);
cooler.setOutTemperature(273.15 + 30.0);
Stream out = cooler.getOutletStream();
// After run: cooler.getDuty() — Watts
HeatExchanger has two feed/outlet sides indexed 0 and 1. Use
setFeedStream(int, StreamInterface) to connect both sides and
getOutStream(int) to retrieve the outlet for each side.
IMPORTANT: Do NOT use getOutletStream() when you need a specific
side — it only returns side 0. Always use getOutStream(int).
HeatExchanger hx = new HeatExchanger("E-100");
hx.setFeedStream(0, shellSideFeed); // side 0 = shell
hx.setFeedStream(1, tubeSideFeed); // side 1 = tube
// Optional: hx.setUAvalue(35000.0); // W/K
// After run: retrieve each side's outlet
Stream shellOut = (Stream) hx.getOutStream(0);
Stream tubeOut = (Stream) hx.getOutStream(1);
double duty = hx.getDuty(); // Watts
# Python
hx = HeatExchanger("E-100")
hx.setFeedStream(0, shell_feed)
hx.setFeedStream(1, tube_feed)
# Downstream connections:
cooler = Cooler("C-100", hx.getOutStream(int(0))) # shell side out
valve = ThrottlingValve("VLV-100", hx.getOutStream(int(1))) # tube side out
ThrottlingValve valve = new ThrottlingValve("JT Valve", stream);
valve.setOutletPressure(20.0);
Stream out = valve.getOutletStream();
CRITICAL: Always use ThrottlingValve inside a ProcessSystem for Joule-Thomson
cooling calculations. Manual PHflash() on a cloned fluid gives wrong JT temperatures
(tested: 14.9°C error vs 1.7°C with ThrottlingValve). The valve handles the isenthalpic
enthalpy bookkeeping internally.
# Python — Correct JT expansion pattern
proc = ProcessSystem()
feed = Stream('SG', fluid.clone())
feed.setFlowRate(flow, 'kg/hr')
feed.setTemperature(T_in, 'C')
feed.setPressure(P_in, 'bara')
proc.add(feed)
valve = ThrottlingValve('JT', feed)
valve.setOutletPressure(P_out)
proc.add(valve)
proc.run()
T_jt = float(valve.getOutletStream().getTemperature('C'))
Mixer mixer = new Mixer("Mix");
mixer.addStream(stream1);
mixer.addStream(stream2);
Stream out = mixer.getOutletStream();
Used to model TEG dehydration contactors as simple water-removal units.
Splits a stream per-component: splitFactor[k] = 1.0 keeps the component in
stream 0 (dry gas), 0.0 removes it to stream 1 (water).
TEG dehydration pattern: water is always the last component added,
so use [1.0] * (N-1) + [0.0] to remove only water.
// Java
ComponentSplitter dehydrator = new ComponentSplitter("TEG contactor", wetGasStream);
int nComp = wetGasStream.getFluid().getNumberOfComponents();
double[] sf = new double[nComp];
Arrays.fill(sf, 1.0);
sf[nComp - 1] = 0.0; // last component = water
dehydrator.setSplitFactors(sf);
// After run:
Stream dryGas = dehydrator.getSplitStream(0); // all components except water
Stream water = dehydrator.getSplitStream(1); // removed water
# Python
water_dehydration = neqsim.process.equipment.splitter.ComponentSplitter(
"dehyd", wet_gas_stream)
complen = wet_gas_stream.getFluid().getNumberOfComponents()
water_dehydration.setSplitFactors([1.0] * (complen - 1) + [0.0])
water_dehydration.run()
dry_gas = water_dehydration.getSplitStream(0)
When to use: Any absorber with a glycol-related name ("glyc", "teg", "dehydrat") should be modeled as a ComponentSplitter rather than a DistillationColumn. This avoids solver convergence issues and is the standard pattern for production platform models.
Pump pump = new Pump("P-100", liquidStream);
pump.setOutletPressure(20.0); // bara
pump.setIsentropicEfficiency(0.75); // 0-1
Stream out = pump.getOutletStream();
// After run: pump.getPower("kW")
Three operating modes:
pump.setOutletTemperature(40.0, "C") → back-calculates powerpump.getPumpChart() → head, efficiency, NPSH curvesAdiabaticPipe pipe = new AdiabaticPipe("Pipeline", stream);
pipe.setLength(50000.0); // meters
pipe.setDiameter(0.508); // meters (20 inch)
Stream out = pipe.getOutletStream();
For route pressure-drop tasks based on STID P&IDs, E3D exports, stress
isometrics, or line-list tables, prefer PipingRouteBuilder over manually
creating many pipe units. It creates a serial ProcessSystem with one
PipeBeggsAndBrills unit per segment and stores explicit material connection
metadata.
PipingRouteBuilder route = new PipingRouteBuilder()
.setDefaultPipeWallRoughness(45.0, "micrometer")
.setMinorLossFrictionFactor(0.02)
.addSegment("S1", "Manifold", "Valve Station", 100.0, "m", 0.2, "m")
.setSegmentWallThickness("S1", 8.0, "mm")
.addMinorLoss("S1", "manual valve", 1.0)
.addSegment("S2", "Valve Station", "Compressor Scrubber", 25.0, "m", 8.0, "inch")
.addMinorLoss("Valve Station->Compressor Scrubber", "long-radius bend", 0.3);
ProcessSystem routeProcess = route.build(feedStream);
routeProcess.run();
String routeJson = route.toJson();
To embed the extracted route in a larger flowsheet, add it to the existing
ProcessSystem and use the returned outlet stream as the inlet to downstream
equipment:
ProcessSystem process = new ProcessSystem("Full plant process");
process.add(feedStream);
StreamInterface routeOutlet = route.addToProcessSystem(process, feedStream);
Cooler downstreamCooler = new Cooler("Downstream cooler", routeOutlet);
process.add(downstreamCooler);
process.run();
If the route starts from an upstream equipment outlet, use the overload with
source-equipment metadata: route.addToProcessSystem(process, sep.getGasOutStream(), "HP Sep", "gasOut").
Always preserve source document/page/row references in the task notes and export
route.toJson() in the task results so later STID work can reuse the route.
Recycles enable iterative convergence of process loops. The ProcessSystem
automatically detects and iterates recycles up to 100 times.
// 1. Create placeholder stream with estimated conditions
Stream placeholder = new Stream("recycle estimate", fluidGuess.clone());
placeholder.setFlowRate(estimatedFlow, "kg/hr");
placeholder.setTemperature(estimatedT, "C");
placeholder.setPressure(estimatedP, "bara");
process.add(placeholder);
// 2. Build downstream equipment using the placeholder as input
Mixer mixer = new Mixer("recycle mixer");
mixer.addStream(mainFeed);
mixer.addStream(placeholder); // ← placeholder used here
process.add(mixer);
// ... more equipment in the loop ...
// 3. Create Recycle that connects actual outlet back to placeholder
Recycle recycle = new Recycle("RCY-1");
recycle.addStream(actualOutletStream); // downstream end of loop
recycle.setOutletStream(placeholder); // connects back to start
recycle.setTolerance(1e-3); // tighter than default 1e-2
process.add(recycle);
Convergence tuning:
recycle.setFlowTolerance(1e-3); // flow convergence (default 1e-2)
recycle.setTemperatureTolerance(1e-3); // temperature convergence
recycle.setCompositionTolerance(1e-3); // composition convergence
recycle.setPriority(50); // lower = solved first (default 100)
recycle.setAccelerationMethod("Wegstein"); // or "Direct Substitution", "Broyden"
Priority-based nesting: Set lower priority numbers on inner recycle loops.
The RecycleController solves lower-priority recycles first, then higher.
ProcessSystem hard cap: 100 iterations (not user-configurable).
Adjuster adjuster = new Adjuster("Adj");
adjuster.setAdjustedVariable(equipment, "methodName");
adjuster.setTargetVariable(stream, "methodName", targetValue);
ProcessSystem process = new ProcessSystem();
process.add(feed);
process.add(separator);
process.add(compressor);
process.add(cooler);
process.run(); // Run ONCE after adding all equipment
For multi-area plants, use ProcessModel to combine multiple ProcessSystem instances (see below).
For large process plants (platforms, refineries, gas plants), split the model into
separate ProcessSystem objects per process area, then combine them into a single
ProcessModel. NEVER try to add a ProcessModule or ProcessSystem to another
ProcessSystem — use ProcessModel as the top-level container.
ProcessModel ("Gas Platform") ← TOP-LEVEL CONTAINER
├── ProcessSystem ("well process") ← Well feed & manifold
├── ProcessSystem ("separation train A") ← HP/LP separation
├── ProcessSystem ("separation train B") ← HP/LP separation
├── ProcessSystem ("TEX process A") ← Turbo-expander
├── ProcessSystem ("TEX process B") ← Turbo-expander
├── ProcessSystem ("export compressor A") ← Gas compression
├── ProcessSystem ("export gas") ← Gas export pipeline
└── ProcessSystem ("export oil") ← Oil export
// Each area is its own ProcessSystem
ProcessSystem wellProcess = new ProcessSystem();
wellProcess.add(wellFeed);
wellProcess.add(manifold);
wellProcess.add(splitter);
ProcessSystem separationA = new ProcessSystem();
separationA.add(new Heater("HP heater", splitter.getSplitStream(0)));
separationA.add(new ThreePhaseSeparator("1st stage", ...));
// ... more equipment
ProcessSystem compressionA = new ProcessSystem();
compressionA.add(new Compressor("export comp",
separationA.getUnit("gas mixer").getOutletStream())); // cross-ref
// Combine into ProcessModel
ProcessModel plant = new ProcessModel();
plant.add("well process", wellProcess);
plant.add("separation train A", separationA);
plant.add("export compressor A", compressionA);
plant.run(); // Iterates until all converge
// Access equipment by process area
plant.get("separation train A").getUnit("1st stage separator");
// Convergence info
System.out.println(plant.getConvergenceSummary());
System.out.println(plant.getMassBalanceReport());
The reference model uses functions that return ProcessSystem objects:
def create_well_feed_model(inp):
well_process = neqsim.process.processmodel.ProcessSystem()
feed = Stream("feed", fluid)
feed.setFlowRate(inp.flow_rate, "kg/hr")
well_process.add(feed)
splitter = Splitter("manifold", feed)
splitter.setSplitFactors([0.5, 0.5])
well_process.add(splitter)
return well_process
def create_separation_process(inp, feed_stream):
sep_process = neqsim.process.processmodel.ProcessSystem()
separator = ThreePhaseSeparator("1st stage", feed_stream) # cross-ref!
sep_process.add(separator)
# ... more equipment
return sep_process
# Build and run each area
well_model = create_well_feed_model(params)
well_model.run()
sep_train_A = create_separation_process(params,
well_model.getUnit("manifold").getSplitStream(0)) # cross-system stream
sep_train_A.run()
# Combine into ProcessModel
ProcessModel = jneqsim.process.processmodel.ProcessModel
plant = ProcessModel()
plant.add("well process", well_model)
plant.add("separation train A", sep_train_A)
plant.run() # Iterates until convergence
print(plant.getConvergenceSummary())
print(plant.getMassBalanceReport())
| Feature | Method |
|---|---|
| Add named sub-process | add("name", processSystem) |
| Get sub-process | get("name") |
| Remove sub-process | remove("name") |
| Run all (iterates to convergence) | run() |
| Run single step | runStep() |
| Run in background thread | runAsTask() returns Future |
| Check convergence | isModelConverged(), getConvergenceSummary() |
| Mass balance report | getMassBalanceReport(), getFailedMassBalanceReport() |
| Validation | validateSetup(), validateAll(), getValidationReport() |
| Execution analysis | getExecutionPartitionInfo() |
| Set convergence tolerance | setTolerance(1e-4) or individual setFlowTolerance() etc. |
| Save/load model | saveToNeqsim("file.neqsim"), loadFromNeqsim("file.neqsim") |
| JSON report | getReport_json() |
| Automation facade | getAutomation() returns ProcessAutomation (string-addressable variables) |
| Lifecycle state | ProcessModelState.fromProcessModel(plant), .saveToFile(), .compare(v1, v2) |
Streams cross sub-system boundaries by direct object reference:
ProcessModel.run() executes systems in insertion orderadd() calls matters — add upstream systems first| Class | Purpose | Use When |
|---|---|---|
ProcessSystem | Single process area with equipment | Always — the basic building block |
ProcessModel | Named collection of ProcessSystems with convergence tracking | Multi-area plants (platforms, gas plants) |
ProcessModule | Legacy container for ProcessSystems | Backward compatibility only — prefer ProcessModel |
NEVER add a ProcessModule or ProcessModel to a ProcessSystem — it will throw TypeError.
fluid.clone() to avoid shared-state bugs(String name, StreamInterface inlet)ProcessSystem in topological orderprocess.run() only ONCE after building the entire flowsheetProcessModel to combine ProcessSystem objects — never nest themUse ProcessAutomation for agent-friendly variable access — no Java class navigation needed.
ProcessAutomation auto = process.getAutomation(); // or plant.getAutomation()
List<String> units = auto.getUnitList(); // ["Feed Gas", "HP Sep", ...]
List<SimulationVariable> vars = auto.getVariableList("HP Sep");
// Each variable: address, name, type (INPUT/OUTPUT), defaultUnit, description
String eqType = auto.getEquipmentType("HP Sep"); // "Separator"
// Read with unit conversion (dot-notation addressing)
double temp = auto.getVariableValue("HP Sep.gasOutStream.temperature", "C");
double flow = auto.getVariableValue("HP Sep.gasOutStream.flowRate", "kg/hr");
// Write INPUT variables, then re-run
auto.setVariableValue("Compressor.outletPressure", 150.0, "bara");
process.run();
ProcessAutomation plantAuto = plant.getAutomation();
List<String> areas = plantAuto.getAreaList();
// Area-qualified: "Area::Unit.property"
double t = plantAuto.getVariableValue("Separation::HP Sep.gasOutStream.temperature", "C");
JSON snapshots for reproducibility and version tracking.
// Save
ProcessSystemState state = ProcessSystemState.fromProcessSystem(process);
state.setName("Gas Processing"); state.setVersion("1.0.0");
state.saveToFile("model_v1.json");
// Load and validate
ProcessSystemState loaded = ProcessSystemState.loadFromFile("model_v1.json");
assert loaded.validate().isValid();
// Multi-area
ProcessModelState ms = ProcessModelState.fromProcessModel(plant);
ms.saveToFile("plant_v1.json");
// Version diff
ProcessModelState.ModelDiff diff = ProcessModelState.compare(v1, v2);
// diff.getModifiedParameters(), diff.getAddedEquipment(), diff.getRemovedEquipment()
// Compressed bytes for API transfer
byte[] bytes = ms.toCompressedBytes();
ProcessModelState restored = ProcessModelState.fromCompressedBytes(bytes);
After running equipment in a process simulation, generate a feasibility report to answer: "Is this machine realistic to build? What will it cost? Who can supply it?"
// After process.run():
CompressorDesignFeasibilityReport report =
new CompressorDesignFeasibilityReport(compressor);
report.setDriverType("gas-turbine");
report.setCompressorType("centrifugal");
report.setAnnualOperatingHours(8000);
report.generateReport();
String verdict = report.getVerdict(); // FEASIBLE / FEASIBLE_WITH_WARNINGS / NOT_FEASIBLE
String json = report.toJson(); // Full JSON with mech design, cost, suppliers, curves
List<SupplierMatch> suppliers = report.getMatchingSuppliers();
// Apply generated performance curves back to compressor
report.applyChartToCompressor();
// After process.run():
HeatExchangerDesignFeasibilityReport hxReport =
new HeatExchangerDesignFeasibilityReport(heatExchanger);
hxReport.setExchangerType("shell-and-tube");
hxReport.setDesignStandard("TEMA-R");
hxReport.setAnnualOperatingHours(8000);
hxReport.generateReport();
String verdict = hxReport.getVerdict();
String json = hxReport.toJson();
List<HXSupplierMatch> suppliers = hxReport.getMatchingSuppliers();
Key points:
run() before generating the reportFEASIBLE, FEASIBLE_WITH_WARNINGS, NOT_FEASIBLEBLOCKER (not feasible), WARNING (review), INFO (note)CompressorSuppliers.csv, HeatExchangerSuppliers.csv)When to run feasibility checks:
TEMA-level shell-and-tube thermal design with tube/shell-side HTCs, pressure drops, LMTD correction, vibration screening, and full mechanical design.
ThermalDesignCalculator calc = new ThermalDesignCalculator();
calc.setTubeODm(0.01905); // 3/4" OD
calc.setTubeIDm(0.01483);
calc.setTubeLengthm(6.0);
calc.setTubeCount(200);
calc.setTubePasses(2);
calc.setTubePitchm(0.0254);
calc.setTriangularPitch(true);
calc.setShellIDm(0.489);
calc.setBaffleSpacingm(0.15);
calc.setBaffleCount(30);
calc.setBaffleCut(0.25);
// Tube-side fluid (density, viscosity, cp, conductivity, massFlow, isHeating)
calc.setTubeSideFluid(995.0, 0.0008, 4180.0, 0.62, 5.0, true);
// Shell-side fluid
calc.setShellSideFluid(820.0, 0.003, 2200.0, 0.13, 8.0);
calc.setShellSideMethod(ThermalDesignCalculator.ShellSideMethod.BELL_DELAWARE);
calc.calculate();
String json = calc.toJson(); // Full results: U, dP, HTCs, zone analysis
double ft = LMTDcorrectionFactor.calcFt(tHotIn, tHotOut, tColdIn, tColdOut, 1); // 1 shell pass
int minShells = LMTDcorrectionFactor.requiredShellPasses(tHotIn, tHotOut, tColdIn, tColdOut);
// MIN_ACCEPTABLE_FT = 0.75
VibrationAnalysis.VibrationResult vib = VibrationAnalysis.performScreening(
tubeOD, tubeID, unsupportedSpan, tubeMaterialE, tubeDensity,
fluidDensityTube, fluidDensityShell, "fixed-fixed",
crossflowVelocity, tubePitch, true, shellID, sonicVelocity);
if (!vib.passed) {
// Check vib.vortexSheddingCritical, vib.fluidElasticCritical, vib.acousticCritical
}
ShellAndTubeDesignCalculator stCalc = new ShellAndTubeDesignCalculator();
stCalc.setTemaDesignation("AES");
stCalc.setTemaClass(TEMAClass.R);
stCalc.setRequiredArea(50.0); // m²
stCalc.setShellSidePressure(30.0); // bara
stCalc.setTubeSidePressure(10.0); // bara
stCalc.setDesignTemperature(200.0); // °C
stCalc.setShellMaterialGrade("SA-516-70");
stCalc.setTubeMaterialGrade("SA-179");
stCalc.setSourServiceAssessment(true);
stCalc.setH2sPartialPressure(0.01); // bar
// Provide fluid properties for thermal + vibration analysis
stCalc.setTubeSideFluidProperties(995.0, 0.0008, 4180.0, 0.62, 5.0, true);
stCalc.setShellSideFluidProperties(820.0, 0.003, 2200.0, 0.13, 8.0);
stCalc.setShellSideMethod(ThermalDesignCalculator.ShellSideMethod.BELL_DELAWARE);
stCalc.calculate(); // Runs mechanical + thermal + vibration
String json = stCalc.toJson(); // MAWP, wall thickness, U, dP, vibration, cost, BOM
Standards: TEMA R/C/B, ASME VIII Div.1 (UHX-13, UG-27, UG-37, UG-99), NACE MR0175/ISO 15156, Bell-Delaware, Gnielinski, Von Karman, Connors criterion.
Full-stack safety analysis for CO2 injection wells covering steady-state flow, phase boundary mapping, impurity enrichment, shutdown transients, and flow corrections.
CO2InjectionWellAnalyzer analyzer = new CO2InjectionWellAnalyzer("InjectionWell-1");
analyzer.setFluid(co2Fluid);
analyzer.setWellGeometry(1300.0, 0.1571, 5e-5); // depth_m, tubingID_m, roughness_m
analyzer.setOperatingConditions(90.0, 25.0, 150000.0); // WHP_bara, WHT_C, flow_kg/hr
analyzer.setFormationTemperature(4.0, 43.0); // top_C, bottom_C
analyzer.addTrackedComponent("hydrogen", 0.10); // name, alarm mol fraction
analyzer.addTrackedComponent("nitrogen", 0.05);
analyzer.runFullAnalysis();
boolean safe = analyzer.isSafeToOperate();
Map<String, Object> results = analyzer.getResults();
ImpurityMonitor monitor = new ImpurityMonitor("H2-Monitor", stream);
monitor.addTrackedComponent("hydrogen", 0.10); // alarm at 10 mol%
monitor.setPrimaryComponent("hydrogen");
// After process.run():
double gasH2 = monitor.getGasPhaseMoleFraction("hydrogen");
double enrichment = monitor.getEnrichmentFactor("hydrogen"); // y_gas / z_feed
boolean alarm = monitor.isAlarmExceeded("hydrogen");
Map<String, Map<String, Double>> report = monitor.getFullReport();
TransientWellbore wellbore = new TransientWellbore("Shutdown", stream);
wellbore.setWellDepth(1300.0);
wellbore.setTubingDiameter(0.1571);
wellbore.setFormationTemperature(273.15 + 4.0, 273.15 + 43.0);
wellbore.setShutdownCoolingRate(6.0); // tau = 6 hours
wellbore.setNumberOfSegments(10);
wellbore.runShutdownSimulation(48.0, 1.0); // 48 hours, 1-hour steps
List<TransientSnapshot> snaps = wellbore.getSnapshots();
double maxH2 = wellbore.getMaxGasPhaseConcentration("hydrogen");
PipeBeggsAndBrills pipe = new PipeBeggsAndBrills("Wellbore", feed);
pipe.setLength(1300.0);
pipe.setElevation(-1300.0); // downward
pipe.setDiameter(0.1571);
pipe.setFormationTemperatureGradient(4.0, -0.03, "C"); // 4°C top, -30°C/km (increases with depth)
pipe.run();
boolean co2Dominant = CO2FlowCorrections.isCO2DominatedFluid(system); // > 50 mol% CO2
double holdupCorr = CO2FlowCorrections.getLiquidHoldupCorrectionFactor(system); // 0.70–0.85
double frictionCorr = CO2FlowCorrections.getFrictionCorrectionFactor(system); // 0.85–0.95
boolean dense = CO2FlowCorrections.isDensePhase(system);
double Tr = CO2FlowCorrections.getReducedTemperature(system);
Generate study-class-appropriate engineering documents from a converged ProcessSystem.
// Standalone — generates all deliverables for the selected study class
EngineeringDeliverablesPackage pkg =
new EngineeringDeliverablesPackage(process, StudyClass.CLASS_A);
pkg.generate();
String json = pkg.toJson();
// Through orchestrator
orchestrator.setStudyClass(StudyClass.CLASS_A);
orchestrator.runCompleteDesignWorkflow();
EngineeringDeliverablesPackage pkg = orchestrator.getEngineeringDeliverables();
| Study Class | Deliverables |
|---|---|
| CLASS_A (FEED/Detail) | PFD, Thermal Utilities, Alarm/Trip, Spare Parts, Fire Scenarios, Noise, Instrument Schedule |
| CLASS_B (Concept/Pre-FEED) | PFD, Thermal Utilities, Fire Scenarios, Instrument Schedule |
| CLASS_C (Screening) | PFD only |
Creates ISA-5.1 tagged instruments and optionally registers real MeasurementDeviceInterface
objects on the ProcessSystem for dynamic simulation:
InstrumentScheduleGenerator instrGen = new InstrumentScheduleGenerator(process);
instrGen.setRegisterOnProcess(true); // bridge: creates live MeasurementDevice objects
instrGen.generate();
// Query instruments
List<InstrumentScheduleGenerator.InstrumentEntry> all = instrGen.getEntries();
List<InstrumentScheduleGenerator.InstrumentEntry> pts =
instrGen.getEntriesByType(InstrumentScheduleGenerator.MeasuredVariable.PRESSURE);
// Each entry has: tag, equipmentName, service, measuredVariable, rangeMin/Max, unit,
// alarmHH/H/L/LL, silRating, liveDevice (if registerOnProcess=true)
for (InstrumentScheduleGenerator.InstrumentEntry e : all) {
System.out.println(e.getTag() + " " + e.getEquipmentName()
+ " SIL=" + e.getSilRating());
if (e.getLiveDevice() != null) {
// Real MeasurementDevice registered on ProcessSystem
System.out.println(" Live: " + e.getLiveDevice().getMeasuredValue());
}
}
String instrJson = instrGen.toJson();
Tag numbering convention: PT-100+, TT-200+, LT-300+, FT-400+ (ISA-5.1).
For phase-envelope generation, plotting, physical branch classification, zero/trace-component
handling, or Michelsen solver changes, load neqsim-phase-envelope. This section is the compact
API reference; the dedicated skill owns the end-to-end workflow and regression rules.
SystemInterface fluid = new SystemSrkEos(273.15 + 25.0, 50.0);
fluid.addComponent("methane", 0.85);
fluid.addComponent("ethane", 0.10);
fluid.addComponent("propane", 0.05);
fluid.setMixingRule("classic");
ThermodynamicOperations ops = new ThermodynamicOperations(fluid);
ops.calcPTphaseEnvelope(true, 1.0); // bubblePointFirst=true, lowPres=1.0 bara
// Access envelope data via the operation object
PTPhaseEnvelopeMichelsen envelope = (PTPhaseEnvelopeMichelsen) ops.getOperation();
double[] cricondenBar = envelope.getCricondenBar(); // [T_K, P_bara, 0]
double[] cricondenTherm = envelope.getCricondenTherm(); // [T_K, P_bara, 0]
double critT = envelope.getCriticalTemperature(); // Kelvin
double critP = envelope.getCriticalPressure(); // bara
When using calcPTphaseEnvelope(true, 1.0) (bubblePointFirst=true), the NeqSim
Michelsen algorithm stores the envelope branches with SWAPPED labels:
getBubblePointTemperatures() / getBubblePointPressures() → actually the DEW curve (right side, higher T, includes cricondentherm)getDewPointTemperatures() / getDewPointPressures() → actually the BUBBLE curve (left side, lower T)Root cause: The algorithm initializes isDewPhase=true regardless of the
bubblePointFirst flag. When starting from the bubble side, initial points go
into the dew list. At the critical point, isDewPhase flips, sending post-CP
points (the actual dew side) into the bubble list.
Always determine which branch is which using physical reasoning:
branch_A_T = np.array(envelope.getBubblePointTemperatures())
branch_A_P = np.array(envelope.getBubblePointPressures())
branch_B_T = np.array(envelope.getDewPointTemperatures())
branch_B_P = np.array(envelope.getDewPointPressures())
# The DEW curve always contains the cricondentherm (maximum temperature)
if branch_A_T.max() > branch_B_T.max():
dew_T, dew_P = branch_A_T, branch_A_P
bub_T, bub_P = branch_B_T, branch_B_P
else:
dew_T, dew_P = branch_B_T, branch_B_P
bub_T, bub_P = branch_A_T, branch_A_P
Bubble point curve (left side of envelope):
Dew point curve (right side of envelope):
Key points on the envelope:
Retrograde condensation region (between cricondenbar and cricondentherm on the dew curve):
When writing code examples for documentation (markdown guides, cookbook recipes, tutorials):
DocExamplesCompilationTest.java)"C20" not "C20+" (the + character breaks parsing)characterisePlusFraction()getUnit("name") not getUnitOperation("name")setDepreciationYears takes double, not intAlternatives
teng-lin/notebooklm-py
Complete API for Google NotebookLM - full programmatic access including features not in the web UI. Create notebooks, add sources, generate all artifact types, download in multiple formats. Activates on explicit /notebooklm or intent like "create a podcast about X"
TencentCloudBase/CloudBase-AI-Toolkit
Build production-ready AI agent backends using the CloudBase Agent Python SDK — create agents with LangGraph/CrewAI/LlamaIndex, serve them via FastAPI with AG-UI protocol streaming + OpenAI-compatible endpoints, add tools (bash, filesystem, MCP, code execution), memory (in-memory, TDAI, MySQL, MongoDB), observability (OpenTelemetry/Langfuse), and middleware (auth, logging). Use this skill when the user wants to create an AI agent server, build a chatbot backend, set up human-in-the-loop workflow
XiaomiMiMo/MiMo-Code
Use this skill whenever a Microsoft PowerPoint (.pptx) file is being produced, opened, transformed, or read. That includes: authoring slide decks, pitch decks, executive readouts, training material, or any presentation deliverable; extracting text or structure from an existing .pptx; filling a .pptx template with values; converting a deck to PDF or images; splitting or merging decks; inspecting slides, layouts, masters, tables, images, charts, speaker notes, or comments. Trigger on words like 'd
alirezarezvani/claude-skills
Use when planning, running, or learning from chaos engineering experiments. Triggers on "chaos experiment", "fault injection", "gameday", "resilience test", "blast radius", "steady state", "abort criteria", "Chaos Toolkit", "Chaos Mesh", "Litmus", "Gremlin", "AWS FIS", or any deliberate failure-injection question. Ships experiment designer, blast-radius calculator, and postmortem generator (all stdlib Python), 4 references on chaos principles + experiment design + attack taxonomy + tooling lands