Skip to content

Latest commit

 

History

History
351 lines (291 loc) · 15 KB

GL_runoff.org

File metadata and controls

351 lines (291 loc) · 15 KB

Table of contents

Introduction

Greenland surface runoff is repackaged from:

Data example

Printout

<xarray.Dataset> Size: 203kB
Dimensions:                         (region: 7, time: 876)
Coordinates:
  * region                          (region) int32 28B 1 2 3 4 5 6 7
  * time                            (time) datetime64[ns] 7kB 1950-01-01 ... ...
Data variables:
    subglacial_discharge_from_land  (region, time) float64 49kB ...
    surface_runoff_from_land        (region, time) float64 49kB ...
    subglacial_discharge_from_ice   (region, time) float64 49kB ...
    surface_runoff_from_ice         (region, time) float64 49kB ...
    min_discharge_depth             (region) float32 28B ...
    region_name                     (region) <U2 56B ...
Attributes:
    title:        Ice sheet runoff by Mougniot region
    history:      TBD
    Conventions:  CF-1.8
    DOI:          https://doi.org/10.5281/zenodo.14020895

Minimum runoff depth per ROI

import xarray as xr
ds = xr.open_dataset('dat/GL_runoff.nc')
ds['min_discharge_depth'].to_dataframe()
regionmin_discharge_depth
1-661
2-824
3-1341
4-1094
5-1158
6-643
7-243

Plots

Annual runoff by type for all of Greenland

Example showing annual data for

  • Land runoff that enters the ocean subglacially (at depth)
  • Land runoff that enters the ocean at the surface
  • Ice runoff that enters the ocean subglacially
  • Ice runoff that enters the ocean at the surface
import xarray as xr
ds = xr.open_dataset('dat/GL_runoff.nc').load()
df = ds.sum(dim='region')\
       .drop_vars(['min_discharge_depth'])\
       .sel({'time':slice('1950-01-01','2021-01-01')})\
       .resample({'time':'YS'})\
       .sum()\
       .to_dataframe()

df = df * 86400 / 1E9 # convert from m^3/s -> ~ Gt/year
ax = df.plot(drawstyle='steps-post')
_ = ax.set_ylabel('Runoff [Gt$^{3}$ year^{-1}$]')

./fig/GL_runoff.png

Region runoff for some years

import xarray as xr
ds = xr.open_dataset('dat/GL_runoff.nc')
df = ds.drop_vars(['min_discharge_depth'])\
       .sel({'time':slice('2017-01-01','2021-01-01')})\
       ['subglacial_discharge_from_ice']\
       .to_dataframe()['subglacial_discharge_from_ice']

df = df.unstack().T
df.columns = ds['region_name'].values
ax = df.plot(drawstyle='steps-post')
_ = ax.set_ylabel('Runoff [m$^{3}$ s$^{-1}$]')

./fig/GL_runoff_region.png

Table: Annual ice-only runoff per region for Greenland

import xarray as xr
ds = xr.open_dataset('dat/GL_runoff.nc').load()
df = ds\
    .drop_vars(['min_discharge_depth'])\
    .sel({'time':slice('2000-01-01','2099-12-31')})\
    .resample({'time':'YS'})\
    .sum()\
    .to_dataframe()

df = df[['subglacial_discharge_from_ice','surface_runoff_from_ice']].sum(axis='columns')
df = df * 86400 / 1E9 # convert from m^3/s -> ~ Gt/year
df = df.unstack()
df.columns = [str(_[0]) + ' ['+_[1]+']' for _ in zip(ds['region'].values, ds['region_name'].values)]
df['GL'] = df.sum(axis='columns')
df.loc['Mean'] = df.mean(axis='rows')
df.index = [str(_)[0:4] for _ in df.index]
df.round()
1 [CE]2 [CW]3 [NE]4 [NO]5 [NW]6 [SE]7 [SW]GL
2000483736333975128395
2001373641404972103377
2002714068464274105446
2003585475606683168565
2004704948314481127449
2005615165575996123511
2006534336305477118412
2007655849345885162511
2008683880676685112516
200954385649556384398
20108572584674128204668
2011515658657670139514
201274868882100111254794
201354385228395894364
2014645153476389135502
201555426872686195460
2016715681636494159588
2017583668414580117446
2018504034333766103363
20198480104909089170707
2020594177755483138526
20218254725266106158590
2022534545495892145488
Mean625061525983137504
df.describe().round()
1 [CE]2 [CW]3 [NE]4 [NO]5 [NW]6 [SE]7 [SW]GL
count2323232323232323
mean625061525983137504
std12141818161739111
min37363428375884363
25%533949374773109429
50%594558495883128502
75%705574646691158546
max858610490100128254794

Fetch data

  • Warning: ~20 GB
mkdir -p tmp/greenland_runoff
pushd tmp/greenland_runoff
wget -r -e robots=off -nH --cut-dirs=3 --content-disposition "https://dataverse.geus.dk/api/datasets/:persistentId/dirindex?persistentId=doi:10.22008/FK2/XKQVL7"
popd

Combine land and ice runoff and bin by ROI

Create one dataset that includes

  • Land runoff (melted snow, and rain on land)
  • Ice runoff (melted snow, melted ice, and rain on the ice sheet that does not refreeze)

Note that land runoff can enter fjords via streams at their surface, or route subglacially and then mix with subglacial discharge at depth in fjords at the grounding line of marine-terminating glaciers. Ice runoff can also enter fjords at depth at the grounding line of marine-terminating glaciers, or at the surface from sub-aerial streams from land terminating glaciers. Metadata will be used to track each of these sources and destinations.

Runoff will be binned by Mouginot regions in Greenland. See Mouginot (2019) https://doi.org/10.7280/d1wt11. This metadata is already include in the product downloaded above.

import xarray as xr
import numpy as np

ds_land = xr.open_mfdataset('tmp/greenland_runoff/freshwater/land/MAR.nc', chunks='auto')
ds_ice = xr.open_mfdataset('tmp/greenland_runoff/freshwater/ice/MAR.nc', chunks='auto')

ds_land = ds_land.reset_coords('alt')
ds_ice = ds_ice.reset_coords('alt')

# Land runoff by destination (use alt metadata = BedMachine depth at outlet location)
land_sub = ds_land.where(ds_land['alt'] < 0).groupby('M2019_region').sum()['discharge'].resample({'time':'MS'}).sum()
land_surf = ds_land.where(ds_land['alt'] >= 0).groupby('M2019_region').sum()['discharge'].resample({'time':'MS'}).sum()

# Max depth of discharge within each region    
sub_depth = ds_land.where(ds_land['alt'] < 0).groupby('M2019_region').min()['alt']

# Ice runoff by destination
ice_sub = ds_ice.where(ds_ice['coast_alt'] < 0).groupby('M2019_region').sum()['discharge'].resample({'time':'MS'}).sum()
ice_surf = ds_ice.where(ds_ice['coast_alt'] >= 0).groupby('M2019_region').sum()['discharge'].resample({'time':'MS'}).sum()

ds = xr.Dataset({'subglacial_discharge_from_land':land_sub,
                 'surface_runoff_from_land':land_surf,
                 'subglacial_discharge_from_ice':ice_sub,
                 'surface_runoff_from_ice':ice_surf,
                 'min_discharge_depth':sub_depth})

# # scale from m^3/s -> km^3/sample_period
# scale = 86400 / 1E9
# # /1E9:  m^3 -> km^3
# # 86400: nuber of seconds in a day. Because sum() used above, works for month or year or any resample period
# scale_items = ['subglacial_discharge_from_land','surface_runoff_from_land',
#                'subglacial_discharge_from_ice','surface_runoff_from_ice']
# ds[scale_items] = ds[scale_items] * scale                 

print(ds)
<xarray.Dataset> Size: 203kB
Dimensions:                         (M2019_region: 7, time: 876)
Coordinates:
  * M2019_region                    (M2019_region) object 56B 'CE' 'CW' ... 'SW'
  * time                            (time) datetime64[ns] 7kB 1950-01-01 ... ...
Data variables:
    subglacial_discharge_from_land  (M2019_region, time) float64 49kB dask.array<chunksize=(7, 19), meta=np.ndarray>
    surface_runoff_from_land        (M2019_region, time) float64 49kB dask.array<chunksize=(7, 19), meta=np.ndarray>
    subglacial_discharge_from_ice   (M2019_region, time) float64 49kB dask.array<chunksize=(7, 46), meta=np.ndarray>
    surface_runoff_from_ice         (M2019_region, time) float64 49kB dask.array<chunksize=(7, 46), meta=np.ndarray>
    min_discharge_depth             (M2019_region) float32 28B dask.array<chunksize=(7,), meta=np.ndarray>

Write it out using Dask so it works on lightweight machines. This takes a few hours.

delayed_obj = ds.to_netcdf('tmp/GL_runoff.nc', compute=False)
from dask.diagnostics import ProgressBar
with ProgressBar():
    results = delayed_obj.compute()
[########################################] | 100% Completed | 110.26 s

Add metadata, extend back to 1840, etc.

ds = xr.open_dataset('tmp/GL_runoff.nc')

ds = ds.rename({'M2019_region':'region'})
ds['region_name'] = ds['region']
ds['region'] = np.arange(7).astype(np.int32) + 1

items = ['subglacial_discharge_from_land','surface_runoff_from_land',
         'subglacial_discharge_from_ice','surface_runoff_from_ice']
for i in items:
    ds[i].attrs['standard_name'] = 'water_volume_transport_into_sea_water_from_rivers'
    ds[i].attrs['units'] = 'm3 s-1'

ds['time'].attrs['long_name'] = 'time'
ds['region'].attrs['long_name'] = 'Mougniot (2019) region'

ds.attrs['title'] = 'Ice sheet runoff by Mougniot region'
ds.attrs['history'] = 'TBD'
ds.attrs['Conventions'] = 'CF-1.8'
ds.attrs['DOI'] = 'https://doi.org/10.5281/zenodo.14020895'
    
comp = dict(zlib=True, complevel=5)
encoding = {var: comp for var in items}
encoding['time'] = {'dtype': 'i4'}

!rm dat/GL_runoff.nc    
ds.to_netcdf('dat/GL_runoff.nc', encoding=encoding)
!ncdump -h dat/GL_runoff.nc
netcdf GL_runoff {
dimensions:
	region = 7 ;
	time = 876 ;
variables:
	int region(region) ;
		region:long_name = "Mougniot (2019) region" ;
	int time(time) ;
		time:long_name = "time" ;
		time:units = "days since 1950-01-01 00:00:00" ;
		time:calendar = "proleptic_gregorian" ;
	double subglacial_discharge_from_land(region, time) ;
		subglacial_discharge_from_land:_FillValue = NaN ;
		subglacial_discharge_from_land:long_name = "MAR discharge" ;
		subglacial_discharge_from_land:standard_name = "water_volume_transport_into_sea_water_from_rivers" ;
		subglacial_discharge_from_land:units = "m3 s-1" ;
	double surface_runoff_from_land(region, time) ;
		surface_runoff_from_land:_FillValue = NaN ;
		surface_runoff_from_land:long_name = "MAR discharge" ;
		surface_runoff_from_land:standard_name = "water_volume_transport_into_sea_water_from_rivers" ;
		surface_runoff_from_land:units = "m3 s-1" ;
	double subglacial_discharge_from_ice(region, time) ;
		subglacial_discharge_from_ice:_FillValue = NaN ;
		subglacial_discharge_from_ice:long_name = "MAR discharge" ;
		subglacial_discharge_from_ice:standard_name = "water_volume_transport_into_sea_water_from_rivers" ;
		subglacial_discharge_from_ice:units = "m3 s-1" ;
	double surface_runoff_from_ice(region, time) ;
		surface_runoff_from_ice:_FillValue = NaN ;
		surface_runoff_from_ice:long_name = "MAR discharge" ;
		surface_runoff_from_ice:standard_name = "water_volume_transport_into_sea_water_from_rivers" ;
		surface_runoff_from_ice:units = "m3 s-1" ;
	float min_discharge_depth(region) ;
		min_discharge_depth:_FillValue = NaNf ;
		min_discharge_depth:long_name = "height_above_mean_sea_level" ;
		min_discharge_depth:standard_name = "altitude" ;
		min_discharge_depth:units = "m" ;
		min_discharge_depth:positive = "up" ;
		min_discharge_depth:axis = "Z" ;
	string region_name(region) ;

// global attributes:
		:title = "Ice sheet runoff by Mougniot region" ;
		:history = "TBD" ;
		:Conventions = "CF-1.8" ;
		:DOI = "https://doi.org/10.5281/zenodo.14020895" ;
}