Source code for opendrift.models.openberg

# This file is part of OpenDrift.
#
# OpenDrift is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 2
#
# OpenDrift is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenDrift.  If not, see <https://www.gnu.org/licenses/>.
#
# Copyright 2015, 2023, Knut-Frode Dagestad, MET Norway
# Copyright 2023, Achref Othmani, NERSC, Norway


import numpy as np
import logging; logger = logging.getLogger(__name__)
from opendrift.models.oceandrift import OceanDrift, Lagrangian3DArray

[docs] class IcebergObj(Lagrangian3DArray): """Extending LagrangianArray with relevant properties for an Iceberg""" variables = Lagrangian3DArray.add_variables([ ('sail', {'dtype': np.float32, # Sail of Iceberg (part above waterline ) 'units': 'm', 'default': 10}), ('draft', {'dtype': np.float32, # Draft of Iceberg (part below waterline) 'units': 'm', 'default': 90}), ('length', {'dtype': np.float32, # length of Iceberg 'units': 'm', 'default': 100}), ('width', {'dtype': np.float32, # width of Iceberg 'units': 'm', 'default': 30}), ('weight_coeff', {'dtype': np.float32, # Proportion of the mass of rectangular Iceberg, weight_coeff = 1.0 if 100%, 0.5 if 50% and 0.35 if 35% 'units': '1', 'default': 1}), ('water_drag_coeff', {'dtype': np.float32, # cdo 'units': '1', 'default': 0.25}), ('wind_drag_coeff', {'dtype': np.float32, # cda 'units': '1', 'default': 0.7}) ])
[docs] class OpenBerg(OceanDrift): ElementType = IcebergObj # Specify which environment variables (e.g. wind, waves, currents...) # are needed/required by the present model, to be used for updating # the element properties (including propagation). required_variables = { 'x_sea_water_velocity': {'fallback': None}, 'y_sea_water_velocity': {'fallback': None}, 'sea_surface_height': {'fallback': 0}, 'sea_floor_depth_below_sea_level': {'fallback': 10000}, 'x_wind': {'fallback': None}, 'y_wind': {'fallback': None}, #'sea_surface_wave_significant_height': {'fallback': None}, # Needed for melting 'land_binary_mask': {'fallback': None}, } # Configuration def __init__(self, *args, **kwargs): # The constructor of parent class must always be called # to perform some necessary common initialisation tasks: super(OpenBerg, self).__init__(*args, **kwargs)
[docs] def thermodynamics(self): pass # not yet implemented
[docs] def update(self): """Update positions and properties of icebergs""" self.thermodynamics() # Constants rho_water = 1027 rho_air = 1.293 rho_ice = 917 rho_iceb = 900 # Areas exposed Ao = abs(self.elements.draft) * self.elements.length # Area_wet Aa = self.elements.sail * self.elements.length # Area_dry # See ACCIBERG presentation # https://docs.google.com/presentation/d/1O5C2v7PA3PW8a93IAGU-aS6BSKt3s-Fw/edit#slide=id.p1 k = rho_air*self.elements.wind_drag_coeff*Aa / (rho_water*self.elements.water_drag_coeff*Ao) f = np.sqrt(k)/(1+np.sqrt(k)) vx = (1-f)*self.environment.x_sea_water_velocity + f*self.environment.x_wind vy = (1-f)*self.environment.y_sea_water_velocity + f*self.environment.y_wind self.update_positions(vx, vy) # Grounding self.deactivate_elements(self.elements.draft > self.environment.sea_floor_depth_below_sea_level, reason='Grounded iceberg')