@@ -304,22 +304,61 @@ def test_v_max_s_holland_2008_pass(self):
304304
305305 def test_holland_2010_pass (self ):
306306 """Test Holland et al. 2010 wind field model."""
307- # test at centroids within and outside of radius of max wind
307+ # The parameter "x" is designed to be exactly 0.5 inside the radius of max wind (RMW) and
308+ # to increase or decrease linearly outside of it in radial direction.
309+ #
310+ # An increase (decrease) of "x" outside of the RMW is for cases where the max wind is very
311+ # high (low), but the RMW is still comparably large (small). This means, wind speeds need
312+ # to decay very sharply (only moderately) outside of the RMW to reach the low prescribed
313+ # peripheral wind speeds.
314+ #
315+ # The "hol_b" parameter tunes the meaning of a "comparably" large or small RMW.
308316 si_track = xr .Dataset ({
309- "rad" : ("time" , KM_TO_M * np .array ([75 , 40 ])),
310- "vmax" : ("time" , [35.0 , 40.0 ]),
311- "hol_b" : ("time" , [1.80 , 2.5 ]),
317+ # four test cases:
318+ # - low vmax, moderate RMW: x decreases moderately
319+ # - large hol_b: x decreases sharply
320+ # - very low vmax: x decreases so much, it needs to be clipped at 0
321+ # - large vmax, large RMW: x increases
322+ "rad" : ("time" , KM_TO_M * np .array ([75 , 75 , 75 , 90 ])),
323+ "vmax" : ("time" , [35.0 , 35.0 , 16.0 , 90.0 ]),
324+ "hol_b" : ("time" , [1.75 , 2.5 , 1.9 , 1.6 ]),
312325 })
313- d_centr = KM_TO_M * np .array ([[35 , 75 , 220 ], [30 , 1000 , 300 ]], dtype = float )
314- close_centr = np .array ([[True , True , True ], [True , False , True ]], dtype = bool )
326+ d_centr = KM_TO_M * np .array ([
327+ # first column is for locations within the storm eye
328+ # second column is for locations at or close to the radius of max wind
329+ # third column is for locations outside the storm eye
330+ # fourth column is for locations exactly at the peripheral radius
331+ # fifth column is for locations outside the peripheral radius
332+ [0. , 75 , 220 , 300 , 490 ],
333+ [30 , 74 , 170 , 300 , 501 ],
334+ [21 , 76 , 230 , 300 , 431 ],
335+ [32 , 91 , 270 , 300 , 452 ],
336+ ], dtype = float )
337+ close_centr = np .array ([
338+ # note that we set one of these to "False" for testing
339+ [True , True , True , True , True ],
340+ [True , True , True , True , False ],
341+ [True , True , True , True , True ],
342+ [True , True , True , True , True ],
343+ ], dtype = bool )
315344 hol_x = _x_holland_2010 (si_track , d_centr , close_centr )
316- np .testing .assert_array_almost_equal (
317- hol_x , [[0.5 , 0.5 , 0.47273 ], [0.5 , 0 , 0.211602 ]])
345+ np .testing .assert_array_almost_equal (hol_x , [
346+ [0.5 , 0.500000 , 0.485077 , 0.476844 , 0.457291 ],
347+ [0.5 , 0.500000 , 0.410997 , 0.289203 , 0.000000 ],
348+ [0.5 , 0.497620 , 0.131072 , 0.000000 , 0.000000 ],
349+ [0.5 , 0.505022 , 1.403952 , 1.554611 , 2.317948 ],
350+ ])
318351
319- # test exactly at radius of maximum wind (35 m/s) and at peripheral radius (17 m/s)
320352 v_ang_norm = _stat_holland_2010 (si_track , d_centr , close_centr , hol_x )
321- np .testing .assert_array_almost_equal (v_ang_norm ,
322- [[15.957853 , 35.0 , 20.99411 ], [33.854826 , 0 , 17.0 ]])
353+ np .testing .assert_array_almost_equal (v_ang_norm , [
354+ # first column: converge to 0 when approaching storm eye
355+ # second column: vmax at RMW
356+ # fourth column: peripheral speed (17 m/s) at peripheral radius (unless x is clipped!)
357+ [0.0000000 , 35.000000 , 21.181497 , 17.00000 , 12.103461 ],
358+ [1.2964800 , 34.990037 , 21.593755 , 17.00000 , 0.0000000 ],
359+ [0.3219518 , 15.997500 , 13.585498 , 16.00000 , 16.000000 ],
360+ [24.823469 , 89.992938 , 24.381965 , 17.00000 , 1.9292020 ],
361+ ])
323362
324363 def test_stat_holland_1980 (self ):
325364 """Test _stat_holland_1980 function. Compare to MATLAB reference."""
0 commit comments