示例#1
0
 def read_process_data (file_path, var_name, grid, mask_option='3d', gtype='t', lev_option=None, ismr=False, psi=False):
     data = read_netcdf(file_path, var_name)
     if mask_option == '3d':
         data = mask_3d(data, grid, gtype=gtype, time_dependent=True)
     elif mask_option == 'except_ice':
         data = mask_except_ice(data, grid, gtype=gtype, time_dependent=True)
     elif mask_option == 'land':
         data = mask_land(data, grid, gtype=gtype, time_dependent=True)
     elif mask_option == 'land_ice':
         data = mask_land_ice(data, grid, gtype=gtype, time_dependent=True)
     else:
         print 'Error (read_process_data): invalid mask_option ' + mask_option
         sys.exit()
     if lev_option is not None:
         if lev_option == 'top':
             data = select_top(data)
         elif lev_option == 'bottom':
             data = select_bottom(data)
         else:
             print 'Error (read_process_data): invalid lev_option ' + lev_option
             sys.exit()
     if ismr:
         data = convert_ismr(data)
     if psi:
         data = np.sum(data, axis=-3)*1e-6
     return data
示例#2
0
def timeseries_area_sfc(option,
                        file_path,
                        var_name,
                        grid,
                        gtype='t',
                        time_index=None,
                        t_start=None,
                        t_end=None,
                        time_average=False):

    # Read the data
    data = read_netcdf(file_path,
                       var_name,
                       time_index=time_index,
                       t_start=t_start,
                       t_end=t_end,
                       time_average=time_average)
    if len(data.shape) == 2:
        # Just one timestep; add a dummy time dimension
        data = np.expand_dims(data, 0)

    # Process one time index at a time to save memory
    timeseries = []
    for t in range(data.shape[0]):
        # Mask
        data_tmp = mask_land_ice(data[t, :], grid, gtype=gtype)
        # Area-average or integrate
        timeseries.append(over_area(option, data_tmp, grid, gtype=gtype))
    return np.array(timeseries)
示例#3
0
def iceberg_meltwater(grid_path, input_dir, output_file, nc_out=None, prec=32):

    from plot_latlon import latlon_plot

    input_dir = real_dir(input_dir)
    file_head = 'icebergs_'
    file_tail = '.nc'

    print 'Building grids'
    # Read the NEMO grid from the first file
    # It has longitude in the range -180 to 180
    file_path = input_dir + file_head + '01' + file_tail
    nemo_lon = read_netcdf(file_path, 'nav_lon')
    nemo_lat = read_netcdf(file_path, 'nav_lat')
    # Build the model grid
    model_grid = Grid(grid_path, max_lon=180)

    print 'Interpolating'
    icebergs_interp = np.zeros([12, model_grid.ny, model_grid.nx])
    for month in range(12):
        print '...month ' + str(month + 1)
        # Read the data
        file_path = input_dir + file_head + '{0:02d}'.format(month +
                                                             1) + file_tail
        icebergs = read_netcdf(file_path, 'berg_total_melt', time_index=0)
        # Interpolate
        icebergs_interp_tmp = interp_nonreg_xy(nemo_lon,
                                               nemo_lat,
                                               icebergs,
                                               model_grid.lon_1d,
                                               model_grid.lat_1d,
                                               fill_value=0)
        # Make sure the land and ice shelf cavities don't get any iceberg melt
        icebergs_interp_tmp[model_grid.land_mask + model_grid.ice_mask] = 0
        # Save to the master array
        icebergs_interp[month, :] = icebergs_interp_tmp

    write_binary(icebergs_interp, output_file, prec=prec)

    print 'Plotting'
    # Make a nice plot of the annual mean
    latlon_plot(mask_land_ice(np.mean(icebergs_interp, axis=0), model_grid),
                model_grid,
                include_shelf=False,
                vmin=0,
                title=r'Annual mean iceberg melt (kg/m$^2$/s)')
    if nc_out is not None:
        # Also write to NetCDF file
        print 'Writing ' + nc_out
        ncfile = NCfile(nc_out, model_grid, 'xyt')
        ncfile.add_time(np.arange(12) + 1, units='months')
        ncfile.add_variable('iceberg_melt',
                            icebergs_interp,
                            'xyt',
                            units='kg/m^2/s')
        ncfile.close()
示例#4
0
def polynya_mask(grid_path, polynya, mask_file, prec=64):

    from plot_latlon import latlon_plot

    # Define the centre and radii of the ellipse bounding the polynya
    if polynya == 'maud_rise':  # Area 2.6 x 10^5 km^2
        lon0 = 0.
        lat0 = -65.
        rlon = 8.
        rlat = 2.
    elif polynya == 'near_shelf':  # Area 2.6 x 10^5 km^2
        lon0 = -30.
        lat0 = -70.
        rlon = 9.
        rlat = 2.2
    elif polynya == 'maud_rise_big':  # Area 6.2 x 10^5 km^2
        lon0 = 0.
        lat0 = -65.
        rlon = 15.
        rlat = 2.5
    elif polynya == 'maud_rise_small':  # Area 0.34 x 10^5 km^2
        lon0 = 0
        lat0 = -65.
        rlon = 2.8
        rlat = 0.75
    else:
        print 'Error (polynya_mask): invalid polynya option ' + polynya
        sys.exit()

    # Build the grid
    grid = Grid(grid_path)
    # Set up the mask
    mask = np.zeros([grid.ny, grid.nx])
    # Select the polynya region
    index = (grid.lon_2d - lon0)**2 / rlon**2 + (grid.lat_2d -
                                                 lat0)**2 / rlat**2 <= 1
    mask[index] = 1

    # Print the area of the polynya
    print 'Polynya area is ' + str(area_integral(mask, grid) * 1e-6) + ' km^2'
    # Plot the mask
    latlon_plot(mask_land_ice(mask, grid),
                grid,
                include_shelf=False,
                title='Polynya mask',
                figsize=(10, 6))

    # Write to file
    write_binary(mask, mask_file, prec=prec)
示例#5
0
def interp_grid(data,
                grid,
                gtype_in,
                gtype_out,
                time_dependent=False,
                mask=True,
                mask_shelf=False,
                mask_with_zeros=False,
                periodic=False):

    depth_dependent = is_depth_dependent(data, time_dependent=time_dependent)
    # Make sure we're not trying to mask the ice shelf from a depth-dependent field
    if mask_shelf and depth_dependent:
        print "Error (interp_grid): can't set mask_shelf=True for a depth-dependent field."
        sys.exit()

    if mask and gtype_in in ['u', 'v', 'psi', 'w']:
        # Fill the mask with zeros (okay because no-slip boundary condition)
        data_tmp = np.copy(data)
        data_tmp[data.mask] = 0.0
    else:
        # Tracer land mask is the least restrictive, so it doesn't matter what the masked values are - they will definitely get re-masked at the end.
        data_tmp = data

    # Interpolate
    data_interp = np.empty(data_tmp.shape)
    if gtype_in == 'u' and gtype_out == 't':
        # Midpoints in the x direction
        data_interp[..., :-1] = 0.5 * (data_tmp[..., :-1] + data_tmp[..., 1:])
        # Extend/wrap the easternmost column
        if periodic:
            data_interp[..., -1] = data_interp[..., 0]
        else:
            data_interp[..., -1] = data_tmp[..., -1]
    elif gtype_in == 'v' and gtype_out == 't':
        # Midpoints in the y direction
        data_interp[..., :-1, :] = 0.5 * (data_tmp[..., :-1, :] +
                                          data_tmp[..., 1:, :])
        # Extend the northernmost row
        data_interp[..., -1, :] = data_tmp[..., -1, :]
    elif gtype_in == 't' and gtype_out == 'u':
        # Midpoints in the x direction
        data_interp[..., 1:] = 0.5 * (data_tmp[..., :-1] + data_tmp[..., 1:])
        # Extend/wrap the westernmost column
        if periodic:
            data_interp[..., 0] = data_interp[..., -1]
        else:
            data_interp[..., 0] = data_tmp[..., 0]
    elif gtype_in == 't' and gtype_out == 'v':
        # Midpoints in the y direction
        data_interp[..., 1:, :] = 0.5 * (data_tmp[..., :-1, :] +
                                         data_tmp[..., :-1, :])
        # Extend the southernmost row
        data_interp[..., 0, :] = data_tmp[..., 0, :]
    else:
        print 'Error (interp_grid): interpolation from the ' + gtype_in + '-grid to the ' + gtype_out + '-grid is not yet supported'
        sys.exit()

    if mask:
        # Now apply the mask
        if depth_dependent:
            data_interp = mask_3d(data_interp,
                                  grid,
                                  gtype=gtype_out,
                                  time_dependent=time_dependent)
        else:
            if mask_shelf:
                data_interp = mask_land_ice(data_interp,
                                            grid,
                                            gtype=gtype_out,
                                            time_dependent=time_dependent)
            else:
                data_interp = mask_land(data_interp,
                                        grid,
                                        gtype=gtype_out,
                                        time_dependent=time_dependent)

        if mask_with_zeros:
            # Remove mask and fill with zeros
            data_interp[data_interp.mask] = 0
            data_interp = data_interp.data

    return data_interp
示例#6
0
def seaice_drag_scaling (grid_path, output_file, rd_scale=1, bb_scale=1, ft_scale=1, prec=64):

    from plot_latlon import latlon_plot

    # Cutoff latitude
    max_lat = -74
    # Longitude bounds on each region
    rd_bounds = [-62, -58]
    bb_bounds = [-57, -49]
    ft_bounds = [-48, -35]
    bounds = [rd_bounds, bb_bounds, ft_bounds]
    scale_factors = [rd_scale, bb_scale, ft_scale]
    # Max distance from the coast (km)
    scale_dist = 150
    # Sigma for smoothing
    sigma = 2

    print 'Building grid'
    grid = Grid(grid_path)
    print 'Selecting coastal points'
    coast_mask = grid.get_coast_mask(ignore_iceberg=True)
    lon_coast = grid.lon_2d[coast_mask].ravel()
    lat_coast = grid.lat_2d[coast_mask].ravel()

    print 'Selecting regions'
    scale_coast = np.ones(lon_coast.shape)
    for n in range(3):
        index = (lon_coast >= bounds[n][0])*(lon_coast <= bounds[n][1])*(lat_coast <= max_lat)
        scale_coast[index] = scale_factors[n]

    print 'Calculating distance from the coast'
    min_dist = None
    nearest_scale = None
    # Loop over all the coastal points
    for i in range(lon_coast.size):
        # Calculate distance of every point in the model grid to this specific coastal point, in km
        dist_to_pt = dist_btw_points([lon_coast[i], lat_coast[i]], [grid.lon_2d, grid.lat_2d])*1e-3
        if min_dist is None:
            # Initialise the arrays
            min_dist = dist_to_pt
            nearest_scale = np.zeros(min_dist.shape) + scale_coast[i]
        else:
            # Figure out which cells have this coastal point as the closest one yet, and update the arrays
            index = dist_to_pt < min_dist
            min_dist[index] = dist_to_pt[index]
            nearest_scale[index] = scale_coast[i]
    # Smooth the result, and mask out the land and ice shelves
    min_dist = mask_land_ice(min_dist, grid)
    nearest_scale = mask_land_ice(smooth_xy(nearest_scale, sigma=sigma), grid)

    print 'Extending scale factors offshore'
    # Cosine function moving from scaling factor to 1 over distance of 300 km offshore
    scale_extend = (min_dist < scale_dist)*(nearest_scale - 1)*np.cos(np.pi/2*min_dist/scale_dist) + 1

    print 'Plotting'
    latlon_plot(scale_extend, grid, ctype='ratio', include_shelf=False, title='Scaling factor', figsize=(10,6))
    latlon_plot(scale_extend, grid, ctype='ratio', include_shelf=False, title='Scaling factor', zoom_fris=True)

    print 'Writing to file'
    # Replace mask with zeros
    mask = scale_extend.mask
    scale_extend = scale_extend.data
    scale_extend[mask] = 0
    write_binary(scale_extend, output_file, prec=prec)
示例#7
0
def katabatic_correction(grid_dir,
                         cmip_file,
                         era5_file,
                         out_file_scale,
                         out_file_rotate,
                         scale_cap=3,
                         xmin=None,
                         xmax=None,
                         ymin=None,
                         ymax=None,
                         prec=64):

    var_names = ['uwind', 'vwind']
    scale_dist = 150.
    # Radius for smoothing
    sigma = 2

    print 'Building grid'
    grid = Grid(grid_dir)
    print 'Selecting coastal points'
    coast_mask = grid.get_coast_mask(ignore_iceberg=True)
    lon_coast = grid.lon_2d[coast_mask].ravel()
    lat_coast = grid.lat_2d[coast_mask].ravel()
    if xmin is None:
        xmin = np.amin(grid.lon_2d)
    if xmax is None:
        xmax = np.amax(grid.lon_2d)
    if ymin is None:
        ymin = np.amin(grid.lat_2d)
    if ymax is None:
        ymax = np.amax(grid.lat_2d)

    print 'Calculating winds in polar coordinates'
    magnitudes = []
    angles = []
    for fname in [cmip_file, era5_file]:
        u = read_netcdf(fname, var_names[0])
        v = read_netcdf(fname, var_names[1])
        magnitudes.append(np.sqrt(u**2 + v**2))
        angle = np.arctan2(v, u)
        angles.append(angle)

    print 'Calculating corrections'
    # Take minimum of the ratio of ERA5 to CMIP wind magnitude, and the scale cap
    scale = np.minimum(magnitudes[1] / magnitudes[0], scale_cap)
    # Smooth and mask the land and ice shelf
    scale = mask_land_ice(smooth_xy(scale, sigma=sigma), grid)
    # Take difference in angles
    rotate = angles[1] - angles[0]
    # Take mod 2pi when necessary
    index = rotate < -np.pi
    rotate[index] += 2 * np.pi
    index = rotate > np.pi
    rotate[index] -= 2 * np.pi
    # Smoothing would be weird with the periodic angle, so just mask
    rotate = mask_land_ice(rotate, grid)

    print 'Calculating distance from the coast'
    min_dist = None
    # Loop over all the coastal points
    for i in range(lon_coast.size):
        # Skip over any points that are out of bounds
        if lon_coast[i] < xmin or lon_coast[i] > xmax or lat_coast[
                i] < ymin or lat_coast[i] > ymax:
            continue
        # Calculate distance of every point in the model grid to this specific coastal point, in km
        dist_to_pt = dist_btw_points([lon_coast[i], lat_coast[i]],
                                     [grid.lon_2d, grid.lat_2d]) * 1e-3
        if min_dist is None:
            # Initialise the array
            min_dist = dist_to_pt
        else:
            # Figure out which cells have this coastal point as the closest one yet, and update the array
            index = dist_to_pt < min_dist
            min_dist[index] = dist_to_pt[index]

    print 'Tapering function offshore'
    # Cosine function moving from scaling factor to 1 over distance of scale_dist km offshore
    scale_tapered = (min_dist < scale_dist) * (scale - 1) * np.cos(
        np.pi / 2 * min_dist / scale_dist) + 1
    # For the rotation, move from scaling factor to 0
    rotate_tapered = (min_dist < scale_dist) * rotate * np.cos(
        np.pi / 2 * min_dist / scale_dist)

    print 'Plotting'
    data_to_plot = [min_dist, scale_tapered, rotate_tapered]
    titles = ['Distance to coast (km)', 'Scaling factor', 'Rotation factor']
    ctype = ['basic', 'ratio', 'plusminus']
    fig_names = ['min_dist.png', 'scale.png', 'rotate.png']
    for i in range(len(data_to_plot)):
        for fig_name in [None, fig_names[i]]:
            latlon_plot(data_to_plot[i],
                        grid,
                        ctype=ctype[i],
                        include_shelf=False,
                        title=titles[i],
                        figsize=(10, 6),
                        fig_name=fig_name)

    print 'Writing to file'
    fields = [scale_tapered, rotate_tapered]
    out_files = [out_file_scale, out_file_rotate]
    for n in range(len(fields)):
        # Replace mask with zeros
        mask = fields[n].mask
        data = fields[n].data
        data[mask] = 0
        write_binary(data, out_files[n], prec=prec)