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
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-24 14:11 +0000
1"""Constants and defaults for aubellhop.
3This file contains various dataclasses and wrapper classes for storing:
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"""
11from __future__ import annotations
12from dataclasses import dataclass, field
13from enum import Enum
16class FileExt:
17 """Strings to define file extensions.
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 """
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"
38class BHStrings(str, Enum):
39 """String definitions to avoid hard-coding magic strings in the source code
41 This helps prevent typos and permits autocomplete (if your editor is smart enough).
42 """
44 default = "default"
45 none = "none"
47 # dimension
48 two_d = "2D"
49 two_half_d = "2.5D"
50 three_d = "3D"
52 # interpolation
53 linear = "linear"
54 spline = "spline"
55 pchip = "pchip"
56 nlinear = "nlinear"
57 quadrilateral = "quadrilateral"
58 hexahedral = "hexahedral"
60 # ati/bty interpolation
61 curvilinear = "curvilinear"
63 # boundaries
64 vacuum = "vacuum"
65 acousto_elastic = "acousto-elastic"
66 rigid = "rigid"
67 grain = "grain"
69 # bathymetry
70 from_file = "from-file"
71 flat = "flat"
73 # sources
74 line = "line"
75 point = "point"
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"
88 # grid
89 rectilinear = "rectilinear"
90 irregular = "irregular"
92 # volume attenuation
93 thorp = "thorp"
94 francois_garrison = "francois-garrison"
95 biological = "biological"
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"
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"
116class FlagMaps:
117 """Mappings from Bellhop single-char input file options to readable Python options
119 These are also defined with reverse mappings in the form:
121 >>> FlagMaps.soundspeed_interp["S"]
122 "spline"
124 >>> FlagMaps.soundspeed_interp_rev["spline"]
125 "S"
127 """
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 }
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()}
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"})
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"})
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"})