1414#
1515# Copyright 2015, 2023, Knut-Frode Dagestad, MET Norway
1616# Copyright 2024, Lenny Hucher, NERSC, Norway
17- # Copyright 2023, 2024, 2025 Achref Othmani, NERSC, Norway
17+ # Copyright 2023, 2025 Achref Othmani, NERSC, Norway
1818
1919"""
2020This code is initiated from the following reference with posterior modifications.
@@ -68,59 +68,71 @@ class IcebergObj(LagrangianArray):
6868 'default' : 30 ,
6969 'description' : 'Width of iceberg)' ,
7070 'level' : CONFIG_LEVEL_ESSENTIAL }),
71- ('weight_coeff' , {'dtype' : np .float32 , # Relative to the shape of iceberg (e.g. 1 for tabular; 0.3 for pinnacle: It affects the mass only)
72- 'units' : '1' ,
73- 'default' : 1 }),
74- ('water_drag_coeff' , {'dtype' : np .float32 , # Ocean drag coeff.
75- 'units' : '1' ,
76- 'default' : 0.25 }),
77- ('wind_drag_coeff' , {'dtype' : np .float32 , # Wind/Air drag coeff.
78- 'units' : '1' ,
79- 'default' : 0.7 }),
80- ("iceb_x_velocity" , {"dtype" : np .float32 , # Iceberg velocity in the x-direction
81- "units" : "m/s" ,
82- "default" : 0.0 }),
83- ("iceb_y_velocity" , {"dtype" : np .float32 , # Iceberg velocity in the y-direction
84- "units" : "m/s" ,
85- "default" : 0.0 }),
71+ ('weight_coef' , {'dtype' : np .float32 , #This parameter is relative to the shape of iceberg (e.g. 1 for tabular; 0.3 for pinnacle: It affects the mass only)
72+ 'units' : '1' ,
73+ 'default' : 1 }),
74+ ('water_form_drag_coef' , {'dtype' : np .float32 , #Ocean form drag coef. (Cw, IK)
75+ 'units' : '1' ,
76+ 'default' : 0.25 }),
77+ ('water_skin_drag_coef' , {'dtype' : np .float32 , #Ocean skin drag coef. (Cdw, IK)
78+ 'units' : '1' ,
79+ 'default' : 0.0055 }),
80+ ('wind_form_drag_coef' , {'dtype' : np .float32 , #Wind/Air form drag coef. (Ca, IK)
81+ 'units' : '1' ,
82+ 'default' : 0.8 }),
83+ ('wind_skin_drag_coef' , {'dtype' : np .float32 , #Wind/Air skin drag coef. (Cda, IK)
84+ 'units' : '1' ,
85+ 'default' : 0.0022 }),
86+ ("iceb_x_velocity" , {'dtype' : np .float32 , #Iceberg velocity in the x-direction
87+ 'units' : "m/s" ,
88+ 'default' : 0.0 }),
89+ ("iceb_y_velocity" , {'dtype' : np .float32 , #Iceberg velocity in the y-direction
90+ 'units' : "m/s" ,
91+ 'default' : 0.0 }),
8692 ])
8793
8894
8995# Define the functions needed
90- def ocean_force (iceb_vel , water_vel , Ao , rho_water , water_drag_coef ):
96+ def ocean_force (iceb_vel , water_vel , Avo , Aho , rho_water , water_form_drag_coef , water_skin_drag_coef ):
9197 """ Ocean force
9298 Args:
9399 iceb_vel : Iceberg's velocity at time t
94100 water_vel : Ocean current velocity
95- Ao : Iceberg's area in contact with ocean (length x draft)
96101 rho_water : Water density
97- water_drag_coef : Co is the drag coefficient applied on the iceberg's draft
102+ Avo : Vertical area of the iceberg in the ocean (length x draft)
103+ Aho : Horizontal area of the iceberg in contact with the ocean (width x draft)
104+ water_form_drag_coef : Co is the ocean form drag coefficient
105+ water_skin_drag_coef : Cdo is the ocean skin drag coefficient
98106 """
99107 vxo , vyo = water_vel [0 ], water_vel [1 ]
100108 x_vel , y_vel = iceb_vel [0 ], iceb_vel [1 ]
101109 rel_water_x_vel = vxo - x_vel
102110 rel_water_y_vel = vyo - y_vel
103111 rel_water_norm = np .sqrt (rel_water_x_vel ** 2 + rel_water_y_vel ** 2 )
104- F_ocean_x = (0.5 * rho_water * water_drag_coef * Ao * rel_water_norm * rel_water_x_vel )
105- F_ocean_y = (0.5 * rho_water * water_drag_coef * Ao * rel_water_norm * rel_water_y_vel )
112+ drag_factor_ocean = (0.5 * rho_water * water_form_drag_coef * Avo ) + (rho_water * water_skin_drag_coef * Aho )
113+ F_ocean_x = drag_factor_ocean * rel_water_norm * rel_water_x_vel
114+ F_ocean_y = drag_factor_ocean * rel_water_norm * rel_water_y_vel
106115 return np .array ([F_ocean_x , F_ocean_y ])
107116
108117
109- def wind_force (iceb_vel , wind_vel , Aa , wind_drag_coef ):
118+ def wind_force (iceb_vel , wind_vel , Ava , Aha , wind_form_drag_coef , wind_skin_drag_coef ):
110119 """ Wind force
111120 Args:
112121 iceb_vel : Iceberg's velocity at time t
113122 wind_vel : Wind velocity
114- Aa : Iceberg's area in contact with wind (length x sail)
115- wind_drag_coef : Ca is the drag coefficient applied on the iceberg's sail
123+ Ava : Vertical area of the iceberg in the air (length x sail)
124+ Aha : Horizontal area of the iceberg in contact with the air (width x sail)
125+ wind_form_drag_coef : Ca is the air form drag coefficient
126+ wind_skin_drag_coef : Cda is the air skin drag coefficient
116127 """
117128 vxa , vya = wind_vel [0 ], wind_vel [1 ]
118129 x_vel , y_vel = iceb_vel [0 ], iceb_vel [1 ]
119130 rel_wind_x_vel = vxa - x_vel
120131 rel_wind_y_vel = vya - y_vel
121132 rel_wind_norm = np .sqrt (rel_wind_x_vel ** 2 + rel_wind_y_vel ** 2 )
122- F_wind_x = 0.5 * rho_air * wind_drag_coef * Aa * rel_wind_norm * rel_wind_x_vel
123- F_wind_y = 0.5 * rho_air * wind_drag_coef * Aa * rel_wind_norm * rel_wind_y_vel
133+ drag_factor_wind = (0.5 * rho_air * wind_form_drag_coef * Ava ) + (rho_air * wind_skin_drag_coef * Aha )
134+ F_wind_x = drag_factor_wind * rel_wind_norm * rel_wind_x_vel
135+ F_wind_y = drag_factor_wind * rel_wind_norm * rel_wind_y_vel
124136 return np .array ([F_wind_x , F_wind_y ])
125137
126138
@@ -402,10 +414,12 @@ def advect_iceberg(self):
402414 draft = self .elements .draft
403415 length = self .elements .length
404416 width = self .elements .width
405- weight_coeff = self .elements .weight_coeff
417+ weight_coef = self .elements .weight_coef
406418 lat = self .elements .lat
407- water_drag_coeff = self .elements .water_drag_coeff
408- wind_drag_coeff = self .elements .wind_drag_coeff
419+ water_form_drag_coef = self .elements .water_form_drag_coef
420+ water_skin_drag_coef = self .elements .water_skin_drag_coef
421+ wind_form_drag_coef = self .elements .wind_form_drag_coef
422+ wind_skin_drag_coef = self .elements .wind_skin_drag_coef
409423
410424 T = self .environment .sea_water_temperature
411425 S = self .environment .sea_water_salinity
@@ -418,12 +432,14 @@ def advect_iceberg(self):
418432 sea_ice_thickness = self .environment .sea_ice_thickness
419433 sea_ice_conc = self .environment .sea_ice_area_fraction
420434 water_depth = self .environment .sea_floor_depth_below_sea_level
421-
422- Ao = abs (draft ) * length # (Alternatively: Ao = weight_coeff * length * width)
423- Aa = sail * length
435+ Avo = length * abs (draft )
436+ Aho = width * abs (draft )
437+ Ava = length * sail
438+ Aha = width * sail
424439 Ai = sea_ice_thickness * length
425- mass = width * (Aa + Ao ) * rho_iceb * weight_coeff
426- k = (rho_air * wind_drag_coeff * Aa / (rho_water * water_drag_coeff * Ao ))
440+
441+ mass = width * (Ava + Avo ) * rho_iceb * weight_coef
442+ k = (rho_air * wind_form_drag_coef * Ava / (rho_water * water_form_drag_coef * Avo ))
427443 f = np .sqrt (k ) / (1 + np .sqrt (k )) # (f is the wind drift factor, only used in the no acceleration model)
428444
429445 wave_rad = self .get_config ('drift:wave_rad' )
@@ -457,13 +473,13 @@ def advect_iceberg(self):
457473 sea_ice_vel = np .array ([self .environment .sea_ice_x_velocity , self .environment .sea_ice_y_velocity ])
458474
459475
460- def dynamic (t ,iceb_vel , water_vel , wind_vel , wave_height , wave_direction , Ao ,
461- Aa , rho_water , water_drag_coef , wind_drag_coef , iceb_length , mass ,lat , sea_slope_x , sea_slope_y ):
476+ def dynamic (t ,iceb_vel , water_vel , wind_vel , wave_height , wave_direction , Avo , Aho ,
477+ Ava , Aha , rho_water , water_form_drag_coef , water_skin_drag_coef , wind_form_drag_coef , wind_skin_drag_coef , iceb_length , mass ,lat , sea_slope_x , sea_slope_y ):
462478 """ Function required by solve_ivp. The t and iceb_vel parameters are required by solve_ivp, shouldn't be deleted """
463479 iceb_vel = iceb_vel .reshape ((2 , - 1 ))
464480 # Individual forces
465- ocean_force_val = ocean_force (iceb_vel , water_vel , Ao , rho_water , water_drag_coef )
466- wind_force_val = wind_force (iceb_vel , wind_vel , Aa , wind_drag_coef )
481+ ocean_force_val = ocean_force (iceb_vel , water_vel , Avo , Aho , rho_water , water_form_drag_coef , water_skin_drag_coef )
482+ wind_force_val = wind_force (iceb_vel , wind_vel , Ava , Aha , wind_form_drag_coef , wind_skin_drag_coef )
467483 wave_radiation_force_val = int (wave_rad ) * wave_radiation_force (rho_water , wave_height , wave_direction , iceb_length )
468484 coriolis_force_val = int (coriolis ) * coriolis_force (iceb_vel , mass , lat )
469485 sea_surface_slope_val = int (sea_surface_slope ) * sea_surface_slope_force (sea_slope_x , sea_slope_y , mass )
@@ -506,8 +522,8 @@ def dynamic(t,iceb_vel, water_vel, wind_vel, wave_height, wave_direction, Ao,
506522 logger .debug ("Grounding process disabled in configuration" )
507523
508524 sol = solve_ivp (dynamic , [0 , self .time_step .total_seconds ()], V0 ,
509- args = (water_vel , wind_vel , wave_height , wave_direction , Ao , Aa , rho_water ,
510- water_drag_coeff , wind_drag_coeff , length , mass , lat , sea_slope_x , sea_slope_y ),
525+ args = (water_vel , wind_vel , wave_height , wave_direction , Avo , Aho , Ava , Aha , rho_water ,
526+ water_form_drag_coef , water_skin_drag_coef , wind_form_drag_coef , wind_skin_drag_coef , length , mass , lat , sea_slope_x , sea_slope_y ),
511527 vectorized = True ,
512528 t_eval = np .array ([self .time_step .total_seconds ()]))
513529 V = sol .y .reshape ((2 , - 1 ))
0 commit comments