Skip to content

Commit

Permalink
fix: update of intrusion module
Browse files Browse the repository at this point in the history
intrusions are built using two classes
intrusionBuilder to create structural frame
IntrusionFeature to simulated thresholds distances

General update of intances name and cleaning of the code
  • Loading branch information
Fer071989 committed Mar 3, 2022
1 parent cd6fe61 commit bba0163
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 255 deletions.
164 changes: 67 additions & 97 deletions LoopStructural/modelling/core/geological_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@

intrusions = True
try:
from LoopStructural.modelling.intrusions import IntrusionNetwork
# from LoopStructural.modelling.intrusions import IntrusionNetwork
from LoopStructural.modelling.intrusions import IntrusionBuilder
from LoopStructural.modelling.intrusions import IntrusionBody
# from LoopStructural.modelling.intrusions import IntrusionBody
from LoopStructural.modelling.intrusions import IntrusionFeature
except ImportError:
intrusions = False
Expand Down Expand Up @@ -1063,49 +1063,46 @@ def create_and_add_folded_fold_frame(
def create_and_add_intrusion(
self,
intrusion_name,
intrusion_frame_name=None,
intrusion_network_type=None,
intrusion_network_contact=None,
contacts_anisotropies=None,
structures_anisotropies=None,
sequence_anisotropies=None,
inet_axis=None,
intrusion_frame_name,
intrusion_lateral_extent_model=None,
intrusion_vertical_extent_model=None,
intrusion_network_parameters={},
lateral_extent_sgs_parameters={},
vertical_extent_sgs_parameters={},
**kwargs,
):
"""
An intrusion in built in two main steps:
(1) Intrusion network and intrusion frame: the algorithm first identify the intrusion network, which is a set of points
representing the roof or floor contact of the intrusion. Then this set of points is used to contraint the main structural
direction of the structural frame.
(2) Intrusion body: simulation of lateral and vertical extent of intrusion, using parameterization provided by the structural frame
(1) Intrusion builder: intrusion builder creates the intrusion structural frame.
This object is curvilinear coordinate system of the intrusion constrained with intrusion network points,
and flow and inflation measurements (provided by the user).
The intrusion network is a representation of the approximated location of roof or floor contact of the intrusion.
This object might be constrained using the anisotropies of the host rock if the roof (or floor) contact is not well constrained.
(2) Intrusion feature: simulation of lateral and vertical extent of intrusion within the model volume.
The simulations outcome consist in thresholds distances along the structural frame coordinates
that are used to constrained the extent of the intrusion.
Parameters
----------
intrusion_name : string,
name of intrusion feature in model data
intrusion_frame_name : string,
name of intrusion frame in model data
intrusion_network_type : string,
algorithm to build intrusion network 'interpolated' or 'shortest path'
intrusion_network_contact : string,
name of contact (roof or floor) to be used to build intrusion network
contacts_anisotropies : list,
name of stratigraphic units where intrusion is emplaced
structures_anisotropies : list,
name of structures exploited by intrusion
sequence_anisotropies = list,
name of anisotropies to look for the shortest path. It could be only starting and end point.
intrusion_lateral_extent_model = function,
geometrical conceptual model for simulation of lateral extent
intrusion_vertical_extent_model = function,
geometrical conceptual model for simulation of vertical extent
lateral_extent_sgs_parameters = dictionary,
intrusion_network_parameters : dictionary, optional
contact : string, contact of the intrusion to be used to create the network (roof or floor)
type : string, type of algorithm to create the intrusion network (interpolated or shortest path).
Shortest path is recommended when intrusion contact is not well constrained
contacts_anisotropies : list of series-type features involved in intrusion emplacement
structures_anisotropies : list of fault-type features involved in intrusion emplacement
sequence_anisotropies : list of anisotropies to look for the shortest path. It could be only starting and end point.
lateral_extent_sgs_parameters = dictionary, optional
parameters for sequential gaussian simulation of lateral extent
vertical_extent_sgs_parameters = dictionary,
vertical_extent_sgs_parameters = dictionary, optional
parameters for sequential gaussian simulation of vertical extent
kwargs
Expand All @@ -1118,27 +1115,11 @@ def create_and_add_intrusion(
if intrusions == False:
logger.error("Libraries not installed")
raise Exception("Libraries not installed")
feature_data = self.data[self.data["feature_name"] == intrusion_name].copy()

# Create and build Intrusion Network
INet = IntrusionNetwork(
feature_data=feature_data,
intrusion_network_contact=intrusion_network_contact,
intrusion_network_type=intrusion_network_type,
model=self,
**kwargs,
)

INet.set_data()
INet.set_contact_anisotropies(contacts_anisotropies, **kwargs)
INet.set_faults_anisotropies(structures_anisotropies)
INet.set_sequence_of_exploited_anisotropies(sequence_anisotropies)
INet.set_velocity_parameters()
INet.set_sections_axis(inet_axis)
logger.info("building intrusion network")
INet.build(**kwargs)

intrusion_data = self.data[self.data["feature_name"] == intrusion_name].copy()
intrusion_frame_data = self.data[self.data["feature_name"] == intrusion_frame_name].copy()

# Create intrusion frame, using intrusion network points, propagation and inflation direction
# -- get variables for intrusion frame interpolation
if "gxxgz" in kwargs: # weight for orthogonality constraint between coord 0 and coord 2
gxxgz = kwargs["gxxgz"]
else:
Expand All @@ -1165,75 +1146,64 @@ def create_and_add_intrusion(
nelements = 1e2

weights = [gxxgz, gxxgy, gyxgz]
logger.info("building intrusion frame")
interpolator = self.get_interpolator(interpolatortype=interpolatortype)
frame_data = self.data[self.data["feature_name"] == intrusion_frame_name].copy()
IFrame_builder = IntrusionBuilder(
interpolator,
model=self,
name=intrusion_frame_name
)
IFrame_builder.set_data(frame_data, INet.intrusion_network_outcome)
IFrame_builder.setup(

intrusion_builder = IntrusionBuilder(
interpolator,
name=intrusion_frame_name,
model = self,
**kwargs)

# -- create intrusion network
intrusion_builder.set_intrusion_network_parameters(intrusion_data, intrusion_network_parameters)
intrusion_network_geometry = intrusion_builder.create_intrusion_network()

# -- create intrusion frame using intrusion network points and flow/inflation measurements
intrusion_builder.set_intrusion_frame_data(intrusion_frame_data, intrusion_network_geometry)

## -- create intrusion frame
intrusion_builder.setup(
nelements = nelements,
# solver = solver,
w2=weights[0],
w1=weights[1],
gxygz=weights[2],
)

IFrame = IFrame_builder.frame
# Create intrusion feature
intrusion_feature = IntrusionFeature(
intrusion_name, structural_frame=IFrame, model=self
)
intrusion_frame = intrusion_builder.frame

# Simulate thresholds distances to constraint intrusion body,
# and set threshold to intrusion feature
IBody = IntrusionBody(
feature_data,
name=intrusion_name,
intrusion_network=INet,
intrusion_frame=IFrame,
model=self,
# -- Create intrusion feature
intrusion_feature = IntrusionFeature(
intrusion_name, model=self
)

intrusion_feature.set_intrusion_network(INet)
intrusion_feature.set_intrusion_frame(IFrame)
intrusion_feature.set_intrusion_body(IBody)

#set data for simulations
logger.info("setting data for lateral thresholds simulation")
IBody.set_data_for_s_simulation()
logger.info("setting data for vertical thresholds simulation")
IBody.set_data_for_g_simulation()


intrusion_feature.builder = intrusion_builder
intrusion_feature.intrusion_frame = intrusion_frame

if intrusion_lateral_extent_model == None:
logger.error(
"Specify conceptual model function for intrusion lateral extent"
)
else:
IBody.set_lateral_extent_conceptual_model(intrusion_lateral_extent_model)
IBody.set_s_simulation_GSLIBparameters(lateral_extent_sgs_parameters)
IBody.make_s_simulation_variogram(lateral_extent_sgs_parameters)
IBody.create_grid_for_simulation()
logger.info("simulating thresholds for lateral extent")
IBody.simulate_s_thresholds()

intrusion_feature.set_simulation_lateral_data(IBody.simulated_s_thresholds)

else:
intrusion_feature.lateral_extent_model = intrusion_lateral_extent_model

if intrusion_vertical_extent_model == None:
logger.error(
"Specify conceptual model function for intrusion vertical extent"
)
else:
IBody.set_vertical_extent_conceptual_model(intrusion_vertical_extent_model)
IBody.set_g_simulation_GSLIBparameters(vertical_extent_sgs_parameters)
IBody.make_g_simulation_variogram(vertical_extent_sgs_parameters)
logger.info("simulating thresholds for vertical extent")
IBody.simulate_g_thresholds()

intrusion_feature.set_simulation_growth_data(IBody.simulated_g_thresholds)
else:
intrusion_feature.vertical_extent_model = intrusion_vertical_extent_model

logger.info("setting data for thresholds simulation")
intrusion_feature.set_data_for_extent_simulation(intrusion_data)
intrusion_feature.create_grid_for_simulation()
intrusion_feature.set_l_sgs_GSLIBparameters(lateral_extent_sgs_parameters)
intrusion_feature.set_g_sgs_GSLIBparameters(vertical_extent_sgs_parameters)
intrusion_feature.make_l_sgs_variogram(lateral_extent_sgs_parameters)
intrusion_feature.make_g_sgs_variogram(vertical_extent_sgs_parameters)

logger.info("simulating thresholds for intrusion lateral and vertical extent")
intrusion_feature.simulate_lateral_thresholds()
intrusion_feature.simulate_growth_thresholds()

return intrusion_feature

Expand Down
4 changes: 1 addition & 3 deletions LoopStructural/modelling/intrusions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from .intrusion_frame import IntrusionBuilder
from .intrusion_network import IntrusionNetwork
from .intrusion_body import IntrusionBody
from .intrusion_feature import IntrusionFeature
from .intrusion_builder import IntrusionBuilder
from .geom_conceptual_models import *
106 changes: 82 additions & 24 deletions LoopStructural/modelling/intrusions/intrusion_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,20 @@ def __init__(
model = None,
**kwargs
):
"""IntrusionBuilder set up the intrusion frame to build an intrusion, and simulated the thresholds distances
along the intrusion frame coordinate to constrain the lateral and vertical extent of the intrusion
parameters:
"""IntrusionBuilder set up the intrusion frame to build an intrusion
The intrusion frame is curvilinear coordinate system of the intrusion that controls the simulation of the intrusion extent.
The object is constrained with intrusion network points (computed) and flow and inflation measurements (provided by the user).
The intrusion network is a representation of the approximated location of roof (or floor) contact of the intrusion.
The intrusion network be constrained using the anisotropies of the host rock if the roof (or floor) contact is not well constrained.
Parameters
----------
interpolator : GeologicalInterpolator, optional
the interpolator to use for building the fault frame, by default None
interpolators : [GeologicalInterpolator, GeologicalInterpolator, GeologicalInterpolator], optional
a list of interpolators to use for building the fault frame, by default None
model : GeologicalModel
reference to the model containing the fault
"""

StructuralFrameBuilder.__init__(self, interpolator, interpolators, **kwargs)
Expand All @@ -37,34 +46,29 @@ def __init__(
self.minimum_origin = self.model.bounding_box[0, :]
self.maximum_maximum = self.model.bounding_box[1, :]

# self.feature_data = feature_data
# self.shortestpath_inlet_mean = None
# self.shortestpath_outlet_mean = None

# intrusion network input data
# -- intrusion network input data
self.intrusion_network_contact = None
self.intrusion_network_type = None
self.intrusion_network_data = None #OK
self.other_contact_data = None #OK
self.grid_to_evaluate_ifx = np.zeros([1, 1]) #OK
self.intrusion_network_data = None
self.other_contact_data = None
self.grid_to_evaluate_ifx = np.zeros([1, 1])

self.anisotropies_series_list = [] #OK
self.anisotropies_series_parameters = {} #OK
self.anisotropies_fault_list = [] #OK
self.anisotropies_fault_parameters = {} #OK
self.anisotropies_series_list = []
self.anisotropies_series_parameters = {}
self.anisotropies_fault_list = []
self.anisotropies_fault_parameters = {}

self.anisotropies_sequence = None #OK
self.velocity_parameters = None #OK
self.shortestpath_sections_axis = None #OK
self.anisotropies_sequence = None
self.velocity_parameters = None
self.shortestpath_sections_axis = None
self.number_of_contacts = None
self.delta_contacts = None
self.delta_faults = None
self.intrusion_network_points = None #OK
self.intrusion_network_points = None


self.velocity_field_arrays = None #BORRAR
self.IFf = None #borrar
self.IFc = None #borrar
self.velocity_field_arrays = None
self.IFf = None #delete?
self.IFc = None #delete?

def update_geometry(self, points):
self.origin = np.nanmin(np.array([np.min(points, axis=0), self.origin]), axis=0)
Expand Down Expand Up @@ -252,6 +256,25 @@ def add_faults_anisotropies(self, fault_list=None):

def set_intrusion_network_parameters(self, intrusion_data, intrusion_network_input, **kwargs):

"""
Set variables to create intrusion network.
Parameters
----------
intrusion_data = DataFrame, intrusion contact data
intrusion_network_input = Dictionary,
contact : string, contact of the intrusion to be used to create the network (roof or floor)
type : string, type of algorithm to create the intrusion network (interpolated or shortest path).
Shortest path is recommended when intrusion contact is not well constrained
contacts_anisotropies : list of series-type features involved in intrusion emplacement
structures_anisotropies : list of fault-type features involved in intrusion emplacement
sequence_anisotropies : list of anisotropies to look for the shortest path. It could be only starting and end point.
Returns
-------
"""

self.intrusion_network_contact = intrusion_network_input.get("contact", 'floor')

self.intrusion_network_type = intrusion_network_input.get("type", 'interpolated')
Expand Down Expand Up @@ -428,6 +451,17 @@ def compute_velocity_field(self, indicator_fx_contacts, indicator_fx_faults):
return velocity_field

def create_intrusion_network(self, **kwargs):

"""
Created a numpy array containing (x,y,z) coordinates of intrusion network points
Parameters
----------
Returns
-------
intrusion_network_points = numpy array
"""

# --- check type of intrusion network
if self.intrusion_network_type == None:
Expand Down Expand Up @@ -634,6 +668,30 @@ def create_intrusion_network(self, **kwargs):
self.velocity_field_arrays = velocity_field_arrays
return shortest_path_points

def get_indicator_function_points(self, ifx_type = 'contacts'):

if ifx_type == 'contacts':
IF = self.IFc
else:
IF = self.IFf

if_mod = np.sum(IF,axis = 1)

grid_points = self.grid_to_evaluate_ifx

counta = sum(1 for i in range(len(IF[:,0])) if if_mod[i]>= 1)
points = np.zeros([counta, 4])
l = 0
for i in range(len(IF[:,0])):
if if_mod[i]>= 1:
points[l,0] = grid_points[i,0] #node
points[l,1] = grid_points[i,1] #X coordinate
points[l,2] = grid_points[i,2] #Y coordinate
points[l,3] = IF[i,0] #Z coordinate
l=l+1

return points

def set_intrusion_frame_data(self, intrusion_frame_data, intrusion_network_points):

"""Adds the intrusion network points as coordinate 0 data for the intrusion frame
Expand Down

0 comments on commit bba0163

Please sign in to comment.