Skip to content

Commit 07ccd54

Browse files
author
Lachlan Grose
committed
fix: add faulted vector calc to lambda feature
1 parent f2c5104 commit 07ccd54

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

LoopStructural/modelling/features/_base_geological_feature.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ def evaluate_gradient(self, pos, ignore_regions=False):
229229
"""
230230
Evaluate the gradient of the feature at a given position.
231231
"""
232-
232+
233233
raise NotImplementedError
234234

235235
def min(self):

LoopStructural/modelling/features/_lambda_geological_feature.py

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
"""
22
Geological features
33
"""
4-
4+
from LoopStructural.utils.maths import regular_tetraherdron_for_points, gradient_from_tetrahedron
55
from ...modelling.features import BaseFeature
66
from ...utils import getLogger
77
from ...modelling.features import FeatureType
88
import numpy as np
99
from typing import Callable, Optional
10+
from ...utils import LoopValueError
1011

1112
logger = getLogger(__name__)
1213

@@ -68,11 +69,11 @@ def evaluate_value(self, pos: np.ndarray, ignore_regions=False) -> np.ndarray:
6869
mask = self._calculate_mask(pos, ignore_regions=ignore_regions)
6970
pos = self._apply_faults(pos)
7071
if self.function is not None:
71-
72+
7273
v[mask] = self.function(pos[mask,:])
7374
return v
7475

75-
def evaluate_gradient(self, pos: np.ndarray, ignore_regions=False) -> np.ndarray:
76+
def evaluate_gradient(self, pos: np.ndarray, ignore_regions=False,element_scale_parameter=None) -> np.ndarray:
7677
"""_summary_
7778
7879
Parameters
@@ -85,7 +86,60 @@ def evaluate_gradient(self, pos: np.ndarray, ignore_regions=False) -> np.ndarray
8586
np.ndarray
8687
_description_
8788
"""
89+
if pos.shape[1] != 3:
90+
raise LoopValueError("Need Nx3 array of xyz points to evaluate gradient")
91+
logger.info(f'Calculating gradient for {self.name}')
92+
if element_scale_parameter is None:
93+
if self.model is not None:
94+
element_scale_parameter = np.min(self.model.bounding_box.step_vector) / 10
95+
else:
96+
element_scale_parameter = 1
97+
else:
98+
try:
99+
element_scale_parameter = float(element_scale_parameter)
100+
except ValueError:
101+
logger.error("element_scale_parameter must be a float")
102+
element_scale_parameter = 1
88103
v = np.zeros((pos.shape[0], 3))
104+
v = np.zeros(pos.shape)
105+
v[:] = np.nan
106+
mask = self._calculate_mask(pos, ignore_regions=ignore_regions)
107+
# evaluate the faults on the nodes of the faulted feature support
108+
# then evaluate the gradient at these points
109+
if len(self.faults) > 0:
110+
# generate a regular tetrahedron for each point
111+
# we will then move these points by the fault and then recalculate the gradient.
112+
# this should work...
113+
resolved = False
114+
tetrahedron = regular_tetraherdron_for_points(pos, element_scale_parameter)
115+
116+
while resolved:
117+
for f in self.faults:
118+
v = (
119+
f[0]
120+
.evaluate_value(tetrahedron.reshape(-1, 3), fillnan='nearest')
121+
.reshape(tetrahedron.shape[0], 4)
122+
)
123+
flag = np.logical_or(np.all(v > 0, axis=1), np.all(v < 0, axis=1))
124+
if np.any(~flag):
125+
logger.warning(
126+
f"Points are too close to fault {f[0].name}. Refining the tetrahedron"
127+
)
128+
element_scale_parameter *= 0.5
129+
tetrahedron = regular_tetraherdron_for_points(pos, element_scale_parameter)
130+
131+
resolved = True
132+
133+
tetrahedron_faulted = self._apply_faults(np.array(tetrahedron.reshape(-1, 3))).reshape(
134+
tetrahedron.shape
135+
)
136+
137+
values = self.function(tetrahedron_faulted.reshape(-1, 3)).reshape(
138+
(-1, 4)
139+
)
140+
v[mask, :] = gradient_from_tetrahedron(tetrahedron[mask, :, :], values[mask])
141+
142+
return v
89143
if self.gradient_function is None:
90144
v[:, :] = np.nan
91145
else:

0 commit comments

Comments
 (0)