Coverage for python / aubellhop / constants.py: 100%

133 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-05-24 14:11 +0000

1"""Constants and defaults for aubellhop. 

2 

3This file contains various dataclasses and wrapper classes for storing: 

4 

5* List of all external file types and their extensions 

6* String constants used throughout the codebase for autocomplete and error-checking 

7* Mappngs between Bellhop character "flags" and their user-level option name 

8* Default settings for various Bellhop classes 

9""" 

10 

11from __future__ import annotations 

12from dataclasses import dataclass, field 

13from enum import Enum 

14 

15 

16class FileExt: 

17 """Strings to define file extensions. 

18 

19 Using this class avoids typos in the source. 

20 It is also used to loop through files to delete them 

21 when needed before/after Bellhop execution. 

22 """ 

23 

24 arr = ".arr" 

25 ati = ".ati" 

26 bty = ".bty" 

27 log = ".log" 

28 sbp = ".sbp" 

29 shd = ".shd" 

30 prt = ".prt" 

31 ray = ".ray" 

32 env = ".env" 

33 ssp = ".ssp" 

34 brc = ".brc" 

35 trc = ".trc" 

36 

37 

38class BHStrings(str, Enum): 

39 """String definitions to avoid hard-coding magic strings in the source code 

40 

41 This helps prevent typos and permits autocomplete (if your editor is smart enough). 

42 """ 

43 

44 default = "default" 

45 none = "none" 

46 

47 # dimension 

48 two_d = "2D" 

49 two_half_d = "2.5D" 

50 three_d = "3D" 

51 

52 # interpolation 

53 linear = "linear" 

54 spline = "spline" 

55 pchip = "pchip" 

56 nlinear = "nlinear" 

57 quadrilateral = "quadrilateral" 

58 hexahedral = "hexahedral" 

59 

60 # ati/bty interpolation 

61 curvilinear = "curvilinear" 

62 

63 # boundaries 

64 vacuum = "vacuum" 

65 acousto_elastic = "acousto-elastic" 

66 rigid = "rigid" 

67 grain = "grain" 

68 

69 # bathymetry 

70 from_file = "from-file" 

71 flat = "flat" 

72 

73 # sources 

74 line = "line" 

75 point = "point" 

76 

77 # beam 

78 cartesian = "cartesian", 

79 ray = "ray", 

80 hat_cartesian = "hat-cartesian", 

81 hat_ray = "hat-ray", 

82 gaussian_simple = "gaussian-simple", 

83 gaussian_cartesian = "gaussian-cartesian", 

84 gaussian_ray = "gaussian-ray", 

85 omnidirectional = "omnidirectional" 

86 single_beam = "single beam" 

87 

88 # grid 

89 rectilinear = "rectilinear" 

90 irregular = "irregular" 

91 

92 # volume attenuation 

93 thorp = "thorp" 

94 francois_garrison = "francois-garrison" 

95 biological = "biological" 

96 

97 # attenuation units 

98 nepers_per_meter = "nepers per meter" 

99 frequency_dependent = "frequency dependent" 

100 db_per_meter = "dB per meter" 

101 db_per_wavelength = "dB per wavelength" 

102 quality_factor = "quality factor" 

103 loss_parameter = "loss parameter" 

104 

105 # tasks 

106 rays = "rays" 

107 eigenrays = "eigenrays" 

108 arrivals = "arrivals" 

109 arrivals_b = "arrivals-binary" 

110 coherent = "coherent" 

111 incoherent = "incoherent" 

112 semicoherent = "semicoherent" 

113 

114 

115 

116class FlagMaps: 

117 """Mappings from Bellhop single-char input file options to readable Python options 

118 

119 These are also defined with reverse mappings in the form: 

120 

121 >>> FlagMaps.soundspeed_interp["S"] 

122 "spline" 

123 

124 >>> FlagMaps.soundspeed_interp_rev["spline"] 

125 "S" 

126 

127 """ 

128 

129 soundspeed_interp = { 

130 "S": BHStrings.spline, 

131 "C": BHStrings.linear, 

132 "Q": BHStrings.quadrilateral, # TODO: add test 

133 "P": BHStrings.pchip, 

134 "H": BHStrings.hexahedral, # TODO: add test 

135 "N": BHStrings.nlinear, 

136 " ": BHStrings.default, 

137 } 

138 bottom_interp = { 

139 "L": BHStrings.linear, 

140 "C": BHStrings.curvilinear, 

141 } 

142 surface_interp = { 

143 "L": BHStrings.linear, 

144 "C": BHStrings.curvilinear, 

145 } 

146 bottom_boundary_condition = { 

147 "V": BHStrings.vacuum, 

148 "A": BHStrings.acousto_elastic, 

149 "R": BHStrings.rigid, 

150 "G": BHStrings.grain, 

151 "F": BHStrings.from_file, 

152 " ": BHStrings.default, 

153 } 

154 surface_boundary_condition = { 

155 "V": BHStrings.vacuum, 

156 "A": BHStrings.acousto_elastic, 

157 "R": BHStrings.rigid, 

158 "F": BHStrings.from_file, 

159 " ": BHStrings.default, 

160 } 

161 attenuation_units = { 

162 "N": BHStrings.nepers_per_meter, 

163 "F": BHStrings.frequency_dependent, 

164 "M": BHStrings.db_per_meter, 

165 "W": BHStrings.db_per_wavelength, 

166 "Q": BHStrings.quality_factor, 

167 "L": BHStrings.loss_parameter, 

168 " ": BHStrings.default, 

169 } 

170 volume_attenuation = { 

171 "T": BHStrings.thorp, 

172 "F": BHStrings.francois_garrison, 

173 "B": BHStrings.biological, 

174 " ": BHStrings.none, 

175 } 

176 _bathymetry = { 

177 "_": BHStrings.flat, 

178 "~": BHStrings.from_file, 

179 "*": BHStrings.from_file, 

180 " ": BHStrings.default, 

181 } 

182 _altimetry = { 

183 "_": BHStrings.flat, 

184 "~": BHStrings.from_file, 

185 "*": BHStrings.from_file, 

186 " ": BHStrings.default, 

187 } 

188 source_type = { 

189 "R": BHStrings.point, 

190 "X": BHStrings.line, 

191 " ": BHStrings.default, 

192 } 

193 _sbp_file = { 

194 "*": BHStrings.from_file, 

195 "O": BHStrings.omnidirectional, 

196 " ": BHStrings.default, 

197 } 

198 grid_type = { 

199 "R": BHStrings.rectilinear, 

200 "I": BHStrings.irregular, 

201 " ": BHStrings.default, 

202 } 

203 beam_type = { 

204 "C": BHStrings.cartesian, 

205 "R": BHStrings.ray, 

206 "G": BHStrings.hat_cartesian, 

207 "^": BHStrings.hat_cartesian, 

208 "g": BHStrings.hat_ray, 

209 "S": BHStrings.gaussian_simple, 

210 "B": BHStrings.gaussian_cartesian, 

211 "b": BHStrings.gaussian_ray, 

212 " ": BHStrings.default, # = "G" 

213 } 

214 dimension = { 

215 " ": BHStrings.two_d, 

216 "2": BHStrings.two_half_d, 

217 "3": BHStrings.three_d, 

218 } 

219 _single_beam = { 

220 "I": BHStrings.single_beam, 

221 " ": BHStrings.default, 

222 } 

223 task = { 

224 "R": BHStrings.rays, 

225 "E": BHStrings.eigenrays, 

226 "A": BHStrings.arrivals, 

227 "a": BHStrings.arrivals_b, 

228 "C": BHStrings.coherent, 

229 "I": BHStrings.incoherent, 

230 "S": BHStrings.semicoherent, 

231 } 

232 mode = { 

233 "C": BHStrings.coherent, 

234 "I": BHStrings.incoherent, 

235 "S": BHStrings.semicoherent, 

236 } 

237 

238 # reverse maps 

239 soundspeed_interp_rev = {v: k for k, v in soundspeed_interp.items()} 

240 bottom_interp_rev = {v: k for k, v in bottom_interp.items()} 

241 surface_interp_rev = {v: k for k, v in surface_interp.items()} 

242 bottom_boundary_condition_rev = {v: k for k, v in bottom_boundary_condition.items()} 

243 surface_boundary_condition_rev = {v: k for k, v in surface_boundary_condition.items()} 

244 attenuation_units_rev = {v: k for k, v in attenuation_units.items()} 

245 volume_attenuation_rev = {v: k for k, v in volume_attenuation.items()} 

246 _bathymetry_rev = {v: k for k, v in _bathymetry.items()} 

247 _altimetry_rev = {v: k for k, v in _altimetry.items()} 

248 source_type_rev = {v: k for k, v in source_type.items()} 

249 grid_type_rev = {v: k for k, v in grid_type.items()} 

250 beam_type_rev = {v: k for k, v in beam_type.items()} 

251 _single_beam_rev = {v: k for k, v in _single_beam.items()} 

252 task_rev = {v: k for k, v in task.items()} 

253 mode_rev = {v: k for k, v in mode.items()} 

254 dimension_rev = {v: k for k, v in dimension.items()} 

255 

256@dataclass 

257class ModelDefaults: 

258 """Defaults within the Bellhop model class.""" 

259 name_2d: str = field(default="bellhop", metadata={"desc": "Name of the class instance for the 2D model"}) 

260 name_3d: str = field(default="bellhop3d", metadata={"desc": "Name of the class instance for the 3D model"}) 

261 exe_2d: str = field(default="bellhop.exe", metadata={"desc": "Executable filename for the 2D model"}) 

262 exe_3d: str = field(default="bellhop3d.exe",metadata={"desc": "Executable filename for the 3D model"}) 

263 dim_2d: int = field(default=2, metadata={"desc": "Number of dimensions in the 2D model"}) 

264 dim_3d: int = field(default=3, metadata={"desc": "Number of dimensions in the 3D model"}) 

265 

266@dataclass 

267class MiscDefaults: 

268 """Defaults for parameters within setup code.""" 

269 beam_angle_halfspace: float = field(default=90.0, metadata={"units": "deg"}) 

270 beam_angle_fullspace: float = field(default=180.0, metadata={"units": "deg"}) 

271 beam_bearing_halfspace: float = field(default=90.0, metadata={"units": "deg"}) 

272 beam_bearing_fullspace: float = field(default=180.0, metadata={"units": "deg"}) 

273 density: float = field(default=1000.0, metadata={"units": "kg/m^3", "desc": "Constant density of the medium"}) 

274 sound_speed: float = field(default=1500.0, metadata={"units": "m/s", "desc": "Constant speed of sound in the medium"}) 

275 

276@dataclass 

277class EnvDefaults: 

278 """Defaults for the Environment class.""" 

279 attenuation_units: str = field(default=BHStrings.frequency_dependent, metadata={"desc": "Attenuation units to define volume attenuation (when setting `bottom_attenuation`, etc)"}) 

280 bottom_attenuation: float = field(default=0.1, metadata={"units": "scale factor","desc": "When acousto-elastic bottom boundary condition is selected, this is the attenuation factor"}) 

281 bottom_boundary_condition: str = field(default=BHStrings.acousto_elastic, metadata={"desc": "Standard boundary condition for seabed"}) 

282 bottom_interp: str = field(default=BHStrings.linear, metadata={"desc": "Interpolation for bathymetry depths"}) 

283 comment_pad: int = field(default=50, metadata={"desc": "Number of characters used before the comment in the constructed .env files."}) 

284 dimension: str = field(default=BHStrings.two_d, metadata={"desc": "Dimension of simulation (2D, 2.5D, 3D)"}) 

285 _dimension: int = field(default=2, metadata={"desc": "Dimension of model (2, 3)"}) 

286 frequency: float = field(default=25000.0, metadata={"desc": "Frequency of sound propagation", "units": "Hz"}) 

287 interference_mode: str = field(default=BHStrings.coherent, metadata={"desc": "Mode of interference when calculating transmission loss"}) 

288 simulation_depth_scale: float = field(default=1.01,metadata={'desc': 'Scaling factor on the maximum depth of the bathymetry to calculate the maximum simulation depth extent.'}) 

289 simulation_range_scale: float = field(default=1.1,metadata={'desc': 'Scaling factor on the maximum range of the receivers to calculate the maximum simulation range extent.'}) 

290 simulation_cross_range_scale: float = field(default=2.0,metadata={'desc': 'Scaling factor on the maximum cross range of the receivers (based on maximum bearing angle) to calculate the maximum simulation cross range extent.'}) 

291 simulation_cross_range_min: float = field(default=10.0,metadata={'desc': 'For very small bearing angles there may be numerical issues with a cross range size approaching zero. This parameter specifies the minimum cross range size of the simulation extent.',"units": "m"}) 

292 soundspeed_interp: str = field(default=BHStrings.linear, metadata={"desc": "Interpolation for sound speed profile data"}) 

293 surface_depth: float = field(default=0.0, metadata={"units": "m", "desc": "Depth of the surface. Should always be `0.0` for flat altimetry."}) 

294 surface_interp: str = field(default=BHStrings.linear, metadata={"desc": "Interpolation for altimetry surface depths"}) 

295 volume_attenuation: str = field(default=BHStrings.none, metadata={"desc": "Type of volume attenuation to apply"}) 

296