resqpy 4.5.0__py3-none-any.whl → 4.6.3__py3-none-any.whl

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.
@@ -14,7 +14,7 @@ from typing import Tuple, Optional, Dict
14
14
  import threading
15
15
 
16
16
  import numba # type: ignore
17
- from numba import njit, cuda # type: ignore
17
+ from numba import cuda # type: ignore
18
18
  from numba.cuda.cudadrv.devicearray import DeviceNDArray # type: ignore
19
19
  import cupy # type: ignore
20
20
 
@@ -39,7 +39,7 @@ def _cross_d(A: DeviceNDArray, B: DeviceNDArray, c: DeviceNDArray):
39
39
  @cuda.jit(device = True)
40
40
  def _negative_d(v: DeviceNDArray, nv: DeviceNDArray):
41
41
  for d in range(v.shape[0]):
42
- nv[d] = numba.float32(-1.) * v[d]
42
+ nv[d] = numba.float32(-1.0) * v[d]
43
43
 
44
44
 
45
45
  @cuda.jit(device = True)
@@ -51,18 +51,38 @@ def _dot_d(v1: DeviceNDArray, v2: DeviceNDArray, prod: DeviceNDArray):
51
51
 
52
52
  @cuda.jit(device = True)
53
53
  def _norm_d(v: DeviceNDArray, n: DeviceNDArray):
54
- n[0] = 0.
54
+ n[0] = 0.0
55
55
  for dim in range(3):
56
- n[0] += v[dim]**2.
56
+ n[0] += v[dim]**2.0
57
57
  n[0] = maths.sqrt(n[0])
58
58
 
59
59
 
60
60
  @cuda.jit
61
- def project_polygons_to_surfaces(faces: DeviceNDArray, triangles: DeviceNDArray, axis: int, index1: int, index2: int,
62
- colx: int, coly: int, nx: int, ny: int, nz: int, dx: float, dy: float, dz: float,
63
- l_tol: float, t_tol: float, return_normal_vectors: bool, normals: DeviceNDArray,
64
- return_depths: bool, depths: DeviceNDArray, return_offsets: bool,
65
- offsets: DeviceNDArray, return_triangles: bool, triangle_per_face: DeviceNDArray):
61
+ def project_polygons_to_surfaces(
62
+ faces: DeviceNDArray,
63
+ triangles: DeviceNDArray,
64
+ axis: int,
65
+ index1: int,
66
+ index2: int,
67
+ colx: int,
68
+ coly: int,
69
+ nx: int,
70
+ ny: int,
71
+ nz: int,
72
+ dx: float,
73
+ dy: float,
74
+ dz: float,
75
+ l_tol: float,
76
+ t_tol: float,
77
+ return_normal_vectors: bool,
78
+ normals: DeviceNDArray,
79
+ return_depths: bool,
80
+ depths: DeviceNDArray,
81
+ return_offsets: bool,
82
+ offsets: DeviceNDArray,
83
+ return_triangles: bool,
84
+ triangle_per_face: DeviceNDArray,
85
+ ):
66
86
  """Maps the projection of a 3D polygon to 2D grid surfaces along a given axis, using GPUs.
67
87
 
68
88
  arguments:
@@ -163,10 +183,10 @@ def project_polygons_to_surfaces(faces: DeviceNDArray, triangles: DeviceNDArray,
163
183
  inside = False
164
184
  # 2a. use cross-product to work out Barycentric weights
165
185
  # this could be made prettier by refactoring a device function
166
- w1_denom = ((tp[1, coly] - tp[0, coly]) * (tp[2, colx] - tp[0, colx]) - (tp[1, colx] - tp[0, colx]) *
167
- (tp[2, coly] - tp[0, coly]))
168
- w2_denom = (tp[2, coly] - tp[0, coly])
169
- if w1_denom == 0. or w2_denom == 0.:
186
+ w1_denom = (tp[1, coly] - tp[0, coly]) * (tp[2, colx] - tp[0, colx]) - (tp[1, colx] - tp[0, colx]) * (
187
+ tp[2, coly] - tp[0, coly])
188
+ w2_denom = tp[2, coly] - tp[0, coly]
189
+ if w1_denom == 0.0 or w2_denom == 0.0:
170
190
  inside = True # point lies on a triangle which is actually a line (normally at boundaries)
171
191
  else:
172
192
  w1 = (tp[0, colx] - numba.float64(px)) * (tp[2, coly] - tp[0, coly]) + (
@@ -174,18 +194,18 @@ def project_polygons_to_surfaces(faces: DeviceNDArray, triangles: DeviceNDArray,
174
194
  w1 /= w1_denom
175
195
  w2 = (numba.float64(py) - tp[0, coly] - w1 * (tp[1, coly] - tp[0, coly]))
176
196
  w2 /= w2_denom
177
- if (w1 >= 0. and w2 >= 0. and (w1 + w2) <= 1.): # inside
197
+ if w1 >= 0.0 and w2 >= 0.0 and (w1 + w2) <= 1.0: # inside
178
198
  inside = True # point lies in triangle
179
199
 
180
200
  # 2b. the point is inside if Barycentric weights meet this condition
181
201
  if inside:
182
- # 3. find intersection point with column centre
202
+ # 3. find intersection point with column centre
183
203
  # 3a. Line start point in 3D which had a projection hit
184
- line_p[axis] = numba.float64(grid_dxyz[axis]) / 2.
204
+ line_p[axis] = numba.float64(grid_dxyz[axis]) / 2.0
185
205
  line_p[2 - index1] = (py + 0.5) * grid_dxyz[2 - index1] # kji / xyz & py=d1
186
206
  line_p[2 - index2] = (px + 0.5) * grid_dxyz[2 - index2] # kji / xyz & px=d2
187
207
 
188
- # 3b. Line end point in 3D
208
+ # 3b. Line end point in 3D
189
209
  for dim in range(3):
190
210
  line_v[dim] = line_p[dim]
191
211
  line_v[axis] = numba.float64(grid_dxyz[axis]) * (n_axis - numba.float64(0.5)) #!
@@ -209,7 +229,7 @@ def project_polygons_to_surfaces(faces: DeviceNDArray, triangles: DeviceNDArray,
209
229
 
210
230
  _dot_d(norm, lp_t0, t)
211
231
  t[0] /= denom[0]
212
- if (t[0] < 0.0 - l_tol or t[0] > 1.0 + l_tol):
232
+ if t[0] < 0.0 - l_tol or t[0] > 1.0 + l_tol:
213
233
  continue
214
234
 
215
235
  _cross_d(p02, line_rv, tmp)
@@ -255,11 +275,11 @@ def project_polygons_to_surfaces(faces: DeviceNDArray, triangles: DeviceNDArray,
255
275
  _cross_d(line_p, line_v, tmp)
256
276
  _norm_d(tmp, v)
257
277
  for dim in range(3):
258
- normals[face_idx[0], face_idx[1], face_idx[2], dim] = -1. * tmp[dim] / v[0]
278
+ normals[face_idx[0], face_idx[1], face_idx[2], dim] = (-1.0 * tmp[dim] / v[0])
259
279
  norm_idx[index2] = int(px)
260
280
  if normals[norm_idx[0], norm_idx[1], norm_idx[2], 2] > 0.0:
261
281
  for dim in range(3):
262
- normals[face_idx[0], face_idx[1], face_idx[2], dim] *= -1.
282
+ normals[face_idx[0], face_idx[1], face_idx[2], dim] *= -1.0
263
283
 
264
284
  if return_triangles:
265
285
  triangle_per_face[face_idx[0], face_idx[1], face_idx[2]] = triangle_num
@@ -287,15 +307,20 @@ def _diffuse_closed_faces(a, k_faces, j_faces, i_faces, index1, index2, axis, st
287
307
  fault_behind = i_faces[iF, jF, kF - 1]
288
308
  fault_back = i_faces[iF, jF, kF]
289
309
  cuda.syncthreads()
290
- a[i,j,k] = (a[i-1,j,k] and (not fault_above)) or (a[i+1,j,k] and (not fault_below)) \
291
- or (a[i,j-1,k] and (not fault_left)) or (a[i,j+1,k] and (not fault_right)) \
292
- or (a[i,j,k-1] and (not fault_behind)) or (a[i,j,k+1] and (not fault_back)) \
293
- or a[i,j,k] # already closed
310
+ a[i, j, k] = ((a[i - 1, j, k] and (not fault_above)) or (a[i + 1, j, k] and (not fault_below)) or
311
+ (a[i, j - 1, k] and (not fault_left)) or (a[i, j + 1, k] and (not fault_right)) or
312
+ (a[i, j, k - 1] and
313
+ (not fault_behind)) or (a[i, j, k + 1] and
314
+ (not fault_back)) or a[i, j, k]) # already closed
294
315
  cuda.syncthreads()
295
316
 
296
317
 
297
- def bisector_from_faces_cuda(grid_extent_kji: Tuple[int, int, int], k_faces: np.ndarray, j_faces: np.ndarray,
298
- i_faces: np.ndarray) -> Tuple[np.ndarray, bool]:
318
+ def bisector_from_faces_cuda(
319
+ grid_extent_kji: Tuple[int, int, int],
320
+ k_faces: np.ndarray,
321
+ j_faces: np.ndarray,
322
+ i_faces: np.ndarray,
323
+ ) -> Tuple[np.ndarray, bool]:
299
324
  """Returns a numpy bool array denoting the bisection of the grid by the face sets, using GPUs.
300
325
 
301
326
  arguments:
@@ -314,18 +339,28 @@ def bisector_from_faces_cuda(grid_extent_kji: Tuple[int, int, int], k_faces: np.
314
339
  assigned to either the True or False part
315
340
  """
316
341
  assert len(grid_extent_kji) == 3
317
- padded_extent_kji = (grid_extent_kji[0] + 2, grid_extent_kji[1] + 2, grid_extent_kji[2] + 2)
342
+ padded_extent_kji = (
343
+ grid_extent_kji[0] + 2,
344
+ grid_extent_kji[1] + 2,
345
+ grid_extent_kji[2] + 2,
346
+ )
318
347
  a = cupy.zeros(padded_extent_kji, dtype = bool)
319
348
  a[1, 1, 1] = True
320
349
 
321
350
  a_count = a_count_before = 0
322
351
  blockSize = (16, 16)
323
- gridSize_k = ((grid_extent_kji[1] + blockSize[0] - 1) // blockSize[0],
324
- (grid_extent_kji[2] + blockSize[1] - 1) // blockSize[1])
325
- gridSize_j = ((grid_extent_kji[0] + blockSize[0] - 1) // blockSize[0],
326
- (grid_extent_kji[2] + blockSize[1] - 1) // blockSize[1])
327
- gridSize_i = ((grid_extent_kji[0] + blockSize[0] - 1) // blockSize[1],
328
- (grid_extent_kji[1] + blockSize[1] - 1) // blockSize[1])
352
+ gridSize_k = (
353
+ (grid_extent_kji[1] + blockSize[0] - 1) // blockSize[0],
354
+ (grid_extent_kji[2] + blockSize[1] - 1) // blockSize[1],
355
+ )
356
+ gridSize_j = (
357
+ (grid_extent_kji[0] + blockSize[0] - 1) // blockSize[0],
358
+ (grid_extent_kji[2] + blockSize[1] - 1) // blockSize[1],
359
+ )
360
+ gridSize_i = (
361
+ (grid_extent_kji[0] + blockSize[0] - 1) // blockSize[1],
362
+ (grid_extent_kji[1] + blockSize[1] - 1) // blockSize[1],
363
+ )
329
364
 
330
365
  while True:
331
366
  # forward sweeps
@@ -351,7 +386,7 @@ def bisector_from_faces_cuda(grid_extent_kji: Tuple[int, int, int], k_faces: np.
351
386
 
352
387
  a = cupy.asnumpy(a[1:-1, 1:-1, 1:-1])
353
388
  cell_count = a.size
354
- assert 1 <= a_count < cell_count, 'face set for surface is leaky or empty (surface does not intersect grid)'
389
+ assert (1 <= a_count < cell_count), "face set for surface is leaky or empty (surface does not intersect grid)"
355
390
 
356
391
  # find mean K for a cells and not a cells; if not a cells mean K is lesser (ie shallower), negate a
357
392
  layer_cell_count = grid_extent_kji[1] * grid_extent_kji[2]
@@ -379,7 +414,7 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
379
414
  name,
380
415
  title = None,
381
416
  agitate = False,
382
- feature_type = 'fault',
417
+ feature_type = "fault",
383
418
  progress_fn = None,
384
419
  return_properties = None,
385
420
  i_surface = 0,
@@ -415,10 +450,10 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
415
450
  to trim first;
416
451
  organisational objects for the feature are created if needed
417
452
  """
418
- # todo: update with extra arguments to keep functionality aligned with find_faces...regular_optimised
453
+ # todo: update with extra arguments to keep functionality aligned with find_faces...regular_optimised
419
454
 
420
455
  cuda.select_device(i_gpu) # bind device to thread
421
- device = cuda.get_current_device() # if no GPU present - this will throw an exception and fall back to CPU
456
+ device = (cuda.get_current_device()) # if no GPU present - this will throw an exception and fall back to CPU
422
457
 
423
458
  assert isinstance(grid, grr.RegularGrid)
424
459
  assert grid.is_aligned
@@ -430,15 +465,21 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
430
465
  return_flange_bool = False
431
466
  if return_properties:
432
467
  assert all([
433
- p in ['triangle', 'depth', 'offset', 'normal vector', 'grid bisector', 'flange bool']
434
- for p in return_properties
468
+ p in [
469
+ "triangle",
470
+ "depth",
471
+ "offset",
472
+ "normal vector",
473
+ "grid bisector",
474
+ "flange bool",
475
+ ] for p in return_properties
435
476
  ])
436
- return_triangles = ('triangle' in return_properties)
437
- return_normal_vectors = ('normal vector' in return_properties)
438
- return_depths = ('depth' in return_properties)
439
- return_offsets = ('offset' in return_properties)
440
- return_bisector = ('grid bisector' in return_properties)
441
- return_flange_bool = ('flange bool' in return_properties)
477
+ return_triangles = "triangle" in return_properties
478
+ return_normal_vectors = "normal vector" in return_properties
479
+ return_depths = "depth" in return_properties
480
+ return_offsets = "offset" in return_properties
481
+ return_bisector = "grid bisector" in return_properties
482
+ return_flange_bool = "flange bool" in return_properties
442
483
  if return_flange_bool:
443
484
  return_triangles = True
444
485
 
@@ -450,37 +491,41 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
450
491
 
451
492
  # prepare surfaces
452
493
  surface = surfaces[i_surface] # get surface under consideration
453
- log.debug(f'intersecting surface {surface.title} with regular grid {grid.title} on a GPU')
494
+ log.debug(f"intersecting surface {surface.title} with regular grid {grid.title} on a GPU")
454
495
  # log.debug(f'grid extent kji: {grid.extent_kji}')
455
496
 
456
497
  # print some information about the CUDA card
457
- log.debug(f'{device.name} | Device Controller {i_gpu} | ' +
458
- f'CC {device.COMPUTE_CAPABILITY_MAJOR}.{device.COMPUTE_CAPABILITY_MINOR} | ' +
459
- f'Processing surface {i_surface}')
498
+ log.debug(f"{device.name} | Device Controller {i_gpu} | " +
499
+ f"CC {device.COMPUTE_CAPABILITY_MAJOR}.{device.COMPUTE_CAPABILITY_MINOR} | " +
500
+ f"Processing surface {i_surface}")
460
501
  # get device attributes to calculate thread dimensions
461
502
  nSMs = device.MULTIPROCESSOR_COUNT # number of SMs
462
- maxBlockSize = device.MAX_BLOCK_DIM_X / 2 # max number of threads per block in x-dim
503
+ maxBlockSize = (device.MAX_BLOCK_DIM_X / 2) # max number of threads per block in x-dim
463
504
  gridSize = 2 * nSMs # prefer 2*nSMs blocks for full occupancy
464
505
  # take the reverse diagonal for relationship between xyz & ijk
465
- grid_dxyz = (grid.block_dxyz_dkji[2, 0], grid.block_dxyz_dkji[1, 1], grid.block_dxyz_dkji[0, 2])
506
+ grid_dxyz = (
507
+ grid.block_dxyz_dkji[2, 0],
508
+ grid.block_dxyz_dkji[1, 1],
509
+ grid.block_dxyz_dkji[0, 2],
510
+ )
466
511
  # extract polygons from surface
467
512
  with compiler_lock: # HDF5 handles seem not to be threadsafe
468
513
  triangles, points = surface.triangles_and_points()
469
- assert triangles is not None and points is not None, f'surface {surface.title} is empty'
514
+ assert (triangles is not None and points is not None), f"surface {surface.title} is empty"
470
515
 
471
516
  if agitate:
472
517
  points += 1.0e-5 * (np.random.random(points.shape) - 0.5) # +/- uniform err.
473
- # log.debug(f'surface: {surface.title}; p0: {points[0]}; crs uuid: {surface.crs_uuid}')
518
+ # log.debug(f'surface: {surface.title}; p0: {points[0]}; crs uuid: {surface.crs_uuid}')
474
519
  # log.debug(f'surface min xyz: {np.min(points, axis = 0)}')
475
520
  # log.debug(f'surface max xyz: {np.max(points, axis = 0)}')
476
521
  if not bu.matching_uuids(grid.crs_uuid, surface.crs_uuid):
477
- log.debug('converting from surface crs to grid crs')
522
+ log.debug("converting from surface crs to grid crs")
478
523
  s_crs = rqc.Crs(surface.model, uuid = surface.crs_uuid)
479
524
  s_crs.convert_array_to(grid.crs, points)
480
525
  surface.crs_uuid = grid.crs.uuid
481
526
  # log.debug(f'surface: {surface.title}; p0: {points[0]}; crs uuid: {surface.crs_uuid}')
482
527
  # log.debug(f'surface min xyz: {np.min(points, axis = 0)}')
483
- # log.debug(f'surface max xyz: {np.max(points, axis = 0)}')
528
+ # log.debug(f'surface max xyz: {np.max(points, axis = 0)}')
484
529
 
485
530
  p_tri_xyz = points[triangles]
486
531
  p_tri_xyz_d = cupy.asarray(p_tri_xyz)
@@ -489,12 +534,12 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
489
534
  if grid.nk > 1:
490
535
  log.debug("searching for k faces")
491
536
  k_faces = np.zeros((grid.nk - 1, grid.nj, grid.ni), dtype = bool)
492
- k_triangles = np.full((grid.nk - 1, grid.nj, grid.ni), -1, dtype = int) if return_triangles else np.full(
493
- (1, 1, 1), -1, dtype = int)
494
- k_depths = np.full((grid.nk - 1, grid.nj, grid.ni), np.nan) if return_depths else np.full((1, 1, 1), np.nan)
495
- k_offsets = np.full((grid.nk - 1, grid.nj, grid.ni), np.nan) if return_offsets else np.full((1, 1, 1), np.nan)
496
- k_normals = np.full((grid.nk - 1, grid.nj, grid.ni, 3), np.nan) if return_normal_vectors else np.full(
497
- (1, 1, 1, 1), np.nan)
537
+ k_triangles = (np.full((grid.nk - 1, grid.nj, grid.ni), -1, dtype = int) if return_triangles else np.full(
538
+ (1, 1, 1), -1, dtype = int))
539
+ k_depths = (np.full((grid.nk - 1, grid.nj, grid.ni), np.nan) if return_depths else np.full((1, 1, 1), np.nan))
540
+ k_offsets = (np.full((grid.nk - 1, grid.nj, grid.ni), np.nan) if return_offsets else np.full((1, 1, 1), np.nan))
541
+ k_normals = (np.full((grid.nk - 1, grid.nj, grid.ni, 3), np.nan) if return_normal_vectors else np.full(
542
+ (1, 1, 1, 1), np.nan))
498
543
  k_faces_d = cupy.asarray(k_faces)
499
544
  k_triangles_d = cupy.asarray(k_triangles)
500
545
  k_depths_d = cupy.asarray(k_depths)
@@ -505,10 +550,10 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
505
550
  axis = 2
506
551
  index1 = 1
507
552
  index2 = 2
508
- blockSize = (p_tri_xyz.shape[0] - 1) // (gridSize - 1) if (
509
- p_tri_xyz.shape[0] < gridSize * maxBlockSize) else 64 # prefer factors of 32 (threads per warp)
553
+ blockSize = ((p_tri_xyz.shape[0] - 1) // (gridSize - 1) if
554
+ (p_tri_xyz.shape[0] < gridSize * maxBlockSize) else 64) # prefer factors of 32 (threads per warp)
510
555
  log.debug(
511
- f'Executing polygon-intersection GPU-kernel along k-axis using gridSize={gridSize}, blockSize={blockSize}')
556
+ f"Executing polygon-intersection GPU-kernel along k-axis using gridSize={gridSize}, blockSize={blockSize}")
512
557
  project_polygons_to_surfaces[gridSize, blockSize](
513
558
  k_faces_d,
514
559
  p_tri_xyz_d,
@@ -523,8 +568,8 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
523
568
  grid_dxyz[0],
524
569
  grid_dxyz[1],
525
570
  grid_dxyz[2],
526
- 0.,
527
- 0.,
571
+ 0.0,
572
+ 0.0,
528
573
  return_normal_vectors,
529
574
  k_normals_d,
530
575
  return_depths,
@@ -556,12 +601,12 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
556
601
  if grid.nj > 1:
557
602
  log.debug("searching for j faces")
558
603
  j_faces = np.zeros((grid.nk, grid.nj - 1, grid.ni), dtype = bool)
559
- j_triangles = np.full((grid.nk, grid.nj - 1, grid.ni), -1, dtype = int) if return_triangles else np.full(
560
- (1, 1, 1), -1, dtype = int)
561
- j_depths = np.full((grid.nk, grid.nj - 1, grid.ni), np.nan) if return_depths else np.full((1, 1, 1), np.nan)
562
- j_offsets = np.full((grid.nk, grid.nj - 1, grid.ni), np.nan) if return_offsets else np.full((1, 1, 1), np.nan)
563
- j_normals = np.full((grid.nk, grid.nj - 1, grid.ni, 3), np.nan) if return_normal_vectors else np.full(
564
- (1, 1, 1, 1), np.nan)
604
+ j_triangles = (np.full((grid.nk, grid.nj - 1, grid.ni), -1, dtype = int) if return_triangles else np.full(
605
+ (1, 1, 1), -1, dtype = int))
606
+ j_depths = (np.full((grid.nk, grid.nj - 1, grid.ni), np.nan) if return_depths else np.full((1, 1, 1), np.nan))
607
+ j_offsets = (np.full((grid.nk, grid.nj - 1, grid.ni), np.nan) if return_offsets else np.full((1, 1, 1), np.nan))
608
+ j_normals = (np.full((grid.nk, grid.nj - 1, grid.ni, 3), np.nan) if return_normal_vectors else np.full(
609
+ (1, 1, 1, 1), np.nan))
565
610
  j_faces_d = cupy.asarray(j_faces)
566
611
  j_triangles_d = cupy.asarray(j_triangles)
567
612
  j_depths_d = cupy.asarray(j_depths)
@@ -572,10 +617,10 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
572
617
  axis = 1
573
618
  index1 = 0
574
619
  index2 = 2
575
- blockSize = (p_tri_xyz.shape[0] - 1) // (gridSize - 1) if (
576
- p_tri_xyz.shape[0] < gridSize * maxBlockSize) else 64 # prefer factors of 32 (threads per warp)
620
+ blockSize = ((p_tri_xyz.shape[0] - 1) // (gridSize - 1) if
621
+ (p_tri_xyz.shape[0] < gridSize * maxBlockSize) else 64) # prefer factors of 32 (threads per warp)
577
622
  log.debug(
578
- f'Executing polygon-intersection GPU-kernel along j-axis using gridSize={gridSize}, blockSize={blockSize}')
623
+ f"Executing polygon-intersection GPU-kernel along j-axis using gridSize={gridSize}, blockSize={blockSize}")
579
624
  project_polygons_to_surfaces[gridSize, blockSize](
580
625
  j_faces_d,
581
626
  p_tri_xyz_d,
@@ -590,8 +635,8 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
590
635
  grid_dxyz[0],
591
636
  grid_dxyz[1],
592
637
  grid_dxyz[2],
593
- 0.,
594
- 0.,
638
+ 0.0,
639
+ 0.0,
595
640
  return_normal_vectors,
596
641
  j_normals_d,
597
642
  return_depths,
@@ -623,12 +668,12 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
623
668
  if grid.ni > 1:
624
669
  log.debug("searching for i faces")
625
670
  i_faces = np.zeros((grid.nk, grid.nj, grid.ni - 1), dtype = bool)
626
- i_triangles = np.full((grid.nk, grid.nj, grid.ni - 1), -1, dtype = int) if return_triangles else np.full(
627
- (1, 1, 1), -1, dtype = int)
628
- i_depths = np.full((grid.nk, grid.nj, grid.ni - 1), np.nan) if return_depths else np.full((1, 1, 1), np.nan)
629
- i_offsets = np.full((grid.nk, grid.nj, grid.ni - 1), np.nan) if return_offsets else np.full((1, 1, 1), np.nan)
630
- i_normals = np.full((grid.nk, grid.nj, grid.ni - 1, 3), np.nan) if return_normal_vectors else np.full(
631
- (1, 1, 1, 1), np.nan)
671
+ i_triangles = (np.full((grid.nk, grid.nj, grid.ni - 1), -1, dtype = int) if return_triangles else np.full(
672
+ (1, 1, 1), -1, dtype = int))
673
+ i_depths = (np.full((grid.nk, grid.nj, grid.ni - 1), np.nan) if return_depths else np.full((1, 1, 1), np.nan))
674
+ i_offsets = (np.full((grid.nk, grid.nj, grid.ni - 1), np.nan) if return_offsets else np.full((1, 1, 1), np.nan))
675
+ i_normals = (np.full((grid.nk, grid.nj, grid.ni - 1, 3), np.nan) if return_normal_vectors else np.full(
676
+ (1, 1, 1, 1), np.nan))
632
677
  i_faces_d = cupy.asarray(i_faces)
633
678
  i_triangles_d = cupy.asarray(i_triangles)
634
679
  i_depths_d = cupy.asarray(i_depths)
@@ -639,10 +684,10 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
639
684
  axis = 0
640
685
  index1 = 0
641
686
  index2 = 1
642
- blockSize = (p_tri_xyz.shape[0] - 1) // (gridSize - 1) if (
643
- p_tri_xyz.shape[0] < gridSize * maxBlockSize) else 64 # prefer factors of 32 (threads per warp)
687
+ blockSize = ((p_tri_xyz.shape[0] - 1) // (gridSize - 1) if
688
+ (p_tri_xyz.shape[0] < gridSize * maxBlockSize) else 64) # prefer factors of 32 (threads per warp)
644
689
  log.debug(
645
- f'Executing polygon-intersection GPU-kernel along i-axis using gridSize={gridSize}, blockSize={blockSize}')
690
+ f"Executing polygon-intersection GPU-kernel along i-axis using gridSize={gridSize}, blockSize={blockSize}")
646
691
  project_polygons_to_surfaces[gridSize, blockSize](
647
692
  i_faces_d,
648
693
  p_tri_xyz_d,
@@ -657,8 +702,8 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
657
702
  grid_dxyz[0],
658
703
  grid_dxyz[1],
659
704
  grid_dxyz[2],
660
- 0.,
661
- 0.,
705
+ 0.0,
706
+ 0.0,
662
707
  return_normal_vectors,
663
708
  i_normals_d,
664
709
  return_depths,
@@ -706,36 +751,36 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
706
751
 
707
752
  # NB. following assumes faces have been added to gcs in a particular order!
708
753
  if return_triangles:
709
- k_tri_list = np.empty((0,)) if k_triangles is None else k_triangles[rgs_ff.where_true(k_faces)]
710
- j_tri_list = np.empty((0,)) if j_triangles is None else j_triangles[rgs_ff.where_true(j_faces)]
711
- i_tri_list = np.empty((0,)) if i_triangles is None else i_triangles[rgs_ff.where_true(i_faces)]
754
+ k_tri_list = (np.empty((0,)) if k_triangles is None else k_triangles[rgs_ff._where_true(k_faces)])
755
+ j_tri_list = (np.empty((0,)) if j_triangles is None else j_triangles[rgs_ff._where_true(j_faces)])
756
+ i_tri_list = (np.empty((0,)) if i_triangles is None else i_triangles[rgs_ff._where_true(i_faces)])
712
757
  all_tris = np.concatenate((k_tri_list, j_tri_list, i_tri_list), axis = 0)
713
758
  # log.debug(f'gcs count: {gcs.count}; all triangles shape: {all_tris.shape}')
714
759
  assert all_tris.shape == (gcs_list[i_surface].count,)
715
760
 
716
761
  # NB. following assumes faces have been added to gcs in a particular order!
717
762
  if return_depths:
718
- k_depths_list = np.empty((0,)) if k_depths is None else k_depths[rgs_ff.where_true(k_faces)]
719
- j_depths_list = np.empty((0,)) if j_depths is None else j_depths[rgs_ff.where_true(j_faces)]
720
- i_depths_list = np.empty((0,)) if i_depths is None else i_depths[rgs_ff.where_true(i_faces)]
763
+ k_depths_list = (np.empty((0,)) if k_depths is None else k_depths[rgs_ff._where_true(k_faces)])
764
+ j_depths_list = (np.empty((0,)) if j_depths is None else j_depths[rgs_ff._where_true(j_faces)])
765
+ i_depths_list = (np.empty((0,)) if i_depths is None else i_depths[rgs_ff._where_true(i_faces)])
721
766
  all_depths = np.concatenate((k_depths_list, j_depths_list, i_depths_list), axis = 0)
722
767
  # log.debug(f'gcs count: {gcs.count}; all depths shape: {all_depths.shape}')
723
768
  assert all_depths.shape == (gcs_list[i_surface].count,)
724
769
 
725
770
  # NB. following assumes faces have been added to gcs in a particular order!
726
771
  if return_offsets:
727
- k_offsets_list = np.empty((0,)) if k_offsets is None else k_offsets[rgs_ff.where_true(k_faces)]
728
- j_offsets_list = np.empty((0,)) if j_offsets is None else j_offsets[rgs_ff.where_true(j_faces)]
729
- i_offsets_list = np.empty((0,)) if i_offsets is None else i_offsets[rgs_ff.where_true(i_faces)]
772
+ k_offsets_list = (np.empty((0,)) if k_offsets is None else k_offsets[rgs_ff._where_true(k_faces)])
773
+ j_offsets_list = (np.empty((0,)) if j_offsets is None else j_offsets[rgs_ff._where_true(j_faces)])
774
+ i_offsets_list = (np.empty((0,)) if i_offsets is None else i_offsets[rgs_ff._where_true(i_faces)])
730
775
  all_offsets = np.concatenate((k_offsets_list, j_offsets_list, i_offsets_list), axis = 0)
731
776
  # log.debug(f'gcs count: {gcs.count}; all offsets shape: {all_offsets.shape}')
732
777
  assert all_offsets.shape == (gcs_list[i_surface].count,)
733
778
 
734
779
  if return_flange_bool:
735
- flange_bool_uuid = surface.model.uuid(title = 'flange bool',
736
- obj_type = 'DiscreteProperty',
780
+ flange_bool_uuid = surface.model.uuid(title = "flange bool",
781
+ obj_type = "DiscreteProperty",
737
782
  related_uuid = surface.uuid)
738
- assert flange_bool_uuid is not None, f"No flange bool property found for surface: {surface.title}"
783
+ assert (flange_bool_uuid is not None), f"No flange bool property found for surface: {surface.title}"
739
784
  flange_bool = rqp.Property(surface.model, uuid = flange_bool_uuid)
740
785
  flange_array = flange_bool.array_ref()
741
786
  all_flange = np.take(flange_array, all_tris)
@@ -743,9 +788,9 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
743
788
 
744
789
  # NB. following assumes faces have been added to gcs in a particular order!
745
790
  if return_normal_vectors:
746
- k_normals_list = np.empty((0, 3)) if k_normals is None else k_normals[rgs_ff.where_true(k_faces)]
747
- j_normals_list = np.empty((0, 3)) if j_normals is None else j_normals[rgs_ff.where_true(j_faces)]
748
- i_normals_list = np.empty((0, 3)) if i_normals is None else i_normals[rgs_ff.where_true(i_faces)]
791
+ k_normals_list = (np.empty((0, 3)) if k_normals is None else k_normals[rgs_ff._where_true(k_faces)])
792
+ j_normals_list = (np.empty((0, 3)) if j_normals is None else j_normals[rgs_ff._where_true(j_faces)])
793
+ i_normals_list = (np.empty((0, 3)) if i_normals is None else i_normals[rgs_ff._where_true(i_faces)])
749
794
  all_normals = np.concatenate((k_normals_list, j_normals_list, i_normals_list), axis = 0)
750
795
  # log.debug(f'gcs count: {gcs.count}; all normals shape: {all_normals.shape}')
751
796
  assert all_normals.shape == (gcs_list[i_surface].count, 3)
@@ -762,17 +807,17 @@ def find_faces_to_represent_surface_regular_cuda_sgpu(
762
807
  if return_properties:
763
808
  props_dict_list[i_surface] = {}
764
809
  if return_triangles:
765
- props_dict_list[i_surface]['triangle'] = all_tris
810
+ props_dict_list[i_surface]["triangle"] = all_tris
766
811
  if return_depths:
767
- props_dict_list[i_surface]['depth'] = all_depths
812
+ props_dict_list[i_surface]["depth"] = all_depths
768
813
  if return_offsets:
769
- props_dict_list[i_surface]['offset'] = all_offsets
814
+ props_dict_list[i_surface]["offset"] = all_offsets
770
815
  if return_normal_vectors:
771
- props_dict_list[i_surface]['normal vector'] = all_normals
816
+ props_dict_list[i_surface]["normal vector"] = all_normals
772
817
  if return_bisector:
773
- props_dict_list[i_surface]['grid bisector'] = (bisector, is_curtain)
818
+ props_dict_list[i_surface]["grid bisector"] = (bisector, is_curtain)
774
819
  if return_flange_bool:
775
- props_dict_list[i_surface]['flange bool'] = all_flange
820
+ props_dict_list[i_surface]["flange bool"] = all_flange
776
821
 
777
822
 
778
823
  def find_faces_to_represent_surface_regular_cuda_mgpu(
@@ -781,7 +826,7 @@ def find_faces_to_represent_surface_regular_cuda_mgpu(
781
826
  name,
782
827
  title = None,
783
828
  agitate = False,
784
- feature_type = 'fault',
829
+ feature_type = "fault",
785
830
  progress_fn = None,
786
831
  return_properties = None,
787
832
  ):
@@ -823,21 +868,23 @@ def find_faces_to_represent_surface_regular_cuda_mgpu(
823
868
  props_dict_list = [None] * n_surfs
824
869
  threads = [None] * n_gpus
825
870
  for i_surface in range(n_surfs):
826
- threads[i_surface % n_gpus] = threading.Thread(target = find_faces_to_represent_surface_regular_cuda_sgpu,
827
- args = (
828
- grid,
829
- surfaces,
830
- name,
831
- title,
832
- agitate,
833
- feature_type,
834
- progress_fn,
835
- return_properties,
836
- i_surface,
837
- i_surface % n_gpus,
838
- gcs_list,
839
- props_dict_list,
840
- ))
871
+ threads[i_surface % n_gpus] = threading.Thread(
872
+ target = find_faces_to_represent_surface_regular_cuda_sgpu,
873
+ args = (
874
+ grid,
875
+ surfaces,
876
+ name,
877
+ title,
878
+ agitate,
879
+ feature_type,
880
+ progress_fn,
881
+ return_properties,
882
+ i_surface,
883
+ i_surface % n_gpus,
884
+ gcs_list,
885
+ props_dict_list,
886
+ ),
887
+ )
841
888
  threads[i_surface % n_gpus].start() # start parallel run
842
889
  # if this is the last GPU available or we're at the last array ...
843
890
  if (i_surface + 1) % n_gpus == 0 or (i_surface + 1) == n_surfs:
resqpy/lines/_common.py CHANGED
@@ -56,22 +56,25 @@ class _BasePolyline(BaseResqpy):
56
56
  self.rep_int_root = interp_root
57
57
 
58
58
 
59
- def load_hdf5_array(object, node, array_attribute, tag = 'Values'):
59
+ def load_hdf5_array(object, node, array_attribute, tag = 'Values', dtype = 'float'):
60
60
  """Loads the property array data as an attribute of object, from the hdf5 referenced in xml node.
61
61
 
62
62
  :meta private:
63
63
  """
64
-
65
64
  assert (rqet.node_type(node) in ['DoubleHdf5Array', 'IntegerHdf5Array', 'Point3dHdf5Array'])
66
65
  # ignore null value
67
66
  h5_key_pair = object.model.h5_uuid_and_path_for_node(node, tag = tag)
68
67
  if h5_key_pair is None:
69
68
  return None
70
- return object.model.h5_array_element(h5_key_pair,
71
- index = None,
72
- cache_array = True,
73
- object = object,
74
- array_attribute = array_attribute)
69
+ object.model.h5_array_element(h5_key_pair,
70
+ index = None,
71
+ cache_array = True,
72
+ dtype = dtype,
73
+ object = object,
74
+ array_attribute = array_attribute)
75
+ a = getattr(object, array_attribute)
76
+ assert a is not None
77
+ return a
75
78
 
76
79
 
77
80
  def shift_polyline(parent_model, poly_root, xyz_shift = (0, 0, 0), title = ''):
resqpy/lines/_polyline.py CHANGED
@@ -563,6 +563,26 @@ class Polyline(rql_c._BasePolyline):
563
563
  segment = -1
564
564
  return meet.point_snapped_to_line_segment_2d(p, self.coordinates[segment], self.coordinates[segment + 1])
565
565
 
566
+ def segment_xyz_from_xy(self, segment, x, y):
567
+ """Returns xyz point on segment given x and y (which should be on or close to the segment).
568
+
569
+ note:
570
+ this method allows a return to a 3D point after working in the 2D xy plane;
571
+ it will fail if the segment is 'vertical', ie. without range in x or y
572
+ """
573
+
574
+ if segment == len(self.coordinates) - 1:
575
+ segment = -1
576
+ seg_vector = self.coordinates[segment + 1] - self.coordinates[segment]
577
+ if abs(seg_vector[0]) > abs(seg_vector[1]):
578
+ assert (x - self.coordinates[segment, 0]) * (x - self.coordinates[segment + 1, 0]) <= 0
579
+ f = (x - self.coordinates[segment, 0]) / seg_vector[0]
580
+ else:
581
+ assert (y - self.coordinates[segment, 1]) * (y - self.coordinates[segment + 1, 1]) <= 0
582
+ f = (y - self.coordinates[segment, 1]) / seg_vector[1]
583
+ assert 0.0 <= f <= 1.0
584
+ return (1.0 - f) * self.coordinates[segment] + f * self.coordinates[segment + 1]
585
+
566
586
  def xy_crossings(self, other):
567
587
  """Returns list of (x, y) pairs of crossing points with other polyline, in xy plane."""
568
588