LoopStructural 1.0.4__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of LoopStructural might be problematic. Click here for more details.
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/__init__.py +33 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__init__.py +12 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/__pycache__/_base.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/_base.py +65 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudius.csv +21049 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/claudiusbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplex.csv +126 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/duplexbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusion.csv +1017 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/intrusionbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefoldbb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/onefolddata.csv +2226 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_bb.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/datasets/data/refolded_fold.csv +2126 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__init__.py +31 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_fold_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/discrete_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/finite_difference_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/geological_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/operator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/piecewiselinear_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_grid.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/structured_tetra.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/__pycache__/surfe_wrapper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.c +27782 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/cython/dsi_helper.cp37-win_amd64.pyd +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_fold_interpolator.py +171 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/discrete_interpolator.py +551 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/finite_difference_interpolator.py +342 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/geological_interpolator.py +190 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/operator.py +60 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/piecewiselinear_interpolator.py +348 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_grid.py +466 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/structured_tetra.py +638 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/interpolators/surfe_wrapper.py +117 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__init__.py +46 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/__pycache__/geological_model.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/core/geological_model.py +1351 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__init__.py +3 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_function_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/__pycache__/fault_segment.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function.py +187 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py +75 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_segment.py +270 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__init__.py +7 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/cross_product_geological_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/geological_feature_builder.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/region_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/structural_frame_builder.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/__pycache__/unconformity_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/cross_product_geological_feature.py +77 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature.py +286 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/geological_feature_builder.py +329 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/region_feature.py +34 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame.py +116 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/structural_frame_builder.py +179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/features/unconformity_feature.py +69 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__init__.py +8 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/fold_rotation_angle_feature.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/foldframe.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/__pycache__/svariogram.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold.py +135 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle.py +132 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/fold_rotation_angle_feature.py +57 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/foldframe.py +192 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fold/svariogram.py +179 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__init__.py +14 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/exceptions.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/helper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/map2loop.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/__pycache__/utils.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/exceptions.py +9 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/helper.py +378 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/map2loop.py +314 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/utils/utils.py +120 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__init__.py +19 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/map_viewer.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_plotter.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/model_visualisation.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/rotation_angle_plotter.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/__pycache__/sphinx_scraper.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/map_viewer.py +307 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_plotter.py +16 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/model_visualisation.py +1012 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/rotation_angle_plotter.py +82 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural/visualisation/sphinx_scraper.py +34 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/PKG-INFO +10 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/SOURCES.txt +60 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/dependency_links.txt +1 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/requires.txt +8 -0
- Miniconda/envs/loop/Lib/site-packages/LoopStructural-1.0.4-py3.7.egg-info/top_level.txt +2 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__init__.py +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/__init__.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_faults.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_fold.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_interpolator.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/__pycache__/test_refolded.cpython-37.pyc +0 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_faults.py +17 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_fold.py +57 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_interpolator.py +88 -0
- Miniconda/envs/loop/Lib/site-packages/tests/test_refolded.py +22 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CubicFunction:
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self):
|
|
13
|
+
"""
|
|
14
|
+
Class to represent a cubic function
|
|
15
|
+
"""
|
|
16
|
+
self.A = [] # np.zeros((4,4))
|
|
17
|
+
self.B = [] # np.zeros((4))
|
|
18
|
+
self.max_v = 999999
|
|
19
|
+
self.min_v = -99999
|
|
20
|
+
self.w = None
|
|
21
|
+
|
|
22
|
+
def add_cstr(self, x, y):
|
|
23
|
+
self.A.append([x ** 3, x ** 2, x, 1.])
|
|
24
|
+
self.B.append(y)
|
|
25
|
+
|
|
26
|
+
def add_grad(self, x, g):
|
|
27
|
+
self.A.append([3 * x ** 2, 2 * x, 1., 0.])
|
|
28
|
+
self.B.append(g)
|
|
29
|
+
|
|
30
|
+
def add_max(self, max_v):
|
|
31
|
+
self.max_v = max_v
|
|
32
|
+
|
|
33
|
+
def add_min(self, min_v):
|
|
34
|
+
self.min_v = min_v
|
|
35
|
+
|
|
36
|
+
def __call__(self, v):
|
|
37
|
+
if len(self.B) < 3:
|
|
38
|
+
print("underdetermined")
|
|
39
|
+
return
|
|
40
|
+
if self.w is None:
|
|
41
|
+
A = np.array(self.A)
|
|
42
|
+
B = np.array(self.B)
|
|
43
|
+
ATA = A.T @ A
|
|
44
|
+
ATB = A.T @ B
|
|
45
|
+
self.w = np.linalg.lstsq(ATA, ATB, rcond=None)[0]
|
|
46
|
+
eva = self.w[0] * v ** 3 + self.w[1] * v ** 2 + self.w[2] * v + self.w[
|
|
47
|
+
3]
|
|
48
|
+
eva[v > self.max_v] = self.w[0] * self.max_v ** 3 + \
|
|
49
|
+
self.w[1] * self.max_v ** 2 + self.w[
|
|
50
|
+
2] * self.max_v + self.w[3]
|
|
51
|
+
eva[v < self.min_v] = self.w[0] * self.min_v ** 3 + \
|
|
52
|
+
self.w[1] * self.min_v ** 2 + self.w[
|
|
53
|
+
2] * self.min_v + self.w[3]
|
|
54
|
+
return eva
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Composite():
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
def __init__(self, positive, negative):
|
|
62
|
+
self.positive = positive
|
|
63
|
+
self.negative = negative
|
|
64
|
+
|
|
65
|
+
def __call__(self, v):
|
|
66
|
+
v = np.array(v)
|
|
67
|
+
r = np.zeros(v.shape)
|
|
68
|
+
r[v > 0] = self.positive(v[v > 0])
|
|
69
|
+
r[v < 0] = self.negative(v[v < 0])
|
|
70
|
+
return r
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Ones:
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
def __init__(self):
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
def __call__(self, v):
|
|
81
|
+
v = np.array(v)
|
|
82
|
+
return np.ones(v.shape)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class Zeros:
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
def __init__(self):
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
def __call__(self, v):
|
|
93
|
+
v = np.array(v)
|
|
94
|
+
return np.zeros(v.shape)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class FaultDisplacement:
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
def __init__(self, hw=None, fw=None, gx=None, gy=None, gz=None, **kwargs):
|
|
102
|
+
self.gx = gx
|
|
103
|
+
if hw is not None and fw is not None:
|
|
104
|
+
self.__gx = Composite(hw, fw)
|
|
105
|
+
self.gy = gy
|
|
106
|
+
self.gz = gz
|
|
107
|
+
self.gx_bounds = None
|
|
108
|
+
self.gy_bounds = None
|
|
109
|
+
self.gz_bounds = None
|
|
110
|
+
|
|
111
|
+
if self.gx == None:
|
|
112
|
+
print('Gx function none setting to ones')
|
|
113
|
+
self.gx = Ones()
|
|
114
|
+
if self.gy == None:
|
|
115
|
+
print('Gy function none setting to ones')
|
|
116
|
+
self.gy = Ones()
|
|
117
|
+
if self.gz == None:
|
|
118
|
+
print('Gz function none setting to ones')
|
|
119
|
+
self.gz = Ones()
|
|
120
|
+
if 'gxmax' in kwargs and 'gxmin' in kwargs:
|
|
121
|
+
self.gx_bounds = (kwargs['gxmin'], kwargs['gxmax'])
|
|
122
|
+
|
|
123
|
+
if 'gymax' in kwargs and 'gymin' in kwargs:
|
|
124
|
+
self.gy_bounds = (kwargs['gymin'], kwargs['gymax'])
|
|
125
|
+
|
|
126
|
+
if 'gzmax' in kwargs and 'gzmin' in kwargs:
|
|
127
|
+
self.gz_bounds = (kwargs['gzmin'], kwargs['gzmax'])
|
|
128
|
+
|
|
129
|
+
def __call__(self, gx, gy, gz):
|
|
130
|
+
if self.gx_bounds is not None:
|
|
131
|
+
mid =(self.gx_bounds[1]+self.gx_bounds[0])/2.
|
|
132
|
+
gx = (gx -mid) / (self.gx_bounds[1]-self.gx_bounds[0])
|
|
133
|
+
if self.gy_bounds is not None:
|
|
134
|
+
mid = (self.gy_bounds[1]+self.gy_bounds[0])/2.
|
|
135
|
+
gy = (gy -mid) / (self.gy_bounds[1]-self.gy_bounds[0])
|
|
136
|
+
if self.gz_bounds is not None:
|
|
137
|
+
mid =(self.gz_bounds[1]+self.gz_bounds[0])/2.
|
|
138
|
+
gz = (gz -mid) / (self.gz_bounds[1]-self.gz_bounds[0])
|
|
139
|
+
return self.gx(gx)*self.gy(gy)*self.gz(gz)
|
|
140
|
+
|
|
141
|
+
def evaluate(self, gy, gz):
|
|
142
|
+
if self.gy_bounds is not None:
|
|
143
|
+
mid = (self.gy_bounds[1]+self.gy_bounds[0])/2.
|
|
144
|
+
gy = (gy -mid) / (self.gy_bounds[1]-self.gy_bounds[0])
|
|
145
|
+
if self.gz_bounds is not None:
|
|
146
|
+
mid =(self.gz_bounds[1]+self.gz_bounds[0])/2.
|
|
147
|
+
gz = (gz -mid) / (self.gz_bounds[1]-self.gz_bounds[0])
|
|
148
|
+
return self.gy(gy)*self.gz(gz)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class BaseFault(object):
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
"""
|
|
155
|
+
hw = CubicFunction()
|
|
156
|
+
hw.add_cstr(0, 1)
|
|
157
|
+
hw.add_grad(0, 0)
|
|
158
|
+
hw.add_cstr(1, 0)
|
|
159
|
+
# hw.add_cstr(1,1)
|
|
160
|
+
|
|
161
|
+
hw.add_grad(1, 0)
|
|
162
|
+
hw.add_max(1)
|
|
163
|
+
fw = CubicFunction()
|
|
164
|
+
fw.add_cstr(0, -1)
|
|
165
|
+
fw.add_grad(0, 0)
|
|
166
|
+
fw.add_cstr(-1, 0)
|
|
167
|
+
fw.add_grad(-1, 0)
|
|
168
|
+
fw.add_min(-1)
|
|
169
|
+
# gyf = CubicFunction()
|
|
170
|
+
# gyf.add_cstr(-1, 0)
|
|
171
|
+
# gyf.add_cstr(1, 0)
|
|
172
|
+
# gyf.add_cstr(-0.2, 1)
|
|
173
|
+
# gyf.add_cstr(0.2, 1)
|
|
174
|
+
# gyf.add_grad(0, 0)
|
|
175
|
+
# gyf.add_min(-1)
|
|
176
|
+
# gyf.add_max(1)
|
|
177
|
+
gyf = Ones()
|
|
178
|
+
gzf = CubicFunction()
|
|
179
|
+
gzf.add_cstr(-1, 0)
|
|
180
|
+
gzf.add_cstr(1, 0)
|
|
181
|
+
gzf.add_cstr(-0.2, 1)
|
|
182
|
+
gzf.add_cstr(0.2, 1)
|
|
183
|
+
gzf.add_grad(0, 0)
|
|
184
|
+
gzf.add_min(-1)
|
|
185
|
+
gzf.add_max(1)
|
|
186
|
+
gxf = Composite(hw, fw)
|
|
187
|
+
fault_displacement = FaultDisplacement(gx=gxf, gy=gyf, gz=gzf)
|
Miniconda/envs/loop/Lib/site-packages/LoopStructural/modelling/fault/fault_function_feature.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FaultDisplacementFeature:
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
def __init__(self, fault_frame, displacement, name = 'fault_displacement'):
|
|
11
|
+
"""
|
|
12
|
+
Geological feature representing the fault displacement
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
fault_frame - geometry of the fault
|
|
17
|
+
displacement - function defining fault displacement
|
|
18
|
+
"""
|
|
19
|
+
self.fault_frame = fault_frame
|
|
20
|
+
self.displacement = displacement
|
|
21
|
+
self.name = name +'_displacement'
|
|
22
|
+
|
|
23
|
+
def evaluate_value(self, location):
|
|
24
|
+
"""
|
|
25
|
+
Return the value of the fault displacement
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
location
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
fault_suface = self.fault_frame.features[0].evaluate_value(location)
|
|
36
|
+
fault_displacement = self.fault_frame.features[1].evaluate_value(
|
|
37
|
+
location)
|
|
38
|
+
fault_strike = self.fault_frame.features[2].evaluate_value(location)
|
|
39
|
+
d = self.displacement(fault_suface, fault_displacement, fault_strike)
|
|
40
|
+
return d
|
|
41
|
+
|
|
42
|
+
def evaluate_gradient(self, location):
|
|
43
|
+
"""
|
|
44
|
+
get the scaled displacement
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
location
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
fault_suface = self.fault_frame.features[0].evaluate_value(location)
|
|
55
|
+
fault_displacement = self.fault_frame.features[1].evaluate_value(
|
|
56
|
+
location)
|
|
57
|
+
fault_strike = self.fault_frame.features[2].evaluate_value(location)
|
|
58
|
+
d = self.displacement(fault_suface, fault_displacement, fault_strike)
|
|
59
|
+
return d
|
|
60
|
+
|
|
61
|
+
def min(self):
|
|
62
|
+
return -1
|
|
63
|
+
|
|
64
|
+
def max(self):
|
|
65
|
+
return 1
|
|
66
|
+
|
|
67
|
+
def evaluate_on_surface(self, location):
|
|
68
|
+
fault_displacement = self.fault_frame.features[1].evaluate_value(
|
|
69
|
+
location)
|
|
70
|
+
fault_strike = self.fault_frame.features[2].evaluate_value(location)
|
|
71
|
+
d = self.displacement.evaluate(fault_displacement, fault_strike)
|
|
72
|
+
return d
|
|
73
|
+
|
|
74
|
+
def mean(self):
|
|
75
|
+
return 0
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from LoopStructural.modelling.fault.fault_function_feature import FaultDisplacementFeature
|
|
4
|
+
from LoopStructural.modelling.fault.fault_function import BaseFault
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FaultSegment:
|
|
11
|
+
"""
|
|
12
|
+
Class for representing a slip event of a fault
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, faultframe,
|
|
16
|
+
faultfunction = None,
|
|
17
|
+
steps = 3,
|
|
18
|
+
displacement=1.,
|
|
19
|
+
**kwargs):
|
|
20
|
+
"""
|
|
21
|
+
A slip event of a fault
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
faultframe : FaultFrame
|
|
26
|
+
the fault frame defining the faut geometry
|
|
27
|
+
faultfunction : function/lambda function
|
|
28
|
+
optional displacement function for spatially variable fault displacement
|
|
29
|
+
steps : int
|
|
30
|
+
how many integration steps for faults
|
|
31
|
+
kwargs
|
|
32
|
+
"""
|
|
33
|
+
self.faultframe = faultframe
|
|
34
|
+
self.type = 'fault'
|
|
35
|
+
self.name = kwargs.get('name', self.faultframe.name)
|
|
36
|
+
self.displacement = displacement
|
|
37
|
+
self.faultfunction = faultfunction
|
|
38
|
+
if faultfunction == 'BaseFault':
|
|
39
|
+
self.faultfunction = BaseFault.fault_displacement
|
|
40
|
+
self.steps = steps
|
|
41
|
+
self.regions = []
|
|
42
|
+
self.faults_enabled = True
|
|
43
|
+
self.displacementfeature = None
|
|
44
|
+
self.model = None
|
|
45
|
+
if self.faultframe is not None:
|
|
46
|
+
self.displacementfeature = FaultDisplacementFeature(
|
|
47
|
+
self.faultframe, self.faultfunction, name = self.name)
|
|
48
|
+
|
|
49
|
+
def __getitem__(self, item):
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
item
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
return self.faultframe[item]
|
|
61
|
+
|
|
62
|
+
def set_model(self, model):
|
|
63
|
+
"""
|
|
64
|
+
Link a geological model to the feature
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
model - GeologicalModel
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
self.model = model
|
|
75
|
+
|
|
76
|
+
def set_displacement(self, displacement, scale = True):
|
|
77
|
+
"""
|
|
78
|
+
Set the fault displacement to a new value
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
displacement - double
|
|
83
|
+
scale - boolean
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
if scale and self.model is not None:
|
|
90
|
+
self.displacement = displacement / self.model.scale_factor
|
|
91
|
+
elif not scale:
|
|
92
|
+
self.displacement = displacement
|
|
93
|
+
else:
|
|
94
|
+
logger.warning("Displacement not updated")
|
|
95
|
+
|
|
96
|
+
def toggle_faults(self):
|
|
97
|
+
"""
|
|
98
|
+
Toggle faults that affect this fault segment
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
self.faults_enabled = ~self.faults_enabled
|
|
105
|
+
for i in range(3):
|
|
106
|
+
self.faultframe[i].toggle_faults()
|
|
107
|
+
|
|
108
|
+
def add_region(self, region):
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
region : boolean function(x,y,z)
|
|
114
|
+
A function that returns true if inside region, false if outside
|
|
115
|
+
can be passed as a lambda function e.g.
|
|
116
|
+
lambda pos : feature.evaluate_value(pos) > 0
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
self.regions.append(region)
|
|
123
|
+
|
|
124
|
+
def evaluate(self, locations):
|
|
125
|
+
"""
|
|
126
|
+
Evaluate which side of fault
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
locations numpy array
|
|
131
|
+
location to evaluate
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
boolean array true if on hanging wall, false if on footwall
|
|
136
|
+
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
return self.faultframe.features[0].evaluate_value(locations) > 0
|
|
140
|
+
|
|
141
|
+
def evaluate_value(self, locations):
|
|
142
|
+
"""
|
|
143
|
+
Return the value of the fault surface scalar field
|
|
144
|
+
|
|
145
|
+
Parameters
|
|
146
|
+
----------
|
|
147
|
+
locations - numpy array
|
|
148
|
+
location to evaluate scalar field
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
v = np.zeros(locations.shape[0])
|
|
155
|
+
v[:] = np.nan
|
|
156
|
+
mask = np.zeros(locations.shape[0]).astype(bool)
|
|
157
|
+
mask[:] = True
|
|
158
|
+
# check regions
|
|
159
|
+
for r in self.regions:
|
|
160
|
+
mask = np.logical_and(mask, r(locations))
|
|
161
|
+
return self.faultframe[0].evaluate_value(locations[mask, :])
|
|
162
|
+
|
|
163
|
+
def mean(self):
|
|
164
|
+
return self.faultframe[0].mean()
|
|
165
|
+
|
|
166
|
+
def max(self):
|
|
167
|
+
return self.faultframe[0].max()
|
|
168
|
+
|
|
169
|
+
def min(self):
|
|
170
|
+
return self.faultframe[0].min()
|
|
171
|
+
|
|
172
|
+
def evaluate_gradient(self, locations):
|
|
173
|
+
"""
|
|
174
|
+
Return the fault slip direction at the location
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
locations - numpy array Nx3
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
v = np.zeros(locations.shape[0])
|
|
186
|
+
v[:] = np.nan
|
|
187
|
+
mask = np.zeros(locations.shape[0]).astype(bool)
|
|
188
|
+
mask[:] = True
|
|
189
|
+
# check regions
|
|
190
|
+
for r in self.regions:
|
|
191
|
+
mask = np.logical_and(mask, r(locations))
|
|
192
|
+
# need to scale with fault displacement
|
|
193
|
+
return self.faultframe[1].evaluate_gradient(locations[mask, :])
|
|
194
|
+
|
|
195
|
+
def apply_to_points(self, points):
|
|
196
|
+
"""
|
|
197
|
+
Unfault the array of points
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
points - numpy array Nx3
|
|
202
|
+
|
|
203
|
+
Returns
|
|
204
|
+
-------
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
steps = self.steps
|
|
208
|
+
newp = np.copy(points).astype(float)
|
|
209
|
+
# evaluate fault function for all points then define mask for only points affected by fault
|
|
210
|
+
with ThreadPoolExecutor(max_workers=8) as executor:
|
|
211
|
+
# all of these operations should be independent so just run as different threads
|
|
212
|
+
gx_future = executor.submit(self.faultframe.features[0].evaluate_value, newp)
|
|
213
|
+
gy_future = executor.submit(self.faultframe.features[1].evaluate_value, newp)
|
|
214
|
+
gz_future = executor.submit(self.faultframe.features[2].evaluate_value, newp)
|
|
215
|
+
gx = gx_future.result()
|
|
216
|
+
gy = gy_future.result()
|
|
217
|
+
gz = gz_future.result()
|
|
218
|
+
d = np.zeros(gx.shape)
|
|
219
|
+
mask = np.logical_and(~np.isnan(gx),~np.isnan(gy))
|
|
220
|
+
mask = np.logical_and(mask,~np.isnan(gz))
|
|
221
|
+
d[~mask] = 0
|
|
222
|
+
gx_mask = np.zeros_like(mask,dtype=bool)
|
|
223
|
+
gx_mask[mask] = gx[mask] > 0
|
|
224
|
+
d[gx_mask] = 1.
|
|
225
|
+
if self.faultfunction is not None:
|
|
226
|
+
d[mask] = self.faultfunction(gx[mask], gy[mask], gz[mask])
|
|
227
|
+
mask = np.abs(d) > 0.
|
|
228
|
+
|
|
229
|
+
d *= self.displacement
|
|
230
|
+
# calculate the fault frame for the evaluation points
|
|
231
|
+
for i in range(steps):
|
|
232
|
+
with ThreadPoolExecutor(max_workers=8) as executor:
|
|
233
|
+
# all of these operations should be independent so just run as different threads
|
|
234
|
+
gx_future = executor.submit(self.faultframe.features[0].evaluate_value, newp[mask, :])
|
|
235
|
+
g_future = executor.submit(self.faultframe.features[1].evaluate_gradient, newp[mask, :])
|
|
236
|
+
gy_future = executor.submit(self.faultframe.features[1].evaluate_value, newp[mask, :])
|
|
237
|
+
gz_future = executor.submit(self.faultframe.features[2].evaluate_value, newp[mask, :])
|
|
238
|
+
gx = gx_future.result()
|
|
239
|
+
g = g_future.result()
|
|
240
|
+
gy = gy_future.result()
|
|
241
|
+
gz = gz_future.result()
|
|
242
|
+
# # get the fault frame val/grad for the points
|
|
243
|
+
# determine displacement magnitude, for constant displacement
|
|
244
|
+
# hanging wall should be > 0
|
|
245
|
+
d = np.zeros(gx.shape)
|
|
246
|
+
mask2 = np.logical_and(~np.isnan(gx), ~np.isnan(gy))
|
|
247
|
+
mask2 = np.logical_and(mask2, ~np.isnan(gz))
|
|
248
|
+
d[~mask2] = 0
|
|
249
|
+
gx_mask2 = np.zeros_like(mask2,dtype=bool)
|
|
250
|
+
gx_mask2[mask2] = gx[mask2] > 0
|
|
251
|
+
# d[~np.isnan(gx)][gx[~np.isnan(gx)]>0] = 1
|
|
252
|
+
d[gx_mask2] = 1.
|
|
253
|
+
# d[mask2][gx[mask2] < 0] = 0.
|
|
254
|
+
# d[gx < 0] = 0.
|
|
255
|
+
if self.faultfunction is not None:
|
|
256
|
+
d[mask2] = self.faultfunction(gx[mask2], gy[mask2], gz[mask2])
|
|
257
|
+
d *= self.displacement
|
|
258
|
+
# normalise when length is >0
|
|
259
|
+
g_mag = np.zeros(g.shape[0])
|
|
260
|
+
g_mag[mask2] = np.linalg.norm(g[mask2], axis=1)
|
|
261
|
+
# g_mag = np.linalg.norm(g[mask2], axis=1)
|
|
262
|
+
g[g_mag > 0.] /= g_mag[g_mag > 0, None]
|
|
263
|
+
# multiply displacement vector by the displacement magnitude for
|
|
264
|
+
# step
|
|
265
|
+
g *= (1. / steps) * d[:, None]
|
|
266
|
+
|
|
267
|
+
# apply displacement
|
|
268
|
+
newp[mask, :] += g
|
|
269
|
+
return newp
|
|
270
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# from .faulted_geological_feature import FaultedGeologicalFeature
|
|
2
|
+
from .geological_feature import GeologicalFeature
|
|
3
|
+
from .geological_feature_builder import GeologicalFeatureInterpolator
|
|
4
|
+
from .region_feature import RegionFeature
|
|
5
|
+
from .structural_frame import StructuralFrame
|
|
6
|
+
from .structural_frame_builder import StructuralFrameBuilder
|
|
7
|
+
from .unconformity_feature import UnconformityFeature
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
"""
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from LoopStructural.modelling.features.geological_feature import \
|
|
8
|
+
GeologicalFeature
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CrossProductGeologicalFeature(GeologicalFeature):
|
|
14
|
+
"""[summary]
|
|
15
|
+
|
|
16
|
+
[extended_summary]
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
GeologicalFeature : [type]
|
|
21
|
+
[description]
|
|
22
|
+
"""
|
|
23
|
+
def __init__(self, name, geological_feature_a, geological_feature_b):
|
|
24
|
+
"""
|
|
25
|
+
Create a geological feature for a vector field using the cross
|
|
26
|
+
product between
|
|
27
|
+
two existing features
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
name: feature name
|
|
31
|
+
geological_feature_a: first feature
|
|
32
|
+
geological_feature_b: second feature
|
|
33
|
+
"""
|
|
34
|
+
super().__init__(name, None)
|
|
35
|
+
self.geological_feature_a = geological_feature_a
|
|
36
|
+
self.geological_feature_b = geological_feature_b
|
|
37
|
+
|
|
38
|
+
def evaluate_gradient(self, locations):
|
|
39
|
+
"""
|
|
40
|
+
Calculate the gradient of the geological feature by using numpy to
|
|
41
|
+
calculate the cross
|
|
42
|
+
product between the two existing feature gradients.
|
|
43
|
+
This means both features have to be evaluated for the locations
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
locations
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
return np.cross(self.geological_feature_a.evaluate_gradient(locations),
|
|
53
|
+
self.geological_feature_b.evaluate_gradient(locations),
|
|
54
|
+
axisa=1,
|
|
55
|
+
axisb=1)
|
|
56
|
+
|
|
57
|
+
def evaluate_value(self, evaluation_points):
|
|
58
|
+
"""
|
|
59
|
+
Return 0 because there is no value for this feature
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
evaluation_points
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
return np.zeros(evaluation_points.shape[0])
|
|
69
|
+
|
|
70
|
+
def mean(self):
|
|
71
|
+
return 0.
|
|
72
|
+
|
|
73
|
+
def min(self):
|
|
74
|
+
return 0.
|
|
75
|
+
|
|
76
|
+
def max(self):
|
|
77
|
+
return 0.
|