We often need 1D, 2D or 3D positions to describe the location of a source, receiver, or other object in the underwater environment. The canonical representation for positions is a named 3-tuple of coordinates of the form (x=0.0, y=0.0, z=0.0). We define the generic data type XYZ to represent such a named tuple:
const XYZ =NamedTuple{(:x,:y,:z)}
It is sometimes more convenient to represent positions in simpler forms, with just a single or two-coordinates. In most places where positions are expected, we automatically convert various input representations to a XYZ. This allows the user to specify scalars, tuples, or named tuples as input. For example, the AcousticReceiver(⋯) accepts receiver position as input:
usingUnderwaterAcoustics# The following are all equivalent:@infoAcousticReceiver((x=0, y=0, z=-10)).pos@infoAcousticReceiver((x=0, z=-10)).pos@infoAcousticReceiver((z=-10,)).pos@infoAcousticReceiver((0, 0, -10)).pos@infoAcousticReceiver((0, -10)).pos@infoAcousticReceiver(-10).pos@infoAcousticReceiver(0, 0, -10).pos@infoAcousticReceiver(0, -10).pos
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
[ Info: (x = 0.0, y = 0.0, z = -10.0)
The last two forms are only available in functions that accept no other positional arguments (other than position), and therefore do not cause any confusion as to the meaning of positional arguments.
Units
We also support units though Unitful.jl. Internally, all quantities are represented as floating point numbers without explicit units, with standard units (mostly SI units) assumed implicitly. Input quantities are automatically converted to the implicit units as necessary. For example, positions can be specified with units:
# The following are all equivalent:@infoAcousticReceiver(1000, -10).pos@infoAcousticReceiver(1000u"m", -10u"m").pos@infoAcousticReceiver(1u"km", -10u"m").pos@infoAcousticReceiver((1u"km", -10u"m")).pos@infoAcousticReceiver((x=1u"km", z=-1000u"cm")).pos
[ Info: (x = 1000.0, y = 0.0, z = -10.0)
[ Info: (x = 1000.0, y = 0.0, z = -10.0)
[ Info: (x = 1000.0, y = 0.0, z = -10.0)
[ Info: (x = 1000.0, y = 0.0, z = -10.0)
[ Info: (x = 1000.0, y = 0.0, z = -10.0)
We may also use units in other places:
@showsoundspeed(0u"°C");@showsoundspeed(32u"°F");@showreflection_coef(10°, 1.2, 1.5); # const ° is defined as u"°"@showabsorption(10u"kHz");
While standard UnderwaterAcoustics.jl API functions automatically convert input values to the appropriate XYZ and units, you may wish to support these features in your own code when extending UnderwaterAcoustics.jl. To do so, you may use the unexported function xyz(⋯) to create a position from various different forms. You may also use the unexported in_units(⋯) function to convert input values to the appropriate units:
usingUnderwaterAcoustics: XYZ, in_unitsfunctionmyfunction(pos, temperature) pos =xyz(pos) temperature =in_units(u"°C", temperature)# ⋯end
API reference
xyz(pos)xyz(x, y, z)xyz(x, z)xyz(z)
Convert a position to a named tuple with fields x, y, and z. If any of the coordinates is not provided, they are assumed to be zero. If the coordinates have units, they are converted to meters.
in_units(u, x)
Get the numerical value of x in units of u. If x is a Unitful.Quantity, it is converted to u. If x is a number, it is assumed to be in u and is returned as is.
If u is u"dB", the x may be specified as a number of a u"dB" quantity. In both cases, the numerical value of x in dB is returned.