1
1
"""A class that provides the Kirchhoff ray mode scattering model."""
2
2
3
3
from math import log10 , pi , sqrt , cos , sin , radians
4
+ from cmath import exp
4
5
import numpy as np
6
+ from scipy .special import j0 , y0 , jvp , yvp
5
7
from .utils import wavenumber , as_dict
6
8
from .scattermodelbase import ScatterModelBase
7
- from .krmdata import KRMfish , KRMshape
9
+ from .krmdata import KRMshape
8
10
9
11
10
12
def _u (x , z , theta ):
@@ -54,7 +56,11 @@ def validate_parameters(self, params):
54
56
def calculate_ts_single (self , medium_c , medium_rho , theta , f , bodies ,
55
57
validate_parameters = True , ** kwargs ) -> float :
56
58
"""
57
- Calculate the scatter using the kirchhoff ray mode model for one set of parameters.
59
+ Calculate the scatter using the Kirchhoff ray mode model for one set of parameters.
60
+
61
+ Warning
62
+ --------
63
+ The low _ka_ part of this model has not yet been verified to give correct results.
58
64
59
65
Parameters
60
66
----------
@@ -68,11 +74,11 @@ def calculate_ts_single(self, medium_c, medium_rho, theta, f, bodies,
68
74
conventions/#coordinate-systems) [°].
69
75
f : float
70
76
Frequency to calculate the scattering at [Hz].
71
- bodies: KRMfish
77
+ bodies: KRMorganism
72
78
The body shapes that make up the model. Currently, `bodies` should contain only two
73
79
shapes, one of which should have a boundary of `fluid` (aka, the fish body) and the
74
- other a boundary of `soft` (aka, the swimbladder). KRMfish .shapes[0] should be the
75
- fish body and KRMfish .shapes[1] the swimbladder.
80
+ other a boundary of `soft` (aka, the swimbladder). KRMorganism .shapes[0] should be the
81
+ fish body and KRMorganism .shapes[1] the swimbladder.
76
82
validate_parameters : bool
77
83
Whether to validate the model parameters.
78
84
@@ -83,7 +89,7 @@ def calculate_ts_single(self, medium_c, medium_rho, theta, f, bodies,
83
89
84
90
Notes
85
91
-----
86
- The class implements the code in Clay & Horne (1994) and when ka < 0.15 as per Clay (1992).
92
+ The class implements the code in Clay & Horne (1994) and when ka < 0.15 uses Clay (1992).
87
93
88
94
References
89
95
----------
@@ -126,14 +132,15 @@ def calculate_ts_single(self, medium_c, medium_rho, theta, f, bodies,
126
132
R_bc = (gp * hp - 1 ) / (gp * hp + 1 ) # Eqn (9)
127
133
128
134
# Equivalent radius of swimbladder (as per Part A of paper)
129
- a_e = sqrt (self ._volume (swimbladder )
130
- / (pi * (np .max (swimbladder .x ) - np .min (swimbladder .x ))))
131
- a_e = 10
135
+ a_e = sqrt (swimbladder .volume () / (pi * swimbladder .length ()))
132
136
133
137
# Choose which modelling approach to use
134
138
if k * a_e < 0.15 :
135
139
# Do the mode solution for the swimbladder (and ignore the body?)
136
- mode_sl = self ._mode_solution (swimbladder )
140
+ # TODO: need to check if it should be target or medium for the numerators
141
+ g = target_rho / swimbladder_rho
142
+ h = target_c / target_c
143
+ mode_sl = self ._mode_solution (swimbladder , g , h , k , a_e , swimbladder .length (), theta )
137
144
return 20 * log10 (abs (mode_sl ))
138
145
139
146
# Do the Kirchhoff-ray approximation for the swimbladder and body
@@ -142,13 +149,53 @@ def calculate_ts_single(self, medium_c, medium_rho, theta, f, bodies,
142
149
143
150
return 20 * log10 (abs (soft_sl + fluid_sl ))
144
151
145
- def _volume (self , shape ):
146
- """Volume of the object."""
147
- return 1.0
152
+ def _mode_solution (self , swimbladder : KRMshape , g : float , h : float ,
153
+ k : float , a : float , L_e : float , theta : float ) -> float :
154
+ """Backscatter from a soft swimbladder at low ka.
155
+
156
+ Parameters
157
+ ----------
158
+ swimbladder :
159
+ The shape.
160
+ g :
161
+ Ratio of medium density over swimbladder density.
162
+ h :
163
+ Ratio of medium sound speed over swimbladder sound speed.
164
+ k :
165
+ The wavenumber in the medium surrounding the swimbladder.
166
+ a :
167
+ Equivalent radius of swimbladder [m].
168
+ L_e :
169
+ Equivalent length of swimbladder [m].
170
+ theta :
171
+ Pitch angle to calculate the scattering at, as per the echoSMs
172
+ [coordinate system](https://ices-tools-dev.github.io/echoSMs/
173
+ conventions/#coordinate-systems) [°].
174
+
175
+ Returns
176
+ -------
177
+ :
178
+ The scattering length [m].
179
+ """
180
+ # Note: equation references in this function are to Clay (1992)
181
+ if h == 0.0 :
182
+ raise ValueError ('Ratio of sound speeds (h) cannot be zero for low ka solution.' )
183
+
184
+ # Chi is approximately this. More accurate equations are in Appendix B of Clay (1992)
185
+ chi = - pi / 4 # Eqn (B10) and paragraph below that equation
186
+
187
+ ka = k * a
188
+ kca = ka / h
189
+
190
+ C_0 = (jvp (0 , kca )* y0 (ka ) - g * h * yvp (0 , ka )* j0 (kca ))\
191
+ / (jvp (0 , kca )* j0 (ka ) - g * h * jvp (0 , ka )* j0 (kca )) # Eqn (A1) with m=0
192
+ b_0 = - 1 / (1 + 1j * C_0 ) # Also Eqn (A1)
193
+
194
+ delta = k * L_e * cos (theta ) # Eqn (4)
195
+
196
+ S_M = (exp (1j * (chi - pi / 4 )) * L_e )/ pi * sin (delta )/ delta * b_0 # Eqn (15)
148
197
149
- def _mode_solution (self , swimbladder ):
150
- """Backscatter from a soft swimbladder at low ka."""
151
- return - 1.
198
+ return S_M
152
199
153
200
def _soft_KA (self , swimbladder , k , k_b , R_bc , TwbTbw , theta ):
154
201
"""Backscatter from a soft object using the Kirchhoff approximation."""
0 commit comments