fullwave25 1.4.2.dev0__tar.gz → 1.4.2.dev2__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 (414) hide show
  1. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.bumpversion.toml +1 -1
  2. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/PKG-INFO +58 -3
  3. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/README.md +56 -1
  4. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/__init__.py +1 -1
  5. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium.py +1 -3
  6. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/binary_manager.py +27 -30
  7. fullwave25-1.4.2.dev2/fullwave/solver/binary_markers.py +87 -0
  8. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/input_file_writer.py +26 -7
  9. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/launcher.py +1 -2
  10. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/solver.py +189 -93
  11. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/source_type.py +16 -12
  12. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/source.py +9 -2
  13. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/transducer.py +24 -19
  14. fullwave25-1.4.2.dev2/fullwave/ultra/__init__.py +15 -0
  15. fullwave25-1.4.2.dev2/fullwave/ultra/backend.py +497 -0
  16. fullwave25-1.4.2.dev2/fullwave/ultra/backend_2d.py +569 -0
  17. fullwave25-1.4.2.dev2/fullwave/ultra/binary.py +158 -0
  18. fullwave25-1.4.2.dev2/fullwave/ultra/dat_io.py +60 -0
  19. fullwave25-1.4.2.dev2/fullwave/ultra/dat_io_3d.py +38 -0
  20. fullwave25-1.4.2.dev2/fullwave/ultra/errors.py +22 -0
  21. fullwave25-1.4.2.dev2/fullwave/ultra/factory.py +21 -0
  22. fullwave25-1.4.2.dev2/fullwave/ultra/medium_to_aexp.py +50 -0
  23. fullwave25-1.4.2.dev2/fullwave/ultra/stencil.py +162 -0
  24. fullwave25-1.4.2.dev2/fullwave/ultra/time_axis.py +61 -0
  25. fullwave25-1.4.2.dev2/fullwave/ultra/writer_2d.py +215 -0
  26. fullwave25-1.4.2.dev2/fullwave/ultra/writer_3d.py +199 -0
  27. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/__init__.py +2 -1
  28. fullwave25-1.4.2.dev2/fullwave/utils/gpu_memory.py +109 -0
  29. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/memory_tempfile.py +21 -0
  30. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/pyproject.toml +2 -2
  31. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/uv.lock +553 -399
  32. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/.gitignore +0 -0
  33. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260911_1813_dead-code.md +0 -0
  34. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_1311_commit_message_of_the_input_generation_speedup.md +0 -0
  35. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_1311_pull_request_of_the_input_generation_speedup.md +0 -0
  36. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_1405_commit_message_of_the_relaxation_memory_estimate.md +0 -0
  37. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_1405_pull_request_of_the_relaxation_memory_estimate.md +0 -0
  38. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_2152_commit_message_of_the_cuda_version_choice.md +0 -0
  39. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_2152_pull_request_of_the_cuda_version_choice.md +0 -0
  40. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_2203_commit_message_of_the_cuda_version_tests.md +0 -0
  41. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_2213_commit_message_of_the_blackwell_version_choice.md +0 -0
  42. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/20260916_2213_pull_request_of_the_blackwell_version_choice.md +0 -0
  43. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/CLAUDE.md +0 -0
  44. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_1844_acquire_the_reflection_matrix.py +0 -0
  45. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_1900_test_on_a_synthetic_acquisition.py +0 -0
  46. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_1913_analyze_the_reflection_matrix.py +0 -0
  47. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_2107_redraw_the_figures_of_an_analysis.py +0 -0
  48. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_2121_write_the_result_tables.py +0 -0
  49. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1126_synthesize_plane_waves_from_the_multistatic_matrix.py +0 -0
  50. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1137_scan_the_speed_of_sound.py +0 -0
  51. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1141_compare_the_laws_with_the_truth.py +0 -0
  52. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1146_evaluate_the_reverberation_filter.py +0 -0
  53. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1208_compare_plane_waves_with_the_synthesis.py +0 -0
  54. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/figures.py +0 -0
  55. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/ground_truth.py +0 -0
  56. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/matrix_imaging.py +0 -0
  57. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/pipeline.py +0 -0
  58. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/reflection_matrix.py +0 -0
  59. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/speed_of_sound.py +0 -0
  60. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/synthetic.py +0 -0
  61. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_0206_band_anchor_cross_check.py +0 -0
  62. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_0233_delivered_power_law_end_to_end.py +0 -0
  63. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_0317_reword_deliver_in_the_library.py +0 -0
  64. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_1220_relaxation_low_frequency_rolloff.py +0 -0
  65. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260825_1937_what_fails_the_pml_golden_tests.py +0 -0
  66. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260825_2329_does_the_wrapper_read_the_record.py +0 -0
  67. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260826_0002_what_the_new_default_table_holds.py +0 -0
  68. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1422_what_the_candidate_tables_hold.py +0 -0
  69. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1427_what_the_deployment_needs.py +0 -0
  70. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1510_where_the_unstretched_ramp_reaches.py +0 -0
  71. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1517_the_blast_radius_of_the_ramp.py +0 -0
  72. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1458_the_3d_region_trimmed_kernel_against_the_reference.py +0 -0
  73. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1505_the_multi_node_kernel_against_the_multi_gpu_one.py +0 -0
  74. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1631_the_3d_multi_node_against_the_multi_gpu_one.py +0 -0
  75. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1642_the_selective_absorbing_layer.py +0 -0
  76. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1728_the_layer_against_the_taper.py +0 -0
  77. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1757_what_the_margin_outside_the_layer_does.py +0 -0
  78. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1808_the_layer_in_3d_and_on_the_multi_node_builds.py +0 -0
  79. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1832_where_the_3d_residual_sits.py +0 -0
  80. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1837_inside_the_layer_at_the_corner.py +0 -0
  81. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1840_inside_the_3d_layer_at_the_corner.py +0 -0
  82. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1912_both_absorbers_on_one_method.py +0 -0
  83. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1922_the_layer_on_the_reflection_method.py +0 -0
  84. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2011_whole_domain_animation.py +0 -0
  85. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2032_the_example_source_kind.py +0 -0
  86. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2148_drive_scale_of_the_strong_beta_cells.py +0 -0
  87. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2159_profile_the_input_map_build.py +0 -0
  88. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2201_build_then_extend_equivalence.py +0 -0
  89. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2304_the_transmit_methods_launch_what_they_say.py +0 -0
  90. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2322_the_unscaled_added_drive_follows_the_courant_number.py +0 -0
  91. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0033_the_three_dimensional_arrays.py +0 -0
  92. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0054_the_elevation_lens_of_a_linear_array.py +0 -0
  93. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0115_run_every_example.sh +0 -0
  94. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0124_move_the_notebooks_to_the_transmit_interface.py +0 -0
  95. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0137_the_air_region_at_four_mechanisms.py +0 -0
  96. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0148_the_element_records_its_own_transmit.py +0 -0
  97. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0150_the_absorbing_layer_of_a_point_source.py +0 -0
  98. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0152_the_exponential_absorbing_layer_against_its_thickness.py +0 -0
  99. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0202_the_rebuilt_exponential_absorbing_layer.py +0 -0
  100. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0216_where_the_three_dimensional_layer_leaks.py +0 -0
  101. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0222_the_absorbing_layer_away_from_the_source.py +0 -0
  102. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1037_where_the_near_field_brightness_comes_from.py +0 -0
  103. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1040_the_aperture_transit_wedge_in_the_channel_data.py +0 -0
  104. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1043_the_transmit_in_the_recorded_trace_and_its_removal.py +0 -0
  105. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1048_the_receive_row_against_the_reference_subtraction.py +0 -0
  106. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1052_the_backing_behind_the_array_face.py +0 -0
  107. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1056_the_transmit_beam_with_the_air_backing.py +0 -0
  108. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1105_the_shipped_transducer_stack_in_the_solver.py +0 -0
  109. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1119_where_the_stack_puts_the_source_and_what_it_costs_the_depth.py +0 -0
  110. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1121_the_depth_the_image_reads_with_the_stack.py +0 -0
  111. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1123_the_depth_the_beamformer_puts_one_point_at.py +0 -0
  112. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1142_the_transmit_offset_the_beamformer_needs.py +0 -0
  113. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1145_the_depth_shift_the_offset_fix_makes.py +0 -0
  114. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1154_the_two_offset_rules_on_the_same_recording.py +0 -0
  115. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1212_what_the_pinned_release_carries.py +0 -0
  116. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1228_the_low_cut_against_the_near_field_haze.py +0 -0
  117. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1301_run_the_beamforming_notebooks.py +0 -0
  118. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1432_point_dataset_generator_at_the_local_fullwave.py +0 -0
  119. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1437_the_aperture_width_the_reference_geometry_reports.py +0 -0
  120. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1454_calibrate_the_ats539_plane_wave.py +0 -0
  121. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1508_show_the_b_mode_in_the_hdf5.py +0 -0
  122. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1534_the_comet_behind_each_wire.py +0 -0
  123. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1547_read_the_calibration_trials.py +0 -0
  124. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1605_what_the_medium_holds_in_the_near_field.py +0 -0
  125. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1607_sweep_one_generator_knob.py +0 -0
  126. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1715_assert_the_ats539_rate_chain.py +0 -0
  127. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1717_measure_every_layer_of_the_stack.py +0 -0
  128. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1720_where_the_trailing_energy_lands.py +0 -0
  129. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1725_offer_the_requested_absorption_to_the_backing.py +0 -0
  130. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1727_let_a_sweep_carry_a_switch.py +0 -0
  131. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1731_expose_the_exponential_absorbing_layer.py +0 -0
  132. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1746_point_the_solver_at_an_older_binary.py +0 -0
  133. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1756_measure_the_point_targets.py +0 -0
  134. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1802_rederive_the_near_field_bounce.py +0 -0
  135. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1810_does_the_shelf_move_with_depth.py +0 -0
  136. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1812_find_the_repeat_delay_in_the_raw_rf.py +0 -0
  137. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1937_give_each_source_row_its_own_launch_delay.py +0 -0
  138. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1943_baffle_the_element_plane.py +0 -0
  139. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1952_take_the_cell_size_from_the_grid.py +0 -0
  140. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2058_run_the_ats539_through_the_batched_solver.py +0 -0
  141. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2105_queue_the_remaining_candidates.py +0 -0
  142. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2122_the_simulator_asks_for_a_clamped_source.py +0 -0
  143. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2126_rename_the_source_types_to_hard_and_soft.py +0 -0
  144. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2140_bind_the_source_type_to_its_entrance.py +0 -0
  145. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2225_how_redundant_are_the_absorbing_layer_files.py +0 -0
  146. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2239_skip_the_constant_absorbing_layer_maps.py +0 -0
  147. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2246_count_the_files_a_run_writes.py +0 -0
  148. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2352_run_the_map_tiers_end_to_end.py +0 -0
  149. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2355_draw_the_absorbing_layer_map_cost.py +0 -0
  150. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1502_can_the_transmit_reach_the_harmonic_band.py +0 -0
  151. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1504_contrast_harmonic_imaging.py +0 -0
  152. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1507_where_each_band_puts_its_largest_sample.py +0 -0
  153. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1519_is_the_harmonic_tail_cumulative.py +0 -0
  154. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1537_does_the_cancellation_work.py +0 -0
  155. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1612_does_a_sparse_bubble_cloud_localize.py +0 -0
  156. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1619_calibrate_the_bubble_scatter_range.py +0 -0
  157. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1622_draw_the_sweep_b_modes.py +0 -0
  158. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1654_where_the_bright_region_sits.py +0 -0
  159. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1701_where_one_bubble_images.py +0 -0
  160. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1702_does_the_portable_example_reproduce_the_evaluation.py +0 -0
  161. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1753_does_the_ported_solver_still_march_the_same.py +0 -0
  162. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1755_do_the_ranks_agree_on_the_bubbles.py +0 -0
  163. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1817_does_the_air_region_reach_every_solver.py +0 -0
  164. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1818_does_the_air_region_reach_every_rank.py +0 -0
  165. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1317_what_the_abdomen_volume_holds.py +0 -0
  166. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1319_art_wave_in_the_abdomen.py +0 -0
  167. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1324_art_figures_from_the_field.py +0 -0
  168. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1744_art_final_animations.py +0 -0
  169. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260904_1216_art_wire_visibility.py +0 -0
  170. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260904_2327_b_mode_of_the_abdomen.py +0 -0
  171. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260905_0038_two_against_three_dimensions.py +0 -0
  172. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_1934_probe_the_reverberation_filter_on_speckle.py +0 -0
  173. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_1939_probe_the_ideal_profile_on_speckle.py +0 -0
  174. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_2044_probe_the_correction_bases_on_a_flat_speckle.py +0 -0
  175. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_2342_measure_the_wall_delay_screen.py +0 -0
  176. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1134_find_the_first_non_finite_value_of_the_plane_wave_correction.py +0 -0
  177. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1234_print_the_summaries_of_analyses.py +0 -0
  178. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/a_maps_checks.py +0 -0
  179. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/b_effective_frequency.py +0 -0
  180. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/c_composed_steps.py +0 -0
  181. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_element_centers.py +0 -0
  182. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_plane_wave_law.py +0 -0
  183. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d2_gate_quarter_period.py +0 -0
  184. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d_gate_cases.py +0 -0
  185. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/e_plate_crash.py +0 -0
  186. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/f_patch_grid.py +0 -0
  187. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/g_frequency_scan.py +0 -0
  188. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/gouy_check.py +0 -0
  189. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/h_pulse_and_wires.py +0 -0
  190. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/i_phase_slope.py +0 -0
  191. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_001.sh +0 -0
  192. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_002.sh +0 -0
  193. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_003.sh +0 -0
  194. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_004.sh +0 -0
  195. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_005.sh +0 -0
  196. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_001.sh +0 -0
  197. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_002.sh +0 -0
  198. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_003.sh +0 -0
  199. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_004.sh +0 -0
  200. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_005.sh +0 -0
  201. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_006.sh +0 -0
  202. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_007.sh +0 -0
  203. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_008.sh +0 -0
  204. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_009.sh +0 -0
  205. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_010.sh +0 -0
  206. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_001.sh +0 -0
  207. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_002.sh +0 -0
  208. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_003.sh +0 -0
  209. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_004.sh +0 -0
  210. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_005.sh +0 -0
  211. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_001.sh +0 -0
  212. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_002.sh +0 -0
  213. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_003.sh +0 -0
  214. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_004.sh +0 -0
  215. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_005.sh +0 -0
  216. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_006.sh +0 -0
  217. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_007.sh +0 -0
  218. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_008.sh +0 -0
  219. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_47c5d913-2f0_a86c7568_001.sh +0 -0
  220. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_001.sh +0 -0
  221. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_002.sh +0 -0
  222. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_003.sh +0 -0
  223. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_004.sh +0 -0
  224. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_005.sh +0 -0
  225. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_006.sh +0 -0
  226. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_007.sh +0 -0
  227. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_008.sh +0 -0
  228. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_009.sh +0 -0
  229. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_001.sh +0 -0
  230. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_002.sh +0 -0
  231. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_003.sh +0 -0
  232. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_004.sh +0 -0
  233. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_005.sh +0 -0
  234. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_006.sh +0 -0
  235. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_007.sh +0 -0
  236. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_001.sh +0 -0
  237. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_002.sh +0 -0
  238. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_003.sh +0 -0
  239. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_004.sh +0 -0
  240. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_005.sh +0 -0
  241. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_006.sh +0 -0
  242. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_007.sh +0 -0
  243. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_008.sh +0 -0
  244. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_009.sh +0 -0
  245. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_010.sh +0 -0
  246. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_011.sh +0 -0
  247. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_012.sh +0 -0
  248. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_013.sh +0 -0
  249. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_014.sh +0 -0
  250. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_015.sh +0 -0
  251. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_016.sh +0 -0
  252. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_guard_run.py +0 -0
  253. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_plane_wave_nan.py +0 -0
  254. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/j_wires_in_wall.py +0 -0
  255. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_checks.py +0 -0
  256. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_das.py +0 -0
  257. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/quick_checks.py +0 -0
  258. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks.py +0 -0
  259. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_2.py +0 -0
  260. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_3.py +0 -0
  261. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_4.py +0 -0
  262. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/toy_plane_wave.py +0 -0
  263. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_check_that_the_records_load.py +0 -0
  264. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_locate_the_non_finite_values_of_an_analysis.py +0 -0
  265. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_measure_the_wire_depth_against_the_time_origin.py +0 -0
  266. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_print_the_time_origin_scans.py +0 -0
  267. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_test_the_entropy_the_antisymmetry_and_the_filter_linearity.py +0 -0
  268. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1247_time_the_phase_reversal_per_patch_against_batched.py +0 -0
  269. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1248_compare_the_synthesis_on_the_card_and_the_host.py +0 -0
  270. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1250_save_and_compare_the_local_laws_of_a_subset.py +0 -0
  271. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1254_analyze_the_2.5mhz_stage_2.sh +0 -0
  272. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1256_print_the_per_depth_curves_of_a_reverberation_test.py +0 -0
  273. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1302_print_the_durations_of_a_chain_log.py +0 -0
  274. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1314_print_the_gouy_points_of_a_speed_of_sound_scan.py +0 -0
  275. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1445_fit_the_moveout_speed_of_the_point_sources.py +0 -0
  276. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1456_fit_the_depth_offset_of_the_reference_arrivals.py +0 -0
  277. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1502_print_the_laws_and_gates_of_an_analysis.py +0 -0
  278. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1503_analyze_with_the_ramp_removal_off_or_every_law_one.py +0 -0
  279. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1504_measure_the_anti_diagonal_share_of_the_clean_clutter.py +0 -0
  280. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1508_estimate_the_speed_with_smaller_windows.py +0 -0
  281. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1553_focus_the_clutter_records_in_sub_bands.py +0 -0
  282. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1553_print_the_band_and_the_screens_of_the_records.py +0 -0
  283. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1554_predict_the_phase_speed_of_the_stencil.py +0 -0
  284. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1556_compute_the_moveout_truth_with_an_eikonal_solver.py +0 -0
  285. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1556_fit_the_height_offset_on_three_grids.py +0 -0
  286. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1600_measure_the_flat_and_the_screen_correction_on_point_targets.py +0 -0
  287. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1604_predict_the_arrivals_from_the_stencil.py +0 -0
  288. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1604_prototype_the_broadband_correction.py +0 -0
  289. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1605_scan_the_time_origin_with_other_element_planes.py +0 -0
  290. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1607_measure_the_local_far_field_structure_of_the_clutter.py +0 -0
  291. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1608_score_the_speed_scans_against_the_eikonal_truth.py +0 -0
  292. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1610_compare_the_unwrapped_law_delays_with_the_truth.py +0 -0
  293. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1611_compare_the_arrival_models_at_the_point_sources.py +0 -0
  294. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1613_compare_the_sensor_pixel_with_the_element_center.py +0 -0
  295. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1613_measure_the_order_of_the_clutter_from_the_contrast_scaling.py +0 -0
  296. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1613_scan_the_speed_of_sound_at_one_time_origin.py +0 -0
  297. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1615_locate_the_source_and_sensor_pixels_of_the_array.py +0 -0
  298. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1617_check_the_data_level_correction_and_the_pulse_band.py +0 -0
  299. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1617_test_local_and_notch_filters_on_the_clutter.py +0 -0
  300. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1621_compute_the_moveout_truth_with_a_chosen_arrival_model.py +0 -0
  301. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1622_measure_the_tilt_spread_of_the_wall_interfaces.py +0 -0
  302. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1623_tabulate_the_broadband_correction_runs.py +0 -0
  303. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1626_measure_the_ghost_depths_of_the_plate.py +0 -0
  304. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1626_score_the_product_of_the_transducer_laws.py +0 -0
  305. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1630_test_the_local_filter_with_padded_windows.py +0 -0
  306. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1632_fit_the_time_origin_and_the_speed_of_the_phantom_scans.py +0 -0
  307. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1634_fit_the_reference_speed_at_the_sensor_row.py +0 -0
  308. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1646_split_the_clutter_into_orders_and_predict_its_floor.py +0 -0
  309. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1652_tabulate_the_pulse_band_check.py +0 -0
  310. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1659_check_the_plane_wave_transform_of_the_elements.py +0 -0
  311. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1103_compare_two_b_mode_roots.py +0 -0
  312. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1214_binary_cache_lookup_order.py +0 -0
  313. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1253_signal_of_old_against_new.py +0 -0
  314. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1300_read_the_numexpr_pool_limit.py +0 -0
  315. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1332_gpu_memory_of_the_relaxation_kernel.py +0 -0
  316. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1401_relaxation_regions_against_the_kernel.py +0 -0
  317. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1420_released_binary_carries_the_fix.py +0 -0
  318. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1601_stable_courant_number_of_the_stencil_table.py +0 -0
  319. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1602_fast_layer_in_a_small_3d_run.py +0 -0
  320. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1719_p4_1_pulse_energy_above_the_trace_nyquist.py +0 -0
  321. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1933_l7_4_run_at_8_ppw_stability_and_trace_sampling.py +0 -0
  322. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1946_l7_4_trace_sampling_by_field_modulus.py +0 -0
  323. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2004_pulse_bands_of_the_two_abdomen_arrays.py +0 -0
  324. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_cuda_version_choice_before_and_after.py +0 -0
  325. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_gpu_architectures_in_cached_binaries.py +0 -0
  326. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_mutation_check_of_the_cuda_version_tests.py +0 -0
  327. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_verify_the_cuda_version_test_findings.py +0 -0
  328. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2212_mutation_check_of_the_blackwell_version_choice.py +0 -0
  329. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260925_1321_selected_cuda_tag.py +0 -0
  330. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260925_1326_release_binary_bit_identity.py +0 -0
  331. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/scratch/20260925_1331_summarize_release_check.py +0 -0
  332. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/settings.local.json +0 -0
  333. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/skills/fullwave25/SKILL.md +0 -0
  334. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/convex_transducer_3d.py +0 -0
  335. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/linear_transducer_3d.py +0 -0
  336. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/matrix_transducer_3d.py +0 -0
  337. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/patch.py +0 -0
  338. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/ruff.toml +0 -0
  339. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/superseded/convex_transducer_3d.py +0 -0
  340. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/superseded/linear_transducer_3d.py +0 -0
  341. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/superseded/matrix_transducer_3d.py +0 -0
  342. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/test_patch.py +0 -0
  343. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/transducer_stack/README.md +0 -0
  344. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/transducer_stack/superseded/full_synthetic_aperture_with_stack.py +0 -0
  345. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.claude/transducer_stack/superseded/plane_wave_compounding_with_stack.py +0 -0
  346. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.gitignore +0 -0
  347. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.pre-commit-config.yaml +0 -0
  348. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/.python-version +0 -0
  349. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/20260120_0844.log +0 -0
  350. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/CITATION.cff +0 -0
  351. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/CONTRIBUTING.md +0 -0
  352. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/LICENSE +0 -0
  353. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/Makefile +0 -0
  354. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/attenuation.png +0 -0
  355. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/beamformer.m +0 -0
  356. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  357. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu +0 -0
  358. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  359. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  360. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  361. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  362. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/docker/Dockerfile +0 -0
  363. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/docker/Dockerfile.dockerignore +0 -0
  364. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/docker/README.md +0 -0
  365. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/experiments/__init__.py +0 -0
  366. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/experiments/exp_scatterer_diameter.py +0 -0
  367. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/beamformer/__init__.py +0 -0
  368. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/beamformer/beamformer.py +0 -0
  369. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/constants/__init__.py +0 -0
  370. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/constants/material_properties.py +0 -0
  371. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/grid.py +0 -0
  372. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/__init__.py +0 -0
  373. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/domain.py +0 -0
  374. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/medium_builder.py +0 -0
  375. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/__init__.py +0 -0
  376. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/data/.keep +0 -0
  377. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat +0 -0
  378. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_abdominal_wall.py +0 -0
  379. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_background.py +0 -0
  380. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_scatterer.py +0 -0
  381. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_simple.py +0 -0
  382. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_water_gel.py +0 -0
  383. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/sensor.py +0 -0
  384. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/__init__.py +0 -0
  385. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118 +0 -0
  386. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  387. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129 +0 -0
  388. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda130 +0 -0
  389. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda118 +0 -0
  390. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda124 +0 -0
  391. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129 +0 -0
  392. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130 +0 -0
  393. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513.mat +0 -0
  394. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513_invalid_cells.json +0 -0
  395. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456.mat +0 -0
  396. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456_invalid_cells.json +0 -0
  397. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/cuda_utils.py +0 -0
  398. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/pml_builder.py +0 -0
  399. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/shipped_database.py +0 -0
  400. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/solver/utils.py +0 -0
  401. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/transmit.py +0 -0
  402. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/check_functions.py +0 -0
  403. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/coordinates.py +0 -0
  404. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/numerical.py +0 -0
  405. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/plot_utils.py +0 -0
  406. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/pulse.py +0 -0
  407. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/relaxation_parameters.py +0 -0
  408. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/scatterer.py +0 -0
  409. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/signal_filter.py +0 -0
  410. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/fullwave/utils/signal_process.py +0 -0
  411. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/logs/20260815_0356_sweep.log +0 -0
  412. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/ruff.log +0 -0
  413. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/ruff.toml +0 -0
  414. {fullwave25-1.4.2.dev0 → fullwave25-1.4.2.dev2}/signal_filter_example.png +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "1.4.2-dev0"
2
+ current_version = "1.4.2-dev2"
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.2-dev0
3
+ Version: 1.4.2-dev2
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
@@ -25,7 +25,7 @@ Requires-Dist: tomli>=2.3.0
25
25
  Requires-Dist: tqdm>=4.67.1
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: line-profiler>=5.0.1; extra == 'dev'
28
- Requires-Dist: pre-commit==4.1.0; extra == 'dev'
28
+ Requires-Dist: pre-commit==4.6.2; extra == 'dev'
29
29
  Requires-Dist: pytest>=8.3.5; extra == 'dev'
30
30
  Requires-Dist: ruff>=0.12.9; extra == 'dev'
31
31
  Provides-Extra: examples
@@ -270,7 +270,7 @@ The arrays are `l7_4` (linear, 128 elements, 5.208 MHz), `c5_2v` (curved, 49.57
270
270
 
271
271
  The transmits are `plane_wave(angle_deg=...)`, `focus(focus_m=...)`, `diverging(virtual_source_m=...)` and `synthetic_aperture(element)`. Each takes `apodization` and `pulse`. Set `transducer.active_source_elements` first to use part of the aperture.
272
272
 
273
- Every transducer is additive by default, which is what the calibrated setups use. Pass `source_type="clamped"` for a hard source.
273
+ The source type is `"hard_released_after"` by default: the transducer assigns its pressure while the drive signal plays, then the source cells evolve freely. `"hard"` assigns it for the whole run, so the cells stay at zero pressure after the drive ends. `"soft"` adds the signal to the field, and is what the calibrated setups use. Pass `source_type=` to `Transducer.l7_4`, `c5_2v`, `p4_1c` or `fullwave.Solver`.
274
274
 
275
275
  `transducer.apply_transducer_stack(...)` paints a probe's backing, matching layer, lens and standoff onto the medium maps before the `Medium` is built. `fullwave.TransducerStack` holds the values.
276
276
 
@@ -389,6 +389,61 @@ Please see the following examples for more advanced usage.
389
389
 
390
390
  ---
391
391
 
392
+ ## Experimental: fullwave2-ultra backend
393
+
394
+ `Solver(..., use_ultra=True)` runs the simulation with the fullwave2-ultra binary instead of the fullwave25 solver binary. It is experimental and the API may change.
395
+
396
+ The fullwave2-ultra backend is optimized for speed at ppw = 6 (`Grid.ppw`); a larger ppw runs, but more slowly, and gives a warning.
397
+
398
+ fullwave25 does not ship the fullwave2-ultra binaries. Get them from <https://github.com/pinton-lab/fullwave2-ultra> or contact the Pinton lab.
399
+
400
+ Point the solver to the binary with `path_fullwave_simulation_bin` or with the environment variable `FW2U_BATCH_BIN`. Either can be the binary file or the folder that contains it. The binary name is `bench_2d_batch` for a 2D grid and `bench_3d_opt` for a 3D grid.
401
+
402
+ ```python
403
+ from pathlib import Path
404
+
405
+ import fullwave
406
+
407
+ solver = fullwave.Solver(
408
+ work_dir=Path("./outputs/ultra"),
409
+ grid=grid, # 2D or 3D fullwave.Grid
410
+ medium=medium, # fullwave.Medium with alpha_power == 1 everywhere
411
+ source=source,
412
+ sensor=sensor,
413
+ path_fullwave_simulation_bin=Path("/path/to/fullwave2-ultra/bin"),
414
+ use_ultra=True,
415
+ )
416
+ traces = solver.run() # (n_sensors, n_frames)
417
+ # 2D only: traces = solver.run_batch(sources) # (n_transmits, n_sensors, n_frames)
418
+ ```
419
+
420
+ In 2D, `run_batch` treats `max_members_per_run` as an upper bound that the free GPU memory can lower, and it keeps the requested value, with a warning, when the free memory cannot be read. The native path uses an explicit `max_members_per_run` as given.
421
+
422
+ Supported now:
423
+
424
+ - 2D grids with `run` and `run_batch`, including air cells.
425
+ - 3D grids with `run`, including air cells.
426
+ - Additive sources (`p0_additive`) and `source_type="soft"` in 2D and 3D.
427
+ - The three source types in 2D and 3D, as on the native path: `"hard"` holds the source cells at zero pressure after `p0` ends, `"hard_released_after"` lets them evolve freely, and `"soft"` (and `p0_additive`) add to the pressure.
428
+
429
+ `UltraUnsupportedError` is raised for:
430
+
431
+ - `run_batch` in 3D.
432
+ - Velocity sources, and sources that are not pressure sources.
433
+ - Sparse-grid sensors, `is_static_map`, and `record_whole_domain`.
434
+ - Media other than `fullwave.Medium` (exponential attenuation), and `alpha_power` other than 1.
435
+ - `use_pml=False`, `m_spatial_order` other than 8, `use_gpu=False`, and an invalid `source_type`.
436
+ - In 2D, a binary that does not read the files for air cells, for the additive channel, or for releasing the source (with such a binary, pad `p0` to `grid.nt`).
437
+ - In 3D, air cells with a binary that does not read `icczero.dat` and `nzero0.dat`, and additive sources with a binary that does not read `ncoords_add.dat` and `icmat_add.dat`.
438
+
439
+ This list will grow as the backend does.
440
+
441
+ The backend runs the exponential attenuation model (frequency-independent: the same attenuation at every frequency). Set the width of its absorbing sponge, in cells, with `ultra_sponge_thickness_px`; the default is 6 wavelengths in 2D and 4 wavelengths in 3D. `exponential_attenuation_pml_thickness_px` no longer sets this width with `use_ultra=True`; a script that relied on it now gets the default width until it passes `ultra_sponge_thickness_px`.
442
+
443
+ Options that only tune the native solver are ignored with a warning, once per process: `pml_layer_thickness_px`, `n_transition_layer`, `pml_alpha_entrance`, `exponential_attenuation_pml_thickness_px` (use `ultra_sponge_thickness_px` instead), `use_gpu_pml`, `save_gpu_memory`, `write_maps_the_solver_does_not_read`, `use_isotropic_relaxation=False`, and a `cuda_device_id` that lists more than one device (the run uses the first one listed). `use_exponential_attenuation=False`, the native default, also warns that the backend runs the exponential attenuation model, whose attenuation is frequency-independent, not the relaxation model, whose attenuation is frequency-dependent. Pass `use_exponential_attenuation=True` to silence it.
444
+
445
+ ---
446
+
392
447
  ## Attention
393
448
 
394
449
  - The simulation grid is defined as follows:
@@ -229,7 +229,7 @@ The arrays are `l7_4` (linear, 128 elements, 5.208 MHz), `c5_2v` (curved, 49.57
229
229
 
230
230
  The transmits are `plane_wave(angle_deg=...)`, `focus(focus_m=...)`, `diverging(virtual_source_m=...)` and `synthetic_aperture(element)`. Each takes `apodization` and `pulse`. Set `transducer.active_source_elements` first to use part of the aperture.
231
231
 
232
- Every transducer is additive by default, which is what the calibrated setups use. Pass `source_type="clamped"` for a hard source.
232
+ The source type is `"hard_released_after"` by default: the transducer assigns its pressure while the drive signal plays, then the source cells evolve freely. `"hard"` assigns it for the whole run, so the cells stay at zero pressure after the drive ends. `"soft"` adds the signal to the field, and is what the calibrated setups use. Pass `source_type=` to `Transducer.l7_4`, `c5_2v`, `p4_1c` or `fullwave.Solver`.
233
233
 
234
234
  `transducer.apply_transducer_stack(...)` paints a probe's backing, matching layer, lens and standoff onto the medium maps before the `Medium` is built. `fullwave.TransducerStack` holds the values.
235
235
 
@@ -348,6 +348,61 @@ Please see the following examples for more advanced usage.
348
348
 
349
349
  ---
350
350
 
351
+ ## Experimental: fullwave2-ultra backend
352
+
353
+ `Solver(..., use_ultra=True)` runs the simulation with the fullwave2-ultra binary instead of the fullwave25 solver binary. It is experimental and the API may change.
354
+
355
+ The fullwave2-ultra backend is optimized for speed at ppw = 6 (`Grid.ppw`); a larger ppw runs, but more slowly, and gives a warning.
356
+
357
+ fullwave25 does not ship the fullwave2-ultra binaries. Get them from <https://github.com/pinton-lab/fullwave2-ultra> or contact the Pinton lab.
358
+
359
+ Point the solver to the binary with `path_fullwave_simulation_bin` or with the environment variable `FW2U_BATCH_BIN`. Either can be the binary file or the folder that contains it. The binary name is `bench_2d_batch` for a 2D grid and `bench_3d_opt` for a 3D grid.
360
+
361
+ ```python
362
+ from pathlib import Path
363
+
364
+ import fullwave
365
+
366
+ solver = fullwave.Solver(
367
+ work_dir=Path("./outputs/ultra"),
368
+ grid=grid, # 2D or 3D fullwave.Grid
369
+ medium=medium, # fullwave.Medium with alpha_power == 1 everywhere
370
+ source=source,
371
+ sensor=sensor,
372
+ path_fullwave_simulation_bin=Path("/path/to/fullwave2-ultra/bin"),
373
+ use_ultra=True,
374
+ )
375
+ traces = solver.run() # (n_sensors, n_frames)
376
+ # 2D only: traces = solver.run_batch(sources) # (n_transmits, n_sensors, n_frames)
377
+ ```
378
+
379
+ In 2D, `run_batch` treats `max_members_per_run` as an upper bound that the free GPU memory can lower, and it keeps the requested value, with a warning, when the free memory cannot be read. The native path uses an explicit `max_members_per_run` as given.
380
+
381
+ Supported now:
382
+
383
+ - 2D grids with `run` and `run_batch`, including air cells.
384
+ - 3D grids with `run`, including air cells.
385
+ - Additive sources (`p0_additive`) and `source_type="soft"` in 2D and 3D.
386
+ - The three source types in 2D and 3D, as on the native path: `"hard"` holds the source cells at zero pressure after `p0` ends, `"hard_released_after"` lets them evolve freely, and `"soft"` (and `p0_additive`) add to the pressure.
387
+
388
+ `UltraUnsupportedError` is raised for:
389
+
390
+ - `run_batch` in 3D.
391
+ - Velocity sources, and sources that are not pressure sources.
392
+ - Sparse-grid sensors, `is_static_map`, and `record_whole_domain`.
393
+ - Media other than `fullwave.Medium` (exponential attenuation), and `alpha_power` other than 1.
394
+ - `use_pml=False`, `m_spatial_order` other than 8, `use_gpu=False`, and an invalid `source_type`.
395
+ - In 2D, a binary that does not read the files for air cells, for the additive channel, or for releasing the source (with such a binary, pad `p0` to `grid.nt`).
396
+ - In 3D, air cells with a binary that does not read `icczero.dat` and `nzero0.dat`, and additive sources with a binary that does not read `ncoords_add.dat` and `icmat_add.dat`.
397
+
398
+ This list will grow as the backend does.
399
+
400
+ The backend runs the exponential attenuation model (frequency-independent: the same attenuation at every frequency). Set the width of its absorbing sponge, in cells, with `ultra_sponge_thickness_px`; the default is 6 wavelengths in 2D and 4 wavelengths in 3D. `exponential_attenuation_pml_thickness_px` no longer sets this width with `use_ultra=True`; a script that relied on it now gets the default width until it passes `ultra_sponge_thickness_px`.
401
+
402
+ Options that only tune the native solver are ignored with a warning, once per process: `pml_layer_thickness_px`, `n_transition_layer`, `pml_alpha_entrance`, `exponential_attenuation_pml_thickness_px` (use `ultra_sponge_thickness_px` instead), `use_gpu_pml`, `save_gpu_memory`, `write_maps_the_solver_does_not_read`, `use_isotropic_relaxation=False`, and a `cuda_device_id` that lists more than one device (the run uses the first one listed). `use_exponential_attenuation=False`, the native default, also warns that the backend runs the exponential attenuation model, whose attenuation is frequency-independent, not the relaxation model, whose attenuation is frequency-dependent. Pass `use_exponential_attenuation=True` to silence it.
403
+
404
+ ---
405
+
351
406
  ## Attention
352
407
 
353
408
  - The simulation grid is defined as follows:
@@ -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.2-dev0"
69
+ __version__ = "1.4.2-dev2"
70
70
 
71
71
  VERSION = __version__ # for convenience
72
72
  logger.info("Fullwave version: %s", __version__)
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
  from collections import OrderedDict
7
- from concurrent.futures import ThreadPoolExecutor
7
+ from concurrent.futures import ThreadPoolExecutor, as_completed
8
8
  from dataclasses import dataclass
9
9
  from pathlib import Path
10
10
  from typing import TYPE_CHECKING
@@ -93,8 +93,6 @@ def _upload_arrays_multi_gpu(
93
93
  dict mapping name -> CuPy array on *target_device*.
94
94
 
95
95
  """
96
- from concurrent.futures import as_completed # noqa: PLC0415
97
-
98
96
  import cupy as cp # noqa: PLC0415
99
97
 
100
98
  n_gpus = cp.cuda.runtime.getDeviceCount()
@@ -21,6 +21,8 @@ import urllib.error
21
21
  import urllib.request
22
22
  from pathlib import Path
23
23
 
24
+ from tqdm import tqdm
25
+
24
26
  logger = logging.getLogger("__main__." + __name__)
25
27
 
26
28
  GITHUB_REPO = "pinton-lab/fullwave25"
@@ -28,7 +30,7 @@ CACHE_DIR = Path.home() / ".cache" / "fullwave25" / "bins"
28
30
 
29
31
  # Pinned release tag for the solver binaries.
30
32
  # Update this only when new binaries are uploaded to a GitHub release.
31
- BINARY_RELEASE_TAG = "fullwave_bin_v1.6"
33
+ BINARY_RELEASE_TAG = "fullwave_bin_v1.7"
32
34
 
33
35
 
34
36
  def _download_url(filename: str, tag: str) -> str:
@@ -36,39 +38,34 @@ def _download_url(filename: str, tag: str) -> str:
36
38
 
37
39
 
38
40
  def _download_binary(url: str, dest: Path) -> None:
39
- """Download *url* to *dest*, showing a tqdm progress bar when available."""
41
+ """Download *url* to *dest*, showing a tqdm progress bar."""
40
42
  dest.parent.mkdir(parents=True, exist_ok=True)
41
43
  tmp = dest.with_suffix(".download_tmp")
42
44
  try:
45
+
46
+ class _Hook:
47
+ def __init__(self) -> None:
48
+ self._bar: tqdm | None = None
49
+
50
+ def __call__(self, block: int, block_size: int, total: int) -> None: # noqa: ARG002
51
+ if self._bar is None:
52
+ self._bar = tqdm(
53
+ total=total if total > 0 else None,
54
+ unit="B",
55
+ unit_scale=True,
56
+ desc=dest.name,
57
+ )
58
+ self._bar.update(block_size)
59
+
60
+ def close(self) -> None:
61
+ if self._bar is not None:
62
+ self._bar.close()
63
+
64
+ hook = _Hook()
43
65
  try:
44
- from tqdm import tqdm # noqa: PLC0415
45
-
46
- class _Hook:
47
- def __init__(self) -> None:
48
- self._bar: tqdm | None = None
49
-
50
- def __call__(self, block: int, block_size: int, total: int) -> None: # noqa: ARG002
51
- if self._bar is None:
52
- self._bar = tqdm(
53
- total=total if total > 0 else None,
54
- unit="B",
55
- unit_scale=True,
56
- desc=dest.name,
57
- )
58
- self._bar.update(block_size)
59
-
60
- def close(self) -> None:
61
- if self._bar is not None:
62
- self._bar.close()
63
-
64
- hook = _Hook()
65
- try:
66
- urllib.request.urlretrieve(url, tmp, reporthook=hook) # noqa: S310
67
- finally:
68
- hook.close()
69
-
70
- except ImportError:
71
- urllib.request.urlretrieve(url, tmp) # noqa: S310
66
+ urllib.request.urlretrieve(url, tmp, reporthook=hook) # noqa: S310
67
+ finally:
68
+ hook.close()
72
69
 
73
70
  tmp.rename(dest)
74
71
  dest.chmod(dest.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
@@ -0,0 +1,87 @@
1
+ """Find out whether a solver binary reads an input file, by the file name in its bytes."""
2
+
3
+ import mmap
4
+ from functools import lru_cache
5
+ from pathlib import Path
6
+ from typing import NamedTuple
7
+
8
+ HOLD_SOURCE_MARKER = b"hold_source.dat"
9
+ DEFAULT_FIX = "rebuild the binary, or set FULLWAVE25_BINARY_TAG to the release that has it"
10
+
11
+
12
+ class HoldSourceUnsupportedError(RuntimeError):
13
+ """Raised when the binary cannot hold the hard source after the drive ends."""
14
+
15
+
16
+ class _FileStamp(NamedTuple):
17
+ """A file with the size and modification time that tell whether it changed."""
18
+
19
+ path: Path
20
+ size: int
21
+ mtime_ns: int
22
+
23
+
24
+ @lru_cache(maxsize=64)
25
+ def _find(stamp: _FileStamp, marker: bytes) -> bool:
26
+ if stamp.size == 0:
27
+ return False
28
+ with stamp.path.open("rb") as file, mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as mm:
29
+ return mm.find(marker) != -1
30
+
31
+
32
+ def binary_has_marker(binary: str | Path, *, marker: bytes) -> bool:
33
+ """Return whether the bytes of ``binary`` contain ``marker``.
34
+
35
+ Parameters
36
+ ----------
37
+ binary : str | Path
38
+ The solver binary.
39
+ marker : bytes
40
+ The name of the input file the binary reads.
41
+
42
+ Returns
43
+ -------
44
+ bool
45
+ True when the binary contains the name. The answer is cached until the file changes.
46
+
47
+ """
48
+ path = Path(binary).resolve()
49
+ stat = path.stat()
50
+ return _find(_FileStamp(path=path, size=stat.st_size, mtime_ns=stat.st_mtime_ns), marker)
51
+
52
+
53
+ def check_binary_holds_source(
54
+ binary: str | Path,
55
+ *,
56
+ marker: bytes = HOLD_SOURCE_MARKER,
57
+ error_type: type[Exception] = HoldSourceUnsupportedError,
58
+ fix: str = DEFAULT_FIX,
59
+ ) -> None:
60
+ """Refuse a binary that would release the hard source cells when the drive ends.
61
+
62
+ Parameters
63
+ ----------
64
+ binary : str | Path
65
+ The solver binary.
66
+ marker : bytes, optional
67
+ The name of the input file that tells the binary to hold the source.
68
+ error_type : type[Exception], optional
69
+ The exception to raise.
70
+ fix : str, optional
71
+ What to do to get a binary that reads the file, worded for the message.
72
+
73
+ Raises
74
+ ------
75
+ Exception
76
+ ``error_type``, when the binary does not contain ``marker``.
77
+
78
+ """
79
+ if binary_has_marker(binary, marker=marker):
80
+ return
81
+ message = (
82
+ f"{Path(binary).name} does not read {marker.decode()}, so it releases the hard source "
83
+ "cells when the drive signal ends and source_type='hard' would not hold them. "
84
+ f"Use a binary that reads it: {fix}. "
85
+ "source_type='hard_released_after' needs no such binary."
86
+ )
87
+ raise error_type(message)
@@ -5,6 +5,7 @@ import logging
5
5
  import os
6
6
  import time
7
7
  from collections.abc import Sequence
8
+ from concurrent.futures import ThreadPoolExecutor, as_completed
8
9
  from pathlib import Path
9
10
 
10
11
  import numpy as np
@@ -64,6 +65,7 @@ class InputFileWriter:
64
65
  exponential_attenuation_pml_interior_offset_px: int = 0,
65
66
  use_gpu: bool = False,
66
67
  write_maps_the_solver_does_not_read: bool = False,
68
+ hold_hard_source: bool = False,
67
69
  ) -> None:
68
70
  """Initialize the InputGeneratorBase instance.
69
71
 
@@ -124,6 +126,11 @@ class InputFileWriter:
124
126
  which an older solver binary needs. The record the skipped maps
125
127
  replace is impedance_constraint.dat, and this writer always writes it
126
128
  on the relaxation path.
129
+ hold_hard_source : bool, optional
130
+ Whether the hard source cells stay at zero pressure after the drive ends.
131
+ True writes the flag file ``hold_source.dat``, which the solver reads to keep
132
+ the cells at zero for the rest of the run; the signals are written as given.
133
+ False, the default, lets the solver release the cells when the signal ends.
127
134
 
128
135
  """
129
136
  logger.debug("Initializing InputFileWriter instance.")
@@ -139,6 +146,7 @@ class InputFileWriter:
139
146
  self.use_isotropic_relaxation = use_isotropic_relaxation
140
147
  self.write_maps_the_solver_does_not_read = write_maps_the_solver_does_not_read
141
148
  self.use_gpu = use_gpu
149
+ self.hold_hard_source = hold_hard_source
142
150
 
143
151
  if validate_input:
144
152
  check_functions.check_path_exists(self.path_fullwave_simulation_bin)
@@ -347,10 +355,21 @@ class InputFileWriter:
347
355
 
348
356
  """
349
357
  if members is None:
350
- return getattr(self.source, name, None)
351
- if getattr(self.source, name, None) is None:
358
+ signal = getattr(self.source, name, None)
359
+ elif getattr(self.source, name, None) is None:
352
360
  return None
353
- return np.concatenate([getattr(member, name) for member in members], axis=0)
361
+ else:
362
+ signal = np.concatenate([getattr(member, name) for member in members], axis=0)
363
+ return signal
364
+
365
+ @property
366
+ def _holds_the_source(self) -> bool:
367
+ """Whether the solver keeps the hard source cells at zero after the drive ends."""
368
+ return (
369
+ self.hold_hard_source
370
+ and self.source.n_sources > 0
371
+ and self.source.icmat.shape[1] < self.grid.nt
372
+ )
354
373
 
355
374
  # --- constructor utils ---
356
375
 
@@ -909,8 +928,6 @@ class InputFileWriter:
909
928
  (c_min_val, c_max_val) of the sound speed.
910
929
 
911
930
  """
912
- from concurrent.futures import ThreadPoolExecutor, as_completed # noqa: PLC0415
913
-
914
931
  import cupy as cp # noqa: PLC0415
915
932
 
916
933
  sound_speed_np = self.medium.sound_speed
@@ -1259,6 +1276,7 @@ class InputFileWriter:
1259
1276
  "ncoordsout",
1260
1277
  "ncoordszero",
1261
1278
  "nTic",
1279
+ "hold_source",
1262
1280
  "modT",
1263
1281
  "modX",
1264
1282
  "modY",
@@ -1357,7 +1375,6 @@ class InputFileWriter:
1357
1375
  self._queue_v_abs_write(np.float32, save_path, var)
1358
1376
 
1359
1377
  def _save_coords_params(self, simulation_dir: Path) -> None:
1360
- nt_ic = self.source.icmat.shape[1]
1361
1378
  var_list = [
1362
1379
  ("nX", self.grid.nx),
1363
1380
  ("nY", self.grid.ny),
@@ -1365,9 +1382,11 @@ class InputFileWriter:
1365
1382
  ("ncoords", self.source.n_sources),
1366
1383
  ("ncoordsout", self.sensor.n_sensors),
1367
1384
  ("ncoordszero", self.medium.n_air),
1368
- ("nTic", nt_ic),
1385
+ ("nTic", self.source.icmat.shape[1]),
1369
1386
  ("modT", self.sensor.sampling_modulus_time),
1370
1387
  ]
1388
+ if self._holds_the_source:
1389
+ var_list.append(("hold_source", 1))
1371
1390
  n_sources_add = getattr(self.source, "n_sources_add", 0)
1372
1391
  if n_sources_add > 0:
1373
1392
  var_list.append(("ncoords_add", n_sources_add))
@@ -13,6 +13,7 @@ from time import time
13
13
  import numpy as np
14
14
  from numpy.typing import NDArray
15
15
 
16
+ from .cuda_utils import find_consecutive_gpus_without_peer_access
16
17
  from .utils import load_dat_data
17
18
 
18
19
  logger = logging.getLogger("__main__." + __name__)
@@ -211,8 +212,6 @@ class Launcher:
211
212
  )
212
213
  return
213
214
  try:
214
- from .cuda_utils import find_consecutive_gpus_without_peer_access # noqa: PLC0415
215
-
216
215
  pairs = find_consecutive_gpus_without_peer_access(device_ids)
217
216
  except (AttributeError, NameError, OSError, RuntimeError, ctypes.ArgumentError) as error:
218
217
  logger.debug("Peer access check skipped: %s", error)