or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

file-operations.mdgeometry-operations.mdgravimetry-subsidence.mdgrid-operations.mdindex.mdrft-plt-data.mdsummary-analysis.mdutilities.mdwell-data.md

well-data.mddocs/

0

# Well Data Processing

1

2

Comprehensive well data analysis including well states, connections, segments, production and injection rates, and time-based well performance tracking from reservoir simulation results.

3

4

## Capabilities

5

6

### Well Information Management

7

8

Central interface for accessing well data and states across simulation time steps.

9

10

```python { .api }

11

class WellInfo:

12

"""Well information container and state management."""

13

14

def get_ts(self, well_name: str) -> list:

15

"""Get time series data for well."""

16

17

def get_state_from_report(self, well_name: str, report_step: int) -> WellState:

18

"""

19

Get well state at specific report step.

20

21

Args:

22

well_name (str): Name of the well

23

report_step (int): Report step number

24

25

Returns:

26

WellState: Well state at the report step

27

"""

28

29

def get_state_from_time(self, well_name: str, time: datetime) -> WellState:

30

"""

31

Get well state at specific time.

32

33

Args:

34

well_name (str): Name of the well

35

time (datetime): Simulation time

36

37

Returns:

38

WellState: Well state at the specified time

39

"""

40

41

def load_rstfile(self, rst_file: ResdataFile):

42

"""Load well data from restart file."""

43

44

def well_names(self) -> list:

45

"""

46

Get list of all well names.

47

48

Returns:

49

list: List of well name strings

50

"""

51

52

def get_well_time_line(self, well_name: str) -> WellTimeLine:

53

"""Get time line for specific well."""

54

```

55

56

### Well State Analysis

57

58

Well state at specific simulation time including production/injection data and connection information.

59

60

```python { .api }

61

class WellState:

62

"""Well state at specific simulation time."""

63

64

def name(self) -> str:

65

"""Get well name."""

66

67

def report_nr(self) -> int:

68

"""Get report number."""

69

70

def sim_time(self) -> float:

71

"""Get simulation time in days."""

72

73

def has_global_connections(self) -> bool:

74

"""Check if well has global connections."""

75

76

def get_global_connections(self) -> list:

77

"""Get list of global connections."""

78

79

def get_connections(self) -> list:

80

"""Get list of well connections."""

81

82

def is_producer(self) -> bool:

83

"""Check if well is a producer."""

84

85

def is_injector(self) -> bool:

86

"""Check if well is an injector."""

87

88

def get_production_rates(self) -> dict:

89

"""

90

Get production rates.

91

92

Returns:

93

dict: Production rates with keys 'oil', 'gas', 'water', 'liquid'

94

"""

95

96

def get_injection_rates(self) -> dict:

97

"""

98

Get injection rates.

99

100

Returns:

101

dict: Injection rates with keys 'water', 'gas'

102

"""

103

```

104

105

### Well Connection Data

106

107

Individual well connection information including perforation data and flow rates.

108

109

```python { .api }

110

class WellConnection:

111

"""Individual well connection data."""

112

113

def i(self) -> int:

114

"""Get I-index of connection."""

115

116

def j(self) -> int:

117

"""Get J-index of connection."""

118

119

def k(self) -> int:

120

"""Get K-index of connection."""

121

122

def is_open(self) -> bool:

123

"""Check if connection is open."""

124

125

def is_shut(self) -> bool:

126

"""Check if connection is shut."""

127

128

def transmissibility_factor(self) -> float:

129

"""Get transmissibility factor."""

130

131

def diameter(self) -> float:

132

"""Get connection diameter."""

133

134

def connection_factor(self) -> float:

135

"""Get connection factor."""

136

137

def depth(self) -> float:

138

"""Get connection depth."""

139

140

def volume_rate(self) -> float:

141

"""Get total volume rate."""

142

143

def oil_rate(self) -> float:

144

"""Get oil production rate."""

145

146

def gas_rate(self) -> float:

147

"""Get gas production rate."""

148

149

def water_rate(self) -> float:

150

"""Get water production rate."""

151

152

def resv_rate(self) -> float:

153

"""Get reservoir volume rate."""

154

```

155

156

### Well Segment Operations

157

158

Well segment information for multi-segment wells including pressure drop and flow characteristics.

159

160

```python { .api }

161

class WellSegment:

162

"""Well segment information for multi-segment wells."""

163

164

def get_id(self) -> int:

165

"""Get segment ID."""

166

167

def get_outlet(self) -> int:

168

"""Get outlet segment ID."""

169

170

def is_active(self) -> bool:

171

"""Check if segment is active."""

172

173

def is_closest(self) -> bool:

174

"""Check if segment is closest to surface."""

175

176

def is_main_stem(self) -> bool:

177

"""Check if segment is in main stem."""

178

179

def get_length(self) -> float:

180

"""Get segment length."""

181

182

def get_depth(self) -> float:

183

"""Get segment depth."""

184

185

def get_diameter(self) -> float:

186

"""Get segment diameter."""

187

```

188

189

### Well Timeline Management

190

191

Time-based well operations and state changes throughout simulation.

192

193

```python { .api }

194

class WellTimeLine:

195

"""Time line for well operations and state changes."""

196

197

def get_first_date(self) -> datetime:

198

"""Get first operation date."""

199

200

def get_last_date(self) -> datetime:

201

"""Get last operation date."""

202

203

def time_list(self) -> list:

204

"""Get list of operation times."""

205

206

def get_state(self, time: datetime) -> WellState:

207

"""Get well state at specific time."""

208

```

209

210

## Usage Examples

211

212

### Basic Well Analysis

213

214

```python

215

from resdata.well import WellInfo

216

from resdata.resfile import ResdataFile

217

218

# Load restart file and extract well information

219

restart = ResdataFile("SIMULATION.UNRST")

220

well_info = WellInfo()

221

well_info.load_rstfile(restart)

222

223

# Get all well names

224

wells = well_info.well_names()

225

print(f"Wells in simulation: {wells}")

226

227

# Analyze each well's final state

228

for well_name in wells:

229

try:

230

# Get final state (last report step)

231

final_state = well_info.get_state_from_report(well_name, -1)

232

233

print(f"\nWell: {well_name}")

234

print(f" Type: {'Producer' if final_state.is_producer() else 'Injector'}")

235

print(f" Report: {final_state.report_nr()}")

236

print(f" Sim time: {final_state.sim_time():.1f} days")

237

238

# Get production/injection rates

239

if final_state.is_producer():

240

rates = final_state.get_production_rates()

241

print(f" Oil rate: {rates.get('oil', 0):.1f} m³/day")

242

print(f" Gas rate: {rates.get('gas', 0):.1f} m³/day")

243

print(f" Water rate: {rates.get('water', 0):.1f} m³/day")

244

else:

245

rates = final_state.get_injection_rates()

246

print(f" Water inj: {rates.get('water', 0):.1f} m³/day")

247

print(f" Gas inj: {rates.get('gas', 0):.1f} m³/day")

248

249

except Exception as e:

250

print(f"Error processing well {well_name}: {e}")

251

```

252

253

### Well Connection Analysis

254

255

```python

256

from resdata.well import WellInfo

257

from resdata.resfile import ResdataFile

258

259

# Load data

260

restart = ResdataFile("SIMULATION.UNRST")

261

well_info = WellInfo()

262

well_info.load_rstfile(restart)

263

264

# Analyze connections for a specific well

265

well_name = "PROD01"

266

final_state = well_info.get_state_from_report(well_name, -1)

267

268

print(f"Connection analysis for {well_name}:")

269

print(f"Has global connections: {final_state.has_global_connections()}")

270

271

connections = final_state.get_connections()

272

print(f"Number of connections: {len(connections)}")

273

274

total_oil_rate = 0.0

275

active_connections = 0

276

277

for i, conn in enumerate(connections):

278

if conn.is_open():

279

print(f"\nConnection {i+1} (Active):")

280

print(f" Grid cell: ({conn.i()}, {conn.j()}, {conn.k()})")

281

print(f" Depth: {conn.depth():.1f} m")

282

print(f" Diameter: {conn.diameter():.3f} m")

283

print(f" Trans factor: {conn.transmissibility_factor():.2e}")

284

print(f" Oil rate: {conn.oil_rate():.2f} m³/day")

285

print(f" Water rate: {conn.water_rate():.2f} m³/day")

286

print(f" Gas rate: {conn.gas_rate():.2f} m³/day")

287

288

total_oil_rate += conn.oil_rate()

289

active_connections += 1

290

else:

291

print(f"\nConnection {i+1} (Shut)")

292

293

print(f"\nSummary:")

294

print(f" Active connections: {active_connections}/{len(connections)}")

295

print(f" Total oil rate: {total_oil_rate:.1f} m³/day")

296

```

297

298

### Well Performance Over Time

299

300

```python

301

from resdata.well import WellInfo

302

from resdata.resfile import ResdataFile

303

from datetime import datetime, timedelta

304

import matplotlib.pyplot as plt

305

306

# Load data

307

restart = ResdataFile("SIMULATION.UNRST")

308

well_info = WellInfo()

309

well_info.load_rstfile(restart)

310

311

# Get well timeline

312

well_name = "PROD01"

313

timeline = well_info.get_well_time_line(well_name)

314

315

# Get operation period

316

start_date = timeline.get_first_date()

317

end_date = timeline.get_last_date()

318

print(f"Well {well_name} active period: {start_date} to {end_date}")

319

320

# Sample well performance monthly

321

performance_data = {

322

'dates': [],

323

'oil_rates': [],

324

'water_rates': [],

325

'water_cuts': []

326

}

327

328

current_date = start_date

329

while current_date <= end_date:

330

try:

331

state = well_info.get_state_from_time(well_name, current_date)

332

if state.is_producer():

333

rates = state.get_production_rates()

334

oil_rate = rates.get('oil', 0)

335

water_rate = rates.get('water', 0)

336

337

# Calculate water cut

338

total_liquid = oil_rate + water_rate

339

water_cut = water_rate / total_liquid if total_liquid > 0 else 0

340

341

performance_data['dates'].append(current_date)

342

performance_data['oil_rates'].append(oil_rate)

343

performance_data['water_rates'].append(water_rate)

344

performance_data['water_cuts'].append(water_cut * 100) # Percentage

345

346

except Exception as e:

347

print(f"No data for {current_date}: {e}")

348

349

# Move to next month

350

if current_date.month == 12:

351

current_date = current_date.replace(year=current_date.year + 1, month=1)

352

else:

353

current_date = current_date.replace(month=current_date.month + 1)

354

355

# Plot performance

356

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))

357

358

# Production rates

359

ax1.plot(performance_data['dates'], performance_data['oil_rates'],

360

'g-', linewidth=2, label='Oil Rate')

361

ax1.plot(performance_data['dates'], performance_data['water_rates'],

362

'b-', linewidth=2, label='Water Rate')

363

ax1.set_ylabel('Rate (m³/day)')

364

ax1.set_title(f'{well_name} Production Performance')

365

ax1.legend()

366

ax1.grid(True)

367

368

# Water cut

369

ax2.plot(performance_data['dates'], performance_data['water_cuts'],

370

'r-', linewidth=2)

371

ax2.set_ylabel('Water Cut (%)')

372

ax2.set_xlabel('Date')

373

ax2.grid(True)

374

375

plt.tight_layout()

376

plt.show()

377

378

# Performance statistics

379

if performance_data['oil_rates']:

380

print(f"\nPerformance Statistics:")

381

print(f" Peak oil rate: {max(performance_data['oil_rates']):.1f} m³/day")

382

print(f" Average oil rate: {sum(performance_data['oil_rates'])/len(performance_data['oil_rates']):.1f} m³/day")

383

print(f" Final water cut: {performance_data['water_cuts'][-1]:.1f}%")

384

```

385

386

### Multi-Segment Well Analysis

387

388

```python

389

from resdata.well import WellInfo

390

from resdata.resfile import ResdataFile

391

392

# Load data (assuming multi-segment well simulation)

393

restart = ResdataFile("SIMULATION.UNRST")

394

well_info = WellInfo()

395

well_info.load_rstfile(restart)

396

397

# Analyze multi-segment well

398

well_name = "MSW01" # Multi-segment well

399

final_state = well_info.get_state_from_report(well_name, -1)

400

401

print(f"Multi-segment well analysis: {well_name}")

402

403

# Note: Segment analysis would require additional well segment data

404

# This is a simplified example showing the interface

405

connections = final_state.get_connections()

406

407

print(f"Well connections: {len(connections)}")

408

for i, conn in enumerate(connections):

409

if conn.is_open():

410

print(f" Connection {i+1}: Cell ({conn.i()}, {conn.j()}, {conn.k()})")

411

print(f" Depth: {conn.depth():.1f} m")

412

print(f" Oil rate: {conn.oil_rate():.2f} m³/day")

413

print(f" Connection factor: {conn.connection_factor():.2e}")

414

```

415

416

### Well State Comparison

417

418

```python

419

from resdata.well import WellInfo

420

from resdata.resfile import ResdataFile

421

422

# Load data

423

restart = ResdataFile("SIMULATION.UNRST")

424

well_info = WellInfo()

425

well_info.load_rstfile(restart)

426

427

# Compare well states at different times

428

well_name = "PROD01"

429

430

# Early production (report step 10)

431

early_state = well_info.get_state_from_report(well_name, 10)

432

433

# Late production (report step -10, i.e., 10th from end)

434

late_state = well_info.get_state_from_report(well_name, -10)

435

436

print(f"Well state comparison: {well_name}")

437

print("\nEarly Production:")

438

print(f" Time: {early_state.sim_time():.1f} days")

439

if early_state.is_producer():

440

early_rates = early_state.get_production_rates()

441

print(f" Oil rate: {early_rates.get('oil', 0):.1f} m³/day")

442

print(f" Water rate: {early_rates.get('water', 0):.1f} m³/day")

443

444

print("\nLate Production:")

445

print(f" Time: {late_state.sim_time():.1f} days")

446

if late_state.is_producer():

447

late_rates = late_state.get_production_rates()

448

print(f" Oil rate: {late_rates.get('oil', 0):.1f} m³/day")

449

print(f" Water rate: {late_rates.get('water', 0):.1f} m³/day")

450

451

# Calculate decline

452

if early_state.is_producer() and late_state.is_producer():

453

early_oil = early_rates.get('oil', 0)

454

late_oil = late_rates.get('oil', 0)

455

456

if early_oil > 0:

457

decline_rate = (early_oil - late_oil) / early_oil * 100

458

print(f"\nOil rate decline: {decline_rate:.1f}%")

459

460

early_wcut = early_rates.get('water', 0) / (early_rates.get('oil', 0) + early_rates.get('water', 0) + 1e-10)

461

late_wcut = late_rates.get('water', 0) / (late_rates.get('oil', 0) + late_rates.get('water', 0) + 1e-10)

462

463

print(f"Water cut increase: {early_wcut*100:.1f}% → {late_wcut*100:.1f}%")

464

```

465

466

## Types

467

468

```python { .api }

469

# Well types

470

WellType = Literal[

471

"UNDOCUMENTED_ZERO", # Unknown/undefined type

472

"PRODUCER", # Production well

473

"WATER_INJECTOR", # Water injection well

474

"GAS_INJECTOR", # Gas injection well

475

"OIL_INJECTOR" # Oil injection well

476

]

477

478

# Connection directions

479

WellConnectionDirection = Literal[

480

"DIR_X", # X-direction perforation

481

"DIR_Y", # Y-direction perforation

482

"DIR_Z", # Z-direction perforation

483

"DIR_FRACX", # X-direction fracture

484

"DIR_FRACY" # Y-direction fracture

485

]

486

487

# Production/injection rates dictionary

488

ProductionRates = dict[str, float] # Keys: 'oil', 'gas', 'water', 'liquid'

489

InjectionRates = dict[str, float] # Keys: 'water', 'gas'

490

491

# Grid cell indices for connections

492

CellIndices = tuple[int, int, int] # (i, j, k)

493

```