PyResToolbox - A collection of Reservoir Engineering Utilities

Overview

pyrestoolbox

A collection of Reservoir Engineering Utilities

This set of functions focuses on those that the author uses often while crafting programming solutions. These are the scripts that are often copy/pasted from previous work - sometimes slightly modified - resulting in a trail of slightly different versions over the years. Some attempt has been made here to make this implementation flexible enough such that it can be relied on as-is going forward.

Includes functions to perform simple calculations including;

  • Inflow for oil and gas
  • PVT Calculations for oil
  • PVT calculation for gas
  • Creation of Black Oil Table information
  • Creation of layered permeability distribution consistent with a Lorenze heterogeneity factor
  • Extract problem cells information from Intesect (IX) print files
  • Generation of AQUTAB include file influence functions for use in ECLIPSE
  • Creation of Corey and LET relative permeability tables in Eclipse format

This is the initial public release, with improvements and additions expected over time. Apologies in advance that it is only in oilfield units with no current plans to add multi-unit support.

Function List

Inflow
  • Gas Flow Rate Radial
  • Gas Flow Rate Linear
  • Oil Flow Rate Radial
  • Oil Flow Rate Linear
Gas PVT
  • Gas Tc & Pc Calculation
  • Gas Z-Factor Calculation
  • Gas Viscosity
  • Gas Viscosity * Z
  • Gas Compressibility
  • Gas Formation Volume Factor
  • Gas Density
  • Gas Water of Condensation
  • Convert P/Z to P
  • Convert Gas Gradient to SG
  • Delta Pseudopressure
  • Gas Condensate FWS SG
Oil PVT
  • Oil Density from MW
  • Oil Critical Properties with Twu
  • Incrememtal GOR post Separation
  • Oil Bubble Point Pressure
  • Oil GOR at Pb
  • Oil GOR at P
  • Oil Compressibility
  • Oil Density
  • Oil Formation Volume Factor
  • Oil Viscosity
  • Generate Black Oil Table data
  • Estimate soln gas SG from oil
  • Estimate SG of gas post separator
  • Calculate weighted average surface gas SG
Brine PVT
  • Calculate suite of brine properties
Permeability Layering
  • Lorenz coefficient from Beta value
  • Lorenz coefficient from flow fraction
  • Lorenz coefficient to flow fraction
  • Lorenz coefficient to permeability array
Simulation Helpers
  • Summarize IX convergence errors from PRT file
  • Create Aquifer Influence Functions
Relative Permeability
  • Create sets of rel perm tables

Getting Started

Install the library with pip:

pip install pyrestoolbox

Import library into your project and start using.

A simple example below of estimating oil bubble point pressure.

>>> from pyrestoolbox import pyrestoolbox as rtb
>>> rtb.oil_pbub(api=43, degf=185, rsb=2350, sg_g =0.72, pbmethod ='VALMC')
5179.51086900132

A set of Gas-Oil relative permeability curves with the LET method

>>> import matplotlib.pyplot as plt
>>> df = rtb.rel_perm(rows=25, krtable='SGOF', krfamily='LET', kromax =1, krgmax =1, swc =0.2, sorg =0.15, Lo=2.5, Eo = 1.25, To = 1.75, Lg = 1.2, Eg = 1.5, Tg = 2.0)
>>> plt.plot(df['Sg'], df['Krgo'], c = 'r', label='Gas')
>>> plt.plot(df['Sg'], df['Krog'], c = 'g', label='Oil')
>>> plt.title('SGOF Gas Oil LET Relative Permeability Curves')
>>> plt.xlabel('Sg')
>>> plt.ylabel('Kr')
>>> plt.legend()
>>> plt.grid('both')
>>> plt.plot()

SGOF Relative Permeability Curves

Or a set of Water-Oil relative permeability curves with the Corey method

>>> df = rtb.rel_perm(rows=25, krtable='SWOF', kromax =1, krwmax =0.25, swc =0.15, swcr = 0.2, sorw =0.15, no=2.5, nw=1.5)
>>> plt.plot(df['Sw'], df['Krow'], c = 'g', label='Oil')
>>> plt.plot(df['Sw'], df['Krwo'], c = 'b', label='Water')
>>> plt.title('SWOF Water Oil Corey Relative Permeability Curves')
>>> plt.xlabel('Sw')
>>> plt.ylabel('Kr')
>>> plt.legend()
>>> plt.grid('both')
>>> plt.plot()

SWOF Relative Permeability Curves

A set of dimensionless pressures for the constant terminal rate Van Everdingin & Hurst aquifer, along with an AQUTAB.INC export for use in ECLIPSE.

>>> ReDs = [1.5, 2, 3, 5, 10, 25, 1000]
>>> tds, pds = rtb.influence_tables(ReDs=ReDs, export=True)
>>>
>>> for p, pd in enumerate(pds):
>>>     plt.plot(tds, pd, label = str(ReDs[p]))
>>>
>>> plt.xscale('log')
>>> plt.yscale('log')
>>> plt.legend(loc='upper left')
>>> plt.grid(which='both')
>>> plt.xlabel('Dimensionless Time (tD)')
>>> plt.ylabel('Dimensionless Pressure Drop (PD)')
>>> plt.title('Constant Terminal Rate Solution')
>>> plt.show()

Constant Terminal Rate influence tables

Or creating black oil table information for oil

>>> results = rtb.make_bot_og(pi=4000, api=38, degf=175, sg_g=0.68, pmax=5000, pb=3900, rsb=2300, nrows=50)
>>> df, st_deno, st_deng, res_denw, res_cw, visw, pb, rsb, rsb_frac, usat = results['bot'], results['deno'], results['deng'], results['denw'], results['cw'], results['uw'], results['pb'], results['rsb'], results['rsb_scale'], results['usat']
>>> print('Stock Tank Oil Density:', st_deno, 'lb/cuft')
>>> print('Stock Tank Gas Density:', st_deng, 'lb/cuft')
>>> print('Reservoir Water Density:', res_denw, 'lb/cuft')
>>> print('Reservoir Water Compressibility:', res_cw, '1/psi')
>>> print('Reservoir Water Viscosity:', visw,'cP')

>>> fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(10,10))
>>> ax1.plot(df['Pressure (psia)'], df['Rs (scf/stb)'])
>>> ax2.plot(df['Pressure (psia)'], df['Bo (rb/stb)'])
>>> ax3.plot(df['Pressure (psia)'], df['uo (cP)'])
>>> ax4.semilogy(df['Pressure (psia)'], df['Co (1/psi)'])
>>> ...
>>> plt.show()
Stock Tank Oil Density: 52.05522123893805 lb/cuft
Stock Tank Gas Density: 0.052025361717109773 lb/cuft
Reservoir Water Density: 61.40223160167964 lb/cuft
Reservoir Water Compressibility: 2.930237693350768e-06 1/psi
Reservoir Water Viscosity: 0.3640686136171888 cP

Black Oil Properties

And gas

>>> fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(10,10))
>>> ax1.semilogy(df['Pressure (psia)'], df['Bg (rb/mscf'])
>>> ax2.plot(df['Pressure (psia)'], df['ug (cP)'])
>>> ax3.plot(df['Pressure (psia)'], df['Gas Z (v/v)'])
>>> ax4.semilogy(df['Pressure (psia)'], df['Cg (1/psi)'])
>>> ...
>>> plt.show()

Dry Gas Properties

With ability to generate Live Oil PVTO style table data as well

>>> pb = 4500
>>> results = rtb.make_bot_og(pvto=True, pi=4000, api=38, degf=175, sg_g=0.68, pmax=5500, pb=pb, nrows=25, export=True)
>>> df, st_deno, st_deng, res_denw, res_cw, visw, pb, rsb, rsb_frac, usat = results['bot'], results['deno'], results['deng'], results['denw'], results['cw'], results['uw'], results['pb'], results['rsb'], results['rsb_scale'], results['usat']
>>>
>>> if len(usat) == 0:
>>>     usat_flag = False
>>> else:
>>>     usat_flag=True
>>>     usat_p, usat_bo, usat_uo = usat
>>>
>>> try:
>>>     pb_idx = df['Pressure (psia)'].tolist().index(pb)
>>>     bob = df['Bo (rb/stb)'].iloc[pb_idx]
>>>     rsb = df['Rs (mscf/stb)'].iloc[pb_idx]
>>>     uob = df['uo (cP)'].iloc[pb_idx]
>>>     cob = df['Co (1/psi)'].iloc[pb_idx]
>>>     no_pb = False
>>> except:
>>>     print('Pb was > Pmax')
>>>     no_pb = True
>>>
>>> print('Pb (psia):', pb)
>>> print('Bob (rb/stb):', bob)
>>> print('Rsb (mscf/stb):', rsb)
>>> print('Rsb Scaling Required:', rsb_frac)
>>> print('Visob (cP):', uob)
>>> print('Cob (1/psi):', cob,'\n')
>>> print('Stock Tank Oil Density:', st_deno, 'lb/cuft')
>>> print('Stock Tank Gas Density:', st_deng, 'lb/cuft')
>>> print('Reservoir Water Density:', res_denw, 'lb/cuft')
>>> print('Reservoir Water Compressibility:', res_cw, '1/psi')
>>> print('Reservoir Water Viscosity:', visw,'cP')
>>>
>>> fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(10,10))
>>> ax1.plot(df['Pressure (psia)'], df['Rs (mscf/stb)'])
>>> ax2.plot(df['Pressure (psia)'], df['Bo (rb/stb)'])
>>> ax3.plot(df['Pressure (psia)'], df['uo (cP)'])
>>> ax4.semilogy(df['Pressure (psia)'], df['Co (1/psi)'])
>>>
>>> ax1.plot([pb], [rsb], 'o', c='r')
>>> ax2.plot([pb], [bob], 'o', c='r')
>>> ax3.plot([pb], [uob], 'o', c='r')
>>> ax4.plot([pb], [cob], 'o', c='r')
>>>
>>> if usat_flag:
>>>     if no_pb == False:
>>>         for i in range(len(usat_bo)):
>>>             ax2.plot(usat_p[i], usat_bo[i], c='k')
>>>             ax3.plot(usat_p[i], usat_uo[i], c='k')
>>>
>>> fig.suptitle('Black Oil Properties')
>>> ..
>>> ..
>>> plt.show()
Pb (psia): 4500
Bob (rb/stb): 1.6072798403441817
Rsb (mscf/stb): 1.2863705330979234
Rsb Scaling Required: 0.9713981737449556
Visob (cP): 0.3422139569449832
Cob (1/psi): 5.711273668114706e-05

Stock Tank Oil Density: 52.05522123893805 lb/cuft
Stock Tank Gas Density: 0.052025361717109773 lb/cuft
Reservoir Water Density: 61.40223160167964 lb/cuft
Reservoir Water Compressibility: 2.930237693350768e-06 1/psi
Reservoir Water Viscosity: 0.3640686136171888 cP

Live Oil Properties

Development

pyrestoolbox is maintained by Mark W. Burgoyne (https://github.com/mwburgoyne).

You might also like...
Python based utilities for interacting with digital multimeters that are built on the FS9721-LP3 chipset.

Python based utilities for interacting with digital multimeters that are built on the FS9721-LP3 chipset.

ZX Spectrum Utilities: (zx-spectrum-utils)
ZX Spectrum Utilities: (zx-spectrum-utils)

Here are a few utility programs that can be used with the zx spectrum. The ZX Spectrum is one of the first home computers from the early 1980s.

A collection of common regular expressions bundled with an easy to use interface.

CommonRegex Find all times, dates, links, phone numbers, emails, ip addresses, prices, hex colors, and credit card numbers in a string. We did the har

Finds price floor for every single attribute in a given collection

Solana Solanart Scanner Enjoy the Free Code Steps to run Download VS Code

Simple collection of GTPS Flood in Python.

GTPS Flood Simple collection of GTPS Flood in Python. NOTE Give me credit if you use this source, don't trade/sell this tool, And USE AT YOUR OWN RISK

A collection of custom scripts for working with Quake assets.

Custom Quake Tools A collection of custom scripts for working with Quake assets. Features Script to list all BSP files in a Quake mod

A collection of resources/tools and analyses for the angr binary analysis framework.

Awesome angr A collection of resources/tools and analyses for the angr binary analysis framework. This page does not only collect links and external r

Modest utility collection for development with AIOHTTP framework.

aiohttp-things Modest utility collection for development with AIOHTTP framework. Documentation https://aiohttp-things.readthedocs.io Installation Inst

Collection of code auto-generation utility scripts for the Horizon `Boot` system module

boot-scripts This is a collection of code auto-generation utility scripts for the Horizon Boot system module, intended for use in Atmosphère. Usage Us

Comments
  • refactor oil sg equations to func and correct 141.4 -> 141.5 per standard API equation

    refactor oil sg equations to func and correct 141.4 -> 141.5 per standard API equation

    There are 4 places in the source code where the oil/condensate specific gravity is calculated from the API. So I refactored those lines with the general equation near the top of the file.

    def oil_sg(api_value: float) -> float: """ Returns oil specific gravity given API value of oil api_value: API value """ return 141.5 / (api_value+131.5)

    The original 4 places the specific gravity was calculated using 141.4 (assume a typo). Petrowiki API Reference

    Thank you for the repo and I will continue reading the source code!

    opened by mwentzWW 1
Releases(1.3.8)
Owner
Mark W. Burgoyne
Principal Reservoir Engineer and Python enthusiast
Mark W. Burgoyne
Random Name and Slug Generator

Random Name and Slug Generator

Alexander Lukanin 104 Nov 30, 2022
A monitor than send discord webhook when a specific monitored product has stock in your nearby pickup stores.

Welcome to Apple In-store Monitor This is a monitor that are not fully scaled, and might still have some bugs.

5 Jun 16, 2022
A fast Python implementation of Ac Auto Mechine

A fast Python implementation of Ac Auto Mechine

Jin Zitian 1 Dec 07, 2021
A python module to validate input.

A python module to validate input.

Matthias 6 Sep 13, 2022
Adding two matrix from scratch using python.

Adding-two-matrix-from-scratch-using-python. Here, I have take two matrix from user and add it without using any library. I made this program from scr

Sachin Vinayak Dabhade 4 Sep 24, 2021
A pythonic dependency injection library.

Pinject Pinject is a dependency injection library for python. The primary goal of Pinject is to help you assemble objects into graphs in an easy, main

Google 1.3k Dec 30, 2022
✨ Un générateur de lien raccourcis en fonction d'un lien totalement fait en Python par moi, et en français.

Shorter Link ❗ Un générateur de lien raccourcis en fonction d'un lien totalement fait en Python par moi, et en français. Dépendences : pip install pys

MrGabin 3 Jun 06, 2021
Tool for generating Memory.scan() compatible instruction search patterns

scanpat Tool for generating Frida Memory.scan() compatible instruction search patterns. Powered by r2. Examples $ ./scanpat.py arm.ks:64 'sub sp, sp,

Ole André Vadla Ravnås 13 Sep 19, 2022
Simplex using Jordan exchanges taught in 236A

Simplex for 236A Python script to solve LP using simplex by Jordan exchanges taught in 236A. You will need python installed along with the 'numpy' and

Kunal Kishore 1 Nov 30, 2021
New time-based UUID formats which are suited for use as a database key

uuid6 New time-based UUID formats which are suited for use as a database key. This module extends immutable UUID objects (the UUID class) with the fun

26 Dec 30, 2022
✨ Un juste prix totalement fait en Python par moi, et en français.

Juste Prix ❗ Un juste prix totalement fait en Python par moi, et en français. 🔮 Avec l'utilisation du module "random", j'ai pu faire un choix aléatoi

MrGabin 3 Jun 06, 2021
Tools for binary data on cassette

Micro Manchester Tape Storage Tools for storing binary data on cassette Includes: Python script for encoding Arduino sketch for decoding Eagle CAD fil

Zack Nelson 28 Dec 25, 2022
Cardano Stakepools: Check for scheduled blocks in current epoch.

ReLeaderLogs For Cardano Stakepool Operators: Lightweight Scheduled Blocks Checker for Current Epoch. No cardano-node Required, data is taken from blo

SNAKE (Cardano Stakepool) 2 Oct 19, 2021
A quick random name generator

Random Profile Generator USAGE & CREDITS Any public or priavte demonstrative usage of this project is strictly prohibited, UNLESS WhineyMonkey10 (http

2 May 05, 2022
Simple RGB to HEX game made in python

Simple RGB to HEX game made in python

5 Aug 26, 2022
A simulator for xkcd 2529's weirdly concrete problem

What is this? This is a quick hack implementation of a simulator for xkcd 2529's weirdly concrete problem. This is barely tested and I suck at computa

Reuben Steenekamp 6 Oct 27, 2021
Casefy (/keɪsfaɪ/) is a lightweight Python package to convert the casing of strings

Casefy (/keɪsfaɪ/) is a lightweight Python package to convert the casing of strings. It has no third-party dependencies and supports Unicode.

Diego Miguel Lozano 12 Jan 08, 2023
A python module to update the console without flashing.

A python module to update the console without flashing.

Matthias 112 Dec 19, 2022
A string extractor module for python

A string extractor module for python

Fayas Noushad 4 Jul 19, 2022
BOLT12 Lightning Address Format

BOLT12 Address Support (DRAFT!) Inspired by the awesome lightningaddress.com, except for BOLT12: Supports BOLT12 Allows BOLT12 vendor string authentic

Rusty Russell 28 Sep 14, 2022