Skip to content

Commit

Permalink
Merge pull request #987 from xylar/use-paolo-ismf
Browse files Browse the repository at this point in the history
Add Paolo et al. (2023) melt rate analysis
  • Loading branch information
xylar authored Feb 24, 2024
2 parents 7f73166 + 0067d43 commit 12f1f9c
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 10 deletions.
4 changes: 2 additions & 2 deletions docs/users_guide/tasks/climatologyMapAntarcticMelt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ climatologyMapAntarcticMelt
===========================

An analysis task for comparison of Antarctic maps of melt rates against
observations from `Adusumilli et al. (2020) <https://doi.org/10.1038/s41561-020-0616-z>`_.
observations from `Paolo et al. (2023) <https://doi.org/10.5194/tc-17-3409-2023>`_.

Component and Tags::

Expand Down Expand Up @@ -76,7 +76,7 @@ For more details, see:
Observations
------------

:ref:`adusumilli_melt`
:ref:`paolo_melt`

Example Result
--------------
Expand Down
5 changes: 3 additions & 2 deletions docs/users_guide/tasks/timeSeriesAntarcticMelt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ timeSeriesAntarcticMelt
=======================

An analysis task for plotting time series of mean melt rates per ice shelf or
Antarctic region along with observations from `Rignot et al. (2013)`_
and `Adusumilli et al. (2020) <https://doi.org/10.1038/s41561-020-0616-z>`_.
Antarctic region along with observations from `Rignot et al. (2013)`_,
`Adusumilli et al. (2020) <https://doi.org/10.1038/s41561-020-0616-z>`_,
and `Paolo et al. (2023) <https://doi.org/10.5194/tc-17-3409-2023>`_.

Component and Tags::

Expand Down
50 changes: 50 additions & 0 deletions mpas_analysis/obs/observational_datasets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,56 @@
</nameInDocs>
</observation>

<observation>
<name>
Antarctic melt rates and fluxes
</name>
<component>
ocean
</component>
<description>
Melt rates and melt fluxes from Paolo et al. (2023)
</description>
<source>
[Data from: ANT_G1920V01_IceShelfMelt.nc](https://doi.org/10.5067/SE3XH9RXQWAM)
</source>
<releasePolicy>
Not stated.
</releasePolicy>
<references>
[Paolo et al. (2023)](https://doi.org/10.5194/tc-17-3409-2023)
</references>
<bibtex>
@article{Paolo2023,
author = {Paolo, F. S. and Gardner, A. S. and Greene, C. A. and Nilsson, J. and Schodlok, M. P. and Schlegel, N.-J. and Fricker, H. A.},
title = {Widespread slowdown in thinning rates of West Antarctic ice shelves},
journal = {The Cryosphere},
volume = {17},
year = {2023},
number = {8},
pages = {3409--3433},
url = {https://tc.copernicus.org/articles/17/3409/2023/},
doi = {10.5194/tc-17-3409-2023}
}
</bibtex>
<dataUrls>
- https://its-live-data.s3.amazonaws.com/height_change/Antarctica/Floating/ANT_G1920V01_IceShelfMelt.nc
</dataUrls>
<preprocessing>
preprocess_observations/preprocess_paolo_melt.py
</preprocessing>
<tasks>
- climatologyMapAntarcticMelt
- timeSeriesAntarcticMelt
</tasks>
<subdirectory>
Ocean/Melt/Paolo
</subdirectory>
<nameInDocs>
paolo_melt
</nameInDocs>
</observation>

<observation>
<name>
HadISST Nino 3.4 Index
Expand Down
12 changes: 6 additions & 6 deletions mpas_analysis/ocean/climatology_map_antarctic_melt.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def __init__(self, config, mpasClimatologyTask, regionMasksTask,
if controlConfig is None:

refTitleLabel = \
'Observations (Adusumilli et al, 2020)'
'Observations (Paolo et al, 2023)'

observationsDirectory = build_obs_path(
config, 'ocean', 'meltSubdirectory')
Expand All @@ -135,12 +135,12 @@ def __init__(self, config, mpasClimatologyTask, regionMasksTask,
res = np.amax(avail_res[valid])

obsFileName = \
f'{observationsDirectory}/Adusumilli/Adusumilli_2020_' \
f'iceshelf_melt_rates_2010-2018_v0_6000x6000km_{res:g}km_' \
f'Antarctic_stereo.20230504.nc'
f'{observationsDirectory}/Paolo/Paolo_2023_' \
f'iceshelf_melt_rates_1992-2017_v1.0_6000x6000km_{res:g}km_' \
f'Antarctic_stereo.20240220.nc'
refFieldName = 'meltRate'
outFileLabel = 'meltAdusumilli'
galleryName = 'Observations: Adusumilli et al. (2020)'
outFileLabel = 'meltPaolo'
galleryName = 'Observations: Paolo et al. (2023)'

remapObservationsSubtask = RemapObservedAntarcticMeltClimatology(
parentTask=self, seasons=seasons, fileName=obsFileName,
Expand Down
31 changes: 31 additions & 0 deletions mpas_analysis/ocean/time_series_antarctic_melt.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from geometric_features import FeatureCollection, read_feature_collection
from geometric_features.aggregation import get_aggregator_by_name
from mpas_tools.cime.constants import constants as cime_constants

from mpas_analysis.shared.analysis_task import AnalysisTask

Expand Down Expand Up @@ -599,6 +600,36 @@ def run_task(self):
'meltRate': ds_shelf.meanMeltRate.values,
'meltRateUncertainty': ds_shelf.meltRateUncertainty.values}

rho_fw = cime_constants['SHR_CONST_RHOFW']
kg_per_gt = constants.kg_per_GT
gt_per_m3 = rho_fw / kg_per_gt

obsFileName = f'{observationsDirectory}/Paolo/' \
f'Paolo_2023_melt_rates.20240220.csv'
obsName = 'Paolo et al. (2023)'
obsDict[obsName] = {}
obsFile = csv.reader(open(obsFileName, 'r'))
next(obsFile, None) # skip the header line
for line in obsFile: # some later useful values commented out
shelfName = line[0]
if shelfName != self.iceShelf:
continue

# km^2 --> m^2
area = 1e6 * float(line[1])
meltRate = float(line[2])
meltRateUncertainty = float(line[3])
meltFlux = gt_per_m3 * area * meltRate
meltFluxUncertainty = gt_per_m3 * area * meltRateUncertainty

# build dict of obs. keyed to filename description
# (which will be used for plotting)
obsDict[obsName] = {
'meltFlux': meltFlux,
'meltFluxUncertainty': meltFluxUncertainty,
'meltRate': meltRate,
'meltRateUncertainty': meltRateUncertainty}

mainRunName = config.get('runs', 'mainRunName')
movingAveragePoints = config.getint('timeSeriesAntarcticMelt',
'movingAveragePoints')
Expand Down
192 changes: 192 additions & 0 deletions preprocess_observations/preprocess_paolo_melt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#!/usr/bin/env python
import os
import shutil

import numpy as np
import pyproj
import xarray as xr
from mpas_tools.cime.constants import constants as cime_constants
from pyremap import Remapper, ProjectionGridDescriptor
from pyremap.polar import get_antarctic_stereographic_projection

from mpas_analysis.shared.io.download import download_files


def download_paolo(out_filename):
"""
Remap the Paolo et al. (2023) melt rates at 1 km resolution to an MPAS
mesh
Parameters
----------
out_filename : str
The original Paolo et al. (2023) melt rates
"""

if os.path.exists(out_filename):
return

download_files(fileList=['ANT_G1920V01_IceShelfMelt.nc'],
urlBase='https://its-live-data.s3.amazonaws.com/height_change/Antarctica/Floating',
outDir='.')
shutil.move('ANT_G1920V01_IceShelfMelt.nc', out_filename)


def process_paolo(in_filename, out_filename):
"""
Convert Paolo et al. (2023) melt rates to freshwater equivalent
Parameters
----------
in_filename : str
The original Paolo et al. (2023) melt rates
out_filename : str
The Paolo et al. (2023) melt rates in freshwater equivalent
"""
if os.path.exists(out_filename):
return

print(f'Reading {in_filename}...')

with xr.open_dataset(in_filename) as ds_in:

x = ds_in.x
y = ds_in.y
melt_rate = ds_in.melt_mean
melt_rate_uncertainty = np.sqrt((ds_in.melt_err**2).mean(dim='time'))

print('done.')

print('Creating an xarray dataset...')
ds = xr.Dataset()

projection = pyproj.Proj('+proj=stere +lat_ts=-71.0 +lat_0=-90 +lon_0=0.0 '
'+k_0=1.0 +x_0=0.0 +y_0=0.0 +ellps=WGS84')
latlon_projection = pyproj.Proj(proj='latlong', datum='WGS84')

print('Computing lat/lon...')
x_2d, y_2d = np.meshgrid(x.values, y.values)
transformer = pyproj.Transformer.from_proj(projection,
latlon_projection)
lon, lat = transformer.transform(x_2d, y_2d)
print('done.')

# Paolo et al. (2023) ice density
rho_ice = 917.
rho_fw = cime_constants['SHR_CONST_RHOFW']
ice_to_fw_equiv = rho_ice / rho_fw

ds['x'] = x
ds['y'] = y
ds['lon'] = (('y', 'x'), lon)
ds.lon.attrs['units'] = 'degrees'
ds['lat'] = (('y', 'x'), lat)
ds.lat.attrs['units'] = 'degrees'
ds['meltRate'] = -ice_to_fw_equiv * melt_rate
ds.meltRate.attrs['units'] = 'm/yr of freshwater'
ds['meltRateUncertainty'] = ice_to_fw_equiv * melt_rate_uncertainty
ds.meltRateUncertainty.attrs['units'] = 'm/yr of freshwater'
print('Writing the dataset...')
ds.to_netcdf(out_filename)
print('done.')


def remap_paolo(in_filename, out_prefix, date, task_count=128):
"""
Remap Paolo et al. (2023) melt rates to comparison grids
Parameters
----------
in_filename : str
The Paolo et al. (2023) melt rates in NetCDF format
out_prefix : str
A prefix for the file to contain the Paolo et al. (2023) melt
rates and melt fluxes remapped to the comparison grid
date : str
A date string to append to the file name.
task_count : int
The number of MPI tasks to use to create the mapping file
"""
ds = xr.open_dataset(in_filename)

melt_attrs = ds.meltRate.attrs
uncert_attrs = ds.meltRateUncertainty.attrs

mask = ds.meltRate.notnull()
ds['meltRate'] = ds.meltRate.where(mask, 0.)
ds['meltMask'] = mask.astype(float)
mask = ds.meltRateUncertainty.notnull()
ds['meltRateUncertSqr'] = (ds.meltRateUncertainty**2).where(mask, 0.)
ds['uncertMask'] = mask.astype(float)
ds = ds.drop_vars(['lat', 'lon', 'meltRateUncertainty'])

in_x = ds.x.values
in_y = ds.y.values
lx = np.abs(1e-3 * (in_x[-1] - in_x[0]))
ly = np.abs(1e-3 * (in_y[-1] - in_y[0]))
dx = np.abs(1e-3 * (in_x[1] - in_x[0]))

in_grid_name = f'{lx:g}x{ly:g}km_{dx:g}km_Antarctic_stereo'

in_projection = pyproj.Proj('+proj=stere +lat_ts=-71.0 +lat_0=-90 '
'+lon_0=0.0 +k_0=1.0 +x_0=0.0 +y_0=0.0 '
'+ellps=WGS84')

in_descriptor = ProjectionGridDescriptor.create(
in_projection, in_x, in_y, in_grid_name)

width = 6000.
reses = [1., 4., 10.]

for res in reses:
x_max = 0.5 * width * 1e3
nx = int(width / res) + 1
out_x = np.linspace(-x_max, x_max, nx)

out_grid_name = f'{width:g}x{width:g}km_{res:g}km_Antarctic_stereo'

out_projection = get_antarctic_stereographic_projection()

out_descriptor = ProjectionGridDescriptor.create(
out_projection, out_x, out_x, out_grid_name)

method = 'conserve'

map_filename = f'map_{in_grid_name}_to_{out_grid_name}_{method}.nc'

remapper = Remapper(in_descriptor, out_descriptor, map_filename)

if not os.path.exists(map_filename):
remapper.build_mapping_file(method=method, mpiTasks=task_count,
esmf_parallel_exec='srun')

ds_out = remapper.remap(ds)
mask = ds_out.meltMask > 0.
ds_out['meltRate'] = ds_out.meltRate.where(mask)
ds_out.meltRate.attrs = melt_attrs
mask = ds_out.uncertMask > 0.
ds_out['meltRateUncertainty'] = \
(np.sqrt(ds_out.meltRateUncertSqr)).where(mask)
ds_out.meltRateUncertainty.attrs = uncert_attrs
ds_out = ds_out.drop_vars(['meltRateUncertSqr'])
ds_out.to_netcdf(f'{out_prefix}_{out_grid_name}.{date}.nc')


def main():
prefix = 'Paolo_2023_iceshelf_melt_rates_1992-2017_v1.0'
date = '20240220'

orig_filename = 'Paolo_2023_ANT_G1920V01_IceShelfMelt.nc'
processed_filename = f'{prefix}.{date}.nc'

download_paolo(orig_filename)
process_paolo(orig_filename, processed_filename)
remap_paolo(processed_filename, prefix, date)


if __name__ == '__main__':
main()

0 comments on commit 12f1f9c

Please sign in to comment.