fullwave25 1.2.6.dev2__py3-none-any.whl → 1.2.6.dev4__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.
- fullwave/__init__.py +1 -1
- fullwave/beamformer/beamformer.py +2 -1
- fullwave/medium.py +8 -4
- fullwave/sensor.py +3 -2
- fullwave/solver/cuda_utils.py +10 -5
- fullwave/solver/launcher.py +20 -3
- fullwave/solver/pml_builder.py +46 -50
- fullwave/solver/solver.py +259 -1
- fullwave/solver/utils.py +16 -8
- fullwave/source.py +1 -1
- fullwave/transducer.py +12 -11
- fullwave/utils/check_functions.py +6 -3
- fullwave/utils/coordinates.py +8 -4
- fullwave/utils/memory_tempfile.py +7 -7
- fullwave/utils/plot_utils.py +3 -3
- fullwave/utils/signal_filter.py +2 -2
- {fullwave25-1.2.6.dev2.dist-info → fullwave25-1.2.6.dev4.dist-info}/METADATA +1 -2
- {fullwave25-1.2.6.dev2.dist-info → fullwave25-1.2.6.dev4.dist-info}/RECORD +20 -20
- {fullwave25-1.2.6.dev2.dist-info → fullwave25-1.2.6.dev4.dist-info}/WHEEL +0 -0
- {fullwave25-1.2.6.dev2.dist-info → fullwave25-1.2.6.dev4.dist-info}/licenses/LICENSE +0 -0
fullwave/__init__.py
CHANGED
|
@@ -60,7 +60,7 @@ try:
|
|
|
60
60
|
__version__ = version("fullwave")
|
|
61
61
|
except PackageNotFoundError:
|
|
62
62
|
# Update via bump-my-version, not manually
|
|
63
|
-
__version__ = "1.2.6-
|
|
63
|
+
__version__ = "1.2.6-dev4"
|
|
64
64
|
|
|
65
65
|
VERSION = __version__ # for convenience
|
|
66
66
|
logger.info("Fullwave version: %s", __version__)
|
|
@@ -14,7 +14,8 @@ class Beamformer:
|
|
|
14
14
|
For faster implementations, consider using libraries such as
|
|
15
15
|
mach beamformer: https://github.com/Forest-Neurotech/mach
|
|
16
16
|
|
|
17
|
-
References
|
|
17
|
+
References
|
|
18
|
+
----------
|
|
18
19
|
- Fullwave2 BMME890 implementation
|
|
19
20
|
- https://github.com/gfpinton/fullwave_bmme890/blob/master/fullwave2_launcher_imaging_planewave.m
|
|
20
21
|
|
fullwave/medium.py
CHANGED
|
@@ -231,7 +231,8 @@ class MediumRelaxationMaps:
|
|
|
231
231
|
) -> None:
|
|
232
232
|
"""Check if the relaxation parameter updates have valid keys and matching shapes.
|
|
233
233
|
|
|
234
|
-
Raises
|
|
234
|
+
Raises
|
|
235
|
+
------
|
|
235
236
|
ValueError: If the keys do not match the desired keys or
|
|
236
237
|
if the shapes of the values do not match the domain shape.
|
|
237
238
|
|
|
@@ -1147,11 +1148,13 @@ class Medium:
|
|
|
1147
1148
|
it uses the relaxation parameters look up table
|
|
1148
1149
|
to generate the relaxation parameters.
|
|
1149
1150
|
|
|
1150
|
-
Returns
|
|
1151
|
+
Returns
|
|
1152
|
+
-------
|
|
1151
1153
|
MediumRelaxationMaps: An instance of MediumRelaxationMaps
|
|
1152
1154
|
built from the retrieved relaxation parameters.
|
|
1153
1155
|
|
|
1154
|
-
Raises
|
|
1156
|
+
Raises
|
|
1157
|
+
------
|
|
1155
1158
|
ValueError: If an unknown attenuation_builder is specified.
|
|
1156
1159
|
|
|
1157
1160
|
"""
|
|
@@ -1216,7 +1219,8 @@ class Medium:
|
|
|
1216
1219
|
def build_exponential(self) -> MediumExponentialAttenuation:
|
|
1217
1220
|
"""Build MediumExponentialAttenuation from alpha and power maps.
|
|
1218
1221
|
|
|
1219
|
-
Returns
|
|
1222
|
+
Returns
|
|
1223
|
+
-------
|
|
1220
1224
|
MediumExponentialAttenuation: An instance of MediumExponentialAttenuation
|
|
1221
1225
|
built from the alpha and power maps.
|
|
1222
1226
|
|
fullwave/sensor.py
CHANGED
|
@@ -21,7 +21,7 @@ class Sensor:
|
|
|
21
21
|
outcoords: NDArray[np.int64]
|
|
22
22
|
sampling_modulus_time: int = 1
|
|
23
23
|
|
|
24
|
-
def __init__(
|
|
24
|
+
def __init__(
|
|
25
25
|
self,
|
|
26
26
|
mask: NDArray[np.bool] | None = None,
|
|
27
27
|
sampling_modulus_time: int = 1,
|
|
@@ -189,7 +189,8 @@ class Sensor:
|
|
|
189
189
|
) -> None:
|
|
190
190
|
"""Plot the transducer mask, optionally exporting and displaying the figure.
|
|
191
191
|
|
|
192
|
-
Raises
|
|
192
|
+
Raises
|
|
193
|
+
------
|
|
193
194
|
ValueError: If the sensor is 3D because plotting is not supported.
|
|
194
195
|
|
|
195
196
|
"""
|
fullwave/solver/cuda_utils.py
CHANGED
|
@@ -113,7 +113,8 @@ def cuda_api_call(func: Callable) -> Callable:
|
|
|
113
113
|
Decorator for CUDA API calls
|
|
114
114
|
Raises RuntimeError if the CUDA call does not return CUDA_SUCCESS.
|
|
115
115
|
|
|
116
|
-
Returns
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
117
118
|
Callable: The wrapped function that checks CUDA API call results.
|
|
118
119
|
|
|
119
120
|
"""
|
|
@@ -138,7 +139,8 @@ def cuda_api_call_warn(func: Callable) -> Callable:
|
|
|
138
139
|
|
|
139
140
|
Prints a warning message if the CUDA call does not return CUDA_SUCCESS.
|
|
140
141
|
|
|
141
|
-
Returns
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
142
144
|
Callable: The wrapped function that checks CUDA API call results.
|
|
143
145
|
|
|
144
146
|
"""
|
|
@@ -230,7 +232,8 @@ def get_cuda_device_specs() -> list[dict[str, Any]]:
|
|
|
230
232
|
'cuda_cores': int
|
|
231
233
|
}
|
|
232
234
|
|
|
233
|
-
Returns
|
|
235
|
+
Returns
|
|
236
|
+
-------
|
|
234
237
|
A list of dictionaries containing specifications for each CUDA device.
|
|
235
238
|
|
|
236
239
|
"""
|
|
@@ -325,7 +328,8 @@ def get_cuda_architecture() -> list[dict[str, Any]]:
|
|
|
325
328
|
'architecture': str,
|
|
326
329
|
}
|
|
327
330
|
|
|
328
|
-
Returns
|
|
331
|
+
Returns
|
|
332
|
+
-------
|
|
329
333
|
A list of dictionaries containing architecture information for each CUDA device.
|
|
330
334
|
|
|
331
335
|
"""
|
|
@@ -363,7 +367,8 @@ def get_cuda_architecture() -> list[dict[str, Any]]:
|
|
|
363
367
|
def retrieve_cuda_version() -> float:
|
|
364
368
|
"""Retrieve the CUDA driver version.
|
|
365
369
|
|
|
366
|
-
Returns
|
|
370
|
+
Returns
|
|
371
|
+
-------
|
|
367
372
|
str: CUDA version in the format "major.minor" or "unknown" if retrieval fails.
|
|
368
373
|
|
|
369
374
|
"""
|
fullwave/solver/launcher.py
CHANGED
|
@@ -31,6 +31,7 @@ class Launcher:
|
|
|
31
31
|
use_gpu: bool = True,
|
|
32
32
|
cuda_device_id: str | int | list | None = None,
|
|
33
33
|
save_gpu_memory: bool = False,
|
|
34
|
+
verify_gpu: bool = True,
|
|
34
35
|
) -> None:
|
|
35
36
|
"""Initialize a FullwaveLauncher instance.
|
|
36
37
|
|
|
@@ -62,6 +63,11 @@ class Launcher:
|
|
|
62
63
|
depending on the hardware and the simulation settings.
|
|
63
64
|
useful in 3D simulations with large grid sizes
|
|
64
65
|
where GPU memory is a limiting factor.
|
|
66
|
+
verify_gpu : bool, optional
|
|
67
|
+
Whether to verify that the specified CUDA devices exist on the system.
|
|
68
|
+
Defaults to True. Set to False when generating input files only
|
|
69
|
+
(``generate_input_only=True``) on a machine that may not have
|
|
70
|
+
the target GPUs available.
|
|
65
71
|
|
|
66
72
|
"""
|
|
67
73
|
self._path_fullwave_simulation_bin = path_fullwave_simulation_bin
|
|
@@ -69,7 +75,10 @@ class Launcher:
|
|
|
69
75
|
assert self._path_fullwave_simulation_bin.exists(), error_msg
|
|
70
76
|
self.is_3d = is_3d
|
|
71
77
|
self.use_gpu = use_gpu
|
|
72
|
-
self.cuda_device_id = self._configure_cuda_device_id(
|
|
78
|
+
self.cuda_device_id = self._configure_cuda_device_id(
|
|
79
|
+
cuda_device_id,
|
|
80
|
+
verify_gpu=verify_gpu,
|
|
81
|
+
)
|
|
73
82
|
self.save_gpu_memory = save_gpu_memory
|
|
74
83
|
logger.debug("Launcher instance created.")
|
|
75
84
|
|
|
@@ -152,13 +161,20 @@ class Launcher:
|
|
|
152
161
|
raise ValueError(message)
|
|
153
162
|
|
|
154
163
|
@staticmethod
|
|
155
|
-
def _configure_cuda_device_id(
|
|
164
|
+
def _configure_cuda_device_id(
|
|
165
|
+
cuda_device_id: str | int | list | None,
|
|
166
|
+
*,
|
|
167
|
+
verify_gpu: bool = True,
|
|
168
|
+
) -> str:
|
|
156
169
|
"""Verify and assign the CUDA device ID.
|
|
157
170
|
|
|
158
171
|
Parameters
|
|
159
172
|
----------
|
|
160
173
|
cuda_device_id : str | int | None
|
|
161
174
|
The CUDA device ID to verify and assign.
|
|
175
|
+
verify_gpu : bool, optional
|
|
176
|
+
Whether to verify that the specified CUDA devices exist.
|
|
177
|
+
Defaults to True.
|
|
162
178
|
|
|
163
179
|
Returns
|
|
164
180
|
-------
|
|
@@ -167,7 +183,8 @@ class Launcher:
|
|
|
167
183
|
|
|
168
184
|
"""
|
|
169
185
|
output = Launcher._parse_cuda_device_id(cuda_device_id)
|
|
170
|
-
|
|
186
|
+
if verify_gpu:
|
|
187
|
+
Launcher._verify_cuda_devices_exist(output)
|
|
171
188
|
return output
|
|
172
189
|
|
|
173
190
|
def run(
|
fullwave/solver/pml_builder.py
CHANGED
|
@@ -5,13 +5,11 @@ import logging
|
|
|
5
5
|
from collections import OrderedDict
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
7
|
from functools import cached_property
|
|
8
|
-
from itertools import starmap
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
|
|
11
10
|
import matplotlib.pyplot as plt
|
|
12
11
|
import numexpr as ne
|
|
13
12
|
import numpy as np
|
|
14
|
-
from joblib import Parallel, delayed
|
|
15
13
|
from numpy.typing import NDArray
|
|
16
14
|
|
|
17
15
|
import fullwave
|
|
@@ -115,7 +113,7 @@ class PMLBuilder:
|
|
|
115
113
|
pml_mask_x: NDArray[np.float64] = field(init=False)
|
|
116
114
|
pml_mask_y: NDArray[np.float64] = field(init=False)
|
|
117
115
|
|
|
118
|
-
def __init__(
|
|
116
|
+
def __init__(
|
|
119
117
|
self,
|
|
120
118
|
grid: fullwave.Grid,
|
|
121
119
|
medium: fullwave.Medium,
|
|
@@ -834,21 +832,24 @@ class PMLBuilder:
|
|
|
834
832
|
|
|
835
833
|
items = list(rename_dict.items())
|
|
836
834
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
835
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
836
|
+
futures = [
|
|
837
|
+
executor.submit(
|
|
838
|
+
_compute_one,
|
|
839
|
+
key_fw2,
|
|
840
|
+
key_py,
|
|
841
|
+
relaxation_param_dict,
|
|
842
|
+
alpha_target_higher_nu,
|
|
843
|
+
d_target_higher_nu,
|
|
844
|
+
alpha_target_pml,
|
|
845
|
+
d_target_pml,
|
|
846
|
+
n_polynomial,
|
|
847
|
+
self.is_3d,
|
|
848
|
+
self._apply_transition_and_pml,
|
|
849
|
+
)
|
|
850
|
+
for key_fw2, key_py in items
|
|
851
|
+
]
|
|
852
|
+
results = [f.result() for f in futures]
|
|
852
853
|
out_dict = dict(results)
|
|
853
854
|
|
|
854
855
|
logger.debug("Calculating PML a and b coefficients...")
|
|
@@ -876,13 +877,9 @@ class PMLBuilder:
|
|
|
876
877
|
# Return keys + values so parent can update dict safely
|
|
877
878
|
return (f"a_pml_{axis}{nu}", a, f"b_pml_{axis}{nu}", b)
|
|
878
879
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
prefer="processes",
|
|
883
|
-
)(
|
|
884
|
-
starmap(delayed(_worker), tasks),
|
|
885
|
-
)
|
|
880
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
881
|
+
futures = [executor.submit(_worker, nu, axis) for nu, axis in tasks]
|
|
882
|
+
results = [f.result() for f in futures]
|
|
886
883
|
|
|
887
884
|
for a_key, a_val, b_key, b_val in results:
|
|
888
885
|
out_dict[a_key] = a_val
|
|
@@ -898,7 +895,7 @@ class PMLBuilder:
|
|
|
898
895
|
|
|
899
896
|
return extended_medium
|
|
900
897
|
|
|
901
|
-
def _apply_pml_3d(
|
|
898
|
+
def _apply_pml_3d(
|
|
902
899
|
self,
|
|
903
900
|
extended_medium: fullwave.MediumRelaxationMaps,
|
|
904
901
|
theoritical_reflection_coefficient: float,
|
|
@@ -1119,21 +1116,24 @@ class PMLBuilder:
|
|
|
1119
1116
|
raise ValueError(error_msg)
|
|
1120
1117
|
|
|
1121
1118
|
items = list(rename_dict.items())
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1119
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
1120
|
+
futures = [
|
|
1121
|
+
executor.submit(
|
|
1122
|
+
_compute_one,
|
|
1123
|
+
key_fw2,
|
|
1124
|
+
key_py,
|
|
1125
|
+
relaxation_param_dict,
|
|
1126
|
+
alpha_target_higher_nu,
|
|
1127
|
+
d_target_higher_nu,
|
|
1128
|
+
alpha_target_pml,
|
|
1129
|
+
d_target_pml,
|
|
1130
|
+
n_polynomial,
|
|
1131
|
+
self.is_3d,
|
|
1132
|
+
self._apply_transition_and_pml,
|
|
1133
|
+
)
|
|
1134
|
+
for key_fw2, key_py in items
|
|
1135
|
+
]
|
|
1136
|
+
results = [f.result() for f in futures]
|
|
1137
1137
|
out_dict = dict(results)
|
|
1138
1138
|
|
|
1139
1139
|
logger.debug("Calculating PML a and b coefficients...")
|
|
@@ -1162,13 +1162,9 @@ class PMLBuilder:
|
|
|
1162
1162
|
# Return keys + values so parent can update dict safely
|
|
1163
1163
|
return (f"a_pml_{axis}{nu}", a, f"b_pml_{axis}{nu}", b)
|
|
1164
1164
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
prefer="processes",
|
|
1169
|
-
)(
|
|
1170
|
-
starmap(delayed(_worker), tasks),
|
|
1171
|
-
)
|
|
1165
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
1166
|
+
futures = [executor.submit(_worker, nu, axis) for nu, axis in tasks]
|
|
1167
|
+
results = [f.result() for f in futures]
|
|
1172
1168
|
|
|
1173
1169
|
for a_key, a_val, b_key, b_val in results:
|
|
1174
1170
|
out_dict[a_key] = a_val
|
|
@@ -1184,7 +1180,7 @@ class PMLBuilder:
|
|
|
1184
1180
|
|
|
1185
1181
|
return extended_medium
|
|
1186
1182
|
|
|
1187
|
-
def _apply_transition_and_pml( # noqa:
|
|
1183
|
+
def _apply_transition_and_pml( # noqa: PLR0912
|
|
1188
1184
|
self,
|
|
1189
1185
|
input_array: NDArray[np.float64],
|
|
1190
1186
|
value_target: float,
|
|
@@ -1465,7 +1461,7 @@ class PMLBuilder:
|
|
|
1465
1461
|
class PMLBuilderExponentialAttenuation(PMLBuilder):
|
|
1466
1462
|
"""A class to set up PML for exponential attenuation media."""
|
|
1467
1463
|
|
|
1468
|
-
def __init__(
|
|
1464
|
+
def __init__(
|
|
1469
1465
|
self,
|
|
1470
1466
|
grid: fullwave.Grid,
|
|
1471
1467
|
medium: fullwave.Medium,
|
fullwave/solver/solver.py
CHANGED
|
@@ -309,7 +309,7 @@ class Solver:
|
|
|
309
309
|
generates the required input files, and runs the simulation executable.
|
|
310
310
|
"""
|
|
311
311
|
|
|
312
|
-
def __init__( # noqa: PLR0912
|
|
312
|
+
def __init__( # noqa: PLR0912
|
|
313
313
|
self,
|
|
314
314
|
work_dir: Path,
|
|
315
315
|
grid: fullwave.Grid,
|
|
@@ -329,6 +329,7 @@ class Solver:
|
|
|
329
329
|
use_isotropic_relaxation: bool = True,
|
|
330
330
|
cuda_device_id: str | int | list | None = None,
|
|
331
331
|
save_gpu_memory: bool = False,
|
|
332
|
+
verify_gpu: bool = True,
|
|
332
333
|
) -> None:
|
|
333
334
|
"""Initialize a Solver instance for the fullwave simulation.
|
|
334
335
|
|
|
@@ -415,6 +416,11 @@ class Solver:
|
|
|
415
416
|
depending on the hardware and the simulation settings.
|
|
416
417
|
useful in 3D simulations with large grid sizes
|
|
417
418
|
where GPU memory is a limiting factor.
|
|
419
|
+
verify_gpu : bool, optional
|
|
420
|
+
Whether to verify that the specified CUDA devices exist on the system.
|
|
421
|
+
Defaults to True. Set to False when generating input files only
|
|
422
|
+
(``generate_input_only=True``) on a machine that may not have
|
|
423
|
+
the target GPUs available.
|
|
418
424
|
|
|
419
425
|
Raises
|
|
420
426
|
------
|
|
@@ -555,6 +561,7 @@ class Solver:
|
|
|
555
561
|
use_gpu=self.use_gpu,
|
|
556
562
|
cuda_device_id=self.cuda_device_id,
|
|
557
563
|
save_gpu_memory=self.save_gpu_memory,
|
|
564
|
+
verify_gpu=verify_gpu,
|
|
558
565
|
)
|
|
559
566
|
|
|
560
567
|
if use_exponential_attenuation:
|
|
@@ -758,6 +765,7 @@ class Solver:
|
|
|
758
765
|
release_after_write: bool = False,
|
|
759
766
|
highpass_cutoff_mhz: float | None = None,
|
|
760
767
|
bandpass_cutoff_mhz: tuple[float, float] | None = None,
|
|
768
|
+
gpu_memory_estimate: bool = False,
|
|
761
769
|
) -> NDArray[np.float64] | Path:
|
|
762
770
|
r"""Run the fullwave simulation and return the result as a NumPy array.
|
|
763
771
|
|
|
@@ -829,6 +837,9 @@ class Solver:
|
|
|
829
837
|
Uses cosine (Hann) tapers on both edges.
|
|
830
838
|
Cannot be combined with ``highpass_cutoff_mhz``.
|
|
831
839
|
Requires ``load_results=True``. Default is ``None`` (no filtering).
|
|
840
|
+
gpu_memory_estimate : bool
|
|
841
|
+
Whether to estimate GPU memory usage before running the simulation.
|
|
842
|
+
Default is True. If True, it estimates the GPU memory usage.
|
|
832
843
|
|
|
833
844
|
Returns
|
|
834
845
|
-------
|
|
@@ -937,6 +948,9 @@ class Solver:
|
|
|
937
948
|
)
|
|
938
949
|
logger.debug(message)
|
|
939
950
|
|
|
951
|
+
if gpu_memory_estimate:
|
|
952
|
+
self._estimate_gpu_memory(sensor)
|
|
953
|
+
|
|
940
954
|
if generate_input_only:
|
|
941
955
|
logger.info(
|
|
942
956
|
"Input data generation completed in %s. Skipping simulation execution.",
|
|
@@ -975,6 +989,250 @@ class Solver:
|
|
|
975
989
|
# which is a list of file names
|
|
976
990
|
return sim_result
|
|
977
991
|
|
|
992
|
+
def _estimate_gpu_memory(
|
|
993
|
+
self,
|
|
994
|
+
sensor: fullwave.Sensor,
|
|
995
|
+
) -> None:
|
|
996
|
+
"""Estimate and log GPU memory usage per device.
|
|
997
|
+
|
|
998
|
+
Provides a pre-launch estimate so users can verify that the simulation
|
|
999
|
+
fits in GPU memory before the binary starts allocating.
|
|
1000
|
+
|
|
1001
|
+
Parameters
|
|
1002
|
+
----------
|
|
1003
|
+
sensor : fullwave.Sensor
|
|
1004
|
+
The sensor that will actually be written to the input files (may
|
|
1005
|
+
differ from ``self.sensor`` when ``record_whole_domain=True``).
|
|
1006
|
+
|
|
1007
|
+
"""
|
|
1008
|
+
# show that this is an experimental feature
|
|
1009
|
+
logger.info("Estimating GPU memory usage... (experimental feature, may be inaccurate)")
|
|
1010
|
+
device_ids = self.fullwave_launcher.cuda_device_id.split(",")
|
|
1011
|
+
n_gpus = len(device_ids)
|
|
1012
|
+
|
|
1013
|
+
grid = self.pml_builder.extended_grid
|
|
1014
|
+
source = self.pml_builder.extended_source
|
|
1015
|
+
medium = self.pml_builder.extended_medium
|
|
1016
|
+
|
|
1017
|
+
depth = grid.nx
|
|
1018
|
+
lateral = grid.ny * grid.nz if self.is_3d else grid.ny
|
|
1019
|
+
halo_depth = 8
|
|
1020
|
+
|
|
1021
|
+
float_bytes = 4
|
|
1022
|
+
int_bytes = 4
|
|
1023
|
+
|
|
1024
|
+
c_map = medium.sound_speed
|
|
1025
|
+
c_range = int(np.rint(c_map.max()) - np.rint(c_map.min()))
|
|
1026
|
+
n_deriv_levels = 1 if c_range == 0 else c_range + 1
|
|
1027
|
+
|
|
1028
|
+
n_source_timesteps = source.icmat.shape[1]
|
|
1029
|
+
|
|
1030
|
+
gb = 1024.0**3
|
|
1031
|
+
|
|
1032
|
+
base_depth = depth // n_gpus
|
|
1033
|
+
remainder = depth % n_gpus
|
|
1034
|
+
|
|
1035
|
+
for rank, dev_id in enumerate(device_ids):
|
|
1036
|
+
depth_this = base_depth + (1 if rank < remainder else 0)
|
|
1037
|
+
|
|
1038
|
+
if n_gpus == 1:
|
|
1039
|
+
n_halo_sides = 0
|
|
1040
|
+
elif rank == 0 or rank == n_gpus - 1:
|
|
1041
|
+
n_halo_sides = 1
|
|
1042
|
+
else:
|
|
1043
|
+
n_halo_sides = 2
|
|
1044
|
+
local_depth = depth_this + n_halo_sides * halo_depth
|
|
1045
|
+
slab = local_depth * lateral
|
|
1046
|
+
|
|
1047
|
+
n_sources = max(source.n_sources // n_gpus, 0)
|
|
1048
|
+
n_sensors = max(sensor.n_sensors // n_gpus, 0)
|
|
1049
|
+
n_air_local = max(medium.n_air // n_gpus, 0)
|
|
1050
|
+
|
|
1051
|
+
if self.use_exponential_attenuation:
|
|
1052
|
+
total = self._mem_exponential(
|
|
1053
|
+
slab,
|
|
1054
|
+
n_deriv_levels,
|
|
1055
|
+
n_sources,
|
|
1056
|
+
n_source_timesteps,
|
|
1057
|
+
save_gpu_memory=self.save_gpu_memory,
|
|
1058
|
+
n_sensors=n_sensors,
|
|
1059
|
+
float_bytes=float_bytes,
|
|
1060
|
+
int_bytes=int_bytes,
|
|
1061
|
+
is_3d=self.is_3d,
|
|
1062
|
+
)
|
|
1063
|
+
else:
|
|
1064
|
+
total = self._mem_relaxation(
|
|
1065
|
+
slab,
|
|
1066
|
+
n_deriv_levels,
|
|
1067
|
+
n_sources,
|
|
1068
|
+
n_source_timesteps,
|
|
1069
|
+
save_gpu_memory=self.save_gpu_memory,
|
|
1070
|
+
n_air=n_air_local,
|
|
1071
|
+
n_sensors=n_sensors,
|
|
1072
|
+
n_relax=self.n_relax_mechanisms,
|
|
1073
|
+
float_bytes=float_bytes,
|
|
1074
|
+
int_bytes=int_bytes,
|
|
1075
|
+
is_3d=self.is_3d,
|
|
1076
|
+
)
|
|
1077
|
+
|
|
1078
|
+
mode = "exponential" if self.use_exponential_attenuation else "relaxation"
|
|
1079
|
+
saving = ", save_gpu_memory=True" if self.save_gpu_memory else ""
|
|
1080
|
+
logger.info(
|
|
1081
|
+
"GPU memory estimate [GPU %s] (%s mode%s): "
|
|
1082
|
+
"%.2f GB (depth=%d +%d halo, lateral=%d)",
|
|
1083
|
+
dev_id.strip(),
|
|
1084
|
+
mode,
|
|
1085
|
+
saving,
|
|
1086
|
+
total / gb,
|
|
1087
|
+
depth_this,
|
|
1088
|
+
n_halo_sides * halo_depth,
|
|
1089
|
+
lateral,
|
|
1090
|
+
)
|
|
1091
|
+
|
|
1092
|
+
@staticmethod
|
|
1093
|
+
def _mem_exponential(
|
|
1094
|
+
slab: int,
|
|
1095
|
+
n_deriv_levels: int,
|
|
1096
|
+
n_sources: int,
|
|
1097
|
+
n_source_timesteps: int,
|
|
1098
|
+
*,
|
|
1099
|
+
save_gpu_memory: bool,
|
|
1100
|
+
n_sensors: int,
|
|
1101
|
+
float_bytes: int,
|
|
1102
|
+
int_bytes: int,
|
|
1103
|
+
is_3d: bool,
|
|
1104
|
+
) -> int:
|
|
1105
|
+
"""Return estimated GPU bytes for exponential-attenuation solver.
|
|
1106
|
+
|
|
1107
|
+
Parameters
|
|
1108
|
+
----------
|
|
1109
|
+
slab : int
|
|
1110
|
+
Grid points per GPU slab (local_depth * lateral).
|
|
1111
|
+
n_deriv_levels : int
|
|
1112
|
+
Number of derivative-map levels.
|
|
1113
|
+
n_sources : int
|
|
1114
|
+
Approximate source count on this GPU.
|
|
1115
|
+
n_source_timesteps : int
|
|
1116
|
+
Number of source time steps.
|
|
1117
|
+
save_gpu_memory : bool
|
|
1118
|
+
Whether memory-saving mode is active.
|
|
1119
|
+
n_sensors : int
|
|
1120
|
+
Approximate sensor count on this GPU.
|
|
1121
|
+
float_bytes : int
|
|
1122
|
+
Bytes per float (4).
|
|
1123
|
+
int_bytes : int
|
|
1124
|
+
Bytes per int (4).
|
|
1125
|
+
is_3d: bool,
|
|
1126
|
+
Whether the simulation is 3D (affects sensor memory).
|
|
1127
|
+
|
|
1128
|
+
Returns
|
|
1129
|
+
-------
|
|
1130
|
+
int
|
|
1131
|
+
Total estimated bytes.
|
|
1132
|
+
|
|
1133
|
+
"""
|
|
1134
|
+
fb = float_bytes
|
|
1135
|
+
ib = int_bytes
|
|
1136
|
+
ndim = 3 if is_3d else 2
|
|
1137
|
+
n_fields = 4 if is_3d else 3 # p, u, [v], w
|
|
1138
|
+
|
|
1139
|
+
# wave fields: n_fields pairs x 2 time levels
|
|
1140
|
+
mem = n_fields * 2 * slab * fb
|
|
1141
|
+
# material: rho + K + beta + a_exp
|
|
1142
|
+
mem += 4 * slab * fb
|
|
1143
|
+
# derivative maps (dmap + dcmap)
|
|
1144
|
+
mem += 9 * 2 * n_deriv_levels * fb + slab * ib
|
|
1145
|
+
# source (icmat + coords)
|
|
1146
|
+
if n_sources > 0:
|
|
1147
|
+
mem += n_sources * fb if save_gpu_memory else n_sources * n_source_timesteps * fb
|
|
1148
|
+
mem += ndim * n_sources * ib
|
|
1149
|
+
# sensor (genoutframe + coordsout_local + p_idx_array)
|
|
1150
|
+
if n_sensors > 0:
|
|
1151
|
+
mem += n_sensors * fb
|
|
1152
|
+
mem += (ndim + 1) * n_sensors * ib
|
|
1153
|
+
mem += n_sensors * ib
|
|
1154
|
+
return mem
|
|
1155
|
+
|
|
1156
|
+
@staticmethod
|
|
1157
|
+
def _mem_relaxation(
|
|
1158
|
+
slab: int,
|
|
1159
|
+
n_deriv_levels: int,
|
|
1160
|
+
n_sources: int,
|
|
1161
|
+
n_source_timesteps: int,
|
|
1162
|
+
*,
|
|
1163
|
+
save_gpu_memory: bool,
|
|
1164
|
+
n_air: int,
|
|
1165
|
+
n_sensors: int,
|
|
1166
|
+
n_relax: int,
|
|
1167
|
+
float_bytes: int,
|
|
1168
|
+
int_bytes: int,
|
|
1169
|
+
is_3d: bool,
|
|
1170
|
+
) -> int:
|
|
1171
|
+
"""Return estimated GPU bytes for relaxation (power-law) solver.
|
|
1172
|
+
|
|
1173
|
+
Parameters
|
|
1174
|
+
----------
|
|
1175
|
+
slab : int
|
|
1176
|
+
Grid points per GPU slab (local_depth * lateral).
|
|
1177
|
+
n_deriv_levels : int
|
|
1178
|
+
Number of derivative-map levels.
|
|
1179
|
+
n_sources : int
|
|
1180
|
+
Approximate source count on this GPU.
|
|
1181
|
+
n_source_timesteps : int
|
|
1182
|
+
Number of source time steps.
|
|
1183
|
+
save_gpu_memory : bool
|
|
1184
|
+
Whether memory-saving mode is active.
|
|
1185
|
+
n_air : int
|
|
1186
|
+
Number of zero-pressure (air) coordinates on this GPU.
|
|
1187
|
+
n_sensors : int
|
|
1188
|
+
Approximate sensor count on this GPU.
|
|
1189
|
+
n_relax : int
|
|
1190
|
+
Number of relaxation mechanisms.
|
|
1191
|
+
float_bytes : int
|
|
1192
|
+
Bytes per float (4).
|
|
1193
|
+
int_bytes : int
|
|
1194
|
+
Bytes per int (4).
|
|
1195
|
+
is_3d: bool,
|
|
1196
|
+
Whether the simulation is 3D (affects sensor memory).
|
|
1197
|
+
|
|
1198
|
+
Returns
|
|
1199
|
+
-------
|
|
1200
|
+
int
|
|
1201
|
+
Total estimated bytes.
|
|
1202
|
+
|
|
1203
|
+
"""
|
|
1204
|
+
fb = float_bytes
|
|
1205
|
+
ib = int_bytes
|
|
1206
|
+
ndim = 3 if is_3d else 2
|
|
1207
|
+
n_fields = 4 if is_3d else 3 # p, u, [v], w
|
|
1208
|
+
|
|
1209
|
+
# wave fields: n_fields pairs x 2 time levels
|
|
1210
|
+
mem = n_fields * 2 * slab * fb
|
|
1211
|
+
# relaxation psi:
|
|
1212
|
+
mem += 2 * (ndim * n_relax * 2 * slab * fb)
|
|
1213
|
+
# material: rho + K + beta
|
|
1214
|
+
mem += 3 * slab * fb
|
|
1215
|
+
# kappa: 2 arrays (kappa_x1, kappa_x2)
|
|
1216
|
+
mem += 2 * slab * fb
|
|
1217
|
+
# PML: pml_x1 + pml_x2, each has 2 * n_relax arrays
|
|
1218
|
+
mem += 2 * (2 * n_relax) * slab * fb
|
|
1219
|
+
# (dmap + dcmap)
|
|
1220
|
+
mem += 9 * 2 * n_deriv_levels * fb + slab * ib
|
|
1221
|
+
# source (icmat + coords)
|
|
1222
|
+
if n_sources > 0:
|
|
1223
|
+
mem += n_sources * fb if save_gpu_memory else n_sources * n_source_timesteps * fb
|
|
1224
|
+
mem += ndim * n_sources * ib
|
|
1225
|
+
|
|
1226
|
+
# air
|
|
1227
|
+
if n_air > 0:
|
|
1228
|
+
mem += ndim * n_air * ib
|
|
1229
|
+
# sensor
|
|
1230
|
+
if n_sensors > 0:
|
|
1231
|
+
mem += n_sensors * fb
|
|
1232
|
+
mem += (ndim + 1) * n_sensors * ib
|
|
1233
|
+
mem += n_sensors * ib
|
|
1234
|
+
return mem
|
|
1235
|
+
|
|
978
1236
|
def print_info(self) -> None:
|
|
979
1237
|
"""Print the Solver instance information."""
|
|
980
1238
|
print(str(self))
|
fullwave/solver/utils.py
CHANGED
|
@@ -17,10 +17,12 @@ def load_dat_data(dat_file_path: Path, dtype: DTypeLike = np.float32) -> NDArray
|
|
|
17
17
|
dat_file_path (Path): Path to the .dat file.
|
|
18
18
|
dtype: Data type to use when reading the file.
|
|
19
19
|
|
|
20
|
-
Raises
|
|
20
|
+
Raises
|
|
21
|
+
------
|
|
21
22
|
ValueError: if dat_file_path does not exist.
|
|
22
23
|
|
|
23
|
-
Returns
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
24
26
|
NDArray[np.float64]: Array of data read from the file.
|
|
25
27
|
|
|
26
28
|
"""
|
|
@@ -58,7 +60,8 @@ def load_dat_and_reshape(
|
|
|
58
60
|
n_sensors: Number of sensors
|
|
59
61
|
dtype: Data type to use when reading the file.
|
|
60
62
|
|
|
61
|
-
Returns
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
62
65
|
NDArray[np.float64]: Array of data read from the file.
|
|
63
66
|
|
|
64
67
|
"""
|
|
@@ -88,7 +91,8 @@ def initialize_relaxation_param_dict(
|
|
|
88
91
|
) -> dict[str, NDArray[np.float64]]:
|
|
89
92
|
"""Initialize a dictionary with relaxation parameters.
|
|
90
93
|
|
|
91
|
-
Returns
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
92
96
|
dict[str, NDArray[np.float64]]: Dictionary of relaxation parameters.
|
|
93
97
|
|
|
94
98
|
"""
|
|
@@ -125,10 +129,12 @@ def load_data_with_time_step(
|
|
|
125
129
|
dtype: Data type to use when reading the file.
|
|
126
130
|
time_step: Time step index to load.
|
|
127
131
|
|
|
128
|
-
Returns
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
129
134
|
NDArray[np.float64]: Array of data read from the file.
|
|
130
135
|
|
|
131
|
-
Raises
|
|
136
|
+
Raises
|
|
137
|
+
------
|
|
132
138
|
ValueError: if file_path does not exist.
|
|
133
139
|
|
|
134
140
|
"""
|
|
@@ -159,10 +165,12 @@ def load_data_with_sensor_index(
|
|
|
159
165
|
sensor_index: Sensor index to load.
|
|
160
166
|
dtype: Data type to use when reading the file.
|
|
161
167
|
|
|
162
|
-
Returns
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
163
170
|
NDArray[np.float64]: Array of data read from the file.
|
|
164
171
|
|
|
165
|
-
Raises
|
|
172
|
+
Raises
|
|
173
|
+
------
|
|
166
174
|
ValueError: if file_path does not exist.
|
|
167
175
|
|
|
168
176
|
"""
|
fullwave/source.py
CHANGED
|
@@ -30,7 +30,7 @@ class Source:
|
|
|
30
30
|
w0: NDArray[np.float64] | None = None
|
|
31
31
|
incoords_w: NDArray[np.int64] | None = None
|
|
32
32
|
|
|
33
|
-
def __init__( # noqa:
|
|
33
|
+
def __init__( # noqa: PLR0912
|
|
34
34
|
self,
|
|
35
35
|
p0: NDArray[np.float64] | None = None,
|
|
36
36
|
mask: NDArray[np.bool] | None = None,
|
fullwave/transducer.py
CHANGED
|
@@ -22,7 +22,8 @@ logger = logging.getLogger("__main__." + __name__)
|
|
|
22
22
|
def _make_pos_int(val: float | tuple[float] | tuple[int]) -> NDArray[np.int64]:
|
|
23
23
|
"""Force value to be a positive integer.
|
|
24
24
|
|
|
25
|
-
Returns
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
26
27
|
NDArray[np.int64]: Array with positive integers.
|
|
27
28
|
|
|
28
29
|
"""
|
|
@@ -202,7 +203,7 @@ class TransducerGeometry:
|
|
|
202
203
|
) = self._create_element_coords()
|
|
203
204
|
logger.debug("TransducerGeometry instance created.")
|
|
204
205
|
|
|
205
|
-
def _init_dimensions( # noqa:
|
|
206
|
+
def _init_dimensions( # noqa: PLR0912
|
|
206
207
|
self,
|
|
207
208
|
grid: Grid,
|
|
208
209
|
element_width_px: int | None,
|
|
@@ -313,7 +314,7 @@ class TransducerGeometry:
|
|
|
313
314
|
assert len(position_m) == 3, "position_m must have 3 elements for 3D transducer"
|
|
314
315
|
return position_px, position_m
|
|
315
316
|
|
|
316
|
-
def _create_element_coords( # noqa: PLR0912
|
|
317
|
+
def _create_element_coords( # noqa: PLR0912
|
|
317
318
|
self,
|
|
318
319
|
) -> tuple[NDArray[np.int64], NDArray[np.int64], NDArray[np.int64], NDArray[np.int64]]:
|
|
319
320
|
"""Build flat coordinate arrays for source and sensor pixels.
|
|
@@ -813,15 +814,15 @@ class Transducer:
|
|
|
813
814
|
def source_coords(self) -> NDArray[np.int64]:
|
|
814
815
|
"""Coordinates of active source pixels; shape [N_src, ndim]."""
|
|
815
816
|
active_ids = np.where(self.active_source_elements)[0] + 1
|
|
816
|
-
mask = np.isin(self.transducer_geometry._source_ids, active_ids)
|
|
817
|
-
return self.transducer_geometry._source_coords[mask]
|
|
817
|
+
mask = np.isin(self.transducer_geometry._source_ids, active_ids)
|
|
818
|
+
return self.transducer_geometry._source_coords[mask]
|
|
818
819
|
|
|
819
820
|
@property
|
|
820
821
|
def sensor_coords(self) -> NDArray[np.int64]:
|
|
821
822
|
"""Coordinates of active sensor pixels; shape [N_snsr, ndim]."""
|
|
822
823
|
active_ids = np.where(self.active_sensor_elements)[0] + 1
|
|
823
|
-
mask = np.isin(self.transducer_geometry._sensor_ids, active_ids)
|
|
824
|
-
return self.transducer_geometry._sensor_coords[mask]
|
|
824
|
+
mask = np.isin(self.transducer_geometry._sensor_ids, active_ids)
|
|
825
|
+
return self.transducer_geometry._sensor_coords[mask]
|
|
825
826
|
|
|
826
827
|
@property
|
|
827
828
|
def element_id_to_element_surface(self) -> dict[int, NDArray[np.int64]]:
|
|
@@ -986,8 +987,8 @@ class Transducer:
|
|
|
986
987
|
@property
|
|
987
988
|
def element_id_to_element_center(self) -> dict[int, NDArray[np.int64]]:
|
|
988
989
|
"""Return the dictionary mapping element IDs to their center coordinates."""
|
|
989
|
-
coords = self.transducer_geometry._source_coords
|
|
990
|
-
ids = self.transducer_geometry._source_ids
|
|
990
|
+
coords = self.transducer_geometry._source_coords
|
|
991
|
+
ids = self.transducer_geometry._source_ids
|
|
991
992
|
n = self.transducer_geometry.number_elements
|
|
992
993
|
ndim = coords.shape[1] if len(coords) else (3 if self.is_3d else 2)
|
|
993
994
|
out: dict[int, NDArray[np.int64]] = {}
|
|
@@ -1049,7 +1050,7 @@ class Transducer:
|
|
|
1049
1050
|
|
|
1050
1051
|
it plots whole transducer geometry including the inactive/active source and sensor elements.
|
|
1051
1052
|
"""
|
|
1052
|
-
import matplotlib.pyplot as plt
|
|
1053
|
+
import matplotlib.pyplot as plt # noqa: PLC0415
|
|
1053
1054
|
|
|
1054
1055
|
fig, ax = plt.subplots(1, 1, figsize=(10, 10))
|
|
1055
1056
|
plot_mask = np.zeros(self.transducer_geometry.stored_grid_size)
|
|
@@ -1089,7 +1090,7 @@ class Transducer:
|
|
|
1089
1090
|
|
|
1090
1091
|
it plots whole transducer geometry including the inactive/active source and sensor elements.
|
|
1091
1092
|
"""
|
|
1092
|
-
import matplotlib.pyplot as plt
|
|
1093
|
+
import matplotlib.pyplot as plt # noqa: PLC0415
|
|
1093
1094
|
|
|
1094
1095
|
fig, ax = plt.subplots(1, 1, figsize=(10, 10))
|
|
1095
1096
|
plot_mask = np.zeros(self.transducer_geometry.stored_grid_size)
|
|
@@ -7,7 +7,8 @@ from typing import Any
|
|
|
7
7
|
def check_instance(target_var: Any, instances: list[Any] | Any) -> None: # noqa: ANN401
|
|
8
8
|
"""Check whether target_var is an instance of the specified type.
|
|
9
9
|
|
|
10
|
-
Raises
|
|
10
|
+
Raises
|
|
11
|
+
------
|
|
11
12
|
TypeError: If target_var is not an instance of instance.
|
|
12
13
|
|
|
13
14
|
"""
|
|
@@ -21,7 +22,8 @@ def check_instance(target_var: Any, instances: list[Any] | Any) -> None: # noqa
|
|
|
21
22
|
def check_path_exists(target_path: Path) -> None:
|
|
22
23
|
"""Check whether the provided target_path exists.
|
|
23
24
|
|
|
24
|
-
Raises
|
|
25
|
+
Raises
|
|
26
|
+
------
|
|
25
27
|
ValueError: If target_path does not exist.
|
|
26
28
|
|
|
27
29
|
"""
|
|
@@ -37,7 +39,8 @@ def check_compatible_value(
|
|
|
37
39
|
) -> None:
|
|
38
40
|
"""Check whether the provided value is in the list of compatible values.
|
|
39
41
|
|
|
40
|
-
Raises
|
|
42
|
+
Raises
|
|
43
|
+
------
|
|
41
44
|
ValueError: If value is not in compatible_values.
|
|
42
45
|
|
|
43
46
|
"""
|
fullwave/utils/coordinates.py
CHANGED
|
@@ -16,7 +16,8 @@ def make_circle_idx(
|
|
|
16
16
|
cen: The center of the circle.
|
|
17
17
|
rad: The radius of the circle.
|
|
18
18
|
|
|
19
|
-
Returns
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
20
21
|
mask: The mask of the circle.
|
|
21
22
|
|
|
22
23
|
"""
|
|
@@ -32,7 +33,8 @@ def map_to_coords(
|
|
|
32
33
|
) -> NDArray[np.int64]:
|
|
33
34
|
"""Map the mask map to coordinates.
|
|
34
35
|
|
|
35
|
-
Returns
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
36
38
|
NDArray[np.int64]: An array of coordinates corresponding to non-zero elements in the mask.
|
|
37
39
|
|
|
38
40
|
"""
|
|
@@ -103,7 +105,8 @@ def map_to_coords_with_sort(map_data: NDArray[np.int64]) -> NDArray[np.int64]:
|
|
|
103
105
|
Args:
|
|
104
106
|
map_data: The mask map.
|
|
105
107
|
|
|
106
|
-
Returns
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
107
110
|
NDArray[np.int64]: An array of coordinates corresponding to non-zero elements in the mask.
|
|
108
111
|
|
|
109
112
|
"""
|
|
@@ -124,7 +127,8 @@ def map_to_coordinates(
|
|
|
124
127
|
is_3d: Whether the grid is 3D or not.
|
|
125
128
|
sort: Whether to sort the coordinates by the first dimension.
|
|
126
129
|
|
|
127
|
-
Returns
|
|
130
|
+
Returns
|
|
131
|
+
-------
|
|
128
132
|
NDArray[np.int64]: An array of coordinates corresponding to non-zero elements in the mask.
|
|
129
133
|
|
|
130
134
|
"""
|
|
@@ -31,7 +31,7 @@ class MemoryTempfile:
|
|
|
31
31
|
and create temporary files and directories.
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
def __init__( # noqa:
|
|
34
|
+
def __init__( # noqa: PLR0912
|
|
35
35
|
self,
|
|
36
36
|
*,
|
|
37
37
|
preferred_paths: list | None = None,
|
|
@@ -182,7 +182,7 @@ class MemoryTempfile:
|
|
|
182
182
|
self,
|
|
183
183
|
suffix: str | None = None,
|
|
184
184
|
prefix: str | None = None,
|
|
185
|
-
dir: str | None = None,
|
|
185
|
+
dir: str | None = None,
|
|
186
186
|
) -> str:
|
|
187
187
|
"""Create a temporary directory.
|
|
188
188
|
|
|
@@ -207,7 +207,7 @@ class MemoryTempfile:
|
|
|
207
207
|
self,
|
|
208
208
|
suffix: str | None = None,
|
|
209
209
|
prefix: str | None = None,
|
|
210
|
-
dir: str | None = None,
|
|
210
|
+
dir: str | None = None,
|
|
211
211
|
*,
|
|
212
212
|
text: bool = False,
|
|
213
213
|
) -> tuple[int, str]:
|
|
@@ -241,7 +241,7 @@ class MemoryTempfile:
|
|
|
241
241
|
self,
|
|
242
242
|
suffix: str | None = None,
|
|
243
243
|
prefix: str | None = None,
|
|
244
|
-
dir: str | None = None,
|
|
244
|
+
dir: str | None = None,
|
|
245
245
|
) -> tempfile.TemporaryDirectory[str]:
|
|
246
246
|
"""Create a temporary directory and return a TemporaryDirectory object.
|
|
247
247
|
|
|
@@ -275,7 +275,7 @@ class MemoryTempfile:
|
|
|
275
275
|
newline: str | None = None,
|
|
276
276
|
suffix: str | None = None,
|
|
277
277
|
prefix: str | None = None,
|
|
278
|
-
dir: str | None = None,
|
|
278
|
+
dir: str | None = None,
|
|
279
279
|
) -> tempfile.SpooledTemporaryFile:
|
|
280
280
|
"""Create a spooled temporary file.
|
|
281
281
|
|
|
@@ -329,7 +329,7 @@ class MemoryTempfile:
|
|
|
329
329
|
newline: str | None = None,
|
|
330
330
|
suffix: str | None = None,
|
|
331
331
|
prefix: str | None = None,
|
|
332
|
-
dir: str | None = None,
|
|
332
|
+
dir: str | None = None,
|
|
333
333
|
*,
|
|
334
334
|
delete: bool = True,
|
|
335
335
|
) -> tempfile.NamedTemporaryFile:
|
|
@@ -379,7 +379,7 @@ class MemoryTempfile:
|
|
|
379
379
|
newline: str | None = None,
|
|
380
380
|
suffix: str | None = None,
|
|
381
381
|
prefix: str | None = None,
|
|
382
|
-
dir: str | None = None,
|
|
382
|
+
dir: str | None = None,
|
|
383
383
|
) -> tempfile.TemporaryFile:
|
|
384
384
|
"""Create and return a temporary file.
|
|
385
385
|
|
fullwave/utils/plot_utils.py
CHANGED
|
@@ -13,7 +13,7 @@ from numpy.typing import NDArray
|
|
|
13
13
|
from tqdm import tqdm
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def plot_array( # noqa:
|
|
16
|
+
def plot_array( # noqa: PLR0912
|
|
17
17
|
x: NDArray[np.float64 | np.int64 | np.bool],
|
|
18
18
|
aspect: float | None = None,
|
|
19
19
|
vmin: float | None = None,
|
|
@@ -553,7 +553,7 @@ def plot_wave_propagation_animation(
|
|
|
553
553
|
animation_data.save(export_name, writer="ffmpeg", dpi=dpi)
|
|
554
554
|
|
|
555
555
|
|
|
556
|
-
def plot_wave_propagation_with_map(
|
|
556
|
+
def plot_wave_propagation_with_map(
|
|
557
557
|
propagation_map: NDArray[np.float64],
|
|
558
558
|
c_map: NDArray[np.float64],
|
|
559
559
|
rho_map: NDArray[np.float64],
|
|
@@ -868,7 +868,7 @@ def plot_wave_propagation_with_map( # noqa: PLR0915, C901
|
|
|
868
868
|
plt.close("all")
|
|
869
869
|
|
|
870
870
|
|
|
871
|
-
def plot_wave_propagation_snapshot(
|
|
871
|
+
def plot_wave_propagation_snapshot(
|
|
872
872
|
propagation_map: NDArray[np.float64],
|
|
873
873
|
c_map: NDArray[np.float64],
|
|
874
874
|
rho_map: NDArray[np.float64],
|
fullwave/utils/signal_filter.py
CHANGED
|
@@ -25,7 +25,7 @@ def _check_cupy() -> bool:
|
|
|
25
25
|
global _CUPY_AVAILABLE # noqa: PLW0603
|
|
26
26
|
if _CUPY_AVAILABLE is None:
|
|
27
27
|
try:
|
|
28
|
-
import cupy # noqa: F401
|
|
28
|
+
import cupy # noqa: F401, PLC0415
|
|
29
29
|
|
|
30
30
|
_CUPY_AVAILABLE = True
|
|
31
31
|
except ImportError:
|
|
@@ -145,7 +145,7 @@ def apply_filter(
|
|
|
145
145
|
)
|
|
146
146
|
|
|
147
147
|
if use_gpu and _check_cupy():
|
|
148
|
-
import cupy as cp
|
|
148
|
+
import cupy as cp # noqa: PLC0415
|
|
149
149
|
|
|
150
150
|
logger.debug("apply_filter: using CuPy GPU backend")
|
|
151
151
|
data_gpu = cp.asarray(data, dtype=cp.float64)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fullwave25
|
|
3
|
-
Version: 1.2.6.
|
|
3
|
+
Version: 1.2.6.dev4
|
|
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
|
|
@@ -13,7 +13,6 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
|
-
Requires-Dist: joblib>=1.5.3
|
|
17
16
|
Requires-Dist: matplotlib>=3.10.7
|
|
18
17
|
Requires-Dist: numba>=0.63.1
|
|
19
18
|
Requires-Dist: numexpr>=2.14.1
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
fullwave/__init__.py,sha256=
|
|
1
|
+
fullwave/__init__.py,sha256=Wb8_IQQeLRrptNyonXRvriurzqUtnqV92_E4kr3MU4c,1780
|
|
2
2
|
fullwave/grid.py,sha256=YbxAAgdYKR8AXwobtTZzHm9C4KR4D5--51zgbs0aQGY,7435
|
|
3
|
-
fullwave/medium.py,sha256=
|
|
4
|
-
fullwave/sensor.py,sha256=
|
|
5
|
-
fullwave/source.py,sha256=
|
|
6
|
-
fullwave/transducer.py,sha256=
|
|
3
|
+
fullwave/medium.py,sha256=A3EoRNs1CM9gB2MISWp5n0ikRDEk9uQqEO6YSdp12jQ,48360
|
|
4
|
+
fullwave/sensor.py,sha256=McHyaSKxM11_Kfb_2hfnOtV9Z1UMBCLkeovncLT8_bA,9308
|
|
5
|
+
fullwave/source.py,sha256=gFitSme70CHecVVik31_Fv7Md7PEZ_4zGsKYohDivz4,18745
|
|
6
|
+
fullwave/transducer.py,sha256=uC9EcKJVpP9gTqKKLrq30sKizT1fhaRVDQcAuhuS9RI,48526
|
|
7
7
|
fullwave/beamformer/__init__.py,sha256=tNPq_5lfLXfAdueyfQtdTxLTVEV6nEDkeSGAeTf7Q5s,88
|
|
8
|
-
fullwave/beamformer/beamformer.py,sha256=
|
|
8
|
+
fullwave/beamformer/beamformer.py,sha256=0jE_B5UlxDDBsUcQSHa5d1q3uSTSCyqgNiUJrU10juI,5601
|
|
9
9
|
fullwave/constants/__init__.py,sha256=WOmkhLsSe86D71gwKsa4Tz8QPeOdayLGgvBCh7UEOPk,104
|
|
10
10
|
fullwave/constants/material_properties.py,sha256=SouMKD4ONzYl0VU8ZsC2I_85y-ZLj9scRNwAArCD7bg,2729
|
|
11
11
|
fullwave/medium_builder/__init__.py,sha256=QVz0sA4niq51O94RnXUVlHutx7FYEIa1TRcR5fDc_Ps,201
|
|
@@ -21,12 +21,12 @@ fullwave/medium_builder/presets/data/.keep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
|
|
|
21
21
|
fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat,sha256=N3JFFxc9HW1S-NaTPcPlFgXWGIzlrr9X40JbDapTo4g,67348
|
|
22
22
|
fullwave/solver/__init__.py,sha256=E0Jg5akBpicqTjku1puw9rAIoKiw7TwtYNDPiv8G5IY,30
|
|
23
23
|
fullwave/solver/binary_manager.py,sha256=oz3WLUX2m0HHXCVaI8tBokDyHEUZcERzdCJWErE6Ig8,5011
|
|
24
|
-
fullwave/solver/cuda_utils.py,sha256=
|
|
24
|
+
fullwave/solver/cuda_utils.py,sha256=n7p3TJYbLAXmIzSMS5Q_8m4OWg5U9VG5_3hAxa0uTYI,11407
|
|
25
25
|
fullwave/solver/input_file_writer.py,sha256=7wE86-ZnxwLhRw2adXUC8yAB3p9iH92E0t0Ew8q_lDQ,44617
|
|
26
|
-
fullwave/solver/launcher.py,sha256=
|
|
27
|
-
fullwave/solver/pml_builder.py,sha256=
|
|
28
|
-
fullwave/solver/solver.py,sha256=
|
|
29
|
-
fullwave/solver/utils.py,sha256=
|
|
26
|
+
fullwave/solver/launcher.py,sha256=zh-3HY4iKGmjreALu9WczDpWX3d74nOcIns9xVvnUIg,10531
|
|
27
|
+
fullwave/solver/pml_builder.py,sha256=gtkZjXG8ujvC0HMFjJ9RLaURQqjZKelLsj6FNE35P5k,70706
|
|
28
|
+
fullwave/solver/solver.py,sha256=Ziz7fOF_tq7ygv5MRhc2zULexcFK3Ft-raZl6JvwEcA,49836
|
|
29
|
+
fullwave/solver/utils.py,sha256=vM8Nwe4JFscb1hpkGoQHydsxC5_Xt93XQMmEOk5hVFg,5474
|
|
30
30
|
fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118,sha256=bIzyHFzr_bsIBSlCcRA3M9LlTSRrBVn6ASJHyozvcwU,1245432
|
|
31
31
|
fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124,sha256=NiYCmOzZIcvAzR7-Mjs3PtUzZGd31jSVQB1IT9nQrLU,1416160
|
|
32
32
|
fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129,sha256=TkyC8OqvFzRoSa_0XRWPmnlDBjPf8tG5NJaGQVFy_PY,1779992
|
|
@@ -37,17 +37,17 @@ fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129,
|
|
|
37
37
|
fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130,sha256=8hzQfyodLl070a7nM-QCmv7ygijLMgRNvZxNOisRYSA,1571848
|
|
38
38
|
fullwave/solver/bins/database/relaxation_params_database_num_relax=2_20260113_0957.mat,sha256=Fei5ie9wgAAN43pIdSFf6xVaPPDgOaBBZodi3qK6WtQ,168056
|
|
39
39
|
fullwave/utils/__init__.py,sha256=yz_pbPte2XrSofb16mdqLmUxr2rXUE7FIzOjCT9y1IE,461
|
|
40
|
-
fullwave/utils/check_functions.py,sha256=
|
|
41
|
-
fullwave/utils/coordinates.py,sha256=
|
|
42
|
-
fullwave/utils/memory_tempfile.py,sha256=
|
|
40
|
+
fullwave/utils/check_functions.py,sha256=benZqFjOQF7aaQDTBGaOq-eplJ-dC8Dz4jcqPE-9HSk,1514
|
|
41
|
+
fullwave/utils/coordinates.py,sha256=TEVQE9JXUIVFoKEyg8ZZMeGh31elbpecHnDgbljHQ14,4402
|
|
42
|
+
fullwave/utils/memory_tempfile.py,sha256=BzMRNvINzLYdtV8NcSNjrTr2F9Qow8vYl1o7RUXFWH8,14350
|
|
43
43
|
fullwave/utils/numerical.py,sha256=khdi2KE3y_Ky9cEnmGXvVHjeYuKfb-8gQTV1a8nx9uA,3260
|
|
44
|
-
fullwave/utils/plot_utils.py,sha256=
|
|
44
|
+
fullwave/utils/plot_utils.py,sha256=wXR6YMnlO0tCUeKoAELKRyi5K_kepKIBqLjlFSRKito,37205
|
|
45
45
|
fullwave/utils/pulse.py,sha256=aqnCdBxivACouIGlot1aE2k4V9nctUxNCEPzdBpsupg,2811
|
|
46
46
|
fullwave/utils/relaxation_parameters.py,sha256=DEHjr67eHGR-DqEaNsQViokseIsDywtjBjB1DvF4-OM,14106
|
|
47
47
|
fullwave/utils/scatterer.py,sha256=CLqD085f9pqX4cF1YiT2IkzT5P0o1xp45Do7lf5BLnM,24049
|
|
48
|
-
fullwave/utils/signal_filter.py,sha256=
|
|
48
|
+
fullwave/utils/signal_filter.py,sha256=_Tf42aBygGtIUrcSPybYqvZoAW2o_4dd-hHTEvZ8--E,5219
|
|
49
49
|
fullwave/utils/signal_process.py,sha256=MP38r37JSPHN4sT-lIReXS5BT2GT_tkRxD0Y1wQ-lNs,5153
|
|
50
|
-
fullwave25-1.2.6.
|
|
51
|
-
fullwave25-1.2.6.
|
|
52
|
-
fullwave25-1.2.6.
|
|
53
|
-
fullwave25-1.2.6.
|
|
50
|
+
fullwave25-1.2.6.dev4.dist-info/METADATA,sha256=b2tSzbymlgrVigxYrdeWk8pvQ31Tzv9ZIGTQlNWW4Ac,18998
|
|
51
|
+
fullwave25-1.2.6.dev4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
52
|
+
fullwave25-1.2.6.dev4.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
53
|
+
fullwave25-1.2.6.dev4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|