Skip to content

Commit b01ad0a

Browse files
authored
Merge pull request #989 from xylar/switch-to-land-ice-freshwater-flux-total
If available, plot climatology of total melt rate
2 parents 12f1f9c + 20dd7ca commit b01ad0a

2 files changed

Lines changed: 216 additions & 50 deletions

File tree

mpas_analysis/ocean/climatology_map_antarctic_melt.py

Lines changed: 182 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ def __init__(self, config, mpasClimatologyTask, regionMasksTask,
7676

7777
sectionName = self.taskName
7878

79-
mpasFieldName = 'timeMonthly_avg_landIceFreshwaterFlux'
8079
iselValues = None
8180

8281
# read in what seasons we want to plot
@@ -109,15 +108,15 @@ def __init__(self, config, mpasClimatologyTask, regionMasksTask,
109108
mpasClimatologyTask=mpasClimatologyTask,
110109
parentTask=self,
111110
climatologyName=fieldName,
112-
variableList=[mpasFieldName],
111+
variableList=None,
113112
comparisonGridNames=comparisonGridNames,
114113
seasons=seasons,
115114
iselValues=iselValues)
116115

117116
if controlConfig is None:
118117

119118
refTitleLabel = \
120-
'Observations (Paolo et al, 2023)'
119+
'Observations (Paolo et al. 2023)'
121120

122121
observationsDirectory = build_obs_path(
123122
config, 'ocean', 'meltSubdirectory')
@@ -138,47 +137,128 @@ def __init__(self, config, mpasClimatologyTask, regionMasksTask,
138137
f'{observationsDirectory}/Paolo/Paolo_2023_' \
139138
f'iceshelf_melt_rates_1992-2017_v1.0_6000x6000km_{res:g}km_' \
140139
f'Antarctic_stereo.20240220.nc'
141-
refFieldName = 'meltRate'
142-
outFileLabel = 'meltPaolo'
143-
galleryName = 'Observations: Paolo et al. (2023)'
144140

145141
remapObservationsSubtask = RemapObservedAntarcticMeltClimatology(
146142
parentTask=self, seasons=seasons, fileName=obsFileName,
147-
outFilePrefix=refFieldName,
143+
outFilePrefix='meltRate',
148144
comparisonGridNames=comparisonGridNames)
149145
self.add_subtask(remapObservationsSubtask)
150146
diffTitleLabel = 'Model - Observations'
151147

152148
else:
153149
remapObservationsSubtask = None
154150
controlRunName = controlConfig.get('runs', 'mainRunName')
155-
galleryName = None
156151
refTitleLabel = f'Control: {controlRunName}'
152+
diffTitleLabel = 'Main - Control'
153+
154+
totalFluxVar = 'timeMonthly_avg_landIceFreshwaterFluxTotal'
155+
landIceFluxVar = 'timeMonthly_avg_landIceFreshwaterFlux'
156+
frazilFluxVar = 'timeMonthly_avg_frazilIceFreshwaterFlux'
157157

158+
mpasFieldName = totalFluxVar
159+
160+
if controlConfig is None:
161+
refFieldName = 'meltRate'
162+
else:
158163
refFieldName = mpasFieldName
159-
outFileLabel = 'melt'
160-
diffTitleLabel = 'Main - Control'
161164

162165
for comparisonGridName in comparisonGridNames:
163166
for season in seasons:
164167
# make a new subtask for this season and comparison grid
165-
subtask = PlotClimatologyMapSubtask(
168+
subtaskName = f'plot_total_melt_{season}_{comparisonGridName}'
169+
subtask = PlotAntarcticMeltSubtask(
166170
self, season, comparisonGridName, remapClimatologySubtask,
167-
remapObservationsSubtask, controlConfig=controlConfig)
171+
remapObservationsSubtask, controlConfig=controlConfig,
172+
subtaskName=subtaskName)
168173

169174
subtask.set_plot_info(
170-
outFileLabel=outFileLabel,
171-
fieldNameInTitle='Melt Rate',
175+
outFileLabel='antMeltTotal',
176+
fieldNameInTitle='Total Melt Flux',
172177
mpasFieldName=mpasFieldName,
173178
refFieldName=refFieldName,
174179
refTitleLabel=refTitleLabel,
175180
diffTitleLabel=diffTitleLabel,
176-
unitsLabel=r'm a$^{-1}$',
177-
imageCaption='Antarctic Melt Rate',
181+
unitsLabel=r'm a$^{-1}$ freshwater equiv.',
182+
imageCaption='Antarctic Total Melt Flux',
178183
galleryGroup='Melt Rate',
179184
groupSubtitle=None,
180185
groupLink='antarctic_melt',
181-
galleryName=galleryName)
186+
galleryName='Total Melt Flux')
187+
188+
self.add_subtask(subtask)
189+
190+
mpasFieldName = landIceFluxVar
191+
192+
if controlConfig is None:
193+
refFieldName = 'meltRate'
194+
else:
195+
refFieldName = mpasFieldName
196+
197+
for comparisonGridName in comparisonGridNames:
198+
for season in seasons:
199+
# make a new subtask for this season and comparison grid
200+
subtaskName = \
201+
f'plot_interface_melt_{season}_{comparisonGridName}'
202+
subtask = PlotAntarcticMeltSubtask(
203+
self, season, comparisonGridName, remapClimatologySubtask,
204+
remapObservationsSubtask, controlConfig=controlConfig,
205+
subtaskName=subtaskName)
206+
207+
# In PlotAntarcticMeltSubtask, we will remove the obs from
208+
# these plots if totalFluxVar is present so we only compare one
209+
# field with obs
210+
211+
subtask.set_plot_info(
212+
outFileLabel='antMeltInterface',
213+
fieldNameInTitle='Melt Rate at Interface',
214+
mpasFieldName=mpasFieldName,
215+
refFieldName=refFieldName,
216+
refTitleLabel=refTitleLabel,
217+
diffTitleLabel=diffTitleLabel,
218+
unitsLabel=r'm a$^{-1}$ freshwater equiv.',
219+
imageCaption='Antarctic Melt Rate at Interface',
220+
galleryGroup='Melt Rate',
221+
groupSubtitle=None,
222+
groupLink='antarctic_melt_int',
223+
galleryName='Melt Rate at the Ice-ocean Interface')
224+
225+
self.add_subtask(subtask)
226+
227+
mpasFieldName = frazilFluxVar
228+
229+
if controlConfig is None:
230+
refTitleLabel = None
231+
refFieldName = None
232+
diffTitleLabel = None
233+
234+
else:
235+
controlRunName = controlConfig.get('runs', 'mainRunName')
236+
refTitleLabel = f'Control: {controlRunName}'
237+
refFieldName = mpasFieldName
238+
diffTitleLabel = 'Main - Control'
239+
240+
for comparisonGridName in comparisonGridNames:
241+
for season in seasons:
242+
# make a new subtask for this season and comparison grid
243+
subtaskName = \
244+
f'plot_interface_frazil_{season}_{comparisonGridName}'
245+
subtask = PlotAntarcticMeltSubtask(
246+
self, season, comparisonGridName, remapClimatologySubtask,
247+
controlConfig=controlConfig, subtaskName=subtaskName)
248+
249+
subtask.set_plot_info(
250+
outFileLabel='antFrazil',
251+
fieldNameInTitle='Frazil Accretion Rate, negative upward',
252+
mpasFieldName=mpasFieldName,
253+
refFieldName=refFieldName,
254+
refTitleLabel=refTitleLabel,
255+
diffTitleLabel=diffTitleLabel,
256+
unitsLabel=r'm a$^{-1}$ freshwater equiv.',
257+
imageCaption='Antarctic Accretion Rate',
258+
galleryGroup='Melt Rate',
259+
groupSubtitle=None,
260+
groupLink='antarctic_frazil_flux',
261+
galleryName='Frazil Accretion Rate')
182262

183263
self.add_subtask(subtask)
184264

@@ -212,11 +292,35 @@ class RemapMpasAntarcticMeltClimatology(RemapMpasClimatologySubtask):
212292
landIceMask : xarray.DataArray
213293
A mask indicating where there is land ice on the ocean grid (thus,
214294
where melt rates are valid)
295+
296+
renameDict : dict
297+
A dictionary use to rename variables in the climatology
215298
"""
216299
# Authors
217300
# -------
218301
# Xylar Asay-Davis
219302

303+
def setup_and_check(self):
304+
"""
305+
Figure out which variable(s) to remap
306+
"""
307+
# Authors
308+
# -------
309+
# Xylar Asay-Davis
310+
311+
totalFluxVar = 'timeMonthly_avg_landIceFreshwaterFluxTotal'
312+
landIceFluxVar = 'timeMonthly_avg_landIceFreshwaterFlux'
313+
frazilFluxVar = 'timeMonthly_avg_frazilIceFreshwaterFlux'
314+
315+
if totalFluxVar in self.mpasClimatologyTask.allVariables:
316+
# include the total and constituent fluxes
317+
self.variableList = [totalFluxVar, landIceFluxVar, frazilFluxVar]
318+
else:
319+
# we only have the old name without the frazil accretion rate
320+
self.variableList = [landIceFluxVar]
321+
322+
super().setup_and_check()
323+
220324
def run_task(self):
221325
"""
222326
Compute climatologies of melt rates from E3SM/MPAS output
@@ -260,12 +364,14 @@ def customize_masked_climatology(self, climatology, season):
260364
# -------
261365
# Xylar Asay-Davis
262366

263-
fieldName = self.variableList[0]
367+
for fieldName in self.variableList:
264368

265-
# scale the field to m/yr from kg/m^2/s and mask out non-land-ice areas
266-
climatology[fieldName] = \
267-
constants.sec_per_year / constants.rho_fw * \
268-
climatology[fieldName].where(self.landIceMask)
369+
# scale the field to m/yr from kg/m^2/s and mask out non-land-ice
370+
# areas
371+
climatology[fieldName] = \
372+
constants.sec_per_year / constants.rho_fw * \
373+
climatology[fieldName].where(self.landIceMask)
374+
climatology[fieldName].attrs['units'] = 'm yr^-1'
269375

270376
return climatology
271377

@@ -422,7 +528,8 @@ def run_task(self):
422528
pool=ThreadPool(1)):
423529

424530
# Load data:
425-
inFileName = self.mpasClimatologyTask.get_file_name(self.season)
531+
inFileName = \
532+
self.mpasClimatologyTask.get_file_name(self.season)
426533
mpasFieldName = 'timeMonthly_avg_landIceFreshwaterFlux'
427534
dsIn = xr.open_dataset(inFileName)
428535
freshwaterFlux = dsIn[mpasFieldName]
@@ -445,7 +552,8 @@ def run_task(self):
445552

446553
# select only those regions we want to plot
447554
dsRegionMask = dsRegionMask.isel(nRegions=regionIndices)
448-
cellMasks = dsRegionMask.regionCellMasks.chunk({'nRegions': 10})
555+
cellMasks = \
556+
dsRegionMask.regionCellMasks.chunk({'nRegions': 10})
449557

450558
restartFileName = \
451559
self.runStreams.readpath('restart')[0]
@@ -548,3 +656,53 @@ def run_task(self):
548656
row[controlRunName] = \
549657
f'{dsControl.totalMeltFlux[index].values}'
550658
writer.writerow(row)
659+
660+
661+
class PlotAntarcticMeltSubtask(PlotClimatologyMapSubtask):
662+
"""
663+
A subtask for plotting antarctic melt fields if available
664+
665+
Attributes
666+
----------
667+
doPlot : bool
668+
Whether the required variable from the climatology is available so that
669+
a plot should be generated
670+
"""
671+
# Authors
672+
# -------
673+
# Xylar Asay-Davis
674+
675+
def setup_and_check(self):
676+
"""
677+
Perform steps to set up the analysis and check for errors in the setup.
678+
"""
679+
allVariables = \
680+
self.remapMpasClimatologySubtask.mpasClimatologyTask.allVariables
681+
682+
totalFluxVar = 'timeMonthly_avg_landIceFreshwaterFluxTotal'
683+
landIceFluxVar = 'timeMonthly_avg_landIceFreshwaterFlux'
684+
plotAll = (totalFluxVar in allVariables)
685+
686+
if self.mpasFieldName == landIceFluxVar and plotAll and \
687+
self.controlConfig is None:
688+
# need to remove obs because we only wnat to plot them vs the
689+
# total flux
690+
self.remapObsClimatologySubtask = None
691+
self.refTitleLabel = None
692+
self.refFieldName = None
693+
self.diffTitleLabel = None
694+
695+
self.doPlot = (self.mpasFieldName == landIceFluxVar or plotAll)
696+
697+
if self.doPlot:
698+
super().setup_and_check()
699+
else:
700+
# still need to call the base class's method
701+
AnalysisTask.setup_and_check(self=self)
702+
703+
def run_task(self):
704+
"""
705+
Plot the variable if available
706+
"""
707+
if self.doPlot:
708+
super().run_task()

0 commit comments

Comments
 (0)