welleng package

Subpackages

Submodules

welleng.architecture module

class welleng.architecture.BHA(*args, **kwargs)[source]

Bases: String

__init__(*args, **kwargs)[source]

Inherits from String class, but this makes it more intuitive.

class welleng.architecture.String(name, top, bottom, *args, method='bottom_up', **kwargs)[source]

Bases: object

__init__(name, top, bottom, *args, method='bottom_up', **kwargs)[source]

A generic well bore architecture collection, e.g. a casing string made up a a number of different lengths of weights and grades.

Parameters:
  • name (str) – The name of the collection.

  • top (float) – The shallowest measured depth at the top of the collection of items in meters.

  • bottom (float) – The deepest measured depth at the bottom of the collection of items in meters.

  • method (string (default: 'bottom up')) – The method in which items are added to the collection, either ‘bottom up’ starting from the deepest element and adding items above, else ‘top down’ starting from the shallowest item and adding items below.

add_section(**kwargs)[source]
add_section_bottom_up(**kwargs)[source]

Sections built from the bottom up until the top of the top section is equal to the defined string top.

Default is to extend the section to the top of the String as defined in the String.top property (when length = top = None).

Parameters:

add_section_top_down(**kwargs)[source]

Sections built from the top down until the bottom of the bottom section is equal to the defined string bottom.

depth(md)[source]
class welleng.architecture.WellBore(*args, **kwargs)[source]

Bases: String

__init__(*args, **kwargs)[source]

Inherits from String class, but this makes it more intuitive.

welleng.clearance module

class welleng.clearance.Clearance(reference: Survey, offset: Survey, k: float = 3.5, sigma_pa: float = 0.5, Sm: float = 0.3, Rr: float = 0.4572, Ro: float = 0.3048, kop_depth: float = -inf)[source]

Bases: object

Initialize a welleng.clearance.Clearance object.

Parameters:
  • reference (welleng.survey.Survey object) – The current well from which other wells are referenced.

  • offset (welleng.survey.Survey object) – The other well.

  • k (float) – The dimensionless scaling factor that determines the probability of well crossing.

  • sigma_pa (float) – Quantifies the 1-SD uncertainty in the projection ahead of the current survey station. Its value is partially correlated with the projection distance, determined as the current survey depth to the bit plus the next survey interval. The magnitude of the actual uncertainty also depends on the planned curvature and on the actual BHA performance at the wellbore attitude in the formation being drilled. The project-ahead uncertainty is only an approximation, and although it is predominantly oriented normal to the reference well, it is mathematically convenient to define sigma_pa as being the radius of a sphere.

  • Sm (float) – The surface margin term increases the effective radius of the offset well. It accommodates small, unidentified errors and helps overcome one of the geometric limitations of the separation rule, described in the Separation-Rule Limitations section. It also defines the minimum acceptable slot separation during facility design and ensures that the separation rule will prohibit the activity before nominal contact between the reference and offset wells, even if the position uncertainty is zero.

  • Rr (float) – The openhole radius of the reference borehole (in meters).

  • Ro (float) – The openhole radius of the offset borehole (in meters).

  • kop_depth (float) – The kick-off point (measured) depth along the well bore - the default value assures that the first survey station is utilized.

References

Sawaryn, S. J., Wilson, H.. , Bang, J.. , Nyrnes, E.. , Sentance, A.. , Poedjono, B.. , Lowdon, R.. , Mitchell, I.. , Codling, J.. , Clark, P. J., and W. T. Allen. “Well-Collision-Avoidance Separation Rule.” SPE Drill & Compl 34 (2019): 01–15. doi: https://doi.org/10.2118/187073-PA

__init__(reference: Survey, offset: Survey, k: float = 3.5, sigma_pa: float = 0.5, Sm: float = 0.3, Rr: float = 0.4572, Ro: float = 0.3048, kop_depth: float = -inf)[source]
class welleng.clearance.IscwsaClearance(*clearance_args, minimize_sf=None, **clearance_kwargs)[source]

Bases: Clearance

Parameters:

clearance_args: List

See ‘welleng.clearance.Clearance` for args.

minimize_sf: bool

If True (default), then the closest points on the reference well are determined and added to the ref object as interpolated stations.

clearance_kwargs: dict

See ‘welleng.clearance.Clearance` for kwargs.

Attributes:

Roarray of floats

The radius of the offset well at each station of the off well.

Rrarray

The radius of the reference well at each station on the ref well.

sfarray of floats

The calculated Separation Factor to the closest point on the offset well for each station on the reference well.

Smfloat

The surface margin term increases the effective radius of the offset well. It accommodates small, unidentified errors and helps overcome one of the geometric limitations of the separation rule, described in the Separation-Rule Limitations section. It also defines the minimum acceptable slot separation during facility design and ensures that the separation rule will prohibit the activity before nominal contact between the reference and offset wells, even if the position uncertainty is zero.

calc_hole: array of floats

The calculated combined equivalent radius of the two well bores, i.e. the sum or their radii plus margins.

closest:

The closest point on the off well from each station on the ref well.

distance_cc:

The closest center to center distance for each station on the ref well to the off well.

eou_boundary:

The sum of the ellipse of uncertainty radii of the ref and off wells.

eou_separation:

The distance between the ellipses of uncertainty of the ref and off wells.

hoz_bearing:

The horizontal bearing between the closest points in radians.

hoz_bearing_deg:

The horizontal bearing between the closest points in degrees.

idx: int

The index of the closest point on the off well for each station on the ref well.

masd:

The Minimum Allowable Separation Distance from the ref well.

off: Survey

The offset well Survey.

off_pcr:

The Pedal Curve Radii for each station on the off well.

off_cov_hla:

The covariance matrix in the HLA domain for each station of the off well.

off_cov_nev:

The covariance matrix in the NEV domain for each station of the off well.

off_nevs:

The NEV coordinates of the off well.

offset: Survey

The initial offset well Survey.

offset_nevs:

The initial NEV coordinates of the offset well.

ref: Survey

The ref well Survey.

ref_pcr:

The Pedal Curve Radii for each station on the ref well.

ref_cov_hla:

The covariance matrix in the HLA domain for each station of the ref well.

ref_cov_nev:

The covariance matrix in the NEV domain for each station of the ref well.

ref_nevs:

The NEV coordinates of the ref well.

reference: Survey

The initial reference well Survey.

reference_nevs:

The initial NEV coordinates of the reference well.

sf:

The Separation Factor between the closest point on the off well for each station on the ref well.

toolface_bearing:

The toolface bearing in radians from each station on the ref well to the closest point on the off well.

trav_cyl_azi_deg:

The heading in degrees from each station on teh ref well to the closest point on the off well.

wellbore_separation:

The distance between the edge of the wellbore for each station on the ref well to the closest point on the off well.

__init__(*clearance_args, minimize_sf=None, **clearance_kwargs)[source]
get_lines()[source]

Extracts the closest points between wells for each survey section.

get_sf_mins()[source]

Method for assessing whether a minima has occurred between survey station SF values on the reference well and if so calculates the minimum SF value between stations (between the previous and next station relative to the identified station).

Modifies the sf attribute to include the interpolated minimum sf values.

class welleng.clearance.MeshClearance(*clearance_args, n_verts: int = 12, sigma: float = 2.445, return_data: bool = True, return_meshes: bool = False, **clearance_kwargs)[source]

Bases: Clearance

Class to calculate the clearance between two well bores using a novel mesh clearance method. This method is experimental and was developed to provide a fast method for determining if well bores are potentially colliding.

This class requires that trimesh is installed along with python-fcl.

Parameters:
  • n_verts (int) – The number of points (vertices) used to generate the uncertainty ellipses which are used to generate a trimesh representation of the well bores. The default is 12 which is a good balance between accuracy and speed.

  • sigma (float) – The required/desired sigma value representation of the generated mesh. The default value of 2.445 represents about 98.5% confidence of the well bore being located within the volume of the generated mesh.

__init__(*clearance_args, n_verts: int = 12, sigma: float = 2.445, return_data: bool = True, return_meshes: bool = False, **clearance_kwargs)[source]
get_lines()[source]

Extracts the closest points between wells for each survey section.

welleng.clearance.get_ref_sigma(sigma1, sigma2, sigma3, kop_index)[source]

welleng.connector module

class welleng.connector.Connector(node1=None, node2=None, pos1=[0.0, 0.0, 0.0], vec1=None, inc1=None, azi1=None, md1=0, dls_design=3.0, dls_design2=None, md2=None, pos2=None, vec2=None, inc2=None, azi2=None, degrees=True, unit='meters', min_error=1e-05, delta_dls=0.1, min_tangent=0.0, max_iterations=1000, force_min_curve=False, closest_approach=False)[source]

Bases: object

__init__(node1=None, node2=None, pos1=[0.0, 0.0, 0.0], vec1=None, inc1=None, azi1=None, md1=0, dls_design=3.0, dls_design2=None, md2=None, pos2=None, vec2=None, inc2=None, azi2=None, degrees=True, unit='meters', min_error=1e-05, delta_dls=0.1, min_tangent=0.0, max_iterations=1000, force_min_curve=False, closest_approach=False)[source]

A class to provide a fast, efficient method for determining well bore section geometry using the appropriate method based upon the provided parameters, with the intent of assisting machine learning fitness functions. Interpolation between the returned control points can be performed posthumously - attempts are made to keep processing to a minimum in the event that the Connector is being used for machine learning.

Only specific combinations of input data are permitted, e.g. if you input both a start vector AND a start inc and azi you’ll get an error (which one is correct after all?). Think about what you’re trying to achieve and provide the data that will facilitate that outcome.

Parameters:
  • pos1 – Start position in NEV coordinates.

  • vec1 – Start position unit vector in NEV coordinates.

  • inc1 (float or None (default: None)) – Start position inclination.

  • azi2 (float or None (default: None)) – Start position azimuth.

  • md1 (float or None (default: None)) – Start position measured depth.

  • dls_design (float (default: 3.0)) – The desired Dog Leg Severity (DLS) for the (first) curved section in degrees per 30 meters or 100 feet.

  • dls_design2 (float or None (default: None)) – The desired DLS for the second curve section in degrees per 30 meters or 100 feet. If set to None then dls_design will be the default value.

  • md2 (float or None (default: None)) – The measured depth of the target position.

  • pos2 – The position of the target in NEV coordinates.

  • vec2 – The target unit vector in NEV coordinates.

  • inc1 – The inclination at the target position.

  • azi2 – The azimuth at the target position.

  • degrees (boolean (default: True)) – Indicates whether the input angles (inc, azi) are in degrees (True) or radians (False).

  • unit (string (default: 'meters')) – Indicates the distance unit, either ‘meters’ or ‘feet’.

  • min_error (float (default: 1e-5):) – Infers the error tolerance of the results and is used to set iteration stops when the desired error tolerance is met. Value must be less than 1. Use with caution as the code may become unstable if this value is changed.

  • delta_radius (float (default: 20)) – The delta radius (first curve and second curve sections) used as an iteration stop when balancing radii. If the resulting delta radius yielded from dls_design and dls_design2 is larger than delta_radius, then delta_radius defaults to the former.

  • delta_dls (float (default: 0.1)) – The delta dls (first curve and second curve sections) used as an iteration stop when balancing radii, i.e. if the dls of the second section is within 0.1 deg/30m of the first curve section then the section is considered balanced and no further iterations are performed. Setting this value too low will likely result in hitting the recursion limit.

  • min_tangent (float (default: 10)) – The minimum tangent length in the curve_hold_curve method used to mitigate instability during iterations (where the tangent section approaches or equals 0).

  • max_iterations (int (default: 1000)) – The maximum number of iterations before giving up trying to fit a curve_hold_curve. This number is limited by Python’s depth of recursion, but if you’re hitting the default stop then consider changing delta_radius and min_tangent as your expectations may be unrealistic (this is open source software after all!)

  • Results

  • -------

  • connector (welleng.connector.Connector object) –

interpolate(step=30)[source]
welleng.connector.angle(vec1, vec2, acute=True)[source]
welleng.connector.check_dogleg(dogleg)[source]
welleng.connector.connect_points(cartesians, vec_start=[0.0, 0.0, 1.0], dls_design=3.0, nev=True, md_start=0.0)[source]

Function for connecting a list or array of only Cartesian points.

Parameters:
  • cartesians ((n, 3) list or array of floats) – Either [n, e, tvd] (default) or [x, y, z]

  • vec_start – Unit start vector (default is pointing down) in the nev or xyz coordinate system.

  • dls_design (float or (n, 1) list or array of floats (default: 3.0)) – The minimum Dog Leg Severity used when attempting to connect the points (a high DLS will be used if necessary).

  • nev (bool (default: True)) – Indicates whether the cartesians are referencing the [nev] (default) or [xyz] coordinate system.

  • step (float (default: 30)) – The desired step interval for the returned Survey object.

  • md_start (float (default: 0)) – The md at the first cartesian point (in the event of a tie-on).

Returns:

data

Return type:

list of welleng.connector.Connector objects

welleng.connector.convert_target_input_to_booleans(*inputs)[source]
welleng.connector.drop_off(target_inc: float, dls: float, delta_md: float | None = None, node: Node | None = None, tol: float = 1e-05) list[source]

Determines the sections necessary to drop off (or build) towards a target inclination, constrained by the section length and dls.

Recommended to use the extend_to_tvd function if a specific tvd target is required.

Parameters:
  • target_inc (float) – The target trajectory inclination in degrees.

  • dls (float) – The design dls in deg/30m.

  • delta_md (float) – The section length in meters.

  • node (Node) – The Node of the current location.

Returns:

nodes – A list of Connectors that describe the required trajectory changes. The list contains at least one value (describing the arc or curve) and a second value if the target inclination was achieved, to maintain a tangent section.

Return type:

list

welleng.connector.extend_to_tvd(target_tvd: float, node: Node | None = None, delta_md: float | None = None, target_inc: float | None = None, dls: float | None = None) list[source]

Determines a list of Connector sections required to drop off (or build) to achieve a target tvd.

Parameters:
  • target_tvd (float) – The target true vertical depth in meters.

  • node (Node | None (default=None)) – The Node describing the current well position. If not provided, defaults to surface and pointing down.

  • delta_md (float | None (default=None)) – Will limit the section length to the value provided in meters.

  • target_inc (float | None (default=None)) – The target inclination at the target tvd in degrees. If provided, will get as close to this value as feasible with the provided dls constraint. If the target inclination can be achieved, a tangent section will be held until the target tvd is achieved.

  • dls (float | None (default=None)) – The design dls in deg/30m. If none provided, defaults to 2.3 deg/30m.

Returns:

nodes – A list of Connector that describe the required trajectory changes. The list contains at least one value (describing the arc or curve) and a second value if the target inclination was achieved, to maintain a tangent section.

Return type:

list

Examples

A well has landed at the top reservoir with an inclination of 30 degrees and the Wells Engineer wants to drop this angle to 0 degrees while drilling the reservoir section.

>>> import welleng as we
>>> from pprint import pprint
>>> node = we.node.Node(pos=[0, 0, 3000], md=4000, inc=30, azi=135)
>>> connectors = we.connector.extend_to_tvd(target_tvd=3200, node=node, target_inc=0, dls=3)
>>> len(connectors)
... 1

Since there’s only one Connector in connectors then likely the target inclination has not been met, else there would also be a tangent section in this case.

>>> pprint(connectors[-1].node_end.__dict__)
... {'azi_deg': 134.99999999999994,
    'azi_rad': 2.356194490192344,
    'cov_nev': array([[[0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.]]]),
    'inc_deg': 8.681065764308594,
    'inc_rad': 0.151513180169343,
    'md': 4213.189342356914,
    'pos_nev': [-49.63739779370637, 49.63739779370647, 3199.9999999980705],
    'pos_xyz': [49.63739779370647, -49.63739779370637, 3199.9999999980705],
    'unit': 'meters',
    'vec_nev': [-0.10672656069796796, 0.1067265606979681, 0.9885438192023488],
    'vec_xyz': [0.1067265606979681, -0.10672656069796796, 0.9885438192023488]}

Indeed, the inc_deg attribute shows the inclination dropped to just below 9 degrees and the z coordinate in pos_nev shows that the target tvd was met.

welleng.connector.get_curve_hold_data(radius, dogleg)[source]
welleng.connector.get_dogleg(inc1, azi1, inc2, azi2)[source]
welleng.connector.get_interpolate_hold(section, step=30, data=None)[source]
welleng.connector.get_interpolate_min_curve_to_target(section, step=30, data=None)[source]
welleng.connector.get_interpolate_min_dist_to_target(section, step=30, data=None)[source]
welleng.connector.get_interpololate_curve_hold_curve(section, step=30, data=None)[source]
welleng.connector.get_min_curve(section, step=30, data=None)[source]
welleng.connector.get_pos(pos1, vec1, vec2, dist_curve, func_dogleg)[source]
welleng.connector.get_radius_critical(radius, distances, min_error)[source]
welleng.connector.get_vec_target(pos1, vec1, pos_target, tangent_length, dist_curve, func_dogleg)[source]
welleng.connector.interpolate_curve(md1, pos1, vec1, vec2, dist_curve, dogleg, func_dogleg, step, endpoint=False)[source]
welleng.connector.interpolate_hold(md1, pos1, vec1, md2, step, endpoint=False)[source]
welleng.connector.interpolate_well(sections, step=30)[source]

Constructs a well survey from a list of sections of control points.

Parameters:
  • sections (list of welleng.connector.Connector objects) –

  • step (float (default: 30)) – The desired delta measured depth between survey points, in addition to the control points.

Returns:

data

Return type:

list of welleng.connector.Connector objects

welleng.connector.min_curve_to_target(distances)[source]

Calculates the control points for a curve section from the start position and vector to the target position which is not achievable with the provided dls_design.

welleng.connector.min_dist_to_target(radius, distances)[source]

Calculates the control points for a curve and hold section from the start position and vector to the target position.

welleng.connector.minimize_target_pos_and_vec_defined(x, c, pos3=None, vec_old=[0.0, 0.0, 0.0], result=False)[source]
welleng.connector.mod_vec(vec, error=1e-05)[source]
welleng.connector.numbafy(functions)[source]
welleng.connector.shape_factor(dogleg)[source]

Function to determine the shape factor of a dogleg.

Parameters:

dogleg (float) – The dogleg angle in radians of a curve section.

welleng.connector.survey_to_plan(survey, tolerance=0.2, dls_design=1.0, step=30.0)[source]

Prototype function for extracting a plan from a drilled well survey - a minimal number of control points (begining/end points of either hold or build/turn sections) required to express the well given the provided input parameters.

Parameters:
  • survey (welleng.survey.Survey object) –

  • tolerance (float (default=0.2)) – Defines how tight to fit the planned well to the survey - a higher number will results in less control points but likely poorer fit.

  • dls_design (float (default=1.0)) – The minimum DLS used to fit the planned trajectory.

  • step (float (default=30)) – The desired md step in the plan survey.

Returns:

sections

Return type:

list of welleng.connector.Connection objects

welleng.error module

class welleng.error.ErrorModel(survey, error_model='ISCWSA MWD Rev5')[source]

Bases: object

A class to initiate the field parameters and error magnitudes for subsequent error calculations.

class Error(code, propagation, e_DIA, cov_DIA, e_NEV, e_NEV_star, sigma_e_NEV, cov_NEV)[source]

Bases: object

Standard components of a well bore survey error.

__init__(code, propagation, e_DIA, cov_DIA, e_NEV, e_NEV_star, sigma_e_NEV, cov_NEV)[source]
__init__(survey, error_model='ISCWSA MWD Rev5')[source]
drk_dAz(survey)[source]

survey1 is previous survey station (with inc and azi in radians) survey2 is current survey station (with inc and azi in radians)

drk_dDepth(survey)[source]

survey1 is previous survey station (with inc and azi in radians) survey2 is current survey station (with inc and azi in radians)

drk_dInc(survey)[source]

survey1 is previous survey station (with inc and azi in radians) survey2 is current survey station (with inc and azi in radians)

drkplus1_dAz(survey)[source]

survey2 is current survey station (with inc and azi in radians) survey3 is next survey station (with inc and azi in radians)

drkplus1_dDepth(survey)[source]

survey2 is current survey station (with inc and azi in radians) survey3 is next survey station (with inc and azi in radians)

drkplus1_dInc(survey)[source]

survey2 is current survey station (with inc and azi in radians) survey3 is next survey station (with inc and azi in radians)

welleng.error.get_error_models(tool_index=None)[source]
welleng.error.get_errors(error)[source]
welleng.error.get_tool_index()[source]
welleng.error.make_diagnostic_data(survey)[source]

welleng.fluid module

class welleng.fluid.DensityDiesel[source]

Bases: object

__init__()[source]

An interpolation wrapper of the pressure, temperature and density diesel data provided in the SPE 11118 paper.

get_density(pressure, temperature)[source]

Interpolate diesel density for given pressure and temperature using the lookup data provided in SPE 11118 paper.

class welleng.fluid.Fluid(fluid_density, reference_temp=32.0, reference_pressure=0.0, base_fluid_water_ratio=0.2, weighting_material='Barite')[source]

Bases: object

__init__(fluid_density, reference_temp=32.0, reference_pressure=0.0, base_fluid_water_ratio=0.2, weighting_material='Barite')[source]

Density profile calculated from SPE 11118 Mathematical Field Model Predicts Downhold Density Changes in Static Drilling Fluids by Roland R. Sorelle et al.

This paper was written in oilfield units, so we’ll convert inputs to ppg, ft, F and psi.

Parameters:
  • fluid_density (float) – The combined fluid density in ppg at reference conditions.

  • reference_temp (float (default 32.0)) – The reference temperature in Fahrenheit

  • reference_pressure (float (default 0.0)) – The reference pressure in psig.

  • weighting_material (str) – The material being used to weight the drilling fluid (see the WEIGHTING_MATERIAL_DENSITY dictionary).

get_density_profile(depth, temperature, pressure_applied=0.0, density_bounds=(6.0, 25.0))[source]

Function that returns a density profile of the fluid, adjusted for temperature and compressibility and assuming that the fluid’s reference parameters are the surface parameters.

Parameters:
  • depth (float or list or (n) array of floats) – The vertical depth of interest relative to surface in feet.

  • temperature (float or list or (n) array of floats) – The temperature corresponding to the vertical depth of interest in Fahrenheit.

  • pressure_applied (float (default=0.)) – Additional pressure applied to the fluid in psi.

  • density_bounds – Density bounds to constrain the optimization algorithm in ppg.

welleng.fluid.main()[source]

welleng.io module

welleng.io.acr_setup(sheet, data)[source]
welleng.io.get_clearance_data(well, sheet, data)[source]
welleng.io.get_standard_data(filename)[source]
welleng.io.get_well_data(well, sheet, data)[source]
welleng.io.import_iscwsa_collision_data(filename)[source]
welleng.io.make_survey(data, well)[source]

welleng.mesh module

class welleng.mesh.WellMesh(survey: Survey, n_verts: int = 12, sigma: float = 3.0, sigma_pa: float = 0.5, Sm: float = 0, method: str = 'ellipse')[source]

Bases: object

__init__(survey: Survey, n_verts: int = 12, sigma: float = 3.0, sigma_pa: float = 0.5, Sm: float = 0, method: str = 'ellipse')[source]

Create a WellMesh object from a welleng Survey object and a welleng Clearance object.

Parameters:
  • survey (welleng.Survey) –

  • clearance (welleng.Clearance) –

  • n_verts (int) – The number of vertices along the uncertainty ellipse edge from which to construct the mesh. Recommended minimum is 12 and that the number is a multiple of 4.

  • sigma (float (default: 3.0)) – The desired standard deviation sigma value of the well bore uncertainty.

  • sigma_pa (float (default: 0.5)) – The desired “project ahead” value. A remnant of the ISCWSA method but may be used in the future to accomodate for well bore curvature that is not captured by the mesh.

  • Sm (float) – From the ISCWSA method, this is an additional factor applied to the well bore radius of the offset well to oversize the hole.

  • method (str (default="ellipse")) – The method for constructing the uncertainty edge. Either “ellipse”, “pedal_curve” or “circle”.

figure(type='mesh3d', **kwargs)[source]
welleng.mesh.fix_mesh(mesh)[source]

For whatever reason, the first pass meshing often results in a mesh that is not watertight. This function fixes that, as well as repairs the windings and normals.

Parameters:

mesh (trimesh object) –

Returns:

good_mesh

Return type:

trimesh object

welleng.mesh.get_ends(n_verts, rows)[source]

Given a number of vertices per station and a number of stations, returns the faces of the trimesh vertices.

welleng.mesh.get_faces(n_verts, rows)[source]
welleng.mesh.make_trimesh_scene(data)[source]

Construct a trimesh scene. A collision manager can’t be saved, but a scene can and a scene can be imported into a collision manager.

Parameters:

data (list of welleng.mesh.WellEng objects.) –

Returns:

scene

Return type:

a trimesh.scene.scene.Scene object.

welleng.mesh.sliced_mesh(survey, n_verts=12, sigma=3.0, sigma_pa=0.5, Sm=0, start=0, stop=-1, step=1, method='mesh_ellipse')[source]

Generates a list of mesh objects of a user defined length.

Parameters:
  • survey (welleng.Survey) –

  • n_verts (int) – The number of vertices along the uncertainty ellipse edge from which to construct the mesh. Recommended minimum is 12 and that the number is a multiple of 4.

  • sigma (float (default: 3.0)) – The desired standard deviation sigma value of the well bore uncertainty.

  • sigma_pa (float (default: 0.5)) – The desired “project ahead” value. A remnant of the ISCWSA method but may be used in the future to accommodate for well bore curvature that is not captured by the mesh.

  • Sm (float) – From the ISCWSA method, this is an additional factor applied to the well bore radius of the offset well to oversize the hole.

  • method (str (default="ellipse")) – The method for constructing the uncertainty edge. Either “ellipse” or “pedal_curve”.

Return type:

list of trimesh.Trimesh mesh objects.

welleng.mesh.transform_trimesh_scene(scene, origin=None, scale=100, redux=0.25)[source]

Transforms a scene by scaling it, reseting the origin/datum and performing a reduction in the number of triangles to reduce the file size.

Parameters:
  • scene (trimesh.scene.scene.Scene object) – A trimesh scene of well meshes

  • origin (3d array [x, y, z]) – The origin of the scene from which the new scene will reset to [0, 0, 0].

  • scale (float) – A scalar reduction will be performed using this float

  • redux (float) – The desired reduction ratio for the number of triangles in each mesh.

Returns:

scene_transformed – A transformed, scaled and reprocessed scene.

Return type:

trimesh.scene.scene.Scene object

welleng.node module

class welleng.node.Node(pos=None, vec=None, md=None, inc=None, azi=None, unit='meters', degrees=True, nev=True, cov_nev=None, **kwargs)[source]

Bases: object

__init__(pos=None, vec=None, md=None, inc=None, azi=None, unit='meters', degrees=True, nev=True, cov_nev=None, **kwargs)[source]
check_angle_inputs(inc, azi, vec, nev, degrees)[source]
get_pos(pos, nev)[source]
static get_unit_vec(vec)[source]
properties()[source]
welleng.node.get_node_params(node)[source]

welleng.survey module

class welleng.survey.SplitSurvey(survey)[source]

Bases: object

__init__(survey)[source]
class welleng.survey.Survey(md, inc, azi, n=None, e=None, tvd=None, x=None, y=None, z=None, vec=None, nev=True, header=None, radius=None, cov_nev=None, cov_hla=None, error_model=None, start_xyz=[0.0, 0.0, 0.0], start_nev=[0.0, 0.0, 0.0], start_cov_nev=None, deg=True, unit='meters', **kwargs)[source]

Bases: object

Initialize a welleng.Survey object. Calculations are performed in the azi_reference “grid” domain.

Parameters:
  • md ((,n) list or array of floats) – List or array of well bore measured depths.

  • inc ((,n) list or array of floats) – List or array of well bore survey inclinations

  • azi ((,n) list or array of floats) – List or array of well bore survey azimuths

  • n ((,n) list or array of floats (default: None)) – List or array of well bore northings

  • e ((,n) list or array of floats (default: None)) – List or array of well bore eastings

  • tvd ((,n) list or array of floats (default: None)) – List or array of local well bore z coordinates, i.e. depth and usually relative to surface or mean sea level.

  • x ((,n) list or array of floats (default: None)) – List or array of local well bore x coordinates, which is usually aligned to the east direction.

  • y ((,n) list or array of floats (default: None)) – List or array of local well bore y coordinates, which is usually aligned to the north direction.

  • z ((,n) list or array of floats (default: None)) – List or array of well bore true vertical depths relative to the well surface datum (usually the drill floor elevation DFE, so not always identical to tvd).

  • vec ((n,3) list or array of (,3) floats (default: None)) – List or array of well bore unit vectors that describe the inclination and azimuth of the well relative to (x,y,z) coordinates.

  • header (SurveyHeader object (default: None)) – A SurveyHeader object with information about the well location and survey data. If left default then a SurveyHeader will be generated with the default properties assigned, but these may not be relevant and may result in incorrect data.

  • radius (float or (,n) list or array of floats (default: None)) – If a single float is specified, this value will be assigned to the entire well bore. If a list or array of floats is provided, these are the radii of the well bore. If None, a well bore radius of 12” or approximately 0.3 m is applied.

  • cov_nev ((n,3,3) list or array of floats (default: None)) – List or array of covariance matrices in the (n,e,v) coordinate system.

  • cov_hla ((n,3,3) list or array of floats (default: None)) – List or array of covariance matrices in the (h,l,a) well bore coordinate system (high side, lateral, along hole).

  • error_model (str (default: None)) – If specified, this model is used to calculate the covariance matrices if they are not present. Currently, only the “ISCWSA_MWD” model is provided.

  • start_xyz ((,3) list or array of floats (default: [0,0,0])) – The start position of the well bore in (x,y,z) coordinates.

  • start_nev ((,3) list or array of floats (default: [0,0,0])) – The start position of the well bore in (n,e,v) coordinates.

  • start_cov_nev ((,3,3) list or array of floats (default: None)) – The covariance matrix for the start position of the well bore in (n,e,v) coordinates.

  • deg (boolean (default: True)) – Indicates whether the provided angles are in degrees (True), else radians (False).

  • unit (str (default: 'meters')) – Indicates whether the provided lengths and distances are in ‘meters’ or ‘feet’, which impacts the calculation of the dls (dog leg severity).

Return type:

A welleng.survey.Survey object.

__init__(md, inc, azi, n=None, e=None, tvd=None, x=None, y=None, z=None, vec=None, nev=True, header=None, radius=None, cov_nev=None, cov_hla=None, error_model=None, start_xyz=[0.0, 0.0, 0.0], start_nev=[0.0, 0.0, 0.0], start_cov_nev=None, deg=True, unit='meters', **kwargs)[source]
directional_difficulty_index(**kwargs)[source]

Taken from IADC/SPE 59196 The Directional Difficulty Index - A New Approach to Performance Benchmarking by Alistair W. Oag et al.

Returns:

data – The ddi for each survey station.

Return type:

  1. array of floats

figure(type='scatter3d', **kwargs)[source]
get_error(error_model, return_error=False)[source]
get_nev_arr()[source]
get_vertical_section(vertical_section_azimuth, deg=True)[source]

Calculate the vertical section.

Parameters:
  • vertical_section_azimuth (float) – The azimuth (relative to the reference azimuth defined in the survey header) along which to calculate the vertical section lateral displacement.

  • deg (boolean (default: True)) – Indicates whether the vertical section azimuth parameter is in degrees or radians (True or False respectively).

Returns:

result

Return type:

(n, 1) ndarray

interpolate_md(md)[source]

Method to interpolate a position based on measured depth and return a node.

Parameters:

md (float) – The measured depth of the point of interest.

Returns:

node – A node with attributes describing the point at the provided measured depth.

Return type:

we.node.Node object

Examples

>>> import welleng as we
>>> survey = we.connector.interpolate_survey(
...    survey=we.survey.Survey(
...       md=[0, 500, 1000, 2000, 3000],
...       inc=[0, 0, 30, 90, 90],
...       azi=[0, 0, 45, 135, 180],
...    ),
...    step=30
... )
>>> node = survey.interpolate_md(1234)
>>> node.properties()
{
    'vec_nev': [0.07584209568113438, 0.5840332282889957, 0.8081789187902809],
    'vec_xyz': [0.5840332282889957, 0.07584209568113438, 0.8081789187902809],
    'inc_rad': 0.6297429542197106,
    'azi_rad': 1.4416597719915565,
    'inc_deg': 36.081613454889634,
    'azi_deg': 82.60102042890875,
    'pos_nev': [141.27728744087796, 201.41424652428694, 1175.5823295305202],
    'pos_xyz': [201.41424652428694, 141.27728744087796, 1175.5823295305202],
    'md': 1234.0,
    'unit': 'meters',
    'interpolated': True
}
interpolate_survey(step=30, dls=1e-08)[source]

Convenience method for interpolating a Survey object’s MD.

interpolate_survey_tvd(start=None, stop=None, step=10)[source]

Convenience method for interpolating a Survey object’s TVD.

interpolate_tvd(tvd)[source]
maximum_curvature(dls_noise=1.0)[source]

Create a well trajectory using the Maximum Curvature method.

Parameters:
  • survey (welleng.survey.Survey object) –

  • dls_noise (float) – The additional Dog Leg Severity (DLS) in deg/30m used to calculate the curvature for the initial section of the survey interval.

Returns:

survey_new – A revised survey object calculated using the Minimum Curvature method with updated survey positions and additional mid-point stations.

Return type:

welleng.Survey.survey object

modified_tortuosity_index(rtol=1.0, dls_tol=0.001, step=1.0, dls_noise=1.0, data=False, **kwargs)[source]

Convenience method for calculating the Tortuosity Index (TI) using a modified version of the method described in the [International Association of Directional Drilling presentation](https://www.iadd-intl.org/media/files/files/47d68cb4/iadd-luncheon-february-22-2018-v2.pdf) by Pradeep Ashok et al.

Parameters:
  • rtol (float) – Relative tolerance when determining closeness of normal vectors.

  • dls_tol (float or None) – Indicates whether or not to check for dls continuity within the defined dls tolerance.

  • step (float or None) – The step length in meters used for interpolating the survey prior to calculating trajectory with the maximum curvature method. If None or dls_noise is None then no interpolation is done.

  • dls_noise (float or None) – The incremental Dog Leg Severity to be added when using the maximum curvature method. If None then no pre-processing will be done and minimum curvature is assumed.

  • data (bool) – If true returns a dictionary of properties.

Returns:

ti – Array of tortuosity index or a dict of results where:

Return type:

(n,1) array or dict

References

Further details regarding the maximum curvature method can be read [here](https://jonnymaserati.github.io/2022/06/19/modified-tortuosity-index-survey-frequency.html)

project_to_bit(delta_md, dls=None, toolface=None)[source]

Convenience method to project the survey ahead to the bit.

Parameters:
  • delta_md (float) – The along hole distance from the surveying tool to the bit in meters.

  • dls (float) – The desired dog leg severity (deg / 30m) between the surveying tool and the bit. Default is to project the DLS of the last survey section.

  • toolface (float) – The desired toolface to project from at the last survey point. The default is to project the current toolface from the last survey station.

Returns:

node

Return type:

welleng.node.Node object

project_to_target(node_target, dls_design=3.0, delta_md=None, dls=None, toolface=None, step=30)[source]
save(filename)[source]

Saves a minimal (control points) survey listing as a .csv file, including the survey header information.

Parameters:

filename (str) – The path and filename for saving the text file.

set_vertical_section(vertical_section_azimuth, deg=True)[source]

Sets the vertical_section_azimuth property in the survey header and the vertical section data with the data calculated for the input azimuth.

Parameters:
  • vertical_section_azimuth (float) – The azimuth (relative to the reference azimuth defined in the survey header) along which to calculate the vertical section lateral displacement.

  • deg (boolean (default: True)) – Indicates whether the vertical section azimuth parameter is in degrees or radians (True or False respectively).

tortuosity_index(rtol=0.01, dls_tol=None, data=False, **kwargs)[source]

A modified version of the Tortuosity Index function originally referenced in an IADD presentation on “Measuring Wellbore Tortuosity” by Pradeep Ashok - https://www.iadd-intl.org/media/ files/files/47d68cb4/iadd-luncheon-february-22-2018-v2.pdf with reference to the original paper “A Novel Method for the Automatic Grading of Retinal Vessel Tortuosity” by Enrico Grisan et al. In SPE/IADC-194099-MS there’s mention that a factor of 1e7 is applied to the TI result since the results are otherwise very small numbers. Unlike the documented version that uses delta inc and azi for determining continuity and directional intervals (which are not independent and so values are double dipped in 3D), this method determines the point around which the well bore is turning and tests for continuity of these points. As such, this function takes account of torsion of the well bore and demonstrates that actual/drilled trajectories are significantly more tortuous than planned trajectories (intuitively).

Parameters:
  • rtol (float) – Relative tolerance when determining closeness of normal vectors.

  • atol (float) – Absolute tolerance when determining closeness of normal vectors.

  • data (boolean) – If true returns a dictionary of properties.

  • Returns

  • ti ((n,1) array) – Array of tortuosity index or a dict or results.

class welleng.survey.SurveyData(survey)[source]

Bases: object

__init__(survey)[source]

A class for extracting the minimal amount of data from a Survey object, with methods for combining data from a list of surveys that describe an entire well path.

Parameters:

survey (welleng.survey.Survey) –

append_survey(survey)[source]

Method to extract data from a survey and append it to the existing survey data existing in the instance.

Parameters:

survey (welleng.survey.Survey) –

get_survey()[source]

Method to create a welleng.survey.Survey object from the survey data existing in the instance.

Returns:

survey

Return type:

welleng.survey.Survey

class welleng.survey.SurveyHeader(name: str = None, longitude=None, latitude=None, altitude=None, survey_date=None, G=9.80665, b_total=None, earth_rate=0.26251614, dip=None, declination=None, convergence=0, azi_reference='true', vertical_inc_limit=0.0001, deg=True, depth_unit='meters', surface_unit='meters', mag_defaults={'b_total': 50000.0, 'declination': 0.0, 'dip': 70.0}, vertical_section_azimuth=0)[source]

Bases: object

A class for storing header information about a well.

Parameters:
  • name (string (default: None)) – The assigned name of the well bore.

  • longitude (float (default: None)) – The longitude of the surface location of the well. If left default (None) then it will be assigned to Grenwich, the undisputed center of the universe.

  • latitude (float (default: None)) – The latitude of the surface location of the well. If left default (None) then it will be assigned to Grenwich, the undisputed center of the universe.

  • altitude (float (default: None)) – The altitude of the surface location. If left defaults (None) then it will be assigned to 0.

  • survey_date (YYYY-mm-dd (default: None)) – The date on which the survey data was recorded. If left default then the current date is assigned.

  • G (float (default: 9.80665)) – The gravitational field strength in m/s^2.

  • b_total (float (default: None)) – The gravitation field strength in nT. If left default, then the value is calculated from the longitude, latitude, altitude and survey_data properties using the magnetic_field_calculator.

  • earth_rate (float (default: 0.26249751949994715)) – The rate of rotation of the earth in radians per hour.

  • noise_reduction_factor (float (default: 1.0)) – A fiddle factor for random gyro noise.

  • dip (float (default: None)) – The dip (inclination) of the magnetic field relative to the earth’s horizontal. If left default, then the value is calculated using the magnetic_field_calculator. The unit (deg of rad) is determined by the deg property.

  • declination (float (default: None)) – The angle between true north and magnetic north at the well location. If left default, then the value is calculated using the magnetic_field_calculator.

  • convergence (float (default: 0)) – The angle of convergence between the projection meridian and the line from true north through the location of the well.

  • azi_reference (string (default: 'true')) – The reference system for the azimuth angles in the survey data, either “true”, “magnetic” or “grid”. Note that survey calculations are performed in the “grid” reference and converted to and from the other systems.

  • vertical_inc_limit (float (default 0.0001)) – For survey inclination angles less than the vertical_inc_limit (in degrees), calculations are approximated to avoid singularities and errors.

  • deg (bool (default: True)) – Indicates whether the survey angles are measured in degrees (True) or radians (False).

  • depth_unit (string (default: "meters")) – The unit of depth for the survey data, either “meters” or “feet”.

  • surface_unit (string (default: "feet")) – The unit of distance for the survey data, either “meters” or “feet”.

  • vertical_section_azimuth (float (default: 0.0)) – The azimuth along which to determine the vertical section data for the well trajectory.

__init__(name: str = None, longitude=None, latitude=None, altitude=None, survey_date=None, G=9.80665, b_total=None, earth_rate=0.26251614, dip=None, declination=None, convergence=0, azi_reference='true', vertical_inc_limit=0.0001, deg=True, depth_unit='meters', surface_unit='meters', mag_defaults={'b_total': 50000.0, 'declination': 0.0, 'dip': 70.0}, vertical_section_azimuth=0)[source]
class welleng.survey.SurveyParameters(projection: str = 'EPSG:23031')[source]

Bases: Proj

Class for calculating survey parameters for input to a Survey Header.

This is a wrapper of pyproj that tries to simplify the process of getting convergence, declination and dip values for a survey header.

Notes

Requires pyproj and magnetic_field_calculator to be installed and access to the internet.

For reference, here’s some EPSG codes: {

‘UTM31_ED50’: ‘EPSG:23031’, ‘UTM31_WGS84’: ‘EPSG:32631’, ‘RD’: ‘EPSG:28992’, ‘ED50-UTM31’: ‘EPSG:23031’, ‘ED50-NEDTM’: ‘EPSG:23095’, # assume same as ED50-UTM31 ‘ETRS89-UTM31’: ‘EPSG:25831’, ‘ED50-UTM32’: ‘EPSG:23032’, ‘ED50-GEOGR’: ‘EPSG:4230’, ‘WGS84-UTM31’: ‘EPSG:32631’

}

References

For more info on transformations between maps, refer to the pyproj project [here](https://pypi.org/project/pyproj/).

__init__(projection: str = 'EPSG:23031') None[source]

Initiates a SurveyParameters object for conversion of map coordinates to WGS84 lat/lon for calculating magnetic field properties.

Parameters:

projection (str (default: "EPSG:23031")) – The EPSG code of the map of interest. The default represents ED50/UTM zone 31N.

References

For codes refer to [EPSG](https://epsg.io).

get_factors_from_x_y(x: float, y: float, altitude: float = None, date: str = None) dict[source]

Calculates the survey header parameters for a given map coordinate.

Parameters:
  • x (float) – The x or East/West coordinate.

  • y (float) – The y or North/South coordinate.

  • altitude (float (default: None)) – The altitude or z value coordinate. If none is provided this will default to zero (sea level).

  • date (str (default: None)) – The date of the survey, used when calculating the magnetic parameters. Will default to the current date.

Returns:

x: float

The x coordinate.

y: float

The y coordinate.

northing: float

The Northing (negative values are South).

easting: float

The Easting (negative values are West).

latitude: float

The WGS84 latitude.

longitude: float

The WGS84 longitude.

convergence: float

Te grid convergence for the provided coordinates.

scale_factor: float

The scale factor for the provided coordinates.

magnetic_field_intensity: float

The total field intensity for the provided coordinates and time.

declination: float

The declination at the provided coordinates and time.

dip: float

The dip angle at the provided coordinates and time.

date:

The date used for determining the magnetic parameters.

Return type:

dict

Examples

In the following example, the parameters for Den Haag in The Netherlands are looked up with the reference map ED50 UTM Zone 31N.

>>> import pprint
>>> from welleng.survey import SurveyParameters
>>> calculator = SurveyParameters('EPSG:23031')
>>> survey_parameters = calculator.get_factors_from_x_y(
...     x=588319.02, y=5770571.03
... )
>>> pprint(survey_parameters)
{'convergence': 1.01664403471959,
'date': '2023-12-16',
'declination': 2.213,
'dip': -67.199,
'easting': 588319.02,
'latitude': 52.077583926214494,
'longitude': 4.288694821453205,
'magnetic_field_intensity': 49381,
'northing': 5770571.03,
'scale_factor': 0.9996957469340414,
'srs': 'EPSG:23031',
'x': 588319.02,
'y': 5770571.03}
transform_coordinates(coords: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], to_projection: str, altitude: float = None, *args, **kwargs) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes][source]

Transforms coordinates from instance’s projection to another projection.

Parameters:
  • coords (arraylike) – A list of decimal coordinates to transform from the instance projection to the specified projection system. Can be 2D or 3D in (x, y, z) format, where x is East/West and y is North/South.

  • to_projection (str) – The EPSG code of the desired coordinates.

Returns:

result – An array of transformed coordinates in the desired projection.

Return type:

ArrayLike

Examples

Convert the coordinates of Den Haag from ED50-UTM31 to WGS84-UTM31:

>>> from welleng.survey import SurveyParameters
>>> calculator = SurveyParameters('EPSG:23031')
>>> result = calculator.transform_coordinates(
...     coords=[(588319.02, 5770571.03)], to_projection='EPSG:32631'
... )
>>> print(result)
[[ 588225.93417027 5770360.56500115]]
class welleng.survey.TurnPoint(md=None, inc=None, azi=None, build_rate=None, turn_rate=None, dls=None, toolface=None, method=None, target=None, tie_on=False, location=None)[source]

Bases: object

__init__(md=None, inc=None, azi=None, build_rate=None, turn_rate=None, dls=None, toolface=None, method=None, target=None, tie_on=False, location=None)[source]
welleng.survey.directional_difficulty_index(survey, **kwargs)[source]

Taken from IADC/SPE 59196 The Directional Difficulty Index - A New Approach to Performance Benchmarking by Alistair W. Oag et al. :param survey: :type survey: welleng.survey.Survey object :param data: If True, returns the ddi at each survey station. :type data: bool

Returns:

  • ddi (float) – The ddi for the well at well (at TD).

  • data ((n) array of floats) – The ddi for each survey station.

welleng.survey.export_csv(survey, filename, tolerance=0.1, dls_cont=False, decimals=3, **kwargs)[source]

Function to export a minimalist (only the control points - i.e. the begining and end points of hold and/or turn sections) survey to input into third party trajectory planning software.

Parameters:
  • survey (welleng.survey.Survey object) –

  • filename (str) – The path and filename for saving the text file.

  • tolerance (float (default: 0.1)) – How close the the final N, E, TVD position of the minimalist survey should be to the original survey point (e.g. within 1 meter)

  • dls_cont (bool) – Whether to explicitly check for dls continuity. May result in a larger number of control points but a trajectory that is a closer fit to the survey.

  • decimals (int (default: 3)) – Number of decimal places provided in the output file listing

welleng.survey.from_connections(section_data, step=None, survey_header=None, start_nev=[0.0, 0.0, 0.0], start_xyz=[0.0, 0.0, 0.0], start_cov_nev=None, radius=10, deg=False, error_model=None, depth_unit='meters', surface_unit='meters', decimals: int | None = None)[source]

Constructs a well survey from a list of sections of control points.

Parameters:
  • section_data (list of dicts with section data) –

  • start_nev – The starting position in NEV coordinates.

  • radius (float (default: 10)) – The radius is passed to the welleng.survey.Survey object and represents the radius of the wellbore. It is also used when visualizing the results, so can be used to make the wellbore thicker in the plot.

  • decimals (int (default=6)) – Round the md decimal when checking for duplicate surveys.

  • Results

  • ------- – survey: welleng.survey.Survey object

welleng.survey.func(x0, survey, dls_cont, tolerance)[source]
welleng.survey.get_circle_radius(survey, **targets)[source]
welleng.survey.get_data(tol, survey, dls_cont)[source]
welleng.survey.get_node(survey, idx, interpolated=False)[source]
welleng.survey.get_node_tvd(survey, node1, node2, tvd, node_origin)[source]
welleng.survey.get_sections(survey, rtol=0.1, atol=0.1, dls_cont=False, **targets)[source]

Tries to discretize a survey file into hold or curve sections. These sections can then be used to generate a WellPlan object to generate a .wbp format file for import into Landmark COMPASS, thus converting a survey file to an editable well trajectory.

Note that this is in development and only tested on output from planning software. In its current form it likely won’t be too successful on “as drilled” surveys (but optimizing the tolerances may help).

Parameters:
  • survey (welleng.survey.Survey object) –

  • rtol (float (default: 1e-1)) – The relative tolerance when comparing the normals using the numpy.isclose() function.

  • atol (float (default: 1e-2)) – The absolute tolerance when comparing the normals using the numpy.isclose() function.

  • dls_cont (bool) – Whether to explicitly check for dls continuity. May results in a larger number of control points but a trajectory that is a closer fit to the survey.

  • **targets (list of Target objects) – Not supported yet…

  • Returns

  • --------

  • sections (list of welleng.exchange.wbp.TurnPoint objects) –

welleng.survey.get_unit(unit)[source]
welleng.survey.interpolate_md(survey, md)[source]

Interpolates a survey at a given measured depth.

welleng.survey.interpolate_survey(survey, step=30, dls=1e-08)[source]

Interpolate a sparse survey with the desired md step.

Parameters:
  • survey (welleng.survey.Survey object) –

  • step (float (default=30)) – The desired delta md between stations.

  • dls (float (default=0.01)) – The design DLS used to calculate the minimum curvature. This will be the minimum DLS used to fit a curve between stations so should be set to a small value to ensure a continuous curve is fit without any tangent sections.

Returns:

survey_interpolated – Note that a interpolated property is added indicating if the survey stations is interpolated (True) or not (False).

Return type:

welleng.survey.Survey object

welleng.survey.interpolate_survey_tvd(survey, start=None, stop=None, step=10)[source]
welleng.survey.interpolate_tvd(survey, tvd, **kwargs)[source]
welleng.survey.make_cov(a, b, c, diag=False)[source]

Make a covariance matrix from the 1-sigma errors.

Parameters:
  • a ((,n) list or array of floats) – Errors in H or N/y axis.

  • b ((,n) list or array of floats) – Errors in L or E/x axis.

  • c ((,n) list or array of floats) – Errors in A or V/TVD axis.

  • diag (boolean (default=False)) – If true, only the lead diagonal is calculated with zeros filling the remainder of the matrix.

Returns:

cov

Return type:

(n,3,3) np.array

welleng.survey.make_long_cov(arr)[source]

Make a covariance matrix from the half covariance 1sigma data.

welleng.survey.make_survey_header(data)[source]

Takes a dictionary of survey header data with the same keys as the SurveyHeader class properties and returns a SurveyHeader object.

welleng.survey.modified_tortuosity_index(survey, rtol=1.0, dls_tol=0.001, data=False, **kwargs)[source]

Method for calculating the Tortuosity Index (TI) using a modified version of the method described in the International Association of Directional Drilling presentation (https://www.iadd-intl.org/media/files/files/47d68cb4/iadd-luncheon-february-22-2018-v2.pdf) by Pradeep Ashok et al.

welleng.survey.project_ahead(pos, vec, delta_md, dls, toolface, md=0.0)[source]

Apply a simple arc or hold from a current position and vector.

Parameters:
  • pos – Current position in n, e, tvd coordinates.

  • vec – Current vector in n, e, tvd coordinates.

  • delta_md (float) – The desired along hole projection length.

  • dls (float) – The desired dogleg severity of the projection. Entering 0.0 will result in a hold section.

  • toolface (float) – The desired toolface for the projection.

  • md (float (optional)) – The current md if applicable.

Returns:

node

Return type:

welleng.node.Node object

welleng.survey.project_to_target(survey, node_target, dls_design=3.0, delta_md=None, dls=None, toolface=None, step=30)[source]

Project a wellpath from the end of a current survey to a target, taking account of the location of the bit relative to the surveying tool if the delta_md property is not None.

Parameters:
  • survey (welleng.survey.Survey obj) –

  • node_target (welleng.node.Node obj) –

  • dls_design (float) – The dls from which to construct the projected wellpath.

  • delta_md (float) – The along hole length from the surveying sensor to the bit.

  • dls (float) – The desired dogleg severity for the projection from the survey tool to the bit. Entering 0.0 will result in a hold section.

  • toolface (float) – The desired toolface for the projection from the survey tool to the bit.

  • step (float) – The desired survey interval for the projected wellpath to the target.

Returns:

node

Return type:

welleng.survey.Survey obj

welleng.survey.slice_survey(survey: Survey, start: int, stop: int = None)[source]

Take a slice from a welleng.survey.Survey object.

Parameters:
  • survey (welleng.survey.Survey object) –

  • start (int) – The start index of the desired slice.

  • stop (int (default: None)) – The stop index of the desired slice, else the remainder of the well bore TD is the default.

Returns:

s – A survey object of the desired slice is returned.

Return type:

welleng.survey.Survey object

welleng.survey.splice_surveys(surveys)[source]

Join together an ordered list of surveys for a well (for example, a list of surveys with a different error model for each survey).

Parameters:

surveys (list of welleng.survey.Survey objects) – The first survey in the list is assumed to be the shallowest and the survey header data is taken from this well. Subsequent surveys are assumed to be ordered by depth, with the first md of the next survey being equal to the last md of the previous survey.

Returns:

spliced_survey – A single survey consisting of the input surveys placed together.

Return type:

welleng.survey.Survey object

Notes

The returned survey will include the covariance data describing the well bore uncertainty, but will not include the error models since these may be different for each well section.

welleng.survey.survey_to_df(survey: Survey) DataFrame[source]
welleng.survey.tortuosity_index(survey, rtol=0.01, dls_tol=None, data=False, **kwargs)[source]

Method for calculating the Tortuosity Index (TI) as described in the International Association of Directional Drilling presentation (https://www.iadd-intl.org/media/files/files/47d68cb4/iadd-luncheon-february-22-2018-v2.pdf) by Pradeep Ashok et al.

welleng.target module

class welleng.target.Target(name, n, e, tvd, shape, locked=0, orientation=0, dip=0, color='green', alpha=0.5, **geometry)[source]

Bases: object

__init__(name, n, e, tvd, shape, locked=0, orientation=0, dip=0, color='green', alpha=0.5, **geometry)[source]
Parameters:

geometry

plot_data()[source]

welleng.torque_drag module

class welleng.torque_drag.HookLoad(survey, wellbore, string, fluid_density, step=30, name=None, ff_range=(0.1, 0.4, 0.1))[source]

Bases: object

__init__(survey, wellbore, string, fluid_density, step=30, name=None, ff_range=(0.1, 0.4, 0.1))[source]

A class for calculating the hookload or broomstick plot data for running or pulling a string in a wellbore.

Parameters:
  • survey (welleng.survey.Survey instance) – The well trajectory of the scenario being modelled.

  • wellbore (welleng.architecture.WellBore instance) – The well bore architecture of the scenario being modelled.

  • string (welleng.architecture.BHA or welleng.architecture.CasingString) –

  • instance – The string being run inside the well bore for the scenario being modelled.

  • fluid_density (float) – The density (in SG) of the fluid in the well bore.

  • step (float) – The measured depth step distance in meters to move the string.

  • name (str) – The name of the scenario being modeled.

  • ff_range – The start, stop and step for the range of friction factors to be used in the hookload calculations.

figure()[source]
get_data()[source]
get_ff_range(ff_range)[source]
class welleng.torque_drag.TorqueDrag(survey, wellbore, string, fluid_density, name=None, wob=None, tob=None, overpull=None)[source]

Bases: object

__init__(survey, wellbore, string, fluid_density, name=None, wob=None, tob=None, overpull=None)[source]

A class for calculating wellbore torque and drag, based on the “Torque and Drag in Directional Wells–Prediction and Measurement (SPE 11380-PA) by C.A. Johancsik et al.

Parameters:
  • survey (welleng.survey.Survey instance) – The well trajectory of the scenario being modelled.

  • wellbore (welleng.architecture.WellBore instance) – The well bore architecture of the scenario being modelled.

  • string (welleng.architecture.BHA or welleng.architecture.CasingString) –

  • instance – The string being run inside the well bore for the scenario being modelled.

  • fluid_density (float) – The density (in SG) of the fluid in the well bore.

  • name (str) – The name of the scenario being modeled.

  • wob (float) – The compressive force (weight on bit) applied at the bottom of the string in N.

  • tob (float) – The torque (torque on bit) applied at the bottom of the string in N.m.

  • overpull (float) – The tension applied at the bottom of the string in N.

add_survey_points_from_strings()[source]

Check that there’s survey stations for the top and bottoms of the string sections to ensure that the torque and drag is calculated for these key locations.

figure()[source]
get_azi_delta()[source]
get_buoyancy_factors()[source]

Determine the buoyancy factor for each string section and add it to the string sections dict.

get_characteristic_od(section)[source]
get_coeff_friction_sliding()[source]
get_forces_and_torsion(wob=False, tob=False, overpull=False)[source]
get_inc_average()[source]
get_inc_delta()[source]
get_weight_buoyed_and_radius()[source]
welleng.torque_drag.buoyancy_factor(fluid_density, string_density=7.85)[source]
Parameters:
  • fluid_density (float) – The density of the fluid in SG.

  • string_density (float) – The density of the string, typically made from steel.

Returns:

result – The buoyancy factor when when multiplied against the string weight yields the bouyed string weight.

Return type:

float

welleng.torque_drag.figure_hookload(hl, units={'depth': 'ft', 'tension': 'lbf', 'torque': 'ft_lbf'})[source]
welleng.torque_drag.figure_string_tension_and_torque(td, units={'depth': 'ft', 'tension': 'lbf', 'torque': 'ft_lbf'})[source]
welleng.torque_drag.force_normal(force_tension, inc_average, inc_delta, azi_delta, weight_buoyed)[source]
welleng.torque_drag.force_tension_delta(weight_buoyed, inc_average, coeff_friction_sliding, force_normal)[source]
welleng.torque_drag.torsion_delta(coeff_friction_sliding, force_normal, radius)[source]

welleng.units module

welleng.utils module

class welleng.utils.Arc(dogleg, radius)[source]

Bases: object

__init__(dogleg, radius)[source]

Generates a generic arc that can be transformed with a specific pos and vec via a transform method. The arc is initialized at a local origin and kicks off down and to the north (assuming an NEV coordinate system).

Parameters:
  • dogleg (float) – The sweep angle of the arc in radians.

  • radius (float) – The radius of the arc in meters.

Returns:

arc

Return type:

Arc object

transform(toolface, pos=None, vec=None, target=False)[source]

Transforms an Arc to a position and orientation.

Parameters:
  • pos ((,3) array) –

  • arc. (The desired position to transform the) –

  • vec ((,3) array) – The orientation unit vector to transform the arc.

  • target (bool) – If true, returned arc vector is reversed.

Returns:

  • tuple (pos_new, vec_new)

  • pos_new ((,3) array) – The position at the end of the arc post transform.

  • vec_new ((,3) array) – The unit vector at the end of the arc post transform.

welleng.utils.HLA_to_NEV(survey, HLA, cov=True, trans=None)[source]
class welleng.utils.MinCurve(md, inc, azi, start_xyz=[0.0, 0.0, 0.0], unit='meters')[source]

Bases: object

__init__(md, inc, azi, start_xyz=[0.0, 0.0, 0.0], unit='meters')[source]

Generate geometric data from a well bore survey.

Parameters:
  • md (list or 1d array of floats) – Measured depth along well path from a datum.

  • inc (list or 1d array of floats) – Well path inclination (relative to z/tvd axis where 0 indicates down), in radians.

  • azi (list or 1d array of floats) – Well path azimuth (relative to y/North axis), in radians.

  • unit (str) – Either “meters” or “feet” to determine the unit of the dogleg severity.

welleng.utils.NEV_to_HLA(survey: ndarray[Any, dtype[_ScalarType_co]], NEV: ndarray[Any, dtype[_ScalarType_co]], cov: bool = True) ndarray[Any, dtype[_ScalarType_co]][source]

Transform from NEV to HLA coordinate system.

Parameters:
  • survey ((n,3) array of floats) – The [md, inc, azi] survey listing array.

  • NEV ((d,3) or (3,3,d) array of floats) – The NEV coordinates or covariance matrices.

  • cov (boolean) – If cov is True then a (3,3,d) array of covariance matrices is expected, else a (d,3) array of coordinates.

Returns:

HLAs – Either a transformed (n,3) array of HLA coordinates or an (3,3,n) array of HLA covariance matrices.

Return type:

NDArray

welleng.utils.annular_volume(od: float, id: float = None, length: float = None)[source]

Calculate an annular volume.

If no id is provided then circular volume is calculated. If no length is provided, then the unit volume is calculated (i.e. the area).

Units are assumed consistent across input parameters, i.e. the calculation is dimensionless.

Parameters:
  • od (float) – The outer diameter.

  • id (float | None, optional) – The inner diameter, default is 0.

  • length (float | None, optional) – The length of the annulus.

Returns:

annular_volume – The (unit) volume of the annulus or cylinder.

Return type:

float

Examples

In the following example we calculate annular volume along a 1,000 meter section length of 9 5/8” casing inside 12 1/4” hole.

>>> from welleng.utils import annular_volume
>>> from welleng.units import ureg
>>> av = annular_volume(
...     od=ureg('12.25 inch').to('meters),
...     id=ureg(f'{9+5/8} inch').to('meter'),
...     length=ureg('1000 meter')
... )
>>> print(av)
3.491531223156194 meter ** 3
welleng.utils.decimal2dms(decimal: tuple | ndarray[Any, dtype[_ScalarType_co]], ndigits: int = None) tuple | ndarray[Any, dtype[_ScalarType_co]][source]

Converts a decimal lat, lon to degrees, minutes and seconds.

Parameters:
  • decimal (tuple | arraylike) – A tuple of (lat, direction) or (lon, direction) or arraylike of ((lat, direction), (lon, direction)) coordinates.

  • ndigits (int (default is None)) – If specified, rounds the seconds decimal to the desired number of digits.

Returns:

dms – An array of (degrees, minutes, seconds, direction).

Return type:

arraylike

Examples

If you want to convert the lat/lon coordinates for Den Haag from decimals to degrees, minutes and seconds:

>>> LAT, LON = [(52.078663, 'N'), (4.288788, 'E')]
>>> dms = decimal2dms((LAT, LON), ndigits=6)
>>> print(dms)
[[52 4 43.1868 'N']
 [4 17 19.6368 'E']]
welleng.utils.dls_from_radius(radius)[source]

Returns the dls in degrees from a radius.

welleng.utils.dms2decimal(dms: tuple | ndarray[Any, dtype[_ScalarType_co]], ndigits: int = None) ndarray[Any, dtype[_ScalarType_co]][source]

Converts a degrees, minutes and seconds lat, lon to decimals.

Parameters:
  • dms (tuple | arraylike) – A tuple or arraylike of (degrees, minutes, seconds, direction) lat and/or lon or arraylike of lat, lon coordinates.

  • ndigits (int (default is None)) – If specified, rounds the decimal to the desired number of digits.

Returns:

degrees – A tuple or array of lats and/or longs in decimals.

Return type:

arraylike

Examples

If you want to convert the lat/lon coordinates for Den Haag from degrees, minutes and seconds to decimals:

>>> LAT, LON = (52, 4, 43.1868, 'N'), (4, 17, 19.6368, 'E')
>>> decimal = dms2decimal((LAT, LON), ndigits=6)
>>> print(decimal)
[[52.078663 'N']
 [4.288788 'E']]
welleng.utils.dms_from_string(text)[source]

Extracts the values from a string dms x or y or northing or easting.

welleng.utils.errors_from_cov(cov, data=False)[source]
Parameters:
  • cov ((n, 3, 3) array) – The error covariance matrices.

  • data (bool (default: False)) – If True returns a dictionary, else returns a list.

welleng.utils.get_angles(vec: ndarray[Any, dtype[_ScalarType_co]], nev: bool = False)[source]

Determines the inclination and azimuth from a vector.

Parameters:
  • vec ((n,3) array of floats) –

  • nev (boolean (default: False)) – Indicates if the vector is in (x,y,z) or (n,e,v) coordinates.

Returns:

[inc, azi] – A numpy array of incs and axis in radians

Return type:

(n,2) array of floats

welleng.utils.get_arc(dogleg, radius, toolface, pos=None, vec=None, target=False) tuple[source]

Creates an Arc instance and transforms it to the desired position and orientation.

Parameters:
  • dogleg (float) – The swept angle of the arc (arc angle) in radians.

  • radius (float) – The radius of the arc (in meters).

  • toolface (float) – The toolface angle in radians (relative to the high side) to rotate the arc at the desired position and orientation.

  • pos ((,3) array) – The desired position to transform the arc.

  • vec ((,3) array) – The orientation unit vector to transform the arc.

  • target (bool) – If true, returned arc vector is reversed.

Returns:

  • tuple of (pos_new, vec_new, arc.delta_md)

  • pos_new ((,3) array) – The position at the end of the arc post transform.

  • vec_new ((,3) array) – The unit vector at the end of the arc post transform.

  • arc.delta_md (int) – The arc length of the arc.

welleng.utils.get_dogleg(inc1, azi1, inc2, azi2)[source]
welleng.utils.get_nev(pos, start_xyz=array([0., 0., 0.]), start_nev=array([0., 0., 0.]))[source]

Convert [x, y, z] coordinates to [n, e, tvd] coordinates.

Parameters:
  • pos ((n,3) array of floats) – Array of [x, y, z] coordinates

  • start_xyz ((,3) array of floats) – The datum of the [x, y, z] cooardinates

  • start_nev ((,3) array of floats) – The datum of the [n, e, tvd] coordinates

Return type:

An (n,3) array of [n, e, tvd] coordinates.

welleng.utils.get_sigmas(cov, long=False)[source]

Extracts the sigma values of a covariance matrix along the principle axii.

Parameters:

cov ((n,3,3) array of floats) –

Returns:

arr

Return type:

(n,3) array of floats

welleng.utils.get_toolface(pos1: ndarray[Any, dtype[_ScalarType_co]], vec1: ndarray[Any, dtype[_ScalarType_co]], pos2: ndarray[Any, dtype[_ScalarType_co]]) float[source]

Returns the toolface of an offset position relative to a reference position and vector.

Parameters:
  • pos1 (ndarray) – The reference NEV coordinate, e.g. current location.

  • vec1 (ndarray) – The reference NEV unit vector, e.g. current vector heading.

  • pos2 (ndarray) – The offset NEV coordinate, e.g. a target position.

Returns:

toolface – The toolface (bearing or required heading) in radians to pos2 from pos1 with vec1.

Return type:

float

welleng.utils.get_transform(survey)[source]

Determine the transform for transforming between NEV and HLA coordinate systems.

Parameters:

survey ((n,3) array of floats) – The [md, inc, azi] survey listing array.

Returns:

transform

Return type:

(n,3,3) array of floats

welleng.utils.get_unit_vec(vec)[source]
welleng.utils.get_vec(inc, azi, nev=False, r=1, deg=True)[source]

Convert inc and azi into a vector.

Parameters:
  • inc (array of n floats) – Inclination relative to the z-axis (up)

  • azi (array of n floats) – Azimuth relative to the y-axis

  • r (float or array of n floats) – Scalar to return a scaled vector

Returns:

vec – An (n,3) array of vectors

Return type:

arraylike

welleng.utils.get_xyz(pos, start_xyz=[0.0, 0.0, 0.0], start_nev=[0.0, 0.0, 0.0])[source]
welleng.utils.linear_convert(data, factor)[source]
welleng.utils.make_cov(a, b, c, long=False)[source]
welleng.utils.pprint_dms(dms, symbols: bool = True, return_data: bool = False)[source]

Pretty prints a (decimal, minutes, seconds) tuple or list.

Parameters:
  • dms (tuple | list) – An x or y or northing or easting (degree, minute, second).

  • symbols (bool (default: True)) – Whether to print symbols for (deg, min, sec).

  • return_data (bool (default: False)) – If True then will return the string rather than print it.

welleng.utils.radius_from_dls(dls)[source]

Returns the radius in meters from a DLS in deg/30m.

welleng.version module

welleng.visual module

class welleng.visual.CubeAxes(**kwargs)[source]

Bases: vtkCubeAxesActor

__init__(**kwargs)[source]
class welleng.visual.Plotter(*args, **kwargs)[source]

Bases: Plotter

__init__(*args, **kwargs)[source]

Notes

On account of Z or TVD pointing down in the drilling world, the coordinate system is right handed. In order to map coordinates in the NEV (or North, East, Vertical) reference correctly, North coordinates are plotted on the X axis and East on the Y axis. Be mindful of this adding objects to a scene.

add(obj, *args, **kwargs) None[source]

Modified method to support direct plotting of welleng.mesh.WellMesh instances and for processing the callback to print well data when the pointer is hovered of a well trajectory.

If the obj is a welleng.mesh.WellMesh instance, then the args and kwargs will be passed to the vedo.Mesh instance to facilate e.g. color options etc.

Notes

welleng.mesh.WellMesh creates trimesh.Mesh instances, a legacy of using the trimesh library for detecting mesh collisions when developing automated well trajectory planning. Therefore, to visualize the meshes with vedo and vtk, the meshes need to be converted.

Meshes in welleng typically reference an ‘NEV’ coordinate system, which is [North, East, Vertical]. To map correctly to vtk, North needs to be mapped to X and East to Y on account of Z pointing down.

show(axes=None, *args, **kwargs)[source]

Render a list of objects.

Parameters:
  • at – (int) number of the renderer to plot to, in case of more than one exists

  • axes – (int) axis type-1 can be fully customized by passing a dictionary. Check addons.Axes() for the full list of options. set the type of axes to be shown: - 0, no axes - 1, draw three gray grid walls - 2, show cartesian axes from (0,0,0) - 3, show positive range of cartesian axes from (0,0,0) - 4, show a triad at bottom left - 5, show a cube at bottom left - 6, mark the corners of the bounding box - 7, draw a 3D ruler at each side of the cartesian axes - 8, show the vtkCubeAxesActor object - 9, show the bounding box outLine - 10, show three circles representing the maximum bounding box - 11, show a large grid on the x-y plane - 12, show polar axes - 13, draw a simple ruler at the bottom of the window

  • azimuth/elevation/roll – (float) move camera accordingly the specified value

  • viewup – str, list either [‘x’, ‘y’, ‘z’] or a vector to set vertical direction

  • resetcam – (bool) re-adjust camera position to fit objects

  • camera

    (dict, vtkCamera) camera parameters can further be specified with a dictionary assigned to the camera keyword (E.g. show(camera={‘pos’:(1,2,3), ‘thickness’:1000,})): - pos, (list), the position of the camera in world coordinates - focal_point (list), the focal point of the camera in world coordinates - viewup (list), the view up direction for the camera - distance (float), set the focal point to the specified distance from the camera position. - clipping_range (float), distance of the near and far clipping planes along the direction of projection. - parallel_scale (float), scaling used for a parallel projection, i.e. the height of the viewport in world-coordinate distances. The default is 1. Note that the “scale” parameter works as an “inverse scale”, larger numbers produce smaller images. This method has no effect in perspective projection mode.

    • thickness (float), set the distance between clipping planes. This method adjusts the far clipping

    plane to be set a distance ‘thickness’ beyond the near clipping plane.

    • view_angle (float), the camera view angle, which is the angular height of the camera view

    measured in degrees. The default angle is 30 degrees. This method has no effect in parallel projection mode. The formula for setting the angle up for perfect perspective viewing is: angle = 2*atan((h/2)/d) where h is the height of the RenderWindow (measured by holding a ruler up to your screen) and d is the distance from your eyes to the screen.

  • interactive – (bool) pause and interact with window (True) or continue execution (False)

  • rate – (float) maximum rate of show() in Hertz

  • mode – (int, str) set the type of interaction: - 0 = TrackballCamera [default] - 1 = TrackballActor - 2 = JoystickCamera - 3 = JoystickActor - 4 = Flight - 5 = RubberBand2D - 6 = RubberBand3D - 7 = RubberBandZoom - 8 = Terrain - 9 = Unicam - 10 = Image - Check out vedo.interaction_modes for more options.

  • bg – (str, list) background color in RGB format, or string name

  • bg2 – (str, list) second background color to create a gradient background

  • size – (str, list) size of the window, e.g. size=”fullscreen”, or size=[600,400]

  • title – (str) window title text

  • screenshot – (str) save a screenshot of the window to file

welleng.visual.figure(obj, type='scatter3d', **kwargs)[source]
welleng.visual.get_lines(clearance)[source]

Add lines per reference well interval between the closest points on the reference well and the offset well and color them according to the calculated Separation Factor (SF) between the two wells at these points.

Parameters:

clearance (welleng.clearance object) –

Returns:

lines – A vedo.Lines object colored by the object’s SF values.

Return type:

vedo.Lines object

welleng.visual.plot(data, names=None, colors=None, lines=None, targets=None, arrows=None, text=None, boxes=None, points=None, **kwargs)[source]

A deprecated wrapper for the Plotter class, maintained only for compatability with older versions.

Parameters:
  • data (a trimesh.Trimesh object or a list of trimesh.Trimesh) –

  • object (objects or a trmiesh.scene) –

  • names (list of strings (default: None)) – A list of names, index aligned to the list of well meshes.

  • colors (list of strings (default: None)) – A list of color or colors. If a single color is listed then this is applied to all meshes in data, otherwise the list of colors is indexed to the list of meshes.

Module contents