|
| 1 | +#!/usr/bin/env python |
| 2 | +''' |
| 3 | +Script to bulldoze marine troughs. |
| 4 | +
|
| 5 | +At a number of locations around Antarctica, it is clear that the |
| 6 | +portion of subglacial troughs seaward of the grounding line are not continuous with |
| 7 | +the portion beneath grounded ice. This is expected from the relative dearth of |
| 8 | +sub-ice-shelf bathymetric measurements compared with the high density of radar |
| 9 | +measurements beneath grounded ice. The coarse representation of bahthymetry on the |
| 10 | +seaward side of the grounding line in these locations leads to strong grounding line |
| 11 | +advance at these outlet glaciers and associated grounded mass gain. |
| 12 | +
|
| 13 | +In this script, a number of trough locations to be deepened are specified by x/y |
| 14 | +coordinate pairs for the start and end of the trough. The smoothTrough function |
| 15 | +is called for each, which applies a parabolic transverse cross section over a centerline |
| 16 | +trough depth that increases linearly between a minimum and maximum value. |
| 17 | +Note that as currently written, the algorithm only works for troughs oriented southwest to |
| 18 | +northeast in grid coordinates! |
| 19 | +
|
| 20 | +The location of the points defining the troughs and the amount to bulldoze is |
| 21 | +hardcoded after the smoothTrough function. Adjustments should be made there. |
| 22 | +
|
| 23 | +Input file is copied with a _bulldozedTroughs.nc suffix before being modified. |
| 24 | +
|
| 25 | +Matt Hoffman, Fall 2022 |
| 26 | +''' |
| 27 | + |
| 28 | +from __future__ import absolute_import, division, print_function, unicode_literals |
| 29 | + |
| 30 | +import sys |
| 31 | +import numpy as np |
| 32 | +from netCDF4 import Dataset |
| 33 | +from optparse import OptionParser |
| 34 | +import matplotlib.pyplot as plt |
| 35 | +import shutil |
| 36 | + |
| 37 | + |
| 38 | +print("** Gathering information. (Invoke with --help for more details. All arguments are optional)") |
| 39 | +parser = OptionParser(description=__doc__) |
| 40 | +parser.add_option("-f", dest="fileName", help="filename to modify", metavar="FILENAME") |
| 41 | +options, args = parser.parse_args() |
| 42 | + |
| 43 | +rhoi=910.0 |
| 44 | +rhosw=1028.0 |
| 45 | + |
| 46 | +# Make a copy of file being modified and work on the copy |
| 47 | +outFileName = options.fileName.split('.nc')[0] + '_bulldozedTroughs.nc' |
| 48 | +shutil.copy(options.fileName, outFileName) |
| 49 | +print("Writing output to:", outFileName) |
| 50 | +f = Dataset(outFileName, 'r+') |
| 51 | + |
| 52 | +nCells = len(f.dimensions['nCells']) |
| 53 | +mu = f.variables['muFriction'][0,:] |
| 54 | +thickness = f.variables['thickness'][0,:] |
| 55 | +bedTopography = f.variables['bedTopography'][0,:] |
| 56 | +cOnC= f.variables['cellsOnCell'][:] |
| 57 | +nEOnC = f.variables['nEdgesOnCell'][:] |
| 58 | +xCell = f.variables['xCell'][:] |
| 59 | +yCell = f.variables['yCell'][:] |
| 60 | +xEdge = f.variables['xEdge'][:] |
| 61 | +yEdge = f.variables['yEdge'][:] |
| 62 | +dcEdge = f.variables['dcEdge'][:] |
| 63 | +lowerSurface = -rhoi/rhosw*thickness # only works for floating cells |
| 64 | +WCT = lowerSurface - bedTopography |
| 65 | + |
| 66 | +floatMask = ((thickness*910/1028+bedTopography)<0.0)*(thickness>0.0) |
| 67 | +#groundMask = ((thickness*910/1028+bedTopography)>0.0)*(thickness>0.0) |
| 68 | + |
| 69 | +def smoothTrough(WCT, p1, p2, minWCT, maxWCT): |
| 70 | + WCTnew = WCT.copy() |
| 71 | + |
| 72 | + # find representative dCell for this area |
| 73 | + ind = np.nonzero( (xEdge>p1[0]) * (xEdge<p2[0]) * (yEdge>p1[1]) * (yEdge<p1[2]) )[0] |
| 74 | + dCell = dcEdge[ind].mean() |
| 75 | + print(f"using dCell={dCell}") |
| 76 | + |
| 77 | + mask = (WCT<maxWCT) * (floatMask==1) * (xCell>(p1[0]-2*dCell)) * (xCell<(p2[0]+2*dCell)) * (yCell>(p1[1]-2*dCell)) * (yCell<(p2[1]+2*dCell)) |
| 78 | + ind = np.nonzero(mask==1)[0] |
| 79 | + length = ( (p2[0]-p1[0])**2 + (p2[1]-p1[1])**2 )**0.5 # length along flowline |
| 80 | + m1 = (p2[1]-p1[1]) / (p2[0]-p1[0]) # xy slope of flowline |
| 81 | + b1 = p1[1] - m1*p1[0] # y int of flowline |
| 82 | + print(f'# cells={len(ind)}, length={length}, m={m1}') |
| 83 | + m2 = -1.0/m1 # slope of all transverse lines |
| 84 | + for c in ind: |
| 85 | + # find width and center at this position |
| 86 | + b2 = yCell[c] - m2 * xCell[c] # y int of transverse line |
| 87 | + dist2orthogline = np.absolute(m2*xCell + -1*yCell + b2) / (m2**2 + (-1)**2)**0.5 |
| 88 | + ind2 = np.nonzero((mask==1) * (dist2orthogline<(1.5*dCell)))[0] # get the points within a certain distance of the orthog line |
| 89 | + dist2centerline = np.absolute(m1*xCell[ind2] + -1*yCell[ind2] + b1) / (m1**2 + (-1)**2)**0.5 |
| 90 | + #dist2centerline = np.absolute( (p2[0]-p1[0]) * (p1[1] - yCell[ind2]) - (p1[0]-xCell[ind2])*(p2[1]-p1[1])) / ( (p2[0]-p1[0])**2 + (p2[1]-p1[1])**2)**0.5 |
| 91 | + dist2centerline *= np.sign((m1*xCell[ind2]+b1) - yCell[ind2]) # make signed distance, assuming NE direction |
| 92 | + print(dist2centerline) |
| 93 | + width = dist2centerline.max()-dist2centerline.min() |
| 94 | + |
| 95 | + # find frac x along center line |
| 96 | + # first need intersection of longit. and ortho lines |
| 97 | + xint = (b2-b1)/(m1-(-1.0/m1)) |
| 98 | + mag = (xint-p1[0]) / (p2[0]-p1[0]) * (maxWCT-minWCT) + minWCT |
| 99 | + |
| 100 | + widthOrgnIdx = ind2[np.argmin(dist2centerline)] #idx of westmost |
| 101 | + widthOrgn = (xCell[widthOrgnIdx], yCell[widthOrgnIdx]) # position of westmost |
| 102 | + widthEndIdx = ind2[np.argmax(dist2centerline)] #idx of westmost |
| 103 | + widthEnd = (xCell[widthEndIdx], yCell[widthEndIdx]) # position of westmost |
| 104 | + widthMidpt = ((widthOrgn[0]+widthEnd[0])/2.0, (widthOrgn[1]+widthEnd[1])/2.0) |
| 105 | + print(xCell[c], yCell[c], widthOrgn) |
| 106 | + #dist2Orgn = ((widthOrgn[0]-xCell[c])**2 + (widthOrgn[1]-yCell[c])**2)**0.5 |
| 107 | + #fracWidth = (dist2Orgn / (width) - 0.5) * 2.0 # [-1,1] range |
| 108 | + dist2Mid = ((widthMidpt[0]-xCell[c])**2 + (widthMidpt[1]-yCell[c])**2)**0.5 |
| 109 | + fracWidth = dist2Mid / (0.5*(width+2*dCell)) # [-1,1] range |
| 110 | + fracWidth = min(fracWidth, 0.95) |
| 111 | + print(f'found {len(ind2)} points along this orthogonal; width={width}; fracWidth={fracWidth}, mag={mag}') |
| 112 | + z = mag * (-1.0 * fracWidth**2 + 1.0) |
| 113 | + WCTnew[c] = max(z, WCT[c]) # don't make WCT thinner than the original |
| 114 | + print(f'old z={WCT[c]}, new z={z}') |
| 115 | + |
| 116 | + return WCTnew |
| 117 | + |
| 118 | + |
| 119 | +# Define maximum and minimum water column thickness along tough centerline |
| 120 | +maxWCT = 300.0 |
| 121 | +minWCT = 50.0 |
| 122 | + |
| 123 | +# Specify start and end x/y coordinates for each trough to be bulldozed |
| 124 | +WCTnew = WCT.copy() |
| 125 | +p1=[-1261073.6, 137133.0]; p2=[-1173862.4, 199332.15] # Rutford |
| 126 | +WCTnew = smoothTrough(WCTnew, p1, p2, minWCT, maxWCT) |
| 127 | +p1=[-1315459.94, 202346.75]; p2=[-1257332.3, 291441.3] # Carlson |
| 128 | +WCTnew = smoothTrough(WCTnew, p1, p2, minWCT, maxWCT) |
| 129 | +p1=[-1513787.6, 311996.4]; p2=[-1386639.4, 337107.2] # Evans |
| 130 | +WCTnew = smoothTrough(WCTnew, p1, p2, minWCT, maxWCT) |
| 131 | +p1=[-34186, 1983479]; p2=[-9070, 2047275] # Fimbul |
| 132 | +WCTnew = smoothTrough(WCTnew, p1, p2, minWCT, maxWCT) |
| 133 | +p1=[-1064519, 206317]; p2=[-1055596, 265431] # lil guy - note different max/minWCT |
| 134 | +WCTnew = smoothTrough(WCTnew, p1, p2, 40.0, 150.0) |
| 135 | + |
| 136 | +f.variables['bedTopography'][0,:] = lowerSurface - WCTnew |
| 137 | + |
| 138 | +f.close() |
| 139 | + |
| 140 | +print("saved") |
| 141 | +s=12 |
| 142 | +ind=(floatMask==1) |
| 143 | +fig, axs = plt.subplots(1,2, figsize=(14,9), num=1, sharex=True, sharey=True) |
| 144 | +plt.sca(axs[0]) |
| 145 | +plt.scatter(xCell[ind], yCell[ind], s=s, c=WCT[ind], vmin=0, vmax=100.0, cmap='RdBu') |
| 146 | +plt.colorbar() |
| 147 | +plt.sca(axs[1]) |
| 148 | +plt.scatter(xCell[ind], yCell[ind], s=s, c=WCTnew[ind], vmin=0, vmax=100.0, cmap='RdBu') |
| 149 | +plt.plot(p1[0], p1[1], 'k*') |
| 150 | +plt.plot(p2[0], p2[1], 'ko') |
| 151 | +axs[0].set_aspect('equal', 'box') |
| 152 | +axs[1].set_aspect('equal', 'box') |
| 153 | +plt.colorbar() |
| 154 | +plt.show() |
0 commit comments