Source code for mpas_analysis.ocean.climatology_map_antarctic_melt

# This software is open source software available under the BSD-3 license.
#
# Copyright (c) 2019 Triad National Security, LLC. All rights reserved.
# Copyright (c) 2019 Lawrence Livermore National Security, LLC. All rights
# reserved.
# Copyright (c) 2019 UT-Battelle, LLC. All rights reserved.
#
# Additional copyright and license information can be found in the LICENSE file
# distributed with this code, or at
# https://raw.githubusercontent.com/MPAS-Dev/MPAS-Analysis/master/LICENSE
from __future__ import absolute_import, division, print_function, \
    unicode_literals

import xarray as xr
from pyremap import ProjectionGridDescriptor

from mpas_analysis.shared import AnalysisTask

from mpas_analysis.shared.io.utility import build_obs_path

from mpas_analysis.shared.climatology import RemapMpasClimatologySubtask, \
    RemapObservedClimatologySubtask, get_antarctic_stereographic_projection

from mpas_analysis.ocean.plot_climatology_map_subtask import \
    PlotClimatologyMapSubtask

from mpas_analysis.shared.mpas_xarray import mpas_xarray

from mpas_analysis.shared.constants import constants


[docs]class ClimatologyMapAntarcticMelt(AnalysisTask): # {{{ """ An analysis task for comparison of Antarctic melt rates against observations """ # Authors # ------- # Xylar Asay-Davis
[docs] def __init__(self, config, mpasClimatologyTask, controlConfig=None): # {{{ """ Construct the analysis task. Parameters ---------- config : ``MpasAnalysisConfigParser`` Configuration options mpasClimatologyTask : ``MpasClimatologyTask`` The task that produced the climatology to be remapped and plotted controlConfig : ``MpasAnalysisConfigParser``, optional Configuration options for a control run (if any) """ # Authors # ------- # Xylar Asay-Davis fieldName = 'meltRate' # call the constructor from the base class (AnalysisTask) super(ClimatologyMapAntarcticMelt, self).__init__( config=config, taskName='climatologyMapAntarcticMelt', componentName='ocean', tags=['climatology', 'horizontalMap', fieldName, 'landIceCavities', 'antarctic']) sectionName = self.taskName mpasFieldName = 'timeMonthly_avg_landIceFreshwaterFlux' iselValues = None # read in what seasons we want to plot seasons = config.getExpression(sectionName, 'seasons') if len(seasons) == 0: raise ValueError('config section {} does not contain valid list ' 'of seasons'.format(sectionName)) comparisonGridNames = config.getExpression(sectionName, 'comparisonGrids') if len(comparisonGridNames) == 0: raise ValueError('config section {} does not contain valid list ' 'of comparison grids'.format(sectionName)) # the variable 'timeMonthly_avg_landIceFreshwaterFlux' will be added to # mpasClimatologyTask along with the seasons. remapClimatologySubtask = RemapMpasAntarcticMeltClimatology( mpasClimatologyTask=mpasClimatologyTask, parentTask=self, climatologyName=fieldName, variableList=[mpasFieldName], comparisonGridNames=comparisonGridNames, seasons=seasons, iselValues=iselValues) if controlConfig is None: refTitleLabel = \ 'Observations (Rignot et al, 2013)' observationsDirectory = build_obs_path( config, 'ocean', 'meltSubdirectory') obsFileName = \ '{}/Rignot_2013_melt_rates_6000.0x6000.0km_10.0km_' \ 'Antarctic_stereo.nc'.format(observationsDirectory) refFieldName = 'meltRate' outFileLabel = 'meltRignot' galleryName = 'Observations: Rignot et al. (2013)' remapObservationsSubtask = RemapObservedAntarcticMeltClimatology( parentTask=self, seasons=seasons, fileName=obsFileName, outFilePrefix=refFieldName, comparisonGridNames=comparisonGridNames) self.add_subtask(remapObservationsSubtask) diffTitleLabel = 'Model - Observations' else: remapObservationsSubtask = None controlRunName = controlConfig.get('runs', 'mainRunName') galleryName = None refTitleLabel = 'Control: {}'.format(controlRunName) refFieldName = mpasFieldName outFileLabel = 'melt' diffTitleLabel = 'Main - Control' for comparisonGridName in comparisonGridNames: for season in seasons: # make a new subtask for this season and comparison grid subtask = PlotClimatologyMapSubtask( self, season, comparisonGridName, remapClimatologySubtask, remapObservationsSubtask, controlConfig=controlConfig) subtask.set_plot_info( outFileLabel=outFileLabel, fieldNameInTitle='Melt Rate', mpasFieldName=mpasFieldName, refFieldName=refFieldName, refTitleLabel=refTitleLabel, diffTitleLabel=diffTitleLabel, unitsLabel=r'm a$^{-1}$', imageCaption='Antarctic Melt Rate', galleryGroup='Melt Rate', groupSubtitle=None, groupLink='antarctic_melt', galleryName=galleryName) self.add_subtask(subtask)
# }}} def setup_and_check(self): # {{{ """ Perform steps to set up the analysis and check for errors in the setup. """ # Authors # ------- # Xylar Asay-Davis # first, call setup_and_check from the base class # (AnalysisTask), which will perform some common setup super(ClimatologyMapAntarcticMelt, self).setup_and_check() landIceFluxMode = self.namelist.get('config_land_ice_flux_mode') if landIceFluxMode not in ['standalone', 'coupled']: raise ValueError('*** climatologyMapMeltAntarctic requires ' 'config_land_ice_flux_mode \n' ' to be standalone or coupled. Otherwise, no ' 'melt rates are available \n' ' for plotting.')
# }}} # }}} class RemapMpasAntarcticMeltClimatology(RemapMpasClimatologySubtask): # {{{ """ A subtask for remapping climatologies of Antarctic melt rates and adding Attributes ---------- landIceMask : xarray.DataArray A mask indicating where there is land ice on the ocean grid (thus, where melt rates are valid) """ # Authors # ------- # Xylar Asay-Davis def run_task(self): # {{{ """ Compute climatologies of melt rates from E3SM/MPAS output This function has been overridden to load ``landIceMask`` from a restart file for later use in masking the melt rate. It then simply calls the run function from """ # Authors # ------- # Xylar Asay-Davis # first, load the land-ice mask from the restart file dsLandIceMask = xr.open_dataset(self.restartFileName) dsLandIceMask = mpas_xarray.subset_variables(dsLandIceMask, ['landIceMask']) dsLandIceMask = dsLandIceMask.isel(Time=0) self.landIceMask = dsLandIceMask.landIceMask > 0. # then, call run from the base class (RemapMpasClimatologySubtask), # which will perform the main function of the task super(RemapMpasAntarcticMeltClimatology, self).run_task() # }}} def customize_masked_climatology(self, climatology, season): # {{{ """ Mask the melt rates using ``landIceMask`` and rescale it to m/yr Parameters ---------- climatology : ``xarray.Dataset`` object the climatology data set season : str The name of the season to be masked Returns ------- climatology : ``xarray.Dataset`` object the modified climatology data set """ # Authors # ------- # Xylar Asay-Davis fieldName = self.variableList[0] # scale the field to m/yr from kg/m^2/s and mask out non-land-ice areas climatology[fieldName] = \ constants.sec_per_year / constants.rho_fw * \ climatology[fieldName].where(self.landIceMask) return climatology # }}} # }}} class RemapObservedAntarcticMeltClimatology(RemapObservedClimatologySubtask): # {{{ """ A subtask for reading and remapping Antarctic melt-rate observations """ # Authors # ------- # Xylar Asay-Davis def get_observation_descriptor(self, fileName): # {{{ ''' get a MeshDescriptor for the observation grid Parameters ---------- fileName : str observation file name describing the source grid Returns ------- obsDescriptor : ``MeshDescriptor`` The descriptor for the observation grid ''' # Authors # ------- # Xylar Asay-Davis # create a descriptor of the observation grid using the x/y polar # stereographic coordinates projection = get_antarctic_stereographic_projection() obsDescriptor = ProjectionGridDescriptor.read( projection, fileName=fileName, xVarName='x', yVarName='y') return obsDescriptor # }}} def build_observational_dataset(self, fileName): # {{{ ''' read in the data sets for observations, and possibly rename some variables and dimensions Parameters ---------- fileName : str observation file name Returns ------- dsObs : ``xarray.Dataset`` The observational dataset ''' # Authors # ------- # Xylar Asay-Davis # Load MLD observational data dsObs = xr.open_dataset(fileName) return dsObs # }}} # }}} # vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python