77#
88
99import xarray as xr
10+ import numpy as np
1011from pyremap import LatLon2DGridDescriptor
1112
1213from mpas_analysis .shared import AnalysisTask
@@ -208,7 +209,7 @@ def setup_and_check(self):
208209
209210 def customize_masked_climatology (self , climatology , season ):
210211 """
211- Compute the risk index outcome from sea-ice concentration and thickness.
212+ Compute the risk index outcome from sea-ice concentration and (floe) thickness.
212213
213214 Parameters
214215 ----------
@@ -232,22 +233,27 @@ def customize_masked_climatology(self, climatology, season):
232233
233234 def _compute_risk_index_outcome (self , climatology ):
234235 """
235- Compute the risk index outcome from sea-ice concentration and thickness.
236+ Compute the risk index outcome from sea-ice concentration and (floe) thickness,
237+ as outlined in by International Maritime Organization (IMO) document.
236238 (https://www.imorules.com/GUID-2C1D86CB-5D58-490F-B4D4-46C057E1D102.html)
237239 """
238240 ds_restart = xr .open_dataset (self .restartFileName )
239241 ds_restart = ds_restart .isel (Time = 0 )
240242
243+ # sea-ice concentration conversion from range [0,1] to range [0,10]
241244 scale_factor = 10
242- pc = self .config .get (self .taskName , 'polarClass' ) - 1
243-
244- concentration = climatology ['timeMonthly_avg_iceAreaCell' ]
245- thickness = climatology ['timeMonthly_avg_iceVolumeCell' ]
245+ # polar class array index should be in the range [0,11], but not checked!
246+ pc = self .config .getint (self .taskName , 'polarClass' ) - 1
246247
248+ # this are labels that should appear in the plot, to indicate the Polar Class of the vessel (included here for the moment)
247249# pic = ["PC1", "PC2", "PC3", "PC4", "PC5", "PC6", "PC7", "IA Super",\
248250# "IA", "IB", "IC", "Not Ice Strengthened"]
249251
252+ # reference floe thicknesses for calculation of Risk Index Values
253+ # (this values were agreed upon by Elizabeth Hunke, Andrew Roberts,
254+ #and Gennaro D'Angelo based on literature and IMO description)
250255 h_riv = np .array ([0.5 , 10 , 15 , 30 , 50 , 70 , 100 , 120 , 170 , 200 , 250 ]) * 0.01
256+ # table of Risk Index Values (defined by IMO)
251257 riv = np .array ([[ 3 , 3 , 3 , 3 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 1 ],\
252258 [ 3 , 3 , 3 , 3 , 2 , 2 , 2 , 2 , 2 , 1 , 1 , 0 ],\
253259 [ 3 , 3 , 3 , 3 , 2 , 2 , 2 , 2 , 2 , 1 , 0 ,- 1 ],\
@@ -261,19 +267,34 @@ def _compute_risk_index_outcome(self, climatology):
261267 [ 3 , 2 , 1 , 0 ,- 1 ,- 2 ,- 3 ,- 4 ,- 5 ,- 6 ,- 7 ,- 8 ],\
262268 [ 3 , 1 , 0 ,- 1 ,- 2 ,- 3 ,- 4 ,- 5 ,- 6 ,- 7 ,- 8 ,- 8 ]])
263269
264- riv_iceCell = np .nan * np .ones (np .shape (thickness ))
270+ concentration = climatology ['timeMonthly_avg_iceAreaCell' ]
271+ thickness = climatology ['timeMonthly_avg_iceVolumeCell' ]
265272
273+ # these lines may not be required, but rio should not be used
274+ # to check concentration and thickness
275+ concentration [np .where (concentration < 0.0 )] = 0.0
276+ concentration [np .where (concentration > 1.0 )] = 1.0
277+ thickness [np .where (concentration == 0.0 )] = 0.0
278+
279+ # introduce riv array and set values in open water
280+ riv_iceCell = np .nan * np .ones (np .shape (thickness ))
266281 riv_mask = np .where (thickness < h_riv [0 ])
267282 riv_iceCell [riv_mask ] = riv [pc , 0 ]
268283
284+ # set riv values for chosen Polar Class of vessel
269285 for ind in range (len (h_riv )- 1 ):
270286# riv_mask = np.logical_and(thickness >= h_riv[ind], thickness < h_riv[ind+1])
271287 riv_mask = np .where (thickness >= h_riv [ind ])
272288 riv_iceCell [riv_mask ] = riv [pc , ind + 1 ]
273289
290+ # set riv for highest floe thickness
274291 riv_mask = np .where (thickness >= h_riv [- 1 ])
275292 riv_iceCell [riv_mask ] = riv [pc , - 1 ]
276293
277- rio = ((1.0 - concentration ) * riv [pc , 0 ] + concentration * riv_iceCell ) * units_scale_factor
294+ # Risk Index Outcome for single-category ice. There are only
295+ # two terms per cell: one coming from the fraction of the cell
296+ # occupied by open water and one coming from the fraction occupied
297+ # by sea ice (rio <= 30 by IMO definition)
298+ rio = scale_factor * ((1.0 - concentration ) * riv [pc , 0 ] + concentration * riv_iceCell )
278299
279300 return rio
0 commit comments