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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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