Python package for reading and writing reservoir simulator result files including RESTART, INIT, RFT, Summary and GRID files in various formats.
—
Comprehensive utility classes and functions supporting core ResData functionality including vector operations, time handling, random number generation, data type management, and testing utilities.
Type-specific vector classes providing high-performance array operations with seamless NumPy integration.
class IntVector:
"""Integer vector operations with dynamic resizing."""
def __init__(self, initial_size: int = 0, default_value: int = 0):
"""
Create integer vector.
Args:
initial_size (int): Initial size
default_value (int): Default value for new elements
"""
def append(self, value: int):
"""Append value to vector."""
def pop(self) -> int:
"""Remove and return last element."""
def get_max(self) -> int:
"""Get maximum value."""
def get_min(self) -> int:
"""Get minimum value."""
def get_max_index(self) -> int:
"""Get index of maximum value."""
def get_min_index(self) -> int:
"""Get index of minimum value."""
def shift(self, offset: int):
"""Shift all values by offset."""
def scale(self, factor: int):
"""Scale all values by factor."""
def sum(self) -> int:
"""Sum all elements."""
def sort(self):
"""Sort in ascending order."""
def rsort(self):
"""Sort in descending order."""
def safe_get(self, index: int) -> int:
"""Get value with bounds checking."""
def set_default(self, default_value: int):
"""Set default value for new elements."""
def numpy_copy(self) -> numpy.ndarray:
"""Get NumPy array copy."""
class DoubleVector:
"""Double precision vector operations."""
def __init__(self, initial_size: int = 0, default_value: float = 0.0):
"""Create double vector."""
def append(self, value: float):
"""Append value to vector."""
def pop(self) -> float:
"""Remove and return last element."""
def get_max(self) -> float:
"""Get maximum value."""
def get_min(self) -> float:
"""Get minimum value."""
def get_max_index(self) -> int:
"""Get index of maximum value."""
def get_min_index(self) -> int:
"""Get index of minimum value."""
def shift(self, offset: float):
"""Shift all values by offset."""
def scale(self, factor: float):
"""Scale all values by factor."""
def sum(self) -> float:
"""Sum all elements."""
def sort(self):
"""Sort in ascending order."""
def rsort(self):
"""Sort in descending order."""
def safe_get(self, index: int) -> float:
"""Get value with bounds checking."""
def set_default(self, default_value: float):
"""Set default value for new elements."""
def numpy_copy(self) -> numpy.ndarray:
"""Get NumPy array copy."""
class BoolVector:
"""Boolean vector operations."""
def __init__(self, initial_size: int = 0, default_value: bool = False):
"""Create boolean vector."""
def append(self, value: bool):
"""Append value to vector."""
def pop(self) -> bool:
"""Remove and return last element."""
def count_true(self) -> int:
"""Count True values."""
def count_false(self) -> int:
"""Count False values."""
def all_true(self) -> bool:
"""Check if all values are True."""
def any_true(self) -> bool:
"""Check if any value is True."""
def safe_get(self, index: int) -> bool:
"""Get value with bounds checking."""
def set_default(self, default_value: bool):
"""Set default value for new elements."""
def numpy_copy(self) -> numpy.ndarray:
"""Get NumPy array copy."""Specialized vector for time-based data with date/time functionality.
class TimeVector:
"""Time vector operations for datetime data."""
def __init__(self):
"""Create time vector."""
def append(self, time: datetime):
"""Append datetime to vector."""
def get_data_ptr(self) -> list:
"""Get internal data pointer."""
def active_list(self) -> list:
"""Get list of active time points."""
def select_matching(self, pattern: str) -> BoolVector:
"""Select times matching pattern."""
def get_active_mask(self) -> BoolVector:
"""Get mask of active time points."""String list container with search and manipulation capabilities.
class StringList:
"""String list operations and management."""
def __init__(self):
"""Create empty string list."""
def append(self, string: str):
"""Append string to list."""
def get_last(self) -> str:
"""Get last string."""
def pop(self) -> str:
"""Remove and return last string."""
def sort(self):
"""Sort strings alphabetically."""
def contains(self, string: str) -> bool:
"""Check if string is in list."""
def find_first(self, string: str) -> int:
"""Find first occurrence index."""
def size(self) -> int:
"""Get number of strings."""Hash table implementations for different data types with key-value storage.
class Hash:
"""Generic hash table operations."""
def __init__(self):
"""Create empty hash table."""
def insert(self, key: str, value):
"""Insert key-value pair."""
def get(self, key: str):
"""Get value by key."""
def has_key(self, key: str) -> bool:
"""Check if key exists."""
def keys(self) -> list:
"""Get list of keys."""
def values(self) -> list:
"""Get list of values."""
def clear(self):
"""Clear all entries."""
def size(self) -> int:
"""Get number of entries."""
class StringHash(Hash):
"""String-specific hash table."""
def insert(self, key: str, value: str):
"""Insert string key-value pair."""
def get(self, key: str) -> str:
"""Get string value by key."""
class IntegerHash(Hash):
"""Integer-specific hash table."""
def insert(self, key: str, value: int):
"""Insert integer key-value pair."""
def get(self, key: str) -> int:
"""Get integer value by key."""
class DoubleHash(Hash):
"""Double-specific hash table."""
def insert(self, key: str, value: float):
"""Insert double key-value pair."""
def get(self, key: str) -> float:
"""Get double value by key."""C-based time operations providing high-performance datetime functionality.
class CTime:
"""C-based time handling and operations."""
def __init__(self, time_input=None):
"""
Create CTime object.
Args:
time_input: datetime, timestamp, or None for current time
"""
def datetime(self) -> datetime:
"""Convert to Python datetime."""
def ctime(self) -> str:
"""Get C-style time string."""
def stripped_copy(self) -> CTime:
"""Create copy with stripped time components."""
def set_date(self, year: int, month: int, day: int):
"""Set date components."""
def date(self) -> tuple:
"""Get (year, month, day) tuple."""
def year(self) -> int:
"""Get year."""
def month(self) -> int:
"""Get month."""
def mday(self) -> int:
"""Get day of month."""Permutation vector for sorting and reordering operations.
class PermutationVector:
"""Permutation operations for data reordering."""
def __init__(self, size: int):
"""Create permutation vector."""
def sort_vector(self, data_vector):
"""Sort vector using permutation."""
def permute_vector(self, data_vector):
"""Apply permutation to vector."""High-quality random number generation with multiple algorithms.
class RandomNumberGenerator:
"""Random number generation with configurable algorithms."""
def __init__(self, algorithm: RngAlgTypeEnum = RngAlgTypeEnum.MZRAN,
init_mode: RngInitModeEnum = RngInitModeEnum.INIT_DEFAULT):
"""
Create random number generator.
Args:
algorithm: RNG algorithm type
init_mode: Initialization mode
"""
def get_double(self) -> float:
"""Get random double [0, 1)."""
def get_int(self, max_value: int) -> int:
"""Get random integer [0, max_value)."""
def seed(self, seed_value: int):
"""Set random seed."""
def state_size(self) -> int:
"""Get state size in bytes."""Lookup table operations for interpolation and data mapping.
class LookupTable:
"""Lookup table for interpolation and mapping."""
def __init__(self):
"""Create empty lookup table."""
def append(self, x: float, y: float):
"""Add (x, y) point to table."""
def get_value(self, x: float) -> float:
"""Get interpolated value at x."""
def has_key(self, x: float) -> bool:
"""Check if exact key exists."""
def size(self) -> int:
"""Get number of points."""
def get_min_arg(self) -> float:
"""Get minimum x value."""
def get_max_arg(self) -> float:
"""Get maximum x value."""Version and build information access.
class ResdataVersion:
"""ResData version and build information."""
@staticmethod
def versionString() -> str:
"""Get version string."""
@staticmethod
def versionTuple() -> tuple:
"""Get version tuple (major, minor, patch)."""
@staticmethod
def isDevelVersion() -> bool:
"""Check if development version."""
@staticmethod
def getGitCommit() -> str:
"""Get git commit hash."""
@staticmethod
def getBuildTime() -> str:
"""Get build timestamp."""Context managers for working directory and other state management.
class CWDContext:
"""Context manager for working directory changes."""
def __init__(self, path: str):
"""
Create working directory context.
Args:
path (str): Target directory path
"""
def __enter__(self):
"""Enter context and change directory."""
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""Exit context and restore directory."""from resdata.util import IntVector, DoubleVector, BoolVector
import numpy as np
# Create and populate integer vector
int_vec = IntVector()
for i in range(10):
int_vec.append(i * i) # Square numbers
print(f"Integer vector size: {int_vec.size()}")
print(f"Max value: {int_vec.get_max()}")
print(f"Min value: {int_vec.get_min()}")
print(f"Sum: {int_vec.sum()}")
# Convert to NumPy for advanced operations
int_array = int_vec.numpy_copy()
print(f"NumPy array: {int_array}")
print(f"Mean: {np.mean(int_array):.2f}")
# Double vector operations
double_vec = DoubleVector(5, 1.0) # Size 5, default value 1.0
double_vec.scale(2.5) # Scale all values
double_vec.shift(10.0) # Add offset
# Boolean vector for masking
bool_vec = BoolVector()
for val in int_array:
bool_vec.append(val > 25) # Values greater than 25
print(f"Values > 25: {bool_vec.count_true()}/{bool_vec.size()}")from resdata.util import StringHash, DoubleHash
# String mapping
well_types = StringHash()
well_types.insert("PROD01", "Producer")
well_types.insert("INJ01", "Water Injector")
well_types.insert("INJ02", "Gas Injector")
print("Well Types:")
for key in well_types.keys():
print(f" {key}: {well_types.get(key)}")
# Numerical properties
well_rates = DoubleHash()
well_rates.insert("PROD01", 150.5)
well_rates.insert("PROD02", 89.2)
well_rates.insert("PROD03", 234.7)
# Find maximum rate
max_rate = 0.0
max_well = ""
for key in well_rates.keys():
rate = well_rates.get(key)
if rate > max_rate:
max_rate = rate
max_well = key
print(f"Highest rate: {max_well} at {max_rate} m³/day")from resdata.util import CTime, TimeVector
from datetime import datetime, timedelta
# Create time objects
start_time = CTime(datetime(2020, 1, 1))
current_time = CTime() # Current time
print(f"Start date: {start_time.datetime()}")
print(f"Current time: {current_time.datetime()}")
# Work with time components
year = start_time.year()
month = start_time.month()
day = start_time.mday()
print(f"Start date components: {year}-{month:02d}-{day:02d}")
# Time vector for series data
time_series = TimeVector()
base_date = datetime(2020, 1, 1)
for i in range(12):
month_date = base_date + timedelta(days=30*i)
time_series.append(month_date)
print(f"Time series length: {len(time_series.active_list())}")from resdata.util import LookupTable
import numpy as np
# Create pressure-depth relationship
pressure_depth = LookupTable()
# Add data points (depth in meters, pressure in bar)
depths = [0, 500, 1000, 1500, 2000, 2500, 3000]
pressures = [1, 51, 101, 151, 201, 251, 301] # Hydrostatic + formation pressure
for depth, pressure in zip(depths, pressures):
pressure_depth.append(depth, pressure)
print(f"Lookup table size: {pressure_depth.size()}")
print(f"Depth range: {pressure_depth.get_min_arg():.0f} - {pressure_depth.get_max_arg():.0f} m")
# Interpolate pressures
test_depths = [750, 1250, 2750]
for depth in test_depths:
pressure = pressure_depth.get_value(depth)
print(f"Pressure at {depth}m: {pressure:.1f} bar")from resdata.util import RandomNumberGenerator, RngAlgTypeEnum
import numpy as np
# Create random number generator
rng = RandomNumberGenerator(RngAlgTypeEnum.MZRAN)
rng.seed(42) # Set seed for reproducibility
# Generate random data
random_doubles = [rng.get_double() for _ in range(1000)]
random_ints = [rng.get_int(100) for _ in range(1000)]
print(f"Random doubles: min={min(random_doubles):.3f}, max={max(random_doubles):.3f}")
print(f"Random ints: min={min(random_ints)}, max={max(random_ints)}")
# Statistical analysis
doubles_array = np.array(random_doubles)
print(f"Mean: {np.mean(doubles_array):.3f}")
print(f"Std dev: {np.std(doubles_array):.3f}")
# Generate normally distributed values (Box-Muller transform)
normal_values = []
for i in range(0, 1000, 2):
u1 = rng.get_double()
u2 = rng.get_double()
# Box-Muller transform
z1 = np.sqrt(-2 * np.log(u1)) * np.cos(2 * np.pi * u2)
z2 = np.sqrt(-2 * np.log(u1)) * np.sin(2 * np.pi * u2)
normal_values.extend([z1, z2])
normal_array = np.array(normal_values[:1000])
print(f"Normal distribution: mean={np.mean(normal_array):.3f}, std={np.std(normal_array):.3f}")from resdata.util import CWDContext
import os
# Get current directory
original_dir = os.getcwd()
print(f"Original directory: {original_dir}")
# Use context manager to change directory
target_dir = "/tmp"
with CWDContext(target_dir):
current_dir = os.getcwd()
print(f"Inside context: {current_dir}")
# Do work in target directory
# Files created here will be in target_dir
# Back to original directory
final_dir = os.getcwd()
print(f"After context: {final_dir}")
assert final_dir == original_dir, "Directory not restored!"from resdata.util import ResdataVersion
# Get version information
version_str = ResdataVersion.versionString()
version_tuple = ResdataVersion.versionTuple()
is_devel = ResdataVersion.isDevelVersion()
git_commit = ResdataVersion.getGitCommit()
build_time = ResdataVersion.getBuildTime()
print(f"ResData Version: {version_str}")
print(f"Version tuple: {version_tuple}")
print(f"Development version: {is_devel}")
print(f"Git commit: {git_commit}")
print(f"Build time: {build_time}")
# Version comparison
major, minor, patch = version_tuple
if major >= 5 and minor >= 1:
print("Using ResData 5.1+ features")
else:
print("Consider upgrading ResData for latest features")# Random number generator enums
RngAlgTypeEnum = Literal[
"MZRAN", # Marsaglia-Zaman random number generator
"RANLUX", # RANLUX generator
"TAUS" # Tausworthe generator
]
RngInitModeEnum = Literal[
"INIT_DEFAULT", # Default initialization
"INIT_CLOCK", # Initialize from system clock
"INIT_DEV_RANDOM" # Initialize from /dev/random
]
# Version tuple type
VersionTuple = tuple[int, int, int] # (major, minor, patch)
# Hash table key-value types
HashKeyValue = dict[str, any] # Generic hash contents
StringHashContents = dict[str, str]
IntegerHashContents = dict[str, int]
DoubleHashContents = dict[str, float]Install with Tessl CLI
npx tessl i tessl/pypi-resdata