fullwave25 1.4.2.dev1__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.dev1 → fullwave25-1.4.2.dev2}/.bumpversion.toml +1 -1
  2. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/PKG-INFO +8 -2
  3. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/README.md +7 -1
  4. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/__init__.py +1 -1
  5. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/solver.py +48 -93
  6. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/backend.py +109 -27
  7. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/backend_2d.py +203 -9
  8. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/binary.py +8 -2
  9. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/writer_2d.py +22 -2
  10. fullwave25-1.4.2.dev2/fullwave/utils/gpu_memory.py +109 -0
  11. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/pyproject.toml +1 -1
  12. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/uv.lock +1 -1
  13. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/.gitignore +0 -0
  14. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260911_1813_dead-code.md +0 -0
  15. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_1311_commit_message_of_the_input_generation_speedup.md +0 -0
  16. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_1311_pull_request_of_the_input_generation_speedup.md +0 -0
  17. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_1405_commit_message_of_the_relaxation_memory_estimate.md +0 -0
  18. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_1405_pull_request_of_the_relaxation_memory_estimate.md +0 -0
  19. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_2152_commit_message_of_the_cuda_version_choice.md +0 -0
  20. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_2152_pull_request_of_the_cuda_version_choice.md +0 -0
  21. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_2203_commit_message_of_the_cuda_version_tests.md +0 -0
  22. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_2213_commit_message_of_the_blackwell_version_choice.md +0 -0
  23. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/20260916_2213_pull_request_of_the_blackwell_version_choice.md +0 -0
  24. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/CLAUDE.md +0 -0
  25. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_1844_acquire_the_reflection_matrix.py +0 -0
  26. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_1900_test_on_a_synthetic_acquisition.py +0 -0
  27. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_1913_analyze_the_reflection_matrix.py +0 -0
  28. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_2107_redraw_the_figures_of_an_analysis.py +0 -0
  29. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260909_2121_write_the_result_tables.py +0 -0
  30. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1126_synthesize_plane_waves_from_the_multistatic_matrix.py +0 -0
  31. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1137_scan_the_speed_of_sound.py +0 -0
  32. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1141_compare_the_laws_with_the_truth.py +0 -0
  33. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1146_evaluate_the_reverberation_filter.py +0 -0
  34. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/20260910_1208_compare_plane_waves_with_the_synthesis.py +0 -0
  35. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/figures.py +0 -0
  36. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/ground_truth.py +0 -0
  37. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/matrix_imaging.py +0 -0
  38. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/pipeline.py +0 -0
  39. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/reflection_matrix.py +0 -0
  40. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/speed_of_sound.py +0 -0
  41. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/matrix_imaging/synthetic.py +0 -0
  42. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_0206_band_anchor_cross_check.py +0 -0
  43. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_0233_delivered_power_law_end_to_end.py +0 -0
  44. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_0317_reword_deliver_in_the_library.py +0 -0
  45. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260821_1220_relaxation_low_frequency_rolloff.py +0 -0
  46. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260825_1937_what_fails_the_pml_golden_tests.py +0 -0
  47. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260825_2329_does_the_wrapper_read_the_record.py +0 -0
  48. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260826_0002_what_the_new_default_table_holds.py +0 -0
  49. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1422_what_the_candidate_tables_hold.py +0 -0
  50. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1427_what_the_deployment_needs.py +0 -0
  51. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1510_where_the_unstretched_ramp_reaches.py +0 -0
  52. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260828_1517_the_blast_radius_of_the_ramp.py +0 -0
  53. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1458_the_3d_region_trimmed_kernel_against_the_reference.py +0 -0
  54. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1505_the_multi_node_kernel_against_the_multi_gpu_one.py +0 -0
  55. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1631_the_3d_multi_node_against_the_multi_gpu_one.py +0 -0
  56. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1642_the_selective_absorbing_layer.py +0 -0
  57. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1728_the_layer_against_the_taper.py +0 -0
  58. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1757_what_the_margin_outside_the_layer_does.py +0 -0
  59. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1808_the_layer_in_3d_and_on_the_multi_node_builds.py +0 -0
  60. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1832_where_the_3d_residual_sits.py +0 -0
  61. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1837_inside_the_layer_at_the_corner.py +0 -0
  62. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1840_inside_the_3d_layer_at_the_corner.py +0 -0
  63. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1912_both_absorbers_on_one_method.py +0 -0
  64. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_1922_the_layer_on_the_reflection_method.py +0 -0
  65. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2011_whole_domain_animation.py +0 -0
  66. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2032_the_example_source_kind.py +0 -0
  67. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2148_drive_scale_of_the_strong_beta_cells.py +0 -0
  68. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2159_profile_the_input_map_build.py +0 -0
  69. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2201_build_then_extend_equivalence.py +0 -0
  70. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2304_the_transmit_methods_launch_what_they_say.py +0 -0
  71. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260830_2322_the_unscaled_added_drive_follows_the_courant_number.py +0 -0
  72. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0033_the_three_dimensional_arrays.py +0 -0
  73. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0054_the_elevation_lens_of_a_linear_array.py +0 -0
  74. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0115_run_every_example.sh +0 -0
  75. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0124_move_the_notebooks_to_the_transmit_interface.py +0 -0
  76. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0137_the_air_region_at_four_mechanisms.py +0 -0
  77. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0148_the_element_records_its_own_transmit.py +0 -0
  78. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0150_the_absorbing_layer_of_a_point_source.py +0 -0
  79. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0152_the_exponential_absorbing_layer_against_its_thickness.py +0 -0
  80. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0202_the_rebuilt_exponential_absorbing_layer.py +0 -0
  81. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0216_where_the_three_dimensional_layer_leaks.py +0 -0
  82. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_0222_the_absorbing_layer_away_from_the_source.py +0 -0
  83. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1037_where_the_near_field_brightness_comes_from.py +0 -0
  84. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1040_the_aperture_transit_wedge_in_the_channel_data.py +0 -0
  85. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1043_the_transmit_in_the_recorded_trace_and_its_removal.py +0 -0
  86. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1048_the_receive_row_against_the_reference_subtraction.py +0 -0
  87. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1052_the_backing_behind_the_array_face.py +0 -0
  88. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1056_the_transmit_beam_with_the_air_backing.py +0 -0
  89. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1105_the_shipped_transducer_stack_in_the_solver.py +0 -0
  90. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1119_where_the_stack_puts_the_source_and_what_it_costs_the_depth.py +0 -0
  91. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1121_the_depth_the_image_reads_with_the_stack.py +0 -0
  92. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1123_the_depth_the_beamformer_puts_one_point_at.py +0 -0
  93. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1142_the_transmit_offset_the_beamformer_needs.py +0 -0
  94. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1145_the_depth_shift_the_offset_fix_makes.py +0 -0
  95. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1154_the_two_offset_rules_on_the_same_recording.py +0 -0
  96. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1212_what_the_pinned_release_carries.py +0 -0
  97. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1228_the_low_cut_against_the_near_field_haze.py +0 -0
  98. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1301_run_the_beamforming_notebooks.py +0 -0
  99. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1432_point_dataset_generator_at_the_local_fullwave.py +0 -0
  100. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1437_the_aperture_width_the_reference_geometry_reports.py +0 -0
  101. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1454_calibrate_the_ats539_plane_wave.py +0 -0
  102. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1508_show_the_b_mode_in_the_hdf5.py +0 -0
  103. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1534_the_comet_behind_each_wire.py +0 -0
  104. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1547_read_the_calibration_trials.py +0 -0
  105. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1605_what_the_medium_holds_in_the_near_field.py +0 -0
  106. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1607_sweep_one_generator_knob.py +0 -0
  107. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1715_assert_the_ats539_rate_chain.py +0 -0
  108. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1717_measure_every_layer_of_the_stack.py +0 -0
  109. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1720_where_the_trailing_energy_lands.py +0 -0
  110. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1725_offer_the_requested_absorption_to_the_backing.py +0 -0
  111. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1727_let_a_sweep_carry_a_switch.py +0 -0
  112. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1731_expose_the_exponential_absorbing_layer.py +0 -0
  113. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1746_point_the_solver_at_an_older_binary.py +0 -0
  114. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1756_measure_the_point_targets.py +0 -0
  115. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1802_rederive_the_near_field_bounce.py +0 -0
  116. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1810_does_the_shelf_move_with_depth.py +0 -0
  117. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1812_find_the_repeat_delay_in_the_raw_rf.py +0 -0
  118. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1937_give_each_source_row_its_own_launch_delay.py +0 -0
  119. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1943_baffle_the_element_plane.py +0 -0
  120. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_1952_take_the_cell_size_from_the_grid.py +0 -0
  121. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2058_run_the_ats539_through_the_batched_solver.py +0 -0
  122. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2105_queue_the_remaining_candidates.py +0 -0
  123. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2122_the_simulator_asks_for_a_clamped_source.py +0 -0
  124. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2126_rename_the_source_types_to_hard_and_soft.py +0 -0
  125. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2140_bind_the_source_type_to_its_entrance.py +0 -0
  126. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2225_how_redundant_are_the_absorbing_layer_files.py +0 -0
  127. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2239_skip_the_constant_absorbing_layer_maps.py +0 -0
  128. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2246_count_the_files_a_run_writes.py +0 -0
  129. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2352_run_the_map_tiers_end_to_end.py +0 -0
  130. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260831_2355_draw_the_absorbing_layer_map_cost.py +0 -0
  131. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1502_can_the_transmit_reach_the_harmonic_band.py +0 -0
  132. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1504_contrast_harmonic_imaging.py +0 -0
  133. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1507_where_each_band_puts_its_largest_sample.py +0 -0
  134. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1519_is_the_harmonic_tail_cumulative.py +0 -0
  135. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1537_does_the_cancellation_work.py +0 -0
  136. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1612_does_a_sparse_bubble_cloud_localize.py +0 -0
  137. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1619_calibrate_the_bubble_scatter_range.py +0 -0
  138. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1622_draw_the_sweep_b_modes.py +0 -0
  139. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1654_where_the_bright_region_sits.py +0 -0
  140. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1701_where_one_bubble_images.py +0 -0
  141. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1702_does_the_portable_example_reproduce_the_evaluation.py +0 -0
  142. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1753_does_the_ported_solver_still_march_the_same.py +0 -0
  143. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1755_do_the_ranks_agree_on_the_bubbles.py +0 -0
  144. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1817_does_the_air_region_reach_every_solver.py +0 -0
  145. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260901_1818_does_the_air_region_reach_every_rank.py +0 -0
  146. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1317_what_the_abdomen_volume_holds.py +0 -0
  147. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1319_art_wave_in_the_abdomen.py +0 -0
  148. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1324_art_figures_from_the_field.py +0 -0
  149. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260902_1744_art_final_animations.py +0 -0
  150. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260904_1216_art_wire_visibility.py +0 -0
  151. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260904_2327_b_mode_of_the_abdomen.py +0 -0
  152. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260905_0038_two_against_three_dimensions.py +0 -0
  153. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_1934_probe_the_reverberation_filter_on_speckle.py +0 -0
  154. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_1939_probe_the_ideal_profile_on_speckle.py +0 -0
  155. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_2044_probe_the_correction_bases_on_a_flat_speckle.py +0 -0
  156. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260909_2342_measure_the_wall_delay_screen.py +0 -0
  157. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1134_find_the_first_non_finite_value_of_the_plane_wave_correction.py +0 -0
  158. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1234_print_the_summaries_of_analyses.py +0 -0
  159. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/a_maps_checks.py +0 -0
  160. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/b_effective_frequency.py +0 -0
  161. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/c_composed_steps.py +0 -0
  162. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_element_centers.py +0 -0
  163. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/check_plane_wave_law.py +0 -0
  164. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d2_gate_quarter_period.py +0 -0
  165. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/d_gate_cases.py +0 -0
  166. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/e_plate_crash.py +0 -0
  167. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/f_patch_grid.py +0 -0
  168. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/g_frequency_scan.py +0 -0
  169. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/gouy_check.py +0 -0
  170. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/h_pulse_and_wires.py +0 -0
  171. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/i_phase_slope.py +0 -0
  172. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_001.sh +0 -0
  173. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_002.sh +0 -0
  174. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_003.sh +0 -0
  175. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_004.sh +0 -0
  176. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a0200910_005.sh +0 -0
  177. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_001.sh +0 -0
  178. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_002.sh +0 -0
  179. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_003.sh +0 -0
  180. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_004.sh +0 -0
  181. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_005.sh +0 -0
  182. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_006.sh +0 -0
  183. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_007.sh +0 -0
  184. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_008.sh +0 -0
  185. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_009.sh +0 -0
  186. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a16f7afd_010.sh +0 -0
  187. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_001.sh +0 -0
  188. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_002.sh +0 -0
  189. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_003.sh +0 -0
  190. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_004.sh +0 -0
  191. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a3e03828_005.sh +0 -0
  192. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_001.sh +0 -0
  193. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_002.sh +0 -0
  194. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_003.sh +0 -0
  195. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_004.sh +0 -0
  196. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_005.sh +0 -0
  197. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_006.sh +0 -0
  198. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_007.sh +0 -0
  199. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_2a8c46c5-7d0_a86c0b02_008.sh +0 -0
  200. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_47c5d913-2f0_a86c7568_001.sh +0 -0
  201. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_001.sh +0 -0
  202. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_002.sh +0 -0
  203. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_003.sh +0 -0
  204. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_004.sh +0 -0
  205. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_005.sh +0 -0
  206. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_006.sh +0 -0
  207. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_007.sh +0 -0
  208. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_008.sh +0 -0
  209. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a09af998_009.sh +0 -0
  210. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_001.sh +0 -0
  211. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_002.sh +0 -0
  212. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_003.sh +0 -0
  213. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_004.sh +0 -0
  214. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_005.sh +0 -0
  215. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_006.sh +0 -0
  216. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a3c684a5_007.sh +0 -0
  217. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_001.sh +0 -0
  218. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_002.sh +0 -0
  219. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_003.sh +0 -0
  220. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_004.sh +0 -0
  221. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_005.sh +0 -0
  222. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_006.sh +0 -0
  223. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_007.sh +0 -0
  224. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_008.sh +0 -0
  225. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_009.sh +0 -0
  226. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_010.sh +0 -0
  227. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_011.sh +0 -0
  228. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_012.sh +0 -0
  229. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_013.sh +0 -0
  230. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_014.sh +0 -0
  231. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_015.sh +0 -0
  232. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/inline_commands/wf_714887dd-b46_a99b1764_016.sh +0 -0
  233. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_guard_run.py +0 -0
  234. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/instrumented_plane_wave_nan.py +0 -0
  235. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/j_wires_in_wall.py +0 -0
  236. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_checks.py +0 -0
  237. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/origin_das.py +0 -0
  238. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/quick_checks.py +0 -0
  239. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks.py +0 -0
  240. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_2.py +0 -0
  241. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_3.py +0 -0
  242. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/scan_checks_4.py +0 -0
  243. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1239_matrix_imaging_agent_checks/toy_plane_wave.py +0 -0
  244. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_check_that_the_records_load.py +0 -0
  245. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_locate_the_non_finite_values_of_an_analysis.py +0 -0
  246. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_measure_the_wire_depth_against_the_time_origin.py +0 -0
  247. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_print_the_time_origin_scans.py +0 -0
  248. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1241_test_the_entropy_the_antisymmetry_and_the_filter_linearity.py +0 -0
  249. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1247_time_the_phase_reversal_per_patch_against_batched.py +0 -0
  250. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1248_compare_the_synthesis_on_the_card_and_the_host.py +0 -0
  251. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1250_save_and_compare_the_local_laws_of_a_subset.py +0 -0
  252. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1254_analyze_the_2.5mhz_stage_2.sh +0 -0
  253. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1256_print_the_per_depth_curves_of_a_reverberation_test.py +0 -0
  254. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1302_print_the_durations_of_a_chain_log.py +0 -0
  255. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1314_print_the_gouy_points_of_a_speed_of_sound_scan.py +0 -0
  256. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1445_fit_the_moveout_speed_of_the_point_sources.py +0 -0
  257. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1456_fit_the_depth_offset_of_the_reference_arrivals.py +0 -0
  258. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1502_print_the_laws_and_gates_of_an_analysis.py +0 -0
  259. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1503_analyze_with_the_ramp_removal_off_or_every_law_one.py +0 -0
  260. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1504_measure_the_anti_diagonal_share_of_the_clean_clutter.py +0 -0
  261. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1508_estimate_the_speed_with_smaller_windows.py +0 -0
  262. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1553_focus_the_clutter_records_in_sub_bands.py +0 -0
  263. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1553_print_the_band_and_the_screens_of_the_records.py +0 -0
  264. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1554_predict_the_phase_speed_of_the_stencil.py +0 -0
  265. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1556_compute_the_moveout_truth_with_an_eikonal_solver.py +0 -0
  266. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1556_fit_the_height_offset_on_three_grids.py +0 -0
  267. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1600_measure_the_flat_and_the_screen_correction_on_point_targets.py +0 -0
  268. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1604_predict_the_arrivals_from_the_stencil.py +0 -0
  269. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1604_prototype_the_broadband_correction.py +0 -0
  270. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1605_scan_the_time_origin_with_other_element_planes.py +0 -0
  271. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1607_measure_the_local_far_field_structure_of_the_clutter.py +0 -0
  272. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1608_score_the_speed_scans_against_the_eikonal_truth.py +0 -0
  273. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1610_compare_the_unwrapped_law_delays_with_the_truth.py +0 -0
  274. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1611_compare_the_arrival_models_at_the_point_sources.py +0 -0
  275. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1613_compare_the_sensor_pixel_with_the_element_center.py +0 -0
  276. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1613_measure_the_order_of_the_clutter_from_the_contrast_scaling.py +0 -0
  277. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1613_scan_the_speed_of_sound_at_one_time_origin.py +0 -0
  278. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1615_locate_the_source_and_sensor_pixels_of_the_array.py +0 -0
  279. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1617_check_the_data_level_correction_and_the_pulse_band.py +0 -0
  280. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1617_test_local_and_notch_filters_on_the_clutter.py +0 -0
  281. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1621_compute_the_moveout_truth_with_a_chosen_arrival_model.py +0 -0
  282. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1622_measure_the_tilt_spread_of_the_wall_interfaces.py +0 -0
  283. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1623_tabulate_the_broadband_correction_runs.py +0 -0
  284. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1626_measure_the_ghost_depths_of_the_plate.py +0 -0
  285. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1626_score_the_product_of_the_transducer_laws.py +0 -0
  286. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1630_test_the_local_filter_with_padded_windows.py +0 -0
  287. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1632_fit_the_time_origin_and_the_speed_of_the_phantom_scans.py +0 -0
  288. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1634_fit_the_reference_speed_at_the_sensor_row.py +0 -0
  289. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1646_split_the_clutter_into_orders_and_predict_its_floor.py +0 -0
  290. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1652_tabulate_the_pulse_band_check.py +0 -0
  291. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260910_1659_check_the_plane_wave_transform_of_the_elements.py +0 -0
  292. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1103_compare_two_b_mode_roots.py +0 -0
  293. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1214_binary_cache_lookup_order.py +0 -0
  294. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1253_signal_of_old_against_new.py +0 -0
  295. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1300_read_the_numexpr_pool_limit.py +0 -0
  296. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1332_gpu_memory_of_the_relaxation_kernel.py +0 -0
  297. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1401_relaxation_regions_against_the_kernel.py +0 -0
  298. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1420_released_binary_carries_the_fix.py +0 -0
  299. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1601_stable_courant_number_of_the_stencil_table.py +0 -0
  300. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1602_fast_layer_in_a_small_3d_run.py +0 -0
  301. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1719_p4_1_pulse_energy_above_the_trace_nyquist.py +0 -0
  302. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1933_l7_4_run_at_8_ppw_stability_and_trace_sampling.py +0 -0
  303. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_1946_l7_4_trace_sampling_by_field_modulus.py +0 -0
  304. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2004_pulse_bands_of_the_two_abdomen_arrays.py +0 -0
  305. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_cuda_version_choice_before_and_after.py +0 -0
  306. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_gpu_architectures_in_cached_binaries.py +0 -0
  307. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_mutation_check_of_the_cuda_version_tests.py +0 -0
  308. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2155_verify_the_cuda_version_test_findings.py +0 -0
  309. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260916_2212_mutation_check_of_the_blackwell_version_choice.py +0 -0
  310. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260925_1321_selected_cuda_tag.py +0 -0
  311. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260925_1326_release_binary_bit_identity.py +0 -0
  312. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/scratch/20260925_1331_summarize_release_check.py +0 -0
  313. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/settings.local.json +0 -0
  314. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/skills/fullwave25/SKILL.md +0 -0
  315. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/convex_transducer_3d.py +0 -0
  316. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/linear_transducer_3d.py +0 -0
  317. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/matrix_transducer_3d.py +0 -0
  318. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/patch.py +0 -0
  319. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/ruff.toml +0 -0
  320. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/superseded/convex_transducer_3d.py +0 -0
  321. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/superseded/linear_transducer_3d.py +0 -0
  322. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/superseded/matrix_transducer_3d.py +0 -0
  323. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/three_dimensional/test_patch.py +0 -0
  324. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/transducer_stack/README.md +0 -0
  325. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/transducer_stack/superseded/full_synthetic_aperture_with_stack.py +0 -0
  326. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.claude/transducer_stack/superseded/plane_wave_compounding_with_stack.py +0 -0
  327. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.gitignore +0 -0
  328. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.pre-commit-config.yaml +0 -0
  329. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/.python-version +0 -0
  330. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/20260120_0844.log +0 -0
  331. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/CITATION.cff +0 -0
  332. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/CONTRIBUTING.md +0 -0
  333. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/LICENSE +0 -0
  334. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/Makefile +0 -0
  335. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/attenuation.png +0 -0
  336. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/beamformer.m +0 -0
  337. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  338. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu +0 -0
  339. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  340. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_2d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  341. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124 +0 -0
  342. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/debug_solver_bin/fullwave2_3d_exponential_attenuation_multi_gpu_cuda124_ +0 -0
  343. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/docker/Dockerfile +0 -0
  344. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/docker/Dockerfile.dockerignore +0 -0
  345. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/docker/README.md +0 -0
  346. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/experiments/__init__.py +0 -0
  347. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/experiments/exp_scatterer_diameter.py +0 -0
  348. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/beamformer/__init__.py +0 -0
  349. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/beamformer/beamformer.py +0 -0
  350. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/constants/__init__.py +0 -0
  351. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/constants/material_properties.py +0 -0
  352. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/grid.py +0 -0
  353. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium.py +0 -0
  354. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/__init__.py +0 -0
  355. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/domain.py +0 -0
  356. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/medium_builder.py +0 -0
  357. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/__init__.py +0 -0
  358. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/data/.keep +0 -0
  359. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/data/abdominal_wall/i2365f_etfw1.mat +0 -0
  360. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_abdominal_wall.py +0 -0
  361. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_background.py +0 -0
  362. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_scatterer.py +0 -0
  363. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_simple.py +0 -0
  364. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/medium_builder/presets/domain_water_gel.py +0 -0
  365. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/sensor.py +0 -0
  366. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/__init__.py +0 -0
  367. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/binary_manager.py +0 -0
  368. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/binary_markers.py +0 -0
  369. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda118 +0 -0
  370. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda124 +0 -0
  371. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda129 +0 -0
  372. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/2d/num_relax=2/fullwave2_2d_2_relax_multi_gpu_cuda130 +0 -0
  373. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda118 +0 -0
  374. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda124 +0 -0
  375. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda129 +0 -0
  376. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/_gpu/3d/num_relax=2/fullwave2_3d_2_relax_multi_gpu_cuda130 +0 -0
  377. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513.mat +0 -0
  378. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=3_20260828_1513_invalid_cells.json +0 -0
  379. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456.mat +0 -0
  380. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/bins/database/relaxation_params_database_num_relax=4_20260828_1456_invalid_cells.json +0 -0
  381. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/cuda_utils.py +0 -0
  382. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/input_file_writer.py +0 -0
  383. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/launcher.py +0 -0
  384. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/pml_builder.py +0 -0
  385. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/shipped_database.py +0 -0
  386. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/source_type.py +0 -0
  387. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/solver/utils.py +0 -0
  388. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/source.py +0 -0
  389. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/transducer.py +0 -0
  390. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/transmit.py +0 -0
  391. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/__init__.py +0 -0
  392. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/dat_io.py +0 -0
  393. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/dat_io_3d.py +0 -0
  394. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/errors.py +0 -0
  395. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/factory.py +0 -0
  396. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/medium_to_aexp.py +0 -0
  397. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/stencil.py +0 -0
  398. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/time_axis.py +0 -0
  399. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/ultra/writer_3d.py +0 -0
  400. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/__init__.py +0 -0
  401. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/check_functions.py +0 -0
  402. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/coordinates.py +0 -0
  403. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/memory_tempfile.py +0 -0
  404. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/numerical.py +0 -0
  405. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/plot_utils.py +0 -0
  406. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/pulse.py +0 -0
  407. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/relaxation_parameters.py +0 -0
  408. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/scatterer.py +0 -0
  409. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/signal_filter.py +0 -0
  410. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/fullwave/utils/signal_process.py +0 -0
  411. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/logs/20260815_0356_sweep.log +0 -0
  412. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/ruff.log +0 -0
  413. {fullwave25-1.4.2.dev1 → fullwave25-1.4.2.dev2}/ruff.toml +0 -0
  414. {fullwave25-1.4.2.dev1 → 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-dev1"
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-dev1
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
@@ -417,6 +417,8 @@ traces = solver.run() # (n_sensors, n_frames)
417
417
  # 2D only: traces = solver.run_batch(sources) # (n_transmits, n_sensors, n_frames)
418
418
  ```
419
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
+
420
422
  Supported now:
421
423
 
422
424
  - 2D grids with `run` and `run_batch`, including air cells.
@@ -430,12 +432,16 @@ Supported now:
430
432
  - Velocity sources, and sources that are not pressure sources.
431
433
  - Sparse-grid sensors, `is_static_map`, and `record_whole_domain`.
432
434
  - Media other than `fullwave.Medium` (exponential attenuation), and `alpha_power` other than 1.
433
- - `use_pml=False`, the PML settings (set the sponge width with `exponential_attenuation_pml_thickness_px`), `m_spatial_order` other than 8, `use_gpu=False`, `save_gpu_memory`, and more than one GPU.
435
+ - `use_pml=False`, `m_spatial_order` other than 8, `use_gpu=False`, and an invalid `source_type`.
434
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`).
435
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`.
436
438
 
437
439
  This list will grow as the backend does.
438
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
+
439
445
  ---
440
446
 
441
447
  ## Attention
@@ -376,6 +376,8 @@ traces = solver.run() # (n_sensors, n_frames)
376
376
  # 2D only: traces = solver.run_batch(sources) # (n_transmits, n_sensors, n_frames)
377
377
  ```
378
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
+
379
381
  Supported now:
380
382
 
381
383
  - 2D grids with `run` and `run_batch`, including air cells.
@@ -389,12 +391,16 @@ Supported now:
389
391
  - Velocity sources, and sources that are not pressure sources.
390
392
  - Sparse-grid sensors, `is_static_map`, and `record_whole_domain`.
391
393
  - Media other than `fullwave.Medium` (exponential attenuation), and `alpha_power` other than 1.
392
- - `use_pml=False`, the PML settings (set the sponge width with `exponential_attenuation_pml_thickness_px`), `m_spatial_order` other than 8, `use_gpu=False`, `save_gpu_memory`, and more than one GPU.
394
+ - `use_pml=False`, `m_spatial_order` other than 8, `use_gpu=False`, and an invalid `source_type`.
393
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`).
394
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`.
395
397
 
396
398
  This list will grow as the backend does.
397
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
+
398
404
  ---
399
405
 
400
406
  ## Attention
@@ -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-dev1"
69
+ __version__ = "1.4.2-dev2"
70
70
 
71
71
  VERSION = __version__ # for convenience
72
72
  logger.info("Fullwave version: %s", __version__)
@@ -1,11 +1,8 @@
1
1
  """solver module."""
2
2
 
3
3
  import contextlib
4
- import gc
5
4
  import logging
6
5
  import os
7
- import shutil
8
- import subprocess
9
6
  import time
10
7
  import warnings
11
8
  from collections.abc import Iterator, Sequence
@@ -30,6 +27,11 @@ from fullwave.utils import (
30
27
  check_functions,
31
28
  run_directory_in_memory,
32
29
  )
30
+ from fullwave.utils.gpu_memory import (
31
+ free_gpu_memory_bytes,
32
+ members_that_fit,
33
+ release_gpu_memory_pools,
34
+ )
33
35
  from fullwave.utils.signal_filter import apply_filter
34
36
 
35
37
  from .binary_manager import ensure_binary
@@ -74,48 +76,6 @@ def _split_evenly(members: list, largest: int) -> list[list]:
74
76
  return runs
75
77
 
76
78
 
77
- def _free_gpu_memory_bytes(device_ids: Sequence[str]) -> dict[str, int] | None:
78
- """Return the free memory of each GPU in bytes, as nvidia-smi reports it.
79
-
80
- Parameters
81
- ----------
82
- device_ids : Sequence[str]
83
- The GPU indices, as nvidia-smi counts them.
84
-
85
- Returns
86
- -------
87
- dict[str, int] | None
88
- The free bytes of each GPU, or None when nvidia-smi cannot be run or does not
89
- report every GPU.
90
-
91
- """
92
- wanted = [device.strip() for device in device_ids]
93
- nvidia_smi_path = shutil.which("nvidia-smi")
94
- if nvidia_smi_path is None:
95
- return None
96
- try:
97
- found = subprocess.run( # noqa: S603
98
- [nvidia_smi_path, "--query-gpu=index,memory.free", "--format=csv,noheader,nounits"],
99
- capture_output=True,
100
- text=True,
101
- check=True,
102
- timeout=30,
103
- ).stdout
104
- except (OSError, subprocess.SubprocessError):
105
- return None
106
- free = {}
107
- for line in found.splitlines():
108
- index, _, mebibytes = line.partition(",")
109
- if index.strip() in wanted:
110
- try:
111
- free[index.strip()] = int(float(mebibytes)) * 1024**2
112
- except ValueError:
113
- return None
114
- if set(free) != set(wanted):
115
- return None
116
- return free
117
-
118
-
119
79
  COMPATIBLE_CUDA_ARCHITECTURES = [
120
80
  "sm_50", # Maxwell: GTX 750, GTX 750 Ti
121
81
  "sm_52", # Maxwell: GTX 980, GTX 970
@@ -513,6 +473,7 @@ class Solver:
513
473
  source_type: str = HARD_RELEASED_AFTER,
514
474
  write_maps_the_solver_does_not_read: bool = False,
515
475
  use_ultra: bool = False,
476
+ ultra_sponge_thickness_px: int | None = None,
516
477
  ) -> None:
517
478
  """Initialize a Solver instance for the fullwave simulation.
518
479
 
@@ -648,11 +609,17 @@ class Solver:
648
609
  Experimental. Run a user-supplied fullwave2-ultra binary (not shipped; pass it
649
610
  as ``path_fullwave_simulation_bin`` or set ``FW2U_BATCH_BIN``): ``bench_2d_batch``
650
611
  for a 2D grid, ``bench_3d_opt`` for a 3D grid.
651
- ``exponential_attenuation_pml_thickness_px`` sets the sponge width in cells.
652
- A source with ``p0_additive`` and ``source_type="soft"`` are added to the pressure
653
- through the binary's additive channel, which needs a binary that reads
654
- ``ncoords_add.dat`` (and ``icmat_add.dat`` on a 3D grid). Unsupported options raise
655
- ``UltraUnsupportedError``.
612
+ The backend runs the exponential attenuation model (frequency-independent:
613
+ the same attenuation at every frequency). A source with ``p0_additive`` and
614
+ ``source_type="soft"`` are added to the pressure through the binary's additive
615
+ channel, which needs a binary that reads ``ncoords_add.dat`` (and ``icmat_add.dat``
616
+ on a 3D grid). Options that only tune the native solver are ignored with a
617
+ warning; the README lists them.
618
+ Other unsupported options raise ``UltraUnsupportedError``.
619
+ ultra_sponge_thickness_px : int, optional
620
+ Width of the absorbing sponge of the ``use_ultra`` backend, in cells.
621
+ None, the default, gives 6 wavelengths in 2D and 4 wavelengths in 3D.
622
+ Used only with ``use_ultra=True``.
656
623
 
657
624
  Raises
658
625
  ------
@@ -676,21 +643,32 @@ class Solver:
676
643
  run_on_memory=run_on_memory,
677
644
  cuda_device_id=cuda_device_id,
678
645
  verify_gpu=verify_gpu,
679
- nbdy=exponential_attenuation_pml_thickness_px,
646
+ nbdy=ultra_sponge_thickness_px,
680
647
  options={
681
648
  "use_pml": use_pml,
682
649
  "m_spatial_order": m_spatial_order,
683
- "pml_layer_thickness_px": pml_layer_thickness_px,
684
- "n_transition_layer": n_transition_layer,
685
650
  "use_gpu": use_gpu,
686
- "use_gpu_pml": use_gpu_pml,
687
- "pml_alpha_entrance": pml_alpha_entrance,
688
651
  "source_type": source_type,
689
- "save_gpu_memory": save_gpu_memory,
690
- "write_maps_the_solver_does_not_read": write_maps_the_solver_does_not_read,
652
+ "use_exponential_attenuation": use_exponential_attenuation,
653
+ "native_only_options": {
654
+ "pml_layer_thickness_px": pml_layer_thickness_px,
655
+ "n_transition_layer": n_transition_layer,
656
+ "pml_alpha_entrance": pml_alpha_entrance,
657
+ "exponential_attenuation_pml_thickness_px": (
658
+ exponential_attenuation_pml_thickness_px
659
+ ),
660
+ "use_gpu_pml": use_gpu_pml,
661
+ "save_gpu_memory": save_gpu_memory,
662
+ "write_maps_the_solver_does_not_read": (
663
+ write_maps_the_solver_does_not_read
664
+ ),
665
+ "use_isotropic_relaxation": use_isotropic_relaxation,
666
+ },
691
667
  },
692
668
  )
693
669
  return
670
+ if ultra_sponge_thickness_px is not None:
671
+ backend.warn_sponge_without_ultra()
694
672
  if exponential_attenuation_pml_thickness_px is not None and not use_exponential_attenuation:
695
673
  error_msg = (
696
674
  "exponential_attenuation_pml_thickness_px belongs to the exponential "
@@ -968,31 +946,6 @@ class Solver:
968
946
  )
969
947
  logger.warning(message)
970
948
 
971
- @staticmethod
972
- def _release_gpu_memory_pools() -> None:
973
- """Release all CuPy GPU memory pool blocks back to CUDA.
974
-
975
- Call ``gc.collect()`` first so that Python releases references to
976
- CuPy arrays, then drain both the device and pinned memory pools.
977
- This prevents stale allocations from causing memory pressure when
978
- subsequent operations allocate large GPU arrays.
979
-
980
- The release is best effort. It does nothing when CuPy is absent, and
981
- it does nothing when CuPy is present without a usable CUDA driver,
982
- which is the case on a machine with no GPU.
983
- """
984
- gc.collect()
985
- try:
986
- import cupy as cp # noqa: PLC0415
987
- except ImportError:
988
- return
989
-
990
- try:
991
- cp.get_default_memory_pool().free_all_blocks()
992
- cp.get_default_pinned_memory_pool().free_all_blocks()
993
- except cp.cuda.runtime.CUDARuntimeError as error:
994
- logger.debug("GPU memory pools were not released: %s", error)
995
-
996
949
  @staticmethod
997
950
  def _check_input(
998
951
  grid: fullwave.Grid,
@@ -1420,10 +1373,10 @@ class Solver:
1420
1373
  "Input data generation completed in %s. Skipping simulation execution.",
1421
1374
  simulation_dir,
1422
1375
  )
1423
- self._release_gpu_memory_pools()
1376
+ release_gpu_memory_pools()
1424
1377
  return simulation_dir
1425
1378
 
1426
- self._release_gpu_memory_pools()
1379
+ release_gpu_memory_pools()
1427
1380
 
1428
1381
  if members is not None:
1429
1382
  return self._run_members(
@@ -1933,9 +1886,8 @@ class Solver:
1933
1886
  def _members_that_fit(self, sensor: fullwave.Sensor) -> int | None:
1934
1887
  """Return how many transmits the GPU memory estimate fits into the free memory.
1935
1888
 
1936
- The estimate of one GPU grows by the same amount for each transmit. The count
1937
- keeps 10 % of the free memory and 512 MiB free for the CUDA context and for
1938
- what the estimate does not count, and takes the smallest count over the GPUs.
1889
+ The estimate of one GPU grows by the same amount for each transmit. The count is the
1890
+ smallest over the GPUs.
1939
1891
 
1940
1892
  Parameters
1941
1893
  ----------
@@ -1948,18 +1900,21 @@ class Solver:
1948
1900
  The count, or None when the free memory cannot be read.
1949
1901
 
1950
1902
  """
1951
- free = _free_gpu_memory_bytes(self.fullwave_launcher.cuda_device_id.split(","))
1903
+ free = free_gpu_memory_bytes(self.fullwave_launcher.cuda_device_id.split(","))
1952
1904
  if free is None:
1953
1905
  return None
1954
1906
  one = self._gpu_memory_bytes(sensor, n_members=1)
1955
1907
  two = self._gpu_memory_bytes(sensor, n_members=2)
1956
- reserve = 512 * 1024**2
1957
1908
  counts = []
1958
1909
  for (device, one_bytes, *_), (_, two_bytes, *_) in zip(one, two, strict=True):
1959
- per_member = max(two_bytes - one_bytes, 1)
1960
- shared = one_bytes - per_member
1961
- usable = 0.9 * free.get(device, 0) - reserve - shared
1962
- counts.append(int(usable // per_member))
1910
+ per_member_bytes = max(two_bytes - one_bytes, 1)
1911
+ counts.append(
1912
+ members_that_fit(
1913
+ free_bytes=free.get(device, 0),
1914
+ shared_bytes=one_bytes - per_member_bytes,
1915
+ per_member_bytes=per_member_bytes,
1916
+ )
1917
+ )
1963
1918
  return min(counts)
1964
1919
 
1965
1920
  def _estimate_gpu_memory(
@@ -2,10 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import inspect
5
6
  import time
6
7
  import warnings
7
8
  from pathlib import Path
8
- from typing import TYPE_CHECKING
9
+ from typing import TYPE_CHECKING, NamedTuple
9
10
 
10
11
  import numpy as np
11
12
 
@@ -36,15 +37,43 @@ if TYPE_CHECKING:
36
37
  CFL_LIMIT_3D = 0.30
37
38
  SPEED_OPTIMIZED_PPW = 6
38
39
 
40
+ PACKAGE_DIR = Path(__file__).parents[1]
41
+
39
42
  _shown_warnings: set[str] = set()
40
43
 
41
44
 
45
+ def _stacklevel_of_first_caller_outside_package() -> int:
46
+ """Return the ``warnings.warn`` stacklevel of the first frame outside the fullwave package."""
47
+ frame = inspect.currentframe()
48
+ stacklevel = 0
49
+ while frame is not None and Path(frame.f_code.co_filename).is_relative_to(PACKAGE_DIR):
50
+ frame = frame.f_back
51
+ stacklevel += 1
52
+ return stacklevel
53
+
54
+
42
55
  def _warn_once(*, name: str, message: str, category: type[Warning]) -> None:
43
- """Warn with ``message`` the first time ``name`` is seen in this process."""
56
+ """Warn with ``message`` the first time ``name`` is seen in this process.
57
+
58
+ The warning points at the line of the user's code, however deep the call is.
59
+ """
44
60
  if name in _shown_warnings:
45
61
  return
46
62
  _shown_warnings.add(name)
47
- warnings.warn(message, category, stacklevel=5)
63
+ warnings.warn(message, category, stacklevel=_stacklevel_of_first_caller_outside_package())
64
+
65
+
66
+ def warn_sponge_without_ultra() -> None:
67
+ """Warn once per process that ``ultra_sponge_thickness_px`` needs ``use_ultra=True``."""
68
+ _warn_once(
69
+ name="sponge_without_ultra",
70
+ message=(
71
+ "ultra_sponge_thickness_px is ignored without use_ultra=True. The native "
72
+ "absorber is sized by pml_layer_thickness_px (relaxation model) or "
73
+ "exponential_attenuation_pml_thickness_px (exponential model)."
74
+ ),
75
+ category=UserWarning,
76
+ )
48
77
 
49
78
 
50
79
  def warn_ppw_above_speed_optimum(*, ppw: int) -> None:
@@ -72,6 +101,25 @@ def warn_experimental() -> None:
72
101
  )
73
102
 
74
103
 
104
+ def warn_ignored(*, option: str, detail: str = "") -> None:
105
+ """Warn once per process that ``use_ultra=True`` ignores ``option``."""
106
+ suffix = f"; {detail}" if detail else ""
107
+ _warn_once(
108
+ name=f"ignored:{option}",
109
+ message=f"{option} is ignored with use_ultra=True{suffix}.",
110
+ category=UserWarning,
111
+ )
112
+
113
+
114
+ def warn_one_device_only(*, device: int) -> None:
115
+ """Warn once per process that ``use_ultra=True`` runs on one GPU, the first one listed."""
116
+ _warn_once(
117
+ name="one_device_only",
118
+ message=f"cuda_device_id lists several GPUs; use_ultra=True runs on GPU {device} only.",
119
+ category=UserWarning,
120
+ )
121
+
122
+
75
123
  def refuse(message: str) -> None:
76
124
  """Raise ``UltraUnsupportedError`` with ``message``."""
77
125
  raise UltraUnsupportedError(message)
@@ -122,9 +170,12 @@ def single_device(cuda_device_id: str | int | list | None) -> int:
122
170
  devices = list(cuda_device_id)
123
171
  else:
124
172
  devices = [cuda_device_id]
125
- if len(devices) != 1:
126
- refuse("use_ultra=True runs on one GPU; give one cuda_device_id")
127
- return int(devices[0])
173
+ if not devices:
174
+ refuse("cuda_device_id lists no device")
175
+ device = int(devices[0])
176
+ if len(devices) > 1:
177
+ warn_one_device_only(device=device)
178
+ return device
128
179
 
129
180
 
130
181
  def work_directory(
@@ -377,39 +428,70 @@ class UltraBackend3D:
377
428
  )
378
429
 
379
430
 
431
+ SPONGE_HINT = "set the sponge width with ultra_sponge_thickness_px"
432
+
433
+
434
+ class NativeOnlyOption(NamedTuple):
435
+ """An option of the native solver that ``use_ultra=True`` ignores."""
436
+
437
+ solver_default: object
438
+ hint: str = ""
439
+
440
+
441
+ NATIVE_ONLY_OPTIONS: dict[str, NativeOnlyOption] = {
442
+ "pml_layer_thickness_px": NativeOnlyOption(solver_default=None, hint=SPONGE_HINT),
443
+ "n_transition_layer": NativeOnlyOption(solver_default=None, hint=SPONGE_HINT),
444
+ "pml_alpha_entrance": NativeOnlyOption(solver_default=None, hint=SPONGE_HINT),
445
+ "exponential_attenuation_pml_thickness_px": NativeOnlyOption(
446
+ solver_default=None, hint=SPONGE_HINT
447
+ ),
448
+ "use_gpu_pml": NativeOnlyOption(solver_default=False),
449
+ "save_gpu_memory": NativeOnlyOption(solver_default=False),
450
+ "write_maps_the_solver_does_not_read": NativeOnlyOption(solver_default=False),
451
+ "use_isotropic_relaxation": NativeOnlyOption(solver_default=True),
452
+ }
453
+
454
+
455
+ def warn_native_only_options(*, options: dict[str, object]) -> None:
456
+ """Warn once per process for each native-only option set to a non-default value."""
457
+ for name, option in NATIVE_ONLY_OPTIONS.items():
458
+ if options[name] != option.solver_default:
459
+ warn_ignored(option=name, detail=option.hint)
460
+
461
+
462
+ def warn_relaxation_model_requested(*, use_exponential_attenuation: bool) -> None:
463
+ """Warn once per process when the relaxation model is requested, as the native default does."""
464
+ if use_exponential_attenuation:
465
+ return
466
+ _warn_once(
467
+ name="attenuation_model",
468
+ message=(
469
+ "use_ultra=True runs the exponential attenuation model, whose attenuation is "
470
+ "frequency-independent (the same at every frequency), not the relaxation model that "
471
+ "use_exponential_attenuation=False requests, whose attenuation is "
472
+ "frequency-dependent."
473
+ ),
474
+ category=UserWarning,
475
+ )
476
+
477
+
380
478
  def check_solver_options(
381
479
  *,
382
480
  use_pml: bool,
383
481
  m_spatial_order: int,
384
- pml_layer_thickness_px: int | None,
385
- n_transition_layer: int | None,
386
482
  use_gpu: bool,
387
- use_gpu_pml: bool,
388
- pml_alpha_entrance: float | None,
389
483
  source_type: str,
390
- save_gpu_memory: bool,
391
- write_maps_the_solver_does_not_read: bool,
484
+ native_only_options: dict[str, object],
485
+ use_exponential_attenuation: bool,
392
486
  ) -> None:
393
- """Refuse the ``Solver`` options that ``use_ultra=True`` cannot honor."""
487
+ """Refuse the ``Solver`` options that ``use_ultra=True`` cannot honor; warn on the rest."""
394
488
  if not use_pml:
395
489
  refuse("use_pml=False is not supported by use_ultra=True")
396
- if (
397
- pml_layer_thickness_px is not None
398
- or n_transition_layer is not None
399
- or use_gpu_pml
400
- or pml_alpha_entrance is not None
401
- ):
402
- refuse(
403
- "PML settings do not apply to use_ultra=True; "
404
- "set the sponge with exponential_attenuation_pml_thickness_px"
405
- )
406
490
  if m_spatial_order != 8:
407
491
  refuse("use_ultra=True supports m_spatial_order=8 only")
408
492
  if not use_gpu:
409
493
  refuse("use_ultra=True needs the GPU")
410
494
  if source_type not in SOURCE_TYPES:
411
495
  refuse(f"source_type must be one of {SOURCE_TYPES}, not {source_type!r}")
412
- if save_gpu_memory:
413
- refuse("save_gpu_memory is not supported by use_ultra=True")
414
- if write_maps_the_solver_does_not_read:
415
- refuse("write_maps_the_solver_does_not_read does not apply to use_ultra=True")
496
+ warn_native_only_options(options=native_only_options)
497
+ warn_relaxation_model_requested(use_exponential_attenuation=use_exponential_attenuation)