Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/neqsim-engine.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
51410f78f6c1d15b22b280836480983e11c21f184eeb5fc8ba0bff985d44fe35 neqsim-3.19.0.jar
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Run pre-commit on pull-requests (and main branch)
on:
pull_request:
push:
branches: [main]
branches: [master]
workflow_dispatch: # Trigger manually

jobs:
Expand Down
124 changes: 124 additions & 0 deletions .github/workflows/sync-neqsim-engine.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Sync bundled NeqSim engine

on:
push:
branches:
- "release/**"
paths:
- ".github/neqsim-engine.sha256"
- ".github/workflows/sync-neqsim-engine.yml"
- "pyproject.toml"
- "scripts/generate_component_literals.py"
- "scripts/generate_stubs.py"
workflow_dispatch:
inputs:
version:
description: "NeqSim release version; defaults to pyproject.toml"
required: false
type: string
jar_sha256:
description: "Expected JAR SHA-256; defaults to .github/neqsim-engine.sha256"
required: false
type: string

permissions:
contents: write

concurrency:
group: sync-neqsim-engine-${{ github.ref }}
cancel-in-progress: false

jobs:
sync-engine:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.ref_name }}

- name: Resolve release inputs
id: release
env:
INPUT_VERSION: ${{ inputs.version }}
INPUT_JAR_SHA256: ${{ inputs.jar_sha256 }}
run: |
version="${INPUT_VERSION}"
if [ -z "${version}" ]; then
version="$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
fi

expected_sha256="${INPUT_JAR_SHA256}"
if [ -z "${expected_sha256}" ]; then
expected_sha256="$(awk 'NR == 1 {print $1}' .github/neqsim-engine.sha256)"
fi

echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "expected_sha256=${expected_sha256}" >> "${GITHUB_OUTPUT}"

- name: Download and verify NeqSim JAR
env:
VERSION: ${{ steps.release.outputs.version }}
EXPECTED_SHA256: ${{ steps.release.outputs.expected_sha256 }}
run: |
jar_name="neqsim-${VERSION}.jar"
curl -fL --retry 3 --retry-delay 2 \
--output "${RUNNER_TEMP}/${jar_name}" \
"https://github.com/equinor/neqsim/releases/download/v${VERSION}/${jar_name}"

actual_sha256="$(sha256sum "${RUNNER_TEMP}/${jar_name}" | awk '{print $1}')"
if [ "${actual_sha256}" != "${EXPECTED_SHA256}" ]; then
echo "JAR checksum mismatch: expected ${EXPECTED_SHA256}, got ${actual_sha256}" >&2
exit 1
fi

find src/neqsim/lib -maxdepth 1 -type f -name 'neqsim-*.jar' -delete
mv "${RUNNER_TEMP}/${jar_name}" "src/neqsim/lib/${jar_name}"

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.13"

- name: Set up uv
uses: astral-sh/setup-uv@v5

- name: Set up Java
uses: actions/setup-java@v6
with:
distribution: temurin
java-version: "21"

- name: Regenerate Java API metadata
run: |
uv sync --group dev
uv run python scripts/generate_stubs.py
uv run python scripts/generate_api_manifest.py
uv run python scripts/generate_component_literals.py
uv run python -c 'from pathlib import Path; [compile(path.read_text(encoding="utf-8"), str(path), "exec") for path in Path("src/jneqsim-stubs").rglob("*.pyi")]'

- name: Commit release artifacts
env:
VERSION: ${{ steps.release.outputs.version }}
run: |
if git diff --quiet -- \
src/neqsim/lib \
src/jneqsim-stubs \
src/jpype-stubs \
src/neqsim/data/neqsim_api.json.gz \
src/neqsim/thermo/component_names.py \
src/neqsim/thermo/component_names.pyi; then
echo "Bundled engine and generated API metadata are already current."
exit 0
fi

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A \
src/neqsim/lib \
src/jneqsim-stubs \
src/jpype-stubs \
src/neqsim/data/neqsim_api.json.gz \
src/neqsim/thermo/component_names.py \
src/neqsim/thermo/component_names.pyi
git commit -m "release: bundle NeqSim Java ${VERSION} and refresh API metadata"
git push origin "HEAD:${GITHUB_REF_NAME}"
3 changes: 3 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ repos:
rev: 26.5.1
hooks:
- id: black
# Java API stubs are generated artifacts owned by stubgenj. Some Java-
# derived names are not valid Python syntax and cannot be parsed by Black.
exclude: ^src/(jneqsim|jpype)-stubs/
4 changes: 2 additions & 2 deletions conda/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{% set name = "neqsim" %}
{% set version = "3.18.0" %}
{% set version = "3.19.0" %}

package:
name: {{ name|lower }}
version: {{ version }}

source:
url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz
sha256: d68cdef13335a62fdfa821c1903f0bc038f7adb236ad41d1818a0216ddcb96c1
sha256: f9d098a5abdf391e66401fca2bce3cc616bf8a5bb376dc85c1b15a8bdddd7fa2

build:
number: 0
Expand Down
48 changes: 48 additions & 0 deletions docs/release-notes/v3.19.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# NeqSim Python 3.19.0

NeqSim Python is the Python interface to the NeqSim engine for thermodynamic
calculations, physical properties, process simulation, and PVT analysis from
Python and Jupyter notebooks.

## Highlights

- Bundles the NeqSim Java 3.19.0 engine for Java 17 or newer.
- Makes the thermodynamic, process-simulation, PVT, electrolyte, refinery,
dynamics, engineering-diagram, and safety improvements released in NeqSim
3.19.0 available through Python and the direct `jneqsim` gateway.
- Retains Python 3.10–3.14 support and the existing NeqSim Python API.

## Install

Use pip when you already have Java installed:

```bash
pip install --upgrade neqsim==3.19.0
```

Use conda when you want OpenJDK installed with the package:

```bash
conda install -c conda-forge neqsim=3.19.0
```

Requirements:

- Python 3.10 or newer.
- Java 17 or newer for pip installs. Download Java from
[Adoptium](https://adoptium.net/).
- Conda installs include OpenJDK through conda-forge.

Verify the installed package version without starting the JVM:

```bash
python -c "from importlib.metadata import version; print(version('neqsim'))"
```

## Useful Links

- Full changelog: https://github.com/equinor/neqsim-python/compare/v3.18.0...v3.19.0
- NeqSim Java 3.19.0 release: https://github.com/equinor/neqsim/releases/tag/v3.19.0
- Documentation: https://equinor.github.io/neqsimhome/
- Python examples: https://github.com/equinor/neqsim-python/tree/master/examples
- Discussions: https://github.com/equinor/neqsim/discussions
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ dependencies:
# Install neqsim from PyPI until conda-forge package is available
- pip
- pip:
- neqsim==3.18.0
- neqsim==3.19.0
12 changes: 4 additions & 8 deletions examples/equationOfState.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@ def create_wet_gas(eos_name):
# =============================================================================
print("\n6. EOS-CG FOR CO2 AND COMBUSTION GASES")
print("-" * 40)
print(
"""
print("""
EOS-CG (Equation of State for Combustion Gases) is based on GERG-2008
but optimized for CO2-rich mixtures and combustion product gases.

Expand All @@ -225,8 +224,7 @@ def create_wet_gas(eos_name):
- Blue/green hydrogen with CO2

Components: CO2, N2, O2, Ar, H2O, CO, H2, H2S, SO2, CH4
"""
)
""")

# Create a typical flue gas / CCS mixture
print("Example: CO2-rich CCS mixture")
Expand Down Expand Up @@ -263,8 +261,7 @@ def create_wet_gas(eos_name):
# =============================================================================
print("\n7. GUIDELINES FOR EoS SELECTION")
print("-" * 40)
print(
"""
print("""
Application | Recommended EoS
-------------------------------------|----------------------
Natural gas properties | GERG-2008 (most accurate)
Expand All @@ -289,6 +286,5 @@ def create_wet_gas(eos_name):
Gas hydrates | CPA with hydrate model
|
Electrolyte solutions (brine) | Electrolyte-CPA
"""
)
""")
print("=" * 70)
6 changes: 2 additions & 4 deletions examples/flashCalculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@
print("\n" + "=" * 70)
print("FLASH CALCULATION SUMMARY")
print("=" * 70)
print(
"""
print("""
Flash Type | Given | Find | Application
-----------|----------------|----------------|---------------------------
TPflash | T, P | Phases, comp. | General equilibrium
Expand All @@ -196,6 +195,5 @@
TVflash | T, V | P, phases | Closed vessels
VHflash | V, H | T, P, phases | Adiabatic closed systems
VUflash | V, U | T, P, phases | Isolated systems
"""
)
""")
print("=" * 70)
6 changes: 2 additions & 4 deletions examples/fluidCreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@
# =============================================================================
print("\n9. COMMONLY USED COMPONENTS")
print("-" * 40)
print(
"""
print("""
Category | Component Names
-------------------|------------------------------------------------
Light gases | nitrogen, oxygen, argon, helium, hydrogen, H2S
Expand All @@ -288,8 +287,7 @@

Note: For components not in database, use addTBPfraction() or
addPlusFraction() with MW and density.
"""
)
""")

# =============================================================================
# 10. ELECTROLYTE FLUIDS
Expand Down
30 changes: 10 additions & 20 deletions examples/hydrateCalculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
# =============================================================================
print("\n1. INTRODUCTION TO GAS HYDRATES")
print("-" * 40)
print(
"""
print("""
Gas hydrates form when water and light gases (C1, C2, C3, CO2, H2S)
combine under high pressure and low temperature conditions.

Expand All @@ -44,8 +43,7 @@
- Temperature: Typically < 25°C
- Pressure: Typically > 10-20 bara
- Presence of free water
"""
)
""")

# =============================================================================
# 2. HYDRATE FORMATION TEMPERATURE
Expand Down Expand Up @@ -116,16 +114,14 @@
# =============================================================================
print("\n4. SUBCOOLING - HYDRATE RISK ASSESSMENT")
print("-" * 40)
print(
"""
print("""
Subcooling (ΔT) = Hydrate formation T - Operating T

Interpretation:
ΔT > 0: Operating BELOW hydrate T → HIGH RISK
ΔT = 0: At hydrate equilibrium → BORDERLINE
ΔT < 0: Operating ABOVE hydrate T → SAFE
"""
)
""")

# Example calculation
gas.setPressure(100.0, "bara")
Expand Down Expand Up @@ -228,8 +224,7 @@
# =============================================================================
print("\n7. INHIBITOR SELECTION GUIDELINES")
print("-" * 40)
print(
"""
print("""
┌─────────────────────────────────────────────────────────────────┐
│ Inhibitor Comparison │
├────────────┬──────────────────────────────────────────────────┐
Expand All @@ -256,16 +251,14 @@
│ │ ✗ Cannot be regenerated │
│ │ → Best for: Drilling fluids, completion ops │
└────────────┴──────────────────────────────────────────────────┘
"""
)
""")

# =============================================================================
# 8. KINETIC HYDRATE INHIBITORS (KHI)
# =============================================================================
print("\n8. KINETIC HYDRATE INHIBITORS (KHI)")
print("-" * 40)
print(
"""
print("""
Unlike thermodynamic inhibitors (MEG, MeOH) that shift equilibrium,
KHIs work by slowing hydrate formation kinetics.

Expand All @@ -280,25 +273,22 @@

Note: NeqSim primarily calculates thermodynamic equilibrium.
KHI effects require separate kinetic models.
"""
)
""")

# =============================================================================
# 9. PRACTICAL EXAMPLE: PIPELINE HYDRATE ASSESSMENT
# =============================================================================
print("\n9. PRACTICAL EXAMPLE: PIPELINE HYDRATE ASSESSMENT")
print("-" * 40)

print(
"""
print("""
Scenario: Subsea pipeline from wellhead to platform
- Wellhead: 150 bara, 80°C
- Pipeline arrival: 80 bara, 5°C
- Gas is water-saturated

Question: Will hydrates form? How much MEG is needed?
"""
)
""")

# Check hydrate risk
pipeline_gas = fluid("cpa")
Expand Down
Loading
Loading