AUBELLHOP: 3D models

The Python Bellhop wrapper supports multiple models, which can be automatically detected depending on the environment parameters and task being computed. The main feature this enables is to provide seamless access to Bellhop3D.

1 Bellhop3D environment definition

Bellhop3D differs from Bellhop (2D) in roughly four ways:

  • Sources and receivers are now defined in 3D:
    • The source location can be shifted to any \((x,y,z)\) coordinate
    • The receiver locations can vary in their bearing angle \(\theta\), with positions defined in cylindical coordinates \((r,\theta,z)\)
  • Altimetry, bathymetry, speed of sound profiles, etc., are defined in 3D.
  • The beam fan is defined in both spherical directions (elevation, bearing).
  • The simulation can be set to either 2.5D or full 3D:
    • 3D allows refraction horizontally due to lateral changes in sound speed;
    • 2.5D traces beams along 3D directions but every beam is restricted to travel along a vertically-oriented plane (i.e., a straight line when viewed from above).

2 Bellhop3D rays

Load Bellhop and check the standard models available out of the box:

Code
import aubellhop as bh
import aubellhop.plot as bhp
print(bh.Models.supported())
['bellhop', 'bellhop3d']

Now define a standard 2D and 3D case and do some computations on them:

Code
env2d = bh.Environment(name="Example Bellhop2D",dimension="2D").check()
env3d = bh.Environment(name="Example Bellhop3D",dimension="3D").check()
output, ind = bh.compute(env=[env2d, env3d],task=["rays"])
print(ind)
                name model  task
i                               
0  Example Bellhop2D  None  rays
1  Example Bellhop3D  None  rays

Now look at the results:

Code
print("Size of output:")
print(f"2D rays: N={len(output[0]['results'])}")
print(f"3D rays: N={len(output[1]['results'])}")

print("Each ray data structure:")
print(output[0]['results'].iloc[1,:])
print(output[1]['results'].iloc[1,:])

print("Ray details 2D:")
print(output[0]['results'].iloc[1,:]['ray'])

print("Ray details 3D:")
print(output[1]['results'].iloc[1,:]['ray'])
Size of output:
2D rays: N=50
3D rays: N=2500
Each ray data structure:
angle_of_departure                                           -86.326531
surface_bounces                                                       1
bottom_bounces                                                        1
ray                   [[0.0, 5.0], [0.16017554995178238, 2.505136518...
Name: 0, dtype: object
angle_of_departure                                            -1.506682
surface_bounces                                                       1
bottom_bounces                                                        1
ray                   [[0.0, 0.0, 5.0], [9.807923727505864e-18, -0.1...
Name: 0, dtype: object
Ray details 2D:
[[0.00000000e+00 5.00000000e+00]
 [1.60175550e-01 2.50513652e+00]
 [3.20351100e-01 1.02730362e-02]
 [3.21010651e-01 0.00000000e+00]
 [3.21010651e-01 0.00000000e+00]
 [4.81186201e-01 2.49486348e+00]
 [6.41361751e-01 4.98972696e+00]
 [8.01537301e-01 7.48459045e+00]
 [9.61712851e-01 9.97945393e+00]
 [1.12188840e+00 1.24743174e+01]
 [1.28206395e+00 1.49691809e+01]
 [1.44223950e+00 1.74640444e+01]
 [1.60241505e+00 1.99589079e+01]
 [1.76259060e+00 2.24537713e+01]
 [1.92276615e+00 2.49486348e+01]
 [1.92606390e+00 2.50000000e+01]
 [1.92606390e+00 2.50000000e+01]]
Ray details 3D:
[[ 0.00000000e+00  0.00000000e+00  5.00000000e+00]
 [ 9.80792373e-18 -1.60175550e-01  2.50513652e+00]
 [ 1.96158475e-17 -3.20351100e-01  1.02730362e-02]
 [ 1.96562333e-17 -3.21010651e-01  0.00000000e+00]
 [ 1.96562333e-17 -3.21010651e-01  0.00000000e+00]
 [ 2.94641570e-17 -4.81186201e-01  2.49486348e+00]
 [ 3.92720807e-17 -6.41361751e-01  4.98972696e+00]
 [ 4.90800045e-17 -8.01537301e-01  7.48459045e+00]
 [ 5.88879282e-17 -9.61712851e-01  9.97945393e+00]
 [ 6.86958519e-17 -1.12188840e+00  1.24743174e+01]
 [ 7.85037757e-17 -1.28206395e+00  1.49691809e+01]
 [ 8.83116994e-17 -1.44223950e+00  1.74640444e+01]
 [ 9.81196231e-17 -1.60241505e+00  1.99589079e+01]
 [ 1.07927547e-16 -1.76259060e+00  2.24537713e+01]
 [ 1.17735471e-16 -1.92276615e+00  2.49486348e+01]
 [ 1.17937400e-16 -1.92606390e+00  2.50000000e+01]
 [ 1.17937400e-16 -1.92606390e+00  2.50000000e+01]]

2.1 Minimal example 2D

Code
import aubellhop as bh
import aubellhop.plot as bhp

env2d = bh.Environment(name="Example Bellhop2D",dimension="2D",beam_angle_min=-45,beam_angle_max=45).check()
rays2d = bh.compute_eigenrays(env2d)
print(env2d)
bhp.plot_rays(rays2d,env=env2d)
{'_altimetry': <BHStrings.flat: 'flat'>,
 '_bathymetry': <BHStrings.flat: 'flat'>,
 '_bottom_attenuation_shear': None,
 '_bottom_depth': None,
 '_bottom_soundspeed_shear': 0.0,
 '_depth_max': 25.0,
 '_depth_sigma': 0.0,
 '_dimension': 2,
 '_fg_depth': None,
 '_fg_pH': None,
 '_fg_salinity': None,
 '_fg_temperature': None,
 '_from_file': None,
 '_mesh_npts': 0,
 '_num_media': 1,
 '_range_max': np.float64(1000.0),
 '_receiver_num': 1,
 '_sbp_file': <BHStrings.default: 'default'>,
 '_single_beam': <BHStrings.default: 'default'>,
 '_source_num': 1,
 '_surface_attenuation_shear': None,
 '_surface_min': 0.0,
 '_surface_soundspeed_shear': 0.0,
 'attenuation_units': <BHStrings.frequency_dependent: 'frequency dependent'>,
 'beam_angle_max': 45,
 'beam_angle_min': -45,
 'beam_bearing_max': 90.0,
 'beam_bearing_min': -90.0,
 'beam_bearing_num': 0,
 'beam_component': None,
 'beam_epsilon_multipler': None,
 'beam_images_num': None,
 'beam_num': 0,
 'beam_range_loop': None,
 'beam_reflection_curvature_change': None,
 'beam_reflection_shift': None,
 'beam_type': <BHStrings.default: 'default'>,
 'beam_width_type': None,
 'beam_window': None,
 'biological_layer_parameters': None,
 'bottom_attenuation': 0.1,
 'bottom_beta': None,
 'bottom_boundary_condition': <BHStrings.acousto_elastic: 'acousto-elastic'>,
 'bottom_density': 1000.0,
 'bottom_depth': 25.0,
 'bottom_grain_size': None,
 'bottom_interp': <BHStrings.linear: 'linear'>,
 'bottom_reflection_coefficient': None,
 'bottom_roughness': 0.0,
 'bottom_soundspeed': 1500.0,
 'bottom_transition_freq': None,
 'comment_pad': 50,
 'dimension': '2D',
 'frequency': 25000.0,
 'grid_type': <BHStrings.default: 'default'>,
 'interference_mode': None,
 'name': 'Example Bellhop2D',
 'receiver_bearing': 0.0,
 'receiver_depth': 10.0,
 'receiver_nbearing': 1,
 'receiver_ndepth': 1,
 'receiver_nrange': 1,
 'receiver_range': 1000.0,
 'simulation_cross_range': np.float64(2000.0),
 'simulation_cross_range_min': 10.0,
 'simulation_cross_range_scale': 2.0,
 'simulation_depth': 25.25,
 'simulation_depth_scale': 1.01,
 'simulation_range': np.float64(1100.0),
 'simulation_range_scale': 1.1,
 'single_beam_index': None,
 'soundspeed':         speed
depth        
0.0    1500.0
25.0   1500.0,
 'soundspeed_interp': <BHStrings.linear: 'linear'>,
 'source_cross_range': 0.0,
 'source_depth': 5.0,
 'source_directionality': None,
 'source_ncrossrange': 1,
 'source_ndepth': 1,
 'source_nrange': 1,
 'source_range': 0.0,
 'source_type': <BHStrings.default: 'default'>,
 'step_size': 0.0,
 'surface_attenuation': None,
 'surface_boundary_condition': <BHStrings.vacuum: 'vacuum'>,
 'surface_density': 1000.0,
 'surface_depth': 0.0,
 'surface_interp': <BHStrings.linear: 'linear'>,
 'surface_min': None,
 'surface_reflection_coefficient': None,
 'surface_soundspeed': 1500.0,
 'task': None,
 'volume_attenuation': <BHStrings.none: 'none'>}

2.2 Minimal example 3D (bokeh)

Only a 2D projection can be plotted (essentially, y-axis ignored):

Code
import aubellhop as bh
import aubellhop.plot as bhp

env3d = bh.Environment(name="Example Bellhop3D",dimension="3D",beam_angle_min=-45,beam_angle_max=45).check()
rays3d = bh.compute_eigenrays(env3d)
bhp.plot_rays(rays3d,env=env3d)

2.3 Minimal example 2D (matplotlib)

Code
import aubellhop as bh
import aubellhop.pyplot as bhp

env2d = bh.Environment(name="Example Bellhop2D",dimension="2D",beam_angle_min=-45,beam_angle_max=45,beam_num=10_000).check()
rays2d = bh.compute_eigenrays(env2d)

bhp.pyplot_rays(rays2d,env=env2d)

2.4 Minimal example 3D (matplotlib)

Code
import matplotlib.pyplot as plt
import aubellhop as bh
import aubellhop.pyplot as bhp

env3d = bh.Environment(name="Example Bellhop3D",dimension="3D",beam_angle_min=-45,beam_angle_max=45,beam_num=10_000).check()
rays3d = bh.compute_eigenrays(env3d)

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
bhp.pyplot_rays(rays3d,env=env3d,ax=ax)
plt.show(fig)
plt.close(fig)