fullwave25 1.4.0__tar.gz → 1.4.1.dev0__tar.gz

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.
Files changed (79) hide show
  1. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/.bumpversion.toml +1 -1
  2. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/PKG-INFO +1 -1
  3. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/__init__.py +1 -1
  4. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/binary_manager.py +1 -1
  5. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/cuda_utils.py +36 -0
  6. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/launcher.py +46 -0
  7. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/pyproject.toml +1 -1
  8. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/uv.lock +1 -1
  9. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/.gitignore +0 -0
  10. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/.pre-commit-config.yaml +0 -0
  11. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/.python-version +0 -0
  12. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/CITATION.cff +0 -0
  13. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/CONTRIBUTING.md +0 -0
  14. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/LICENSE +0 -0
  15. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/Makefile +0 -0
  16. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/README.md +0 -0
  17. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/attenuation.png +0 -0
  18. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/beamformer.m +0 -0
  19. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/debug_solver_bin/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  20. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu +0 -0
  21. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  22. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  23. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  24. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  25. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/experiments/__init__.py +0 -0
  26. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/experiments/exp_scatterer_diameter.py +0 -0
  27. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/beamformer/__init__.py +0 -0
  28. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/beamformer/beamformer.py +0 -0
  29. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/constants/__init__.py +0 -0
  30. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/constants/material_properties.py +0 -0
  31. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/grid.py +0 -0
  32. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium.py +0 -0
  33. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/__init__.py +0 -0
  34. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/domain.py +0 -0
  35. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/medium_builder.py +0 -0
  36. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/__init__.py +0 -0
  37. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/data/.keep +0 -0
  38. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat +0 -0
  39. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/domain_abdominal_wall.py +0 -0
  40. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/domain_background.py +0 -0
  41. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/domain_scatterer.py +0 -0
  42. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/domain_simple.py +0 -0
  43. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/medium_builder/presets/domain_water_gel.py +0 -0
  44. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/sensor.py +0 -0
  45. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/__init__.py +0 -0
  46. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118 +0 -0
  47. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  48. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129 +0 -0
  49. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda130 +0 -0
  50. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda118 +0 -0
  51. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda124 +0 -0
  52. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129 +0 -0
  53. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130 +0 -0
  54. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513.mat +0 -0
  55. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513_invalid_cells.json +0 -0
  56. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456.mat +0 -0
  57. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456_invalid_cells.json +0 -0
  58. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/input_file_writer.py +0 -0
  59. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/pml_builder.py +0 -0
  60. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/shipped_database.py +0 -0
  61. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/solver.py +0 -0
  62. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/source_type.py +0 -0
  63. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/solver/utils.py +0 -0
  64. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/source.py +0 -0
  65. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/transducer.py +0 -0
  66. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/transmit.py +0 -0
  67. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/__init__.py +0 -0
  68. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/check_functions.py +0 -0
  69. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/coordinates.py +0 -0
  70. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/memory_tempfile.py +0 -0
  71. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/numerical.py +0 -0
  72. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/plot_utils.py +0 -0
  73. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/pulse.py +0 -0
  74. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/relaxation_parameters.py +0 -0
  75. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/scatterer.py +0 -0
  76. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/signal_filter.py +0 -0
  77. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/fullwave/utils/signal_process.py +0 -0
  78. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/ruff.toml +0 -0
  79. {fullwave25-1.4.0 → fullwave25-1.4.1.dev0}/signal_filter_example.png +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "1.4.0"
2
+ current_version = "1.4.1-dev0"
3
3
  parse = """(?x)
4
4
  (?P<major>0|[1-9]\\d*)\\.
5
5
  (?P<minor>0|[1-9]\\d*)\\.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: fullwave25
3
- Version: 1.4.0
3
+ Version: 1.4.1-dev0
4
4
  Summary: Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities
5
5
  Author: Masashi Sode, Gianmarco Pinton
6
6
  Maintainer: Masashi Sode
@@ -66,7 +66,7 @@ try:
66
66
  __version__ = version("fullwave")
67
67
  except PackageNotFoundError:
68
68
  # Update via bump-my-version, not manually
69
- __version__ = "1.4.0"
69
+ __version__ = "1.4.1-dev0"
70
70
 
71
71
  VERSION = __version__ # for convenience
72
72
  logger.info("Fullwave version: %s", __version__)
@@ -28,7 +28,7 @@ CACHE_DIR = Path.home() / ".cache" / "fullwave25" / "bins"
28
28
 
29
29
  # Pinned release tag for the solver binaries.
30
30
  # Update this only when new binaries are uploaded to a GitHub release.
31
- BINARY_RELEASE_TAG = "fullwave_bin_v1.5"
31
+ BINARY_RELEASE_TAG = "fullwave_bin_v1.5.1"
32
32
 
33
33
 
34
34
  def _download_url(filename: str, tag: str) -> str:
@@ -213,6 +213,42 @@ def cuCtxDetach(ctx): # noqa: ANN001, ANN201, D103, N802
213
213
  return cuda.cuCtxDetach(ctx)
214
214
 
215
215
 
216
+ @cuda_api_call
217
+ def cuDeviceCanAccessPeer(can_access, dev, peer_dev): # noqa: ANN001, ANN201, D103, N802
218
+ return cuda.cuDeviceCanAccessPeer(can_access, dev, peer_dev)
219
+
220
+
221
+ def find_consecutive_gpus_without_peer_access(ordinals: list[int]) -> list[tuple[int, int]]:
222
+ """Return the consecutive GPU pairs that cannot access each other's memory directly.
223
+
224
+ Parameters
225
+ ----------
226
+ ordinals : list[int]
227
+ CUDA device ordinals as this process sees them, in the requested order.
228
+
229
+ Returns
230
+ -------
231
+ list[tuple[int, int]]
232
+ Each consecutive pair (a, b) of ``ordinals`` where a cannot access b or b
233
+ cannot access a.
234
+
235
+ """
236
+ cuInit(0)
237
+ pairs = []
238
+ for first, second in zip(ordinals, ordinals[1:], strict=False):
239
+ device_first = ctypes.c_int()
240
+ device_second = ctypes.c_int()
241
+ cuDeviceGet(ctypes.byref(device_first), first)
242
+ cuDeviceGet(ctypes.byref(device_second), second)
243
+ forward = ctypes.c_int()
244
+ backward = ctypes.c_int()
245
+ cuDeviceCanAccessPeer(ctypes.byref(forward), device_first, device_second)
246
+ cuDeviceCanAccessPeer(ctypes.byref(backward), device_second, device_first)
247
+ if not forward.value or not backward.value:
248
+ pairs.append((first, second))
249
+ return pairs
250
+
251
+
216
252
  # Main function to get CUDA device specs
217
253
  @lru_cache(maxsize=1)
218
254
  def get_cuda_device_specs() -> list[dict[str, Any]]:
@@ -1,5 +1,6 @@
1
1
  """Module for launching Fullwave simulation."""
2
2
 
3
+ import ctypes
3
4
  import logging
4
5
  import os
5
6
  import re
@@ -79,6 +80,8 @@ class Launcher:
79
80
  cuda_device_id,
80
81
  verify_gpu=verify_gpu,
81
82
  )
83
+ if use_gpu and verify_gpu:
84
+ self._warn_if_gpus_lack_peer_access(self.cuda_device_id)
82
85
  self.save_gpu_memory = save_gpu_memory
83
86
  logger.debug("Launcher instance created.")
84
87
 
@@ -160,6 +163,49 @@ class Launcher:
160
163
  message = f"CUDA device ID {device_id} does not exist."
161
164
  raise ValueError(message)
162
165
 
166
+ @staticmethod
167
+ def _warn_if_gpus_lack_peer_access(device_id_str: str) -> None:
168
+ """Warn when consecutive GPUs of a multi-GPU run have no peer-to-peer access.
169
+
170
+ Without peer access (no NVLink, and a PCIe chipset or GPU that refuses it,
171
+ as on GeForce cards), a multi-GPU run is much slower than with peer access.
172
+
173
+ The binary runs with ``CUDA_VISIBLE_DEVICES`` set to ``device_id_str``. The
174
+ CUDA ordinals of this process name the same GPUs only when this process has
175
+ no ``CUDA_VISIBLE_DEVICES`` of its own, so the check is skipped otherwise.
176
+ It never raises: if the CUDA driver cannot answer, it logs at debug level.
177
+
178
+ Parameters
179
+ ----------
180
+ device_id_str : str
181
+ The CUDA device ID(s) in string format, for example "0,1,2,3".
182
+
183
+ """
184
+ device_ids = [int(device_id) for device_id in device_id_str.split(",")]
185
+ if len(device_ids) < 2:
186
+ return
187
+ if "CUDA_VISIBLE_DEVICES" in os.environ:
188
+ logger.debug(
189
+ "Peer access check skipped: CUDA_VISIBLE_DEVICES is set in this process.",
190
+ )
191
+ return
192
+ try:
193
+ from .cuda_utils import find_consecutive_gpus_without_peer_access # noqa: PLC0415
194
+
195
+ pairs = find_consecutive_gpus_without_peer_access(device_ids)
196
+ except (AttributeError, NameError, OSError, RuntimeError, ctypes.ArgumentError) as error:
197
+ logger.debug("Peer access check skipped: %s", error)
198
+ return
199
+ if not pairs:
200
+ return
201
+ pair_text = ", ".join(f"GPU {first} <-> GPU {second}" for first, second in pairs)
202
+ logger.warning(
203
+ "No peer-to-peer access between %s. A multi-GPU run on these GPUs is much "
204
+ "slower than on GPUs with NVLink or PCIe peer access. Check with a short "
205
+ "run whether fewer GPUs give a faster simulation.",
206
+ pair_text,
207
+ )
208
+
163
209
  @staticmethod
164
210
  def _configure_cuda_device_id(
165
211
  cuda_device_id: str | int | list | None,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fullwave25"
3
- version = "1.4.0" # Update via bump-my-version, not manually
3
+ version = "1.4.1-dev0" # Update via bump-my-version, not manually
4
4
  description = "Fullwave 2.5: Ultrasound wave propagation simulation with heterogeneous power law attenuation modelling capabilities"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -761,7 +761,7 @@ wheels = [
761
761
 
762
762
  [[package]]
763
763
  name = "fullwave25"
764
- version = "1.4.0"
764
+ version = "1.4.1.dev0"
765
765
  source = { editable = "." }
766
766
  dependencies = [
767
767
  { name = "cupy-cuda12x" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes