-
Notifications
You must be signed in to change notification settings - Fork 51
Fix/speed up #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/speed up #284
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,8 +66,25 @@ def evaluate_value(self, pos: np.ndarray, ignore_regions=False) -> np.ndarray: | |
| v = np.zeros((pos.shape[0])) | ||
| v[:] = np.nan | ||
|
|
||
| mask = self._calculate_mask(pos, ignore_regions=ignore_regions) | ||
| pos = self._apply_faults(pos) | ||
| # Precompute each fault's scalar value (gx = fault.__getitem__(0).evaluate_value) | ||
| # once and reuse for both the region mask check and fault application. | ||
| # FaultSegment.evaluate_value(pos) == self.__getitem__(0).evaluate_value(pos) == gx. | ||
| # apply_to_points also needs gx to determine the displacement mask — passing it | ||
| # avoids the duplicate evaluation on the np.copy of pos. | ||
| precomputed_gx = {id(f): f.evaluate_value(pos) for f in self.faults} | ||
|
|
||
| # Region mask: pass precomputed gx so PositiveRegion/NegativeRegion skip re-evaluation | ||
| mask = np.ones(pos.shape[0], dtype=bool) | ||
| if not ignore_regions: | ||
| for r in self.regions: | ||
| pre = precomputed_gx.get(id(getattr(r, 'feature', None))) | ||
| mask = np.logical_and(mask, r(pos, precomputed_val=pre)) | ||
|
|
||
|
Comment on lines
+78
to
+82
|
||
| # Apply faults: pass precomputed gx so apply_to_points skips one evaluate_value call | ||
| if self.faults_enabled: | ||
| for f in self.faults: | ||
| pos = f.apply_to_points(pos, precomputed_gx=precomputed_gx.get(id(f))) | ||
|
|
||
|
Comment on lines
+69
to
+87
|
||
| if self.function is not None: | ||
| v[mask] = self.function(pos[mask,:]) | ||
| return v | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -311,13 +311,14 @@ def evaluate_displacement(self, points): | |
| d[mask] = self.faultfunction(gx[mask] + self.fault_offset, gy[mask], gz[mask]) | ||
| return d * self.displacement | ||
|
|
||
| def apply_to_points(self, points, reverse=False): | ||
| def apply_to_points(self, points, reverse=False, precomputed_gx=None): | ||
| """ | ||
| Unfault the array of points | ||
|
|
||
| Parameters | ||
| ---------- | ||
| points - numpy array Nx3 | ||
| precomputed_gx - optional pre-evaluated gx values (same points, avoids duplicate evaluation) | ||
|
|
||
| Returns | ||
| ------- | ||
|
|
@@ -328,10 +329,12 @@ def apply_to_points(self, points, reverse=False): | |
| newp = np.copy(points).astype(float) | ||
| # evaluate fault function for all points | ||
| # then define mask for only points affected by fault | ||
| gx = None | ||
| gy = None | ||
| gz = None | ||
| if use_threads: | ||
| # gx may be supplied by caller to avoid re-evaluation (precomputed from region check) | ||
| if precomputed_gx is not None: | ||
| gx = precomputed_gx | ||
| gy = self.__getitem__(1).evaluate_value(newp) | ||
| gz = self.__getitem__(2).evaluate_value(newp) | ||
| elif use_threads: | ||
| with ThreadPoolExecutor(max_workers=8) as executor: | ||
| # all of these operations should be | ||
| # independent so just run as different threads | ||
|
|
@@ -361,27 +364,32 @@ def apply_to_points(self, points, reverse=False): | |
| d *= -1.0 | ||
| # calculate the fault frame for the evaluation points | ||
| for _i in range(steps): | ||
| gx = None | ||
| gy = None | ||
| gz = None | ||
| g = None | ||
| if use_threads: | ||
| if _i == 0: | ||
| # Reuse gx/gy/gz from the initial full-array evaluation above — newp[mask] hasn't | ||
| # moved yet on the first iteration, so values are identical. | ||
| gx_m = gx[mask] | ||
| gy_m = gy[mask] | ||
| gz_m = gz[mask] | ||
| g = self.__getitem__(1).evaluate_gradient(newp[mask, :], ignore_regions=True) | ||
| elif use_threads: | ||
| with ThreadPoolExecutor(max_workers=8) as executor: | ||
| # all of these operations should be | ||
| # independent so just run as different threads | ||
| gx_future = executor.submit(self.__getitem__(0).evaluate_value, newp[mask, :]) | ||
| g_future = executor.submit(self.__getitem__(1).evaluate_gradient, newp[mask, :]) | ||
| gy_future = executor.submit(self.__getitem__(1).evaluate_value, newp[mask, :]) | ||
| gz_future = executor.submit(self.__getitem__(2).evaluate_value, newp[mask, :]) | ||
| gx = gx_future.result() | ||
| gx_m = gx_future.result() | ||
| g = g_future.result() | ||
| gy = gy_future.result() | ||
| gz = gz_future.result() | ||
| gy_m = gy_future.result() | ||
| gz_m = gz_future.result() | ||
|
Comment on lines
379
to
+386
|
||
| else: | ||
| gx = self.__getitem__(0).evaluate_value(newp[mask, :]) | ||
| gy = self.__getitem__(1).evaluate_value(newp[mask, :]) | ||
| gz = self.__getitem__(2).evaluate_value(newp[mask, :]) | ||
| gx_m = self.__getitem__(0).evaluate_value(newp[mask, :]) | ||
| gy_m = self.__getitem__(1).evaluate_value(newp[mask, :]) | ||
| gz_m = self.__getitem__(2).evaluate_value(newp[mask, :]) | ||
| g = self.__getitem__(1).evaluate_gradient(newp[mask, :], ignore_regions=True) | ||
| gx, gy, gz = gx_m, gy_m, gz_m # alias for block below | ||
| # # get the fault frame val/grad for the points | ||
| # determine displacement magnitude, for constant displacement | ||
| # hanging wall should be > 0 | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.