When using create_env2d() with a range-depth-dependent ssp and a constant scalar water depth, arlpy creates the environment successfully. However, a subsequent call to compute_transmission_loss() fails with the following Bellhop error:
[BELLHOP] *** FATAL ERROR ***
[BELLHOP] Generated by program or subroutine: READIN
[BELLHOP] Unknown bottom option letter in second position
The above error can be reproduced directly using the range-dependent ssp example from the documentation:
import arlpy.uwapm as pm
import pandas as pd
ssp2 = pd.DataFrame({
0: [1540, 1530, 1532, 1533], # profile at 0 m range
100: [1540, 1535, 1530, 1533], # profile at 100 m range
200: [1530, 1520, 1522, 1525] # profile at 200 m range
}, index=[0, 10, 20, 30]) # depths of the profile entries in m
env = pm.create_env2d(depth=20, soundspeed=ssp2)
pm.compute_transmission_loss(env) # And then calling the tl function
While the error manifests during the transmission loss computation, the issue stems from how the .env file is written by arlpy and how Bellhop interprets it.
Internally, arlpy correctly detects the use of a range-dependent ssp and sets the ssp interpolation flag to 'Q'. It also correctly assumes a flat-bottom environment and sets the bathymetry option to just 'A' (constant depth) without a '*' and does not generate a .bty file.
Individually, both settings are valid. However, in combination, they lead to an edge case that Bellhop cannot handle: when the ssp is range-dependent, Bellhop expects a corresponding .bty file, even if the bottom is flat. Without it, Bellhop fails with the somewhat confusing error above. Bellhop's documentation seem to imply this as well. In the example below a flat bottom is implemented via a .bty file even when the depth is constant across range:

The error can be avoided by explicitly providing a flat, range-dependent bathymetry:
depth = [[0, 20], [200., 20]]
env = pm.create_env2d(depth=depth, soundspeed=ssp2)
This causes arlpy to generate the .bty file and correctly set the bottom flag to 'A*', resolving the issue.
Sggested solutions:
- In my view, the main issue isn’t the edge case itself, but rather that the error message from Bellhop is uninformative. arlpy could proactively catch this configuration in
check_env2d() or _create_env_file() and raise a clear validation error when a range-dependent ssp is provided alongside a scalar depth like so:
'Range-dependent soundspeed profile requires range-dependent bathymetry. Please provide `depth` as a Nx2 array (e.g., [[0, depth], ..., [max_range, depth]])'
And also addressing the example in the documentation.
- Automatically convert scalar depth to a flat range-dependent profile (e.g.,
[0, depth], [max_range, depth]) when soundspeed is range dependent as well.
Thanks for the package!
When using
create_env2d()with a range-depth-dependent ssp and a constant scalar water depth, arlpy creates the environment successfully. However, a subsequent call tocompute_transmission_loss()fails with the following Bellhop error:The above error can be reproduced directly using the range-dependent ssp example from the documentation:
While the error manifests during the transmission loss computation, the issue stems from how the
.envfile is written by arlpy and how Bellhop interprets it.Internally, arlpy correctly detects the use of a range-dependent ssp and sets the ssp interpolation flag to
'Q'. It also correctly assumes a flat-bottom environment and sets the bathymetry option to just'A'(constant depth) without a'*'and does not generate a.btyfile.Individually, both settings are valid. However, in combination, they lead to an edge case that Bellhop cannot handle: when the ssp is range-dependent, Bellhop expects a corresponding
.btyfile, even if the bottom is flat. Without it, Bellhop fails with the somewhat confusing error above. Bellhop's documentation seem to imply this as well. In the example below a flat bottom is implemented via a.btyfile even when the depth is constant across range:The error can be avoided by explicitly providing a flat, range-dependent bathymetry:
This causes arlpy to generate the
.btyfile and correctly set the bottom flag to'A*', resolving the issue.Sggested solutions:
check_env2d()or_create_env_file()and raise a clear validation error when a range-dependent ssp is provided alongside a scalar depth like so:'Range-dependent soundspeed profile requires range-dependent bathymetry. Please provide `depth` as a Nx2 array (e.g., [[0, depth], ..., [max_range, depth]])'And also addressing the example in the documentation.
[0, depth], [max_range, depth]) when soundspeed is range dependent as well.Thanks for the package!