run_flash_experiments
Automates batch execution of NeqSim flash calculations and data generation for benchmarking.
Install
mkdir -p .claude/skills/run-flash-experiments && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/10653" && unzip -o skill.zip -d .claude/skills/run-flash-experiments && rm skill.zipInstalls to .claude/skills/run-flash-experiments
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Execute NeqSim flash calculations in batch mode, collect metrics, and produceKey capabilities
- →Generate flash calculation cases
- →Execute batch NeqSim simulations
- →Collect performance metrics
- →Compare EOS algorithm results
- →Record environment metadata
How it works
The skill generates a grid of thermodynamic cases from a configuration file, executes them in batch mode using NeqSim, and records timing and convergence metrics.
Inputs & outputs
When to use run_flash_experiments
- →Run flash benchmarks
- →Generate raw data for validation
- →Compare algorithm performance
- →Collect simulation metrics
About this skill
Skill: Run Flash Experiments
Purpose
Execute NeqSim flash calculations in batch mode, collect metrics, and produce structured result files for paper-quality benchmarking.
When to Use
- Running a benchmark suite designed by the
design_flash_benchmarkskill - Comparing baseline vs candidate algorithms
- Generating raw data for the validation agent
Execution Procedure
Step 1: Load Benchmark Config
import json
with open("benchmark_config.json") as f:
config = json.load(f)
Step 2: Generate All Cases
import numpy as np
from itertools import product
def generate_all_cases(config):
"""Generate all benchmark cases from config."""
cases = []
case_id = 0
for family in config["families"]:
# Base composition
base = family["base_composition"]
# Composition variants
names = list(base.keys())
alpha = np.array([base[n] for n in names]) * family["dirichlet_concentration"]
np.random.seed(42) # Reproducible
compositions = [base] # Include base
for _ in range(family["n_composition_variants"] - 1):
x = np.random.dirichlet(alpha)
compositions.append(dict(zip(names, x.tolist())))
# PT grid
T_vals = np.linspace(family["T_range_K"][0], family["T_range_K"][1], family["n_T"])
P_vals = np.logspace(
np.log10(family["P_range_bara"][0]),
np.log10(family["P_range_bara"][1]),
family["n_P"]
)
for comp in compositions:
for T, P in product(T_vals, P_vals):
cases.append({
"case_id": f"{family['name'][:2].upper()}-{case_id:05d}",
"family": family["name"],
"components": comp,
"T_K": float(T),
"P_bara": float(P)
})
case_id += 1
return cases
Step 3: Run Single Flash Case
import time
from tools.neqsim_bootstrap import get_jneqsim
jneqsim = get_jneqsim()
SystemSrkEos = jneqsim.thermo.system.SystemSrkEos
SystemPrEos = jneqsim.thermo.system.SystemPrEos
ThermodynamicOperations = jneqsim.thermodynamicoperations.ThermodynamicOperations
EOS_MAP = {
"SRK": SystemSrkEos,
"PR": SystemPrEos,
}
def run_flash_case(case, eos_name="SRK", timing_repeats=3):
"""Run a single TPflash and return metrics."""
EosClass = EOS_MAP[eos_name]
# Create fluid system
fluid = EosClass(case["T_K"], case["P_bara"])
for comp_name, frac in case["components"].items():
fluid.addComponent(comp_name, frac)
fluid.setMixingRule("classic")
ops = ThermodynamicOperations(fluid)
# Warmup run
try:
ops.TPflash()
except Exception:
pass
# Timed runs
times_ns = []
for _ in range(timing_repeats):
# Reset and re-flash
fluid2 = fluid.clone()
ops2 = ThermodynamicOperations(fluid2)
t0 = time.perf_counter_ns()
try:
ops2.TPflash()
elapsed = time.perf_counter_ns() - t0
times_ns.append(elapsed)
fluid2.initProperties()
n_phases = int(fluid2.getNumberOfPhases())
beta_vapor = float(fluid2.getBeta(0)) if n_phases > 0 else 0.0
converged = True
error = None
except Exception as e:
elapsed = time.perf_counter_ns() - t0
times_ns.append(elapsed)
n_phases = -1
beta_vapor = -1.0
converged = False
error = str(e)
median_time_ms = float(np.median(times_ns)) / 1e6
return {
"case_id": case["case_id"],
"family": case["family"],
"eos": eos_name,
"T_K": case["T_K"],
"P_bara": case["P_bara"],
"converged": converged,
"cpu_time_ms": round(median_time_ms, 4),
"n_phases": n_phases,
"beta_vapor": round(beta_vapor, 6) if beta_vapor >= 0 else None,
"error": error
}
Step 4: Run Full Suite
import json
import os
from pathlib import Path
def run_benchmark_suite(config, algorithm_name, results_dir):
"""Run the complete benchmark suite."""
cases = generate_all_cases(config)
results_path = Path(results_dir) / "raw"
results_path.mkdir(parents=True, exist_ok=True)
output_file = results_path / f"{algorithm_name}_results.jsonl"
n_converged = 0
n_total = 0
failures = []
with open(output_file, "w") as f:
for i, case in enumerate(cases):
result = run_flash_case(case, eos_name=config["eos_models"][0])
result["algorithm"] = algorithm_name
f.write(json.dumps(result) + "\n")
n_total += 1
if result["converged"]:
n_converged += 1
else:
failures.append(result)
if (i + 1) % 100 == 0:
print(f" Progress: {i+1}/{len(cases)} "
f"({n_converged}/{n_total} converged)")
# Write summary
summary = {
"algorithm": algorithm_name,
"eos": config["eos_models"][0],
"total_cases": n_total,
"converged": n_converged,
"failed": n_total - n_converged,
"convergence_rate_pct": round(100.0 * n_converged / n_total, 2)
}
with open(Path(results_dir) / f"summary_{algorithm_name}.json", "w") as f:
json.dump(summary, f, indent=2)
# Write failures
with open(Path(results_dir) / f"failures_{algorithm_name}.json", "w") as f:
json.dump(failures, f, indent=2)
return summary
Step 5: Record Metadata
import platform
import subprocess
def record_metadata(results_dir):
"""Record benchmark environment metadata."""
metadata = {
"date": "2026-03-31",
"hostname": platform.node(),
"os": platform.platform(),
"python": platform.python_version(),
"java": "OpenJDK 17", # or read from java -version
"cpu": platform.processor(),
"neqsim_version": "3.3.0",
"random_seed": 42
}
try:
result = subprocess.run(
["git", "rev-parse", "HEAD"],
capture_output=True, text=True
)
metadata["git_commit"] = result.stdout.strip()
except Exception:
metadata["git_commit"] = "unknown"
with open(Path(results_dir) / "benchmark_metadata.json", "w") as f:
json.dump(metadata, f, indent=2)
Output Files
| File | Format | Content |
|---|---|---|
raw/<algorithm>_results.jsonl | JSONL | One result per line, all cases |
summary_<algorithm>.json | JSON | Aggregate statistics |
failures_<algorithm>.json | JSON | Failed case details |
benchmark_metadata.json | JSON | Environment info |
Error Handling
- Java exception: Catch, record error message, mark as failed
- Timeout: Set a 10-second per-case timeout
- NaN/Inf results: Detect and mark as failed
- Memory issues: Run in batches of 500, flush results to disk
Performance Tips
- Use
fluid.clone()instead of recreating from scratch - Warm up the JVM before timing
- Report median of 3 runs, not mean (avoids GC outliers)
- Run baseline and candidate interleaved, not sequentially
When not to use it
- →Interactive simulation debugging
- →Real-time process control
Prerequisites
Limitations
- →10-second per-case timeout
- →Requires Java environment
How it compares
It automates the generation and execution of thousands of flash calculations with standardized metadata, replacing manual script-based benchmarking.
Compared to similar skills
run_flash_experiments side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| run_flash_experiments (this skill) | 0 | 1mo | Review | Advanced |
| neqsim-field-development | 0 | 3mo | No flags | Advanced |
| data-engineering | 13 | 7mo | Review | Advanced |
| crawl4ai | 21 | 8mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by equinor
View all by equinor →You might also like
neqsim-field-development
equinor
Field development workflows, concept selection, and integrated project evaluation using NeqSim. USE WHEN: performing field development studies, concept screening, tieback analysis, production forecasting, or integrated field planning. Covers the full lifecycle from discovery through operations with
data-engineering
pluginagentmarketplace
ETL pipelines, Apache Spark, data warehousing, and big data processing. Use for building data pipelines, processing large datasets, or data infrastructure.
crawl4ai
basher83
This skill should be used when users need to scrape websites, extract structured data, handle JavaScript-heavy pages, crawl multiple URLs, or build automated web data pipelines. Includes optimized extraction patterns with schema generation for efficient, LLM-free extraction.
data-cleaning-pipeline
aj-geddes
Build robust processes for data cleaning, missing value imputation, outlier handling, and data transformation for data preprocessing, data quality, and data pipeline automation
workflow-orchestration-patterns
wshobson
Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
paddle-ocr-validation
jgtolentino
PaddleOCR-based receipt and BIR form extraction with validation