Skip to content
Merged
26 changes: 22 additions & 4 deletions .github/workflows/core-run-build-test-and-javadoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,28 @@ jobs:
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Run numerical and absence contracts
run: >-
mvn -B test -ntp -f ${{ matrix.pom }} -DskipITs -Djacoco.skip=true
"-Dtest=ModelSpec*Test,ComponentCorrelationSpecTest"
-DfailIfNoTests=true -Dsurefire.failIfNoSpecifiedTests=true
shell: bash
run: |
set -o pipefail
for attempt in 1 2; do
# -U also rechecks missing releases cached by a failed download.
if mvn -B -U test -ntp -f ${{ matrix.pom }} -DskipITs -Djacoco.skip=true \
"-Dtest=ModelSpec*Test,ComponentCorrelationSpecTest" \
-DfailIfNoTests=true -Dsurefire.failIfNoSpecifiedTests=true \
2>&1 | tee "$RUNNER_TEMP/model-spec-maven-$attempt.log"; then
exit 0
else
status=$?
fi
# Retry only Maven resolution failures, never compilation or test failures.
if [ "$attempt" -eq 2 ] || ! grep -Eq \
'^\[ERROR\] \[Help [0-9]+\] https?://[^ ]+/(PluginResolutionException|DependencyResolutionException)$' \
"$RUNNER_TEMP/model-spec-maven-$attempt.log"; then
exit "$status"
fi
echo "Maven dependency resolution failed; retrying once in 10 seconds."
sleep 10
done
- name: Retain per-case evidence
if: always()
uses: actions/upload-artifact@v7
Expand Down
62 changes: 62 additions & 0 deletions docs/development/TASK_LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ requirement`, or `confidential compressor route`.
**Solution:** Reuse the evidence-routing test fixture from PR #4312 commit `d469208aa227449d40c3f441e8f5a345795aa29a` and the eight-shard slow-suite partition from PR #4328 commit `9bcca37f1ac0b717c18a499b3a1a74bcdeec1126` in the renamed workflows.
**Notes:** Reproduced 27 routing assertions that required absent optional enterprise agents, then isolated agent discovery with synthetic installed/plugin catalogs. Add production guard regressions to Devtools CI, retain fast/slow Surefire reports, and let both fast-suite platforms finish after a failure. Four compatibility gates preserve historical required-check names and require all eight slow shards to succeed. Correct the duplicated `.yml` suffix in the documentation pre-push filter. Document test isolation, report artifacts, shard membership, and compatibility behavior in BUILD and the workflow catalog. Numerical methods and acceptance thresholds are unchanged.

### 2026-10-14 — Recover model-specification CI from Maven resolution failures
**Type:** G (Workflow)
**Keywords:** Java 8, Maven Central, dependency resolution, model specifications, PR 4320
**Solution:** `.github/workflows/core-run-build-test-and-javadoc.yml` retries the model-specification command once after a Maven plugin/dependency resolution failure and forces missing-release rechecks with `-U`.
**Notes:** The Java 8 job on `15d1b8d` failed before compilation while resolving `maven-resources-plugin:3.3.1`; absent test artifacts were secondary failures. Match Maven's terminal resolution-error help line, preserve the failing command's exit status, and fail immediately on compilation/test errors. The retry is bounded to two attempts with a ten-second delay. Numerical code, test selection, tolerances, and required evidence checks are unchanged. Documentation impact: CI recovery behavior is documented here and beside the workflow command; no simulation/API documentation changes are needed.

### 2026-10-11 — Review source routing and reusable tie-back guidance
**Type:** E (Feature)
**Keywords:** source attribution, evidence routing, duplicate manifest, VFP, host model, regression
Expand Down Expand Up @@ -1677,3 +1683,59 @@ Validation: Java getting-started documentation tests (2 passed), direct Spotless
documentation-search audit (788 Markdown pages and one HTML page), and diff whitespace check.
Package qualification and hosted release publication are tracked in the release PR.
Documentation impact: installation examples, citation and release build provenance updated.


### 2026-10-13 — Trace-water flash repair acceptance and cost qualification
**Type:** E (Feature)
**Keywords:** TPflash, trace water, aqueous, PSflash, pump, PR 4320, conservation, performance
**Solution:** `TPflash` bounds the existing aqueous repair, avoids duplicate EOS initialization,
and validates repaired endpoints before public return. `TPflashTraceWaterRepairTest` adds public
SRK/PR/CPA lifecycle and pump closure checks plus explicit failure/guard contracts.
**Notes:** Local acceptance targets are material balance `1e-10`, normalization `1e-12`, and
log-fugacity residual `1e-8`; ordinary TP/PS tolerances are unchanged. Expanded endpoint benchmark
records allocation and p95 alongside numerical validity. Synthetic public cases qualify lifecycle
behavior, not the unavailable original process snapshot or experimental phase behavior.


### 2026-10-14 — PR 4320 reservoir compatibility and bounded repair cost
**Type:** B (Bug fix)
**Keywords:** trace water, TPflash, flow scaling, reservoir, conservation, performance
**Solution:** Corrected cancellation in `SystemThermo.setTotalFlowRate` by rebuilding positive
component inventories. Trace-water gas/aqueous recovery now retains its qualified candidate
instead of replaying the ordinary flash; stalled/non-finite repairs stop early. Acceptance
tolerances and final failure reporting remain unchanged.
**Validation:** The public reservoir reproducer fails at exact prior head `645e5e6`; the two
updated/new test classes expose seven failures there. The candidate passes 397 focused and
integration tests with no failures/errors (one pre-existing disabled display test), including
all previously failing reservoir/well/field classes. Changed Java compiles with `--release 8`;
the complete Maven build and test execution use Java 17. Numerical qualification includes
component inventory, normalization, equilibrium, repeated state changes and pump closure.
**Documentation impact:** Flow-setter guide and TP-flash algorithm document the corrected
inventory scaling, bounded failure handling and candidate transfer. Exact-head CI and paired
full-flash/process timings are recorded in PR 4320; this is not a global stability certificate.

Current-master integration (`b0de5165`) also passes the expanded regression set, including
network topology, well-flow and named-component wax fraction coverage. Both numerical fixes
and strict recovery qualification are retained; generated engineering coverage is rebuilt.

### 2026-10-14 — PR 4320 broad-process regression repair
**Type:** B (Bug fix)
**Keywords:** flow inventory, cancellation, distillation, VLP, reservoir, performance
**Solution:** Restrict positive inventory rebuilding to downward flow changes whose prospective
component or total difference update loses more than `1e-12` relative accuracy. Accurate ordinary
updates, upward changes and same-rate updates keep their established arithmetic. The check uses
no additional EOS initialization, clone or temporary array. Two-fluid VLP now retains its cloned
reference inventory for intensive properties and applies the trial rate only in its existing
velocity calculation, avoiding unnecessary initialization at positive near-zero rates.
**Engineering evidence:** The previous reservoir setter produced 1,260,096.07887 kg/hr oil for a
requested 1,259,689.92248 kg/hr (0.0322% excess). Correct inventory gives the requested rate and
355.175066 bara after ten annual depletion/injection steps. The regression retains its 0.1 bar
pressure tolerance and now checks all four requested rates, each component inventory against
integrated production/injection, and constant reservoir volume at every step. Independent audit
found maximum relative component imbalance of `1.50e-16` and relative volume error below `1.5e-12`.
The VLP regression covers positive near-zero rate continuity, reference-flow magnitude invariance
and preservation of the source stream. The existing explicit zero-flow boundary is unchanged.
**Validation:** Reproduced ten failures at `2b67ee0`; the same 76 affected tests pass on master
`b0de5165`. Final expanded test results, formatting/documentation gates and paired performance
measurements are recorded in the PR validation update. No physical acceptance threshold is relaxed.
**Documentation impact:** Updated flow-setting and well-simulation guides and the setter JavaDoc.
6 changes: 6 additions & 0 deletions docs/simulation/well_simulation_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,12 @@ configured tolerance.
| DRIFT_FLUX | Accounts for phase slip velocity | Medium | Better for high GOR |
| TWO_FLUID | Separate gas/liquid momentum | Slowest | Highest accuracy |

The `TWO_FLUID` VLP calculation retains the reservoir fluid's reference inventory while
evaluating density and transport properties. The requested production rate enters the
velocity calculation separately. This keeps the property basis independent of the trial
rate for positive near-zero trials and leaves the source stream unchanged. The existing
explicit zero-flow boundary returns the target wellhead pressure without a property march.

---

## See Also
Expand Down
11 changes: 11 additions & 0 deletions docs/thermo/reading_fluid_properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,17 @@ fluid.setPressure(725.0, "psia"); // 725 psi absolute

#### Flow Rate Setters

For a nonempty fluid, changing the total flow preserves the component ratios, including
trace components when scaling reservoir inventories down to stream rates. For a downward
change, the setter checks whether its established difference update retains
each component and the total inventory to `1e-12` relative accuracy. If this check fails,
it rebuilds positive component inventories from normalized overall fractions. This avoids
loss of precision when a reservoir inventory is converted to a much smaller producer flow,
while preserving accurate ordinary process endpoints. Upward and same-rate updates retain
their established arithmetic and empty-stream initialization. The check adds no EOS
initialization or system clone. Unit conversion and the existing initialization behavior
are unchanged; reflash after changing temperature, pressure or composition.

| Method | Description | Supported Units |
|--------|-------------|-----------------|
| `setTotalFlowRate(value, unit)` | Set total flow | `"kg/sec"`, `"kg/min"`, `"kg/hr"`, `"kg/day"`, `"m3/sec"`, `"m3/min"`, `"m3/hr"`, `"Sm3/sec"`, `"Sm3/hr"`, `"Sm3/day"`, `"MSm3/day"`, `"MSm3/hr"`, `"mole/sec"`, `"mol/sec"`, `"mole/min"`, `"mol/min"`, `"mole/hr"`, `"mol/hr"`, `"kmole/sec"`, `"kmol/sec"`, `"kmole/min"`, `"kmol/min"`, `"kmole/hr"`, `"kmol/hr"`, `"kmole/day"`, `"kmol/day"`, `"idSm3/hr"`, `"gallons/min"` |
Expand Down
60 changes: 59 additions & 1 deletion docs/thermodynamicoperations/TPflash_algorithm.md
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,7 @@ Commercial process simulators do not publish all implementation details, but pub
original only when phase fractions, normalization, material balance, fugacity equality, distinct compositions, and
lower Gibbs energy all pass. Thus the enrichment and beta values gate cost; they do not decide stability. An
already-active neutral aqueous split with a
non-finite material residual or one above `1e-8` may use the existing three-step beta correction below that threshold;
non-finite material residual or one above `1e-8` may use the bounded existing-phase beta repair below that threshold;
this does not search for or create a phase. A trace-water GAS+OIL endpoint with a confirmed non-finite or at-least
`1e-8` log-fugacity residual may run the existing guarded multiphase candidate and is replaced only by a strictly
feasible lower-Gibbs result. That invalid-endpoint retry is restricted to an incipient secondary phase with
Expand Down Expand Up @@ -2893,3 +2893,61 @@ These public synthetic fluids qualify translated-PR TP-flash closure and lifecyc
do not validate the volume-translation correlation or parameters, phase-envelope accuracy,
experimental PVT predictions, PS/PH flashes, or acoustic-speed calculations. No production solver,
public API, model parameter, unit, default, or wall-clock performance claim is introduced.


### Existing trace-water aqueous split repair (PR #4320)

An aqueous label alone does not establish a valid equilibrium. For neutral, unconstrained
fluid flashes with a positive water feed fraction below 0.01, an already-present two-phase
aqueous split enters the existing endpoint recovery only when its component material-balance
residual is non-finite or exceeds `1e-8`. Balanced endpoints require no candidate clone or
additional EOS initialization. Chemical, ionic, solid, wax, forced-phase and phase-locked
states are excluded from this new existing-aqueous repair path.

The detached candidate retains its active phases and starts from an interior 50/50 beta seed.
That seed is purely numerical. Up to 20 complete `TPmultiflash.solveBeta()` calls update beta,
compositions and fugacities; each call also has its own bounded inner iteration loop. No
redundant `init(1)` is performed after these calls. Acceptance requires finite bounded beta
and compositions, beta and composition normalization within `1e-12`, component material
balance within `1e-10`, and interphase log-fugacity residual below `1e-8`, together with the
existing distinct-phase and candidate-selection checks. These stricter tolerances apply to
this repair only; ordinary solver tolerances are unchanged.

Two consecutive solves that fail to reduce the larger material/fugacity residual by at
least one part per million stop the repair early. Non-finite residuals also stop it. The
same strict acceptance and final failure checks apply. A qualified trace-water gas/aqueous
candidate is copied directly, just like an oil/aqueous candidate; it is not discarded by
replaying the ordinary flash used for water-rich cross-algorithm recovery.

The public reservoir regression exposed an upstream inventory problem in
`SystemThermo.setTotalFlowRate`: subtracting a reservoir-sized component amount to obtain
a stream-sized flow loses significant digits. Repeated beta solves cannot close a feed
whose overall fractions do not sum to one. Flow scaling now rebuilds positive component
amounts from normalized ratios, with no extra EOS initialization or system clone. The
250 bara, 363.15 K gas-producer regression exercises extraction, both rate changes and
repeated public TP flashes. Separate inventory tests cover initial amounts from `1e-12`
to `1e18` mol and retain a `1e-10` mole-fraction nitrogen component. They check component
ratios, total flow and normalization without loosening the flash contract.

If repair was attempted, the public `TPflash.run()` return also checks the final endpoint after
subsequent phase selection and cleanup. This final check permits one, two or three phases;
it does not force the repaired two-phase topology. An unqualified endpoint raises
`IllegalStateException` with temperature, pressure and material residual instead of returning
silently. Iterative PH/PS callers can therefore observe an unrecovered numerical failure.
The check certifies local conservation, normalization and equilibrium closure, not global
thermodynamic stability or experimental accuracy.

`TPflashTraceWaterRepairTest` qualifies public temperature sweeps, pressure changes and return,
operation reuse, cold-reference agreement, and actual pump entropy/mass/energy closure with
SRK, PR and CPA. Separate injected-state tests exercise strict acceptance, failure reporting
and the no-clone/no-initialization guard. The original deliberately corrupted endpoint test
remains. The synthetic public cases are lifecycle qualification; they do not reproduce the
unavailable original process snapshot.

`TPflashEndpointRecoveryBenchmark` includes dry gas, ordinary two-phase, CPA, condensate,
trace-water oil/aqueous, undersaturated water and three-phase workloads. Arguments are output
path, flashes per batch, batch count, warmup count, and optional family-name prefix. It records
elapsed and thread CPU time, p95 latency, allocated bytes where supported, and numerical
snapshots for both unchanged and changed states. Compare identical harnesses and JVM settings
against an exact baseline in alternating fresh JVMs. Timing is diagnostic, never a CI assertion;
failed numerical states must remain visible and cannot count as successful faster flashes.
Original file line number Diff line number Diff line change
Expand Up @@ -1154,9 +1154,9 @@ private double calculateVLP_BHP_DriftFlux(double flowRate) {
* @return calculated bottom-hole pressure in bara
*/
private double calculateVLP_BHP_TwoFluid(double flowRate) {
// Get fluid properties
// VLP uses intensive properties; apply the requested rate only to the velocities below.
// Retain the reference inventory to avoid roundoff at shut-in and near-zero trial rates.
SystemInterface tempFluid = reservoirStream.getThermoSystem().clone();
tempFluid.setTotalFlowRate(flowRate / 86400.0, "Sm3/sec");

// March up the tubing from wellhead to bottomhole
int numSegments = 20;
Expand Down
Loading
Loading