Skip to content

Commit

Permalink
Merge pull request #1343 from knutfrode/dev
Browse files Browse the repository at this point in the history
Updated example to illustrate coastline interaction
  • Loading branch information
knutfrode authored Jul 1, 2024
2 parents a08a626 + 0fb5da5 commit d39aa8c
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 156 deletions.
83 changes: 69 additions & 14 deletions examples/example_coastline_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,89 @@
Example to illustrate stranding options using an artificial
east-west oscillating current field
Knut-Frode Dagestad, Feb 2017
"""

from datetime import datetime
from datetime import datetime, timedelta
from opendrift.readers import reader_oscillating
from opendrift.models.oceandrift import OceanDrift
duration = timedelta(hours=36)
time_step = timedelta(hours=.5)
number = 500

o = OceanDrift(loglevel=50) # Set loglevel to 0 for debug information

# Oscillating east-west current to illustrate stranding options
reader_osc = reader_oscillating.Reader('x_sea_water_velocity', amplitude=1,
zero_time=datetime.utcnow())
o.add_reader([reader_osc]) # Oscillating east-west current component

o.set_config('environment:fallback:y_sea_water_velocity', .2) # Adding northwards drift
#%%
# Coastline option "stranding"
# ============================
#
# Note that particles are "jumping" a distance onto land, depending on calculation timestep
o = OceanDrift(loglevel=50)
o.add_reader([reader_osc])
o.set_config('environment:fallback:y_sea_water_velocity', .2)
o.set_config('general:coastline_action', 'stranding')
o.seed_elements(lon=12.2, lat=67.7, radius=5000, number=number, time=reader_osc.zero_time)
o.run(duration=duration, time_step=time_step)
print(f'Calculation time: {o.timing["total time"]}')
o.animation()

#%%
# Try different options: 'previous', 'stranding', 'none'
o.set_config('general:coastline_action', 'previous')
# .. image:: /gallery/animations/example_coastline_options_0.gif

o.seed_elements(lon=12.2, lat=67.7, radius=5000, number=25, time=reader_osc.zero_time)
#%%
# Coastline option "stranding" with higher precision
# ==================================================
#
# by setting config "general:coastline_approximation_precision" to desired accuracy in degrees.
# Note that with a (too) large compuation time step, particles may still "jump" over islands.
# An alternative to avoid this possibility is to use a smaller timestep for the simulation, though at a larger computational cost.
o = OceanDrift(loglevel=50)
o.add_reader([reader_osc])
o.set_config('environment:fallback:y_sea_water_velocity', .2)
o.set_config('general:coastline_action', 'stranding')
o.set_config('general:coastline_approximation_precision', .001) # approx 100m
o.seed_elements(lon=12.2, lat=67.7, radius=5000, number=number, time=reader_osc.zero_time)
o.run(duration=duration, time_step=time_step)
print(f'Calculation time: {o.timing["total time"]}')
o.animation()

o.run(steps=36*4, time_step=900, time_step_output=1800)
#%%
# .. image:: /gallery/animations/example_coastline_options_1.gif

#%
# Coastline option "previous"
# ===========================
#
# Particles hitting land are moved back to last position in water,
# and may move offshore if currents/winds/forcing changes direction.
# Here we see that several particles are jumping over small island.
# Reducing timestep to e.g. 15 minutes will reduce this problem.
o = OceanDrift(loglevel=50)
o.add_reader([reader_osc])
o.set_config('environment:fallback:y_sea_water_velocity', .2)
o.set_config('general:coastline_action', 'previous')
o.seed_elements(lon=12.2, lat=67.7, radius=5000, number=number, time=reader_osc.zero_time)
o.run(duration=duration, time_step=time_step)
print(f'Calculation time: {o.timing["total time"]}')
o.animation()

#%%
# Print and plot results
print(o)
# .. image:: /gallery/animations/example_coastline_options_2.gif

#%
# Coastline option "none"
# =======================
#
# No interaction with land, as used by e.g. WindBlow model (atmospheric drift)
o = OceanDrift(loglevel=50)
o.add_reader([reader_osc])
o.set_config('environment:fallback:y_sea_water_velocity', .2)
o.set_config('general:coastline_action', 'none')
o.seed_elements(lon=12.2, lat=67.7, radius=5000, number=number, time=reader_osc.zero_time)
o.run(duration=duration, time_step=time_step)
print(f'Calculation time: {o.timing["total time"]}')
o.animation()
o.plot()

#%%
# .. image:: /gallery/animations/example_coastline_options_0.gif
# .. image:: /gallery/animations/example_coastline_options_3.gif
3 changes: 1 addition & 2 deletions examples/example_fjord.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
Fjord
==================================
=====
"""

from datetime import timedelta
Expand Down Expand Up @@ -40,4 +40,3 @@
# .. image:: /gallery/animations/example_fjord_0.gif

o.plot()

Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
# Define domain of possible origin
lons = np.arange(3.4, 5, .1/20)
lats = np.arange(59.7, 60.8, .05/20)
#lons = lons[0::2] # using every second, due to memory limitation on CircleCI
#lats = lats[0::2]
corners = [lons[0], lons[-1], lats[0], lats[-1]]
lons, lats = np.meshgrid(lons, lats)

Expand All @@ -53,15 +55,16 @@
density_backwards = density_backwards.where(density_backwards>0)
density_backwards = density_backwards/density_backwards.sum()*100
vmax = density_backwards.max()
o.plot(background=density_backwards, clabel='Probability of origin [%]', text=text, corners=corners, fast=True, markersize=.5, lalpha=.02, vmin=0, vmax=vmax)
o.plot(background=density_backwards, clabel='Probability of origin [%]', text=text, corners=corners,
fast=True, markersize=.5, lalpha=.02, vmin=0, vmax=vmax)
os.remove(outfile)

#%%
# Simulating then forwards, starting at a uniform grid 24 hours earlier (440 x 320 = 140800 elements at ~500m separation)
o = Leeway(loglevel=50)
o.add_reader([reader_norkyst, reader_arome])
o.seed_elements(lon=lons, lat=lats, radius=0,
time=start_time, object_type=object_type)
time=start_time, object_type=object_type)
o.run(duration=duration, time_step=900, time_step_output=3600, outfile=outfile)
print(o)

Expand All @@ -78,16 +81,20 @@
hit_start_lats = lat[hits, 0]
o_hit = opendrift.open(outfile, elements=hits)

o.animation(compare=o_hit, legend=['Elements not hitting target', 'Elements hitting target'], fast=True, corners=corners, text=text)
o.animation(compare=o_hit, legend=['Elements not hitting target', 'Elements hitting target'],
fast=True, corners=corners, text=text)

#%%
# .. image:: /gallery/animations/example_leeway_backtrack_0.gif

o.plot(compare=o_hit, legend=['Elements not hitting target', 'Elements hitting target'], show_elements=False, fast=True, corners=corners, text=text)
o.plot(compare=o_hit, legend=['Elements not hitting target', 'Elements hitting target'],
show_elements=False, fast=True, corners=corners, text=text)

#%%
# Plot the initial density of elements that actually hit the target after 24 hours. To be compared with the density figure from backwards simulation (see top)
of = opendrift.open_xarray(outfile, elements=hits)
density_forwards = of.get_histogram(pixelsize_m=5000).isel(time=0).isel(origin_marker=0)
density_forwards = density_forwards.where(density_forwards>0)
o_hit.plot(background=density_forwards/density_forwards.sum()*100, clabel='Probability of origin [%]', text=text, corners=corners, fast=True, markersize=.5, lalpha=.02, vmin=0, vmax=vmax)
ratio = density_forwards/density_forwards.sum()*100
o_hit.plot(background=ratio, clabel='Probability of origin [%]', text=text, corners=corners,
fast=True, markersize=.5, lalpha=.02, vmin=0, vmax=vmax)
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
Icebergs (openberg)
====================
Icebergs (OpenBerg module)
==========================
"""

from opendrift.models.openberg import OpenBerg
Expand Down
64 changes: 0 additions & 64 deletions examples/example_openberg_det.py

This file was deleted.

64 changes: 0 additions & 64 deletions examples/example_openberg_stat.py

This file was deleted.

2 changes: 1 addition & 1 deletion examples/example_wind_measurements.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
Using wind measurements
===============
=======================
"""

from datetime import datetime, timedelta, date
Expand Down
8 changes: 7 additions & 1 deletion history.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
History
=======

Next release
------------
* New feature by TheSylex to move stranded particles closer to the actual coastline with a precision given by config setting `general:coastline_approximation_precision` in unit of degrees (1deg approx 111 km)
* Major updates to OpenBerg iceberg drift model (Achref Othmani, Lenny Hucher)

2024-06-27 / Release v1.11.10
----------------------------
-----------------------------
* Using now standard env variable names COPERNICUSMARINE_SERVICE_USERNAME and COPERNICUSMARINE_SERVICE_PASSWORD for reader_copernicus. Env variable COPERNICUSMARINE_CACHE_DIRECTORY can be set to empty string to disable caching.

2024-06-27 / Release v1.11.9
Expand All @@ -11,6 +16,7 @@ History
* Hack in generic reader to make sure wind from ECMWF files is at 10m height

* Raising now error if all elements are seeded on land

2024-06-26 / Release v1.11.8
----------------------------
* Raising now error if all elements are seeded on land
Expand Down
3 changes: 0 additions & 3 deletions opendrift/models/leeway.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,8 @@ def __init__(self, d=None, *args, **kwargs):
'processes:capsizing': {
'type': 'bool',
'default': False,
'min': 0,
'max': 1,
'description':
'If True, elements can be capsized when wind exceeds threshold given by config item capsize:wind_threshold',
'units': 'fraction',
'level': CONFIG_LEVEL_BASIC
},
'capsizing:leeway_fraction': {
Expand Down

0 comments on commit d39aa8c

Please sign in to comment.