Difference between revisions of "PVT API"
(→Plots property curves) |
(→Phyton Quick Start) |
||
| (18 intermediate revisions by the same user not shown) | |||
| Line 3: | Line 3: | ||
==PVT API== | ==PVT API== | ||
The PVT calculator models reservoir fluid properties (oil, gas, water) over a pressure range using various correlations, and returns property curves (plots), single‑point reservoir‑condition values (solution), and a stepped property table (results) available in [[:Category:PVT|PVT calculator]] of the [[:Category: Pengtools | pengtools]]. | The PVT calculator models reservoir fluid properties (oil, gas, water) over a pressure range using various correlations, and returns property curves (plots), single‑point reservoir‑condition values (solution), and a stepped property table (results) available in [[:Category:PVT|PVT calculator]] of the [[:Category: Pengtools | pengtools]]. | ||
| + | |||
| + | ==Python Quick Start== | ||
==Endpoints== | ==Endpoints== | ||
| Line 28: | Line 30: | ||
|} | |} | ||
| − | Use /calc (synchronous) for normal interactive requests — a single PVT model computes in well under a second and the result comes back in the HTTP response. | + | Use <code>/calc</code> (synchronous) for normal interactive requests — a single PVT model computes in well under a second and the result comes back in the HTTP response. |
| − | Use /calc-async only for batch/heavy workloads where you would rather not hold an open HTTP connection. The async path enqueues an api_task row that is picked up by the CalcDaemon worker; you then poll status and fetch output-data. The async job runs the same calculatePvt() code as the sync endpoint, so the result is identical for identical input. | + | Use <code>/calc-async</code> only for batch/heavy workloads where you would rather not hold an open HTTP connection. The async path enqueues an <code>api_task</code> row that is picked up by the <code>CalcDaemon</code> worker; you then poll <code>status</code> and fetch <code>output-data</code> . The async job runs the same <code>calculatePvt()</code> code as the sync endpoint, so the result is identical for identical input. |
==Synchronous request== | ==Synchronous request== | ||
| Line 36: | Line 38: | ||
POST /pvt-calculator/calc | POST /pvt-calculator/calc | ||
| − | The request body is a JSON object containing PVT calculator attributes plus two optional unit-control keys: | + | The request body is a JSON object containing PVT calculator attributes plus two optional unit-control keys (see Units): |
| − | + | <pre> | |
| + | { | ||
"unit_system": "RU", | "unit_system": "RU", | ||
"defaultFluidType": "OIL", | "defaultFluidType": "OIL", | ||
| Line 49: | Line 52: | ||
"sgGas": 0.75, | "sgGas": 0.75, | ||
"sgWater": 1.0 | "sgWater": 1.0 | ||
| − | + | } | |
| − | + | </pre> | |
On success the endpoint returns HTTP 200 with: | On success the endpoint returns HTTP 200 with: | ||
| Line 56: | Line 59: | ||
Where <code>data</code> carries: | Where <code>data</code> carries: | ||
| − | * plots — property curves | + | * <code>plots</code> — property curves |
| − | * solution — single-point reservoir-condition values | + | * <code>solution</code> — single-point reservoir-condition values |
| − | * results — stepped property table | + | * <code>results</code> — stepped property table |
==Units== | ==Units== | ||
| Line 64: | Line 67: | ||
Input field names (e.g., maximumPressure, temperature) carry no unit. The unit system determines how values are interpreted. | Input field names (e.g., maximumPressure, temperature) carry no unit. The unit system determines how values are interpreted. | ||
| − | + | <code>unit_system</code> a shortcut that applies a whole preset of units. Accepted values (case‑insensitive): | |
| − | |||
* METRIC - Metric system | * METRIC - Metric system | ||
* FIELD - Field system | * FIELD - Field system | ||
| − | Example | + | ====Example==== |
| − | + | <pre> | |
| + | { | ||
"unit_system": "METRIC", | "unit_system": "METRIC", | ||
"maximumPressure": 300, | "maximumPressure": 300, | ||
"temperature": 90 | "temperature": 90 | ||
| − | + | } | |
| + | </pre> | ||
===Attribute units=== | ===Attribute units=== | ||
| Line 147: | Line 151: | ||
On success, data contains up to three blocks, gated by <code>needPlots / needSolution / needResults</code>. Each block is keyed by fluid (<code>OIL, GAS, WATER</code>) — only the fluids in <code>forFluid</code> (and, for oil curves, only when <code>defaultFluidType is OIL</code>) are present. | On success, data contains up to three blocks, gated by <code>needPlots / needSolution / needResults</code>. Each block is keyed by fluid (<code>OIL, GAS, WATER</code>) — only the fluids in <code>forFluid</code> (and, for oil curves, only when <code>defaultFluidType is OIL</code>) are present. | ||
| − | === | + | ===Plots - property curves=== |
Each fluid maps curve names to an array of [pressure, value] pairs, one pair per pressure step (200 steps by default). The pressure axis is in the output pressure unit (see Units section). | Each fluid maps curve names to an array of [pressure, value] pairs, one pair per pressure step (200 steps by default). The pressure axis is in the output pressure unit (see Units section). | ||
| Line 161: | Line 165: | ||
|} | |} | ||
| − | Example | + | ====Example==== |
<pre> | <pre> | ||
| Line 173: | Line 177: | ||
</pre> | </pre> | ||
| + | ===Solution - reservoir‑condition values=== | ||
| + | Single scalar values evaluated at reservoir conditions. | ||
| + | |||
| + | {| class="wikitable" | ||
| + | |- | ||
| + | ! Fluid !! Keys | ||
| + | |- | ||
| + | | OIL || solution_pBubble, solution_rsb, solution_Rs, solution_compressibility, solution_density, solution_fvf, solution_deadOilViscosity, solution_viscosity, solution_tension | ||
| + | |- | ||
| + | | GAS || solution_ZFactor, solution_compressibilitygas, solution_densitygas, solution_fvfgas, solution_viscositygas | ||
| + | |- | ||
| + | | WATER || solution_compressibilitywater, solution_densitywater, solution_fvfwater, solution_viscositywater, solution_tensionwater | ||
| + | |} | ||
| + | |||
| + | ====Example==== | ||
| + | <pre> | ||
| + | "solution": { | ||
| + | "OIL": { | ||
| + | "solution_pBubble": 115.0, | ||
| + | "solution_rsb": 60.0, | ||
| + | "solution_density": 756.0, | ||
| + | "solution_fvf": 1.197 | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | ===Results - stepped table=== | ||
| + | Each fluid maps to a list of rows. The first row is standard conditions; the next nine rows are stepped pressures between the bubble point (oil) or p/2 (gas/water) and the maximum pressure. Each row is a positional array with these columns: | ||
| + | |||
| + | {| class="wikitable" | ||
| + | |- | ||
| + | ! Fluid !! Columns (in order) | ||
| + | |- | ||
| + | | OIL || pressure, Rs, density, fvf, viscosity, temperature, compressibility, tension | ||
| + | |- | ||
| + | | GAS || pressure, ZFactor, densitygas, fvfgas, viscositygas, temperature, compressibilitygas | ||
| + | |- | ||
| + | | WATER || pressure, compressibilitywater, densitywater, fvfwater, viscositywater, temperature, tensionwater | ||
| + | |} | ||
| + | |||
| + | <pre> | ||
| + | "results": { | ||
| + | "OIL": [ | ||
| + | [1.0, 0.0, 845.0, 1.01, 2.1, 20.0, 0.00012, 30.5], | ||
| + | [12.8, 22.0, 812.4, 1.08, 1.6, 90.0, 0.00018, 12.1], | ||
| + | "… 8 more rows …" | ||
| + | ] | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | ==HTTP status codes== | ||
| + | {| class="wikitable" | ||
| + | |- | ||
| + | ! Status !! Meaning !! Body (data) | ||
| + | |- | ||
| + | | 200 || Success || { plots, solution, results } | ||
| + | |- | ||
| + | | 401 || Missing or invalid API key || Yii error payload | ||
| + | |- | ||
| + | | 404 || Unknown async token || Yii error payload | ||
| + | |- | ||
| + | | 422 || Validation / calculation error || { "errors": … } | ||
| + | |- | ||
| + | | 429 || Rate limit exceeded || error message | ||
| + | |} | ||
| + | |||
| + | ===422 - validation and calculation errors=== | ||
| + | Field validation errors are keyed by attribute: | ||
| + | { "success": false, "data": { "errors": { "temperature": ["Temperature must be no less than 529.47."] } } } | ||
| + | Errors raised while loading the body or running the calculation (e.g. an unknown <code>defaultFluidType</code>, or a physical guard inside <code>calculatePvt()</code>) come back as a flat list: | ||
| + | { "success": false, "data": { "errors": ["Invalid input: Wrong default fluid type"] } } | ||
| + | |||
| + | ===429 - rate limiting=== | ||
| + | Limits are per API key over a 60‑second window, and the cap depends on the license tier that grants access to the <code>pvtCalculator</code> module. | ||
| + | |||
| + | ==Asynchronous flow== | ||
| + | |||
| + | <pre> | ||
| + | POST /pvt-calculator/calc-async → { "token": "<token>" } | ||
| + | GET /pvt-calculator/<token>/status → { "status": <code>, "progress": <number> } | ||
| + | GET /pvt-calculator/<token>/output-data → { plots, solution, results } | ||
| + | </pre> | ||
| + | |||
| + | <code>status</code> is returned as a numeric code (the raw api_task.status value), not a string: | ||
| + | |||
| + | {| class="wikitable" | ||
| + | |- | ||
| + | ! Code !! Meaning | ||
| + | |- | ||
| + | | 1 || CREATED | ||
| + | |- | ||
| + | | 2 || IN_PROGRESS | ||
| + | |- | ||
| + | | 3 || ERROR | ||
| + | |- | ||
| + | | 4 || STOPPED | ||
| + | |- | ||
| + | | 5 || SUCCESS | ||
| + | |} | ||
| + | |||
| + | A job cycles 1 → 2 → 5 (or 3 / 4). Poll <code>status</code> until it reaches a terminal code (3, 4, 5), then fetch <code>output-data</code> when it is 5. The <code>CalcDaemon </code>worker must be running for jobs to progress. | ||
[[Category:API]] | [[Category:API]] | ||
Latest revision as of 11:07, 15 July 2026
Contents
PVT API
The PVT calculator models reservoir fluid properties (oil, gas, water) over a pressure range using various correlations, and returns property curves (plots), single‑point reservoir‑condition values (solution), and a stepped property table (results) available in PVT calculator of the pengtools.
Python Quick Start
Endpoints
All endpoints require the Authorization: Bearer <api_key> header and are subject to rate limiting. The response envelope is always { "success": <bool>, "data": <payload> }
| Method | Path | Purpose |
|---|---|---|
| POST | /pvt-calculator/calc | Synchronous — compute and return the result in the same request |
| POST | /pvt-calculator/calc-async | Asynchronous — enqueue a job, return a {token} |
| GET | /pvt-calculator/{token}/status | Job status and progress |
| GET | /pvt-calculator/{token}/output-data | Job result (same shape as the sync data) |
| GET | /pvt-calculator/{token}/input-data | The input the job was created with |
| POST | /pvt-calculator/{token}/start | Reset and re-run the job |
| POST | /pvt-calculator/{token}/stop | Stop a running job |
| DELETE | /pvt-calculator/{token} | Delete the job |
Use /calc (synchronous) for normal interactive requests — a single PVT model computes in well under a second and the result comes back in the HTTP response.
Use /calc-async only for batch/heavy workloads where you would rather not hold an open HTTP connection. The async path enqueues an api_task row that is picked up by the CalcDaemon worker; you then poll status and fetch output-data . The async job runs the same calculatePvt() code as the sync endpoint, so the result is identical for identical input.
Synchronous request
POST /pvt-calculator/calc
The request body is a JSON object containing PVT calculator attributes plus two optional unit-control keys (see Units):
{
"unit_system": "RU",
"defaultFluidType": "OIL",
"maximumPressure": 300,
"reservoirPressure": 300,
"temperature": 90,
"pBubbleInitial": 200,
"rsbInitial": 60,
"isRsbUsedForPb": true,
"sgOil": 0.85,
"sgGas": 0.75,
"sgWater": 1.0
}
On success the endpoint returns HTTP 200 with:
{ "success": true, "data": { "plots": {},"solution": {}, "results": {} } }
Where data carries:
-
plots— property curves -
solution— single-point reservoir-condition values -
results— stepped property table
Units
Input field names (e.g., maximumPressure, temperature) carry no unit. The unit system determines how values are interpreted.
unit_system a shortcut that applies a whole preset of units. Accepted values (case‑insensitive):
- METRIC - Metric system
- FIELD - Field system
Example
{
"unit_system": "METRIC",
"maximumPressure": 300,
"temperature": 90
}
Attribute units
| Field | METRIC | FIELD |
|---|---|---|
| maximumPressure | ATM | PSIA |
| minimumPressure | ATM | PSIA |
| reservoirPressure | ATM | PSIA |
| pBubbleInitial | ATM | PSIA |
| temperature | CELSIUS | FAHRENHEIT |
| rsbInitial | M3_PER_M3 | SCF_PER_BBL |
| sgOil | SPECIFIC_GRAVITY | API |
| sgGas | SPECIFIC_GRAVITY | SPECIFIC_GRAVITY |
| sgWater | SPECIFIC_GRAVITY | SPECIFIC_GRAVITY |
Input parameter specification
Ranges below are expressed in internal units (the units the validator sees), with common METRIC/FIELD equivalents for convenience.
| Field | Required | Internal unit | Range (internal) | METRIC | FIELD | Notes |
|---|---|---|---|---|---|---|
| defaultFluidType | yes | — | OIL or GAS | — | — | Selects the primary fluid path. WATER is only valid inside forFluid. |
| maximumPressure | yes | PSIA | 25 … 10000 | ≈ 1.7 … 680 ATM | 25 … 10000 psi | Upper bound of the pressure sweep. |
| minimumPressure | no (default 14.6) | PSIA | 14.6 … 10000 | ≈ 1.0 … 680 ATM | 14.6 … 10000 psi | Lower bound of the sweep; must be ≤ maximumPressure. |
| reservoirPressure | yes | PSIA | 25 … 10000 | ≈ 1.7 … 680 ATM | 25 … 10000 psi | Reservoir-condition pressure for solution. |
| temperature | yes | RANKIN | 529.47 … 851.67 | ≈ 21 … 200 °C | ≈ 70 … 392 °F | Reservoir-condition temperature for solution. |
| pBubbleInitial | yes | PSIA | 0 … 20000 | ≈ 0 … 1361 ATM | 0 … 20000 psi | Initial bubble point. See isRsbUsedForPb. |
| rsbInitial | yes (when OIL) | M3_PER_M3 | > 0 | m³·m⁻³ | scf/bbl | Solution GOR at bubble point. |
| sgOil | yes | SPECIFIC_GRAVITY | 0.75 … 0.99 | 0.75 … 0.99 SG | ≈ 11.4 … 57.2 °API | Oil specific gravity. US system accepts API. |
| sgGas | yes | SPECIFIC_GRAVITY | 0.55 … 1.8 | 0.55 … 1.8 SG | 0.55 … 1.8 SG | Gas specific gravity (air = 1). |
| sgWater | yes | SPECIFIC_GRAVITY | 0.9 … 1.2 | 0.9 … 1.2 SG | 0.9 … 1.2 SG | Water specific gravity. |
| isRsbUsedForPb | no (default false) | bool | true / false | — | — | true: derive bubble point from rsbInitial. false: derive GOR from pBubbleInitial. |
| forFluid | no (default all) | — | subset of OIL,GAS,WATER | — | — | Which fluids to compute. |
| needPlots | no (default true) | bool | true / false | — | — | Include the plots block. |
| needSolution | no (default true) | bool | true / false | — | — | Include the solution block. |
| needResults | no (default true) | bool | true / false | — | — | Include the results block. |
Notes
For an oil model, both pBubbleInitial and rsbInitialare required; isRsbUsedForPb decides which one is the input and which is derived.
Response format
On success, data contains up to three blocks, gated by needPlots / needSolution / needResults. Each block is keyed by fluid (OIL, GAS, WATER) — only the fluids in forFluid (and, for oil curves, only when defaultFluidType is OIL) are present.
Plots - property curves
Each fluid maps curve names to an array of [pressure, value] pairs, one pair per pressure step (200 steps by default). The pressure axis is in the output pressure unit (see Units section).
| Fluid | Curves |
|---|---|
| OIL | Rs, density, fvf, viscosity, tension, compressibility |
| GAS | ZFactor, densitygas, fvfgas, viscositygas, compressibilitygas |
| WATER | densitywater, fvfwater, viscositywater, compressibilitywater, tensionwater |
Example
"plots": {
"OIL": {
"Rs": [[14.6, 0.0], [36.4, 5.1], "…", [4351.13, 200.0]],
"fvf": [[14.6, 1.02], "…"],
"density": [[14.6, 812.4], "…"]
}
}
Solution - reservoir‑condition values
Single scalar values evaluated at reservoir conditions.
| Fluid | Keys |
|---|---|
| OIL | solution_pBubble, solution_rsb, solution_Rs, solution_compressibility, solution_density, solution_fvf, solution_deadOilViscosity, solution_viscosity, solution_tension |
| GAS | solution_ZFactor, solution_compressibilitygas, solution_densitygas, solution_fvfgas, solution_viscositygas |
| WATER | solution_compressibilitywater, solution_densitywater, solution_fvfwater, solution_viscositywater, solution_tensionwater |
Example
"solution": {
"OIL": {
"solution_pBubble": 115.0,
"solution_rsb": 60.0,
"solution_density": 756.0,
"solution_fvf": 1.197
}
}
Results - stepped table
Each fluid maps to a list of rows. The first row is standard conditions; the next nine rows are stepped pressures between the bubble point (oil) or p/2 (gas/water) and the maximum pressure. Each row is a positional array with these columns:
| Fluid | Columns (in order) |
|---|---|
| OIL | pressure, Rs, density, fvf, viscosity, temperature, compressibility, tension |
| GAS | pressure, ZFactor, densitygas, fvfgas, viscositygas, temperature, compressibilitygas |
| WATER | pressure, compressibilitywater, densitywater, fvfwater, viscositywater, temperature, tensionwater |
"results": {
"OIL": [
[1.0, 0.0, 845.0, 1.01, 2.1, 20.0, 0.00012, 30.5],
[12.8, 22.0, 812.4, 1.08, 1.6, 90.0, 0.00018, 12.1],
"… 8 more rows …"
]
}
HTTP status codes
| Status | Meaning | Body (data) |
|---|---|---|
| 200 | Success | { plots, solution, results } |
| 401 | Missing or invalid API key | Yii error payload |
| 404 | Unknown async token | Yii error payload |
| 422 | Validation / calculation error | { "errors": … } |
| 429 | Rate limit exceeded | error message |
422 - validation and calculation errors
Field validation errors are keyed by attribute:
{ "success": false, "data": { "errors": { "temperature": ["Temperature must be no less than 529.47."] } } }
Errors raised while loading the body or running the calculation (e.g. an unknown defaultFluidType, or a physical guard inside calculatePvt()) come back as a flat list:
{ "success": false, "data": { "errors": ["Invalid input: Wrong default fluid type"] } }
429 - rate limiting
Limits are per API key over a 60‑second window, and the cap depends on the license tier that grants access to the pvtCalculator module.
Asynchronous flow
POST /pvt-calculator/calc-async → { "token": "<token>" }
GET /pvt-calculator/<token>/status → { "status": <code>, "progress": <number> }
GET /pvt-calculator/<token>/output-data → { plots, solution, results }
status is returned as a numeric code (the raw api_task.status value), not a string:
| Code | Meaning |
|---|---|
| 1 | CREATED |
| 2 | IN_PROGRESS |
| 3 | ERROR |
| 4 | STOPPED |
| 5 | SUCCESS |
A job cycles 1 → 2 → 5 (or 3 / 4). Poll status until it reaches a terminal code (3, 4, 5), then fetch output-data when it is 5. The CalcDaemon worker must be running for jobs to progress.
