Source code for deepfield.field.well_segment
#pylint: disable=too-many-lines
"""Wells and WellSegment components."""
import numpy as np
import pandas as pd
from anytree import NodeMixin
from .rates import apply_perforations, calculate_cf
from .base_component import BaseComponent
[docs]
class WellSegment(BaseComponent, NodeMixin):
"""Well's node.
Parameters
----------
name : str, optional
Node's name.
is_group : bool, optional
Should a node represet a group of wells. Default to False.
Attributes
----------
is_group : bool
Indicator of a group.
is_main_branch : bool
Indicator of a main branch.
name : str
Node's name.
fullname : str
Node's full name from root.
"""
def __init__(self, *args, parent=None, children=None, name=None, ntype=None, **kwargs):
super().__init__(*args, **kwargs)
super().__setattr__('parent', parent)
self._name = name
self._ntype = ntype
if children is not None:
super().__setattr__('children', children)
[docs]
def copy(self):
"""Returns a deepcopy. Cached properties are not copied."""
copy = super().copy()
copy._name = self._name #pylint: disable=protected-access
copy._ntype = self._ntype #pylint: disable=protected-access
return copy
@property
def is_group(self):
"""Check that node is a group of wells."""
return self._ntype == 'group'
@property
def is_main_branch(self):
"""Check that node in a main well's branch."""
return (not self._ntype == 'group') and (':' not in self.name)
@property
def ntype(self):
"""Node's type."""
return self._ntype
@property
def name(self):
"""Node's name."""
return self._name
@property
def fullname(self):
"""Full name from root."""
return self.separator.join([node.name for node in self.path[1:]])
@property
def total_rates(self):
"""Total rates for the current node and all its branches."""
columns = ['DATE', 'WOPR', 'WWPR', 'WGPR', 'WFGPR']
if 'RESULTS' not in self:
df = pd.DataFrame(columns=columns).set_index('DATE')
else:
df = self.results[[x for x in columns if x in self.results]].set_index('DATE')
for node in self.children:
df = df.add(node.total_rates.set_index('DATE'), fill_value=0)
return df.reset_index()
@property
def cum_rates(self):
"""Cumulative rates for the current node and all its branches."""
return self.total_rates.set_index('DATE').cumsum().reset_index()
[docs]
def perforated_indices(self, t=None):
"""Mask indicating perforated blocks."""
if t is not None:
raise NotImplementedError('Time parameter is not yet implemented.')
if 'BLOCKS_INFO' in self.attributes:
return (self.blocks_info['PERF_RATIO'] > 0).values
return np.array([], dtype=bool)
[docs]
def perforated_blocks(self, t=None):
"""List of perforated blocks for current node."""
if 'BLOCKS' in self.attributes:
return self.blocks[self.perforated_indices(t)]
return np.array([])
[docs]
def all_perforated_blocks(self, t=None):
"""List of perforated blocks for current node and all its descendants."""
res = [node.perforated_blocks(t) for node in self.descendants]
res.append(self.perforated_blocks(t))
res = [x for x in res if len(x)]
return np.unique(np.vstack(res), axis=0) if res else np.array([])
[docs]
def apply_perforations(self, current_date=None):
"""Open or close perforation intervals for given time interval.
Parameters
----------
segment : WellSegment
Well's node.
current_date : pandas.Timestamp
Final date to open new perforations.
Returns
-------
segment : WellSegment
Segment with a blocks_info attribute that contains:
- projections of welltrack in grid blocks
- MD values for corresponding grid blocks
- ratio of perforated part of the well for each grid block.
"""
apply_perforations(self, current_date=current_date)
return self
[docs]
def calculate_cf(self, rock, grid, beta=1, units='METRIC', cf_aggregation='sum'):
"""Calculate connection factor values for each grid block of a segment.
Parameters
----------
rock : Rock
Rock component of geological model.
grid : Grid
Rock component of geological model.
segment : WellSegment
Well's node.
beta : list or ndarray
Additional multiplicator for productivity index of well.
units : str, 'METRIC' or 'FIELD'
Field units.
cf_aggregation: str, 'sum' or 'eucl'
The way of aggregating cf projection ('sum' - sum, 'eucl' - Euclid norm).
Returns
-------
segment : WellSegment
Segment with a blocks_info attribute extended with calculated connection
factor values for all segment blocks.
"""
calculate_cf(rock, grid, self, beta, units, cf_aggregation)
return self