2727from climada import CONFIG
2828from climada .util import ureg
2929from climada .hazard .tc_tracks import TCTracks
30- from climada .hazard .trop_cyclone import TropCyclone ,\
31- _bs_hol08 , _close_centroids , _stat_holland , _vtrans
30+ from climada .hazard .trop_cyclone import (
31+ TropCyclone , _close_centroids , _vtrans , _B_holland_1980 , _bs_holland_2008 ,
32+ _v_max_s_holland_2008 , _x_holland_2010 , _stat_holland_1980 , _stat_holland_2010 )
3233from climada .hazard .centroids .centr import Centroids
3334
3435DATA_DIR = CONFIG .hazard .test_data .dir ()
@@ -91,11 +92,11 @@ def test_set_one_pass(self):
9192 self .assertEqual (tc_haz .intensity .shape , (1 , 296 ))
9293 self .assertEqual (np .nonzero (tc_haz .intensity )[0 ].size , 280 )
9394
95+ np .testing .assert_array_almost_equal (
96+ tc_haz .intensity [0 , intensity_idx ].toarray ()[0 ], intensity_values [metric ])
9497 for idx , val in zip (intensity_idx , intensity_values [metric ]):
9598 if val == 0 :
9699 self .assertEqual (tc_haz .intensity [0 , idx ], 0 )
97- else :
98- self .assertAlmostEqual (tc_haz .intensity [0 , idx ], val )
99100
100101 windfields = tc_haz .windfields [0 ].toarray ()
101102 windfields = windfields .reshape (windfields .shape [0 ], - 1 , 2 )
@@ -104,6 +105,34 @@ def test_set_one_pass(self):
104105 msk = (intensity > 0 )
105106 np .testing .assert_array_equal (windfield_norms [msk ], intensity [msk ])
106107
108+ def test_windfield_models (self ):
109+ """Test _tc_from_track function with different wind field models."""
110+ intensity_idx = [0 , 1 , 2 , 3 , 80 , 100 , 120 , 200 , 220 , 250 , 260 , 295 ]
111+ intensity_values = {
112+ "H08" : [25.60778909 , 26.90887264 , 28.26624642 , 25.54092386 , 31.21941738 , 36.16596567 ,
113+ 21.11399856 , 28.01452136 , 32.65076804 , 31.33884098 , 0 , 40.27002104 ],
114+ "H10" : [27.477252 , 28.626236 , 29.829914 , 27.393616 , 32.495186 , 37.113324 ,
115+ 23.573216 , 29.552127 , 33.767067 , 32.530964 , 19.656737 , 41.014578 ],
116+ # Holland 1980 is the only model that uses recorded wind speeds, while the above use
117+ # pressure values only. That's why the results for Holland 1980 are so different:
118+ "H1980" : [20.291397 , 22.678914 , 25.428598 , 20.44718 , 31.868592 , 41.920317 ,
119+ 0 , 25.715983 , 38.351686 , 35.591153 , 0 , 46.873912 ],
120+ }
121+
122+ tc_track = TCTracks ()
123+ tc_track .read_processed_ibtracs_csv (TEST_TRACK )
124+ tc_track .equal_timestep ()
125+ tc_track .data = tc_track .data [:1 ]
126+
127+ for model in ["H08" , "H10" , "H1980" ]:
128+ tc_haz = TropCyclone ()
129+ tc_haz .set_from_tracks (tc_track , centroids = CENTR_TEST_BRB , model = model )
130+ np .testing .assert_array_almost_equal (
131+ tc_haz .intensity [0 , intensity_idx ].toarray ()[0 ], intensity_values [model ])
132+ for idx , val in zip (intensity_idx , intensity_values [model ]):
133+ if val == 0 :
134+ self .assertEqual (tc_haz .intensity [0 , idx ], 0 )
135+
107136 def test_set_one_file_pass (self ):
108137 """Test set function set_from_tracks with one input."""
109138 tc_track = TCTracks ()
@@ -181,59 +210,78 @@ def test_close_centroids_pass(self):
181210 mask = _close_centroids (t_lat , t_lon , centroids , buffer = 5 )
182211 np .testing .assert_equal (mask , test_mask )
183212
184- def test_bs_hol08_pass (self ):
185- """Test _bs_hol08 function. Compare to MATLAB reference."""
186- v_trans = 5.241999541820597
187- penv = 1010
188- pcen = 1005.263333333329
189- prepcen = 1005.258500000000
190- lat = 12.299999504631343
191- tint = 1
192- _bs_res = _bs_hol08 (v_trans , penv , pcen , prepcen , lat , tint )
193- self .assertAlmostEqual (_bs_res , 1.270856908796045 )
194-
195- v_trans = 5.123882725120426
196- penv = 1010
197- pcen = 1005.268166666671
198- prepcen = 1005.263333333329
199- lat = 12.299999279463769
200- tint = 1
201- _bs_res = _bs_hol08 (v_trans , penv , pcen , prepcen , lat , tint )
202- self .assertAlmostEqual (_bs_res , 1.265551666104679 )
203-
204- def test_stat_holland (self ):
205- """Test _stat_holland function. Compare to MATLAB reference."""
206- d_centr = np .array ([[293.6067129546862 , 298.2652319413182 ]])
207- r_max = np .array ([75.547902916671745 ])
208- hol_b = np .array ([1.265551666104679 ])
209- penv = np .array ([1010.0 ])
210- pcen = np .array ([1005.268166666671 ])
211- lat = np .array ([12.299999279463769 ])
212- mask = np .ones_like (d_centr , dtype = bool )
213-
214- _v_arr = _stat_holland (d_centr , r_max , hol_b , penv , pcen , lat , mask )[0 ]
215- self .assertAlmostEqual (_v_arr [0 ], 5.384115724400597 )
216- self .assertAlmostEqual (_v_arr [1 ], 5.281356766052531 )
217-
218- d_centr = np .array ([[]])
219- mask = np .ones_like (d_centr , dtype = bool )
220- _v_arr = _stat_holland (d_centr , r_max , hol_b , penv , pcen , lat , mask )[0 ]
221- self .assertTrue (np .array_equal (_v_arr , np .array ([])))
222-
213+ def test_B_holland_1980_pass (self ):
214+ """Test _B_holland_1980 function."""
215+ gradient_winds = np .array ([35 , 40 ])
216+ penv = np .array ([1010 , 1010 ])
217+ pcen = np .array ([995 , 980 ])
218+ _B_res = _B_holland_1980 (gradient_winds , penv , pcen )
219+ np .testing .assert_array_almost_equal (_B_res , [2.5 , 1.667213 ])
220+
221+ def test_bs_holland_2008_pass (self ):
222+ """Test _bs_holland_2008 function. Compare to MATLAB reference."""
223+ v_trans = np .array ([5.241999541820597 , 5.123882725120426 ])
224+ penv = np .array ([1010 , 1010 ])
225+ pcen = np .array ([1005.263333333329 , 1005.268166666671 ])
226+ prepcen = np .array ([1005.258500000000 , 1005.263333333329 ])
227+ lat = np .array ([12.299999504631343 , 12.299999279463769 ])
228+ tint = np .array ([1.0 , 1.0 ])
229+ _bs_res = _bs_holland_2008 (v_trans , penv , pcen , prepcen , lat , tint )
230+ np .testing .assert_array_almost_equal (_bs_res , [1.270856908796045 , 1.265551666104679 ])
231+
232+ def test_v_max_s_holland_2008_pass (self ):
233+ """Test _v_max_s_holland_2008 function."""
234+ # Numbers analogous to test_B_holland_1980_pass
235+ penv = np .array ([1010 , 1010 ])
236+ pcen = np .array ([995 , 980 ])
237+ b_s = np .array ([2.5 , 1.67 ])
238+ v_max_s = _v_max_s_holland_2008 (penv , pcen , b_s )
239+ np .testing .assert_array_almost_equal (v_max_s , [34.635341 , 40.033421 ])
240+
241+ def test_holland_2010_pass (self ):
242+ """Test Holland et al. 2010 wind field model."""
243+ # test at centroids within and outside of radius of max wind
244+ d_centr = np .array ([[35e3 , 75e3 , 220e3 ], [30e3 , 1000e3 , 300e3 ]])
245+ r_max = np .array ([75e3 , 40e3 ])
246+ v_max_s = np .array ([35.0 , 40.0 ])
247+ hol_b = np .array ([1.80 , 2.5 ])
248+ mask = np .array ([[True , True , True ], [True , False , True ]], dtype = bool )
249+ hol_x = _x_holland_2010 (d_centr , r_max , v_max_s , hol_b , mask )
250+ np .testing .assert_array_almost_equal (hol_x , [[0.5 , 0.5 , 0.47273 ], [0.5 , 0 , 0.211602 ]])
251+
252+ # test exactly at radius of maximum wind (35 m/s) and at peripheral radius (17 m/s)
253+ v_ang_norm = _stat_holland_2010 (d_centr , v_max_s , r_max , hol_b , mask , hol_x )
254+ np .testing .assert_array_almost_equal (v_ang_norm ,
255+ [[15.957853 , 35.0 , 20.99411 ], [33.854826 , 0 , 17.0 ]])
256+
257+ def test_stat_holland_1980 (self ):
258+ """Test _stat_holland_1980 function. Compare to MATLAB reference."""
223259 d_centr = np .array ([
224- [299.4501244109841 , 291.0737897183741 , 292.5441003235722 ]
260+ [299.4501244109841 , 291.0737897183741 , 292.5441003235722 , 40.665454622610511 ],
261+ [293.6067129546862 , 1000.0 , 298.2652319413182 , 70.0 ],
225262 ])
226- r_max = np .array ([40.665454622610511 ])
227- hol_b = np .array ([1.486076257880692 ])
228- penv = np .array ([1010.0 ])
229- pcen = np .array ([970.8727666672957 ])
230- lat = np .array ([14.089110370469488 ])
263+ r_max = np .array ([40.665454622610511 , 75.547902916671745 ])
264+ hol_b = np .array ([1.486076257880692 , 1.265551666104679 ])
265+ penv = np .array ([1010.0 , 1010.0 ])
266+ pcen = np .array ([970.8727666672957 , 1005.268166666671 ])
267+ lat = np .array ([- 14.089110370469488 , 12.299999279463769 ])
268+ mask = np .array ([[True , True , True , True ], [True , False , True , True ]], dtype = bool )
269+ v_ang_norm = _stat_holland_1980 (d_centr , r_max , hol_b , penv , pcen , lat , mask )
270+ np .testing .assert_array_almost_equal (v_ang_norm ,
271+ [[11.279764005440288 , 11.682978583939310 , 11.610940769149384 , 42.412845 ],
272+ [5.384115724400597 , 0 , 5.281356766052531 , 12.763087 ]])
273+
274+ # without Coriolis force, values are higher, esp. far away from the center:
275+ v_ang_norm = _stat_holland_1980 (d_centr , r_max , hol_b , penv , pcen , lat , mask ,
276+ cyclostrophic = True )
277+ np .testing .assert_array_almost_equal (v_ang_norm ,
278+ [[15.719924 , 16.037052 , 15.980323 , 43.128461 ],
279+ [8.836768 , 0 , 8.764678 , 13.807452 ]])
280+
281+ d_centr = np .array ([[], []])
231282 mask = np .ones_like (d_centr , dtype = bool )
232-
233- _v_arr = _stat_holland (d_centr , r_max , hol_b , penv , pcen , lat , mask )[0 ]
234- self .assertAlmostEqual (_v_arr [0 ], 11.279764005440288 )
235- self .assertAlmostEqual (_v_arr [1 ], 11.682978583939310 )
236- self .assertAlmostEqual (_v_arr [2 ], 11.610940769149384 )
283+ v_ang_norm = _stat_holland_1980 (d_centr , r_max , hol_b , penv , pcen , lat , mask )
284+ np .testing .assert_array_equal (v_ang_norm , np .array ([[], []]))
237285
238286 def test_vtrans_pass (self ):
239287 """Test _vtrans function. Compare to MATLAB reference."""
0 commit comments