def build_cell_width_lat_lon(self): """ Create cell width array for this mesh on a regular latitude-longitude grid Returns ------- cellWidth : numpy.array m x n array of cell width in km lon : numpy.array longitude in degrees (length n and between -180 and 180) lat : numpy.array longitude in degrees (length m and between -90 and 90) """ dlon = 10. dlat = 0.1 nlon = int(360. / dlon) + 1 nlat = int(180. / dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) cellWidthVsLat = mdt.EC_CellWidthVsLat(lat) cellWidth = np.outer(cellWidthVsLat, np.ones([1, lon.size])) return cellWidth, lon, lat
def cellWidthVsLatLon(): """ Create cell width array for this mesh on a regular latitude-longitude grid. Returns ------- cellWidth : ndarray m x n array, entries are desired cell width in km lat : ndarray latitude, vector of length m, with entries between -90 and 90, degrees lon : ndarray longitude, vector of length n, with entries between -180 and 180, degrees """ dlon = 0.1 dlat = dlon nlon = int(360./dlon) + 1 nlat = int(180./dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) cellWidthVsLat = mdt.EC_CellWidthVsLat(lat) _, cellWidth = np.meshgrid(lon, cellWidthVsLat) fc = read_feature_collection('north_mid_res_region.geojson') earth_radius = constants['SHR_CONST_REARTH'] mr_signed_distance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) fc = read_feature_collection('arctic_high_res_region.geojson') hr_signed_distance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) frac = (-mr_signed_distance / (-mr_signed_distance + hr_signed_distance)) frac = np.maximum(0., np.minimum(1., frac)) dx_min = 15. dx_max = 30. arctic_widths = dx_max + (dx_min - dx_max) * frac trans_width = 1000e3 trans_start = 0. weights = 0.5 * (1 + np.tanh((mr_signed_distance - trans_start) / trans_width)) cellWidth = arctic_widths * (1 - weights) + cellWidth * weights return cellWidth, lon, lat
def setspac(): spac = jigsawpy.jigsaw_msh_t() #------------------------------------ define spacing pattern spac.mshID = "ellipsoid-grid" spac.radii = np.full(3, FULL_SPHERE_RADIUS, dtype=spac.REALS_t) spac.xgrid = np.linspace(-1. * np.pi, +1. * np.pi, 360) spac.ygrid = np.linspace(-.5 * np.pi, +.5 * np.pi, 181) vals = \ mdt.EC_CellWidthVsLat(spac.ygrid * 180. / np.pi) spac.value = np.array(np.tile(vals, (1, spac.xgrid.size)), dtype=spac.REALS_t) return spac
def cellWidthVsLatLon(): """ Create cell width array for this mesh on a regular latitude-longitude grid. Returns ------- cellWidth : ndarray m x n array, entries are desired cell width in km lat : ndarray latitude, vector of length m, with entries between -90 and 90, degrees lon : ndarray longitude, vector of length n, with entries between -180 and 180, degrees """ lat = np.arange(-90, 90.01, 0.1) lon = np.arange(-180, 180.01, 10.0) cellWidthVsLat = mdt.EC_CellWidthVsLat(lat) cellWidth = np.outer(cellWidthVsLat, np.ones([1, lon.size])) return cellWidth, lon, lat
def create_background_mesh( grd_box, ddeg, mesh_type, dx_min, dx_max, # {{{ plot_option=False, plot_box=[], call=None): """ Create a background field of cell widths Parameters ---------- grd_box : list of float A list of 4 floats defining the bounds (min lon, max lon, min lat, max lat) of the grid ddeg : float The resolution of the mesh in degrees mesh_type : {'QU', 'EC', 'RRS'} The type of mesh: quasi-uniform (QU), Eddy-closure (EC) or Rossby-radius scaling (RRS) dx_min : float The resolution in meters of a QU mesh or the minimum resolution of of an RRS mesh. This parameter is ignored for EC meshes and the default function arguments to ``EC_CellWidthVsLat()`` are used instead. dx_max : float The maximum resolution in meters of of an RRS mesh. This parameter is ignored for QU meshes and EC meshes. For EC meshes, the default function arguments are used instead. plot_option : bool, optional Whether to plot the resulting cell width and save it to files named ``bckgrnd_grid_cell_width_vs_lat###.png`` and ``bckgnd_grid_cell_width###.png``, where ``###`` is given by ``call`` and is meant to indicate how many times this function has been called during mesh creation. plot_box : list of float, optional The extent of the plot if ``plot_option=True`` call : int, optional The number of times the function has been called, used to give the plot a unique name. Returns ------- cell_width : ndarray A 2D array of cell widths in meters. lon_grd : ndarray A 1D array of longitudes in degrees in the range from -180 to 180 lat_grd : ndarray A 1D array of latitudes in degrees in the range from -90 to 90 """ print("Create background mesh") print("------------------------") # Create cell width background grid ny_grd = int((grd_box[3] - grd_box[2]) / ddeg) + 1 nx_grd = int((grd_box[1] - grd_box[0]) / ddeg) + 1 lat_grd = grd_box[2] + ddeg * np.arange(ny_grd) lon_grd = grd_box[0] + ddeg * np.arange(nx_grd) print(" Background grid dimensions:", ny_grd, nx_grd) # Assign background grid cell width values if mesh_type == 'QU': cell_width_lat = dx_max / km * np.ones(lat_grd.size) elif mesh_type == 'EC': cell_width_lat = mdt.EC_CellWidthVsLat(lat_grd) elif mesh_type == 'RRS': cell_width_lat = mdt.RRS_CellWidthVsLat(lat_grd, dx_max / km, dx_min / km) else: raise ValueError('Unknown mesh_type {}'.format(mesh_type)) cell_width = np.tile(cell_width_lat, (nx_grd, 1)).T * km # Plot background cell width if plot_option: print(" Plotting background cell width") plt.figure() plt.plot(lat_grd, cell_width_lat) plt.savefig('bckgrnd_grid_cell_width_vs_lat' + str(call) + '.png') fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree()) plt.contourf(lon_grd, lat_grd, cell_width, transform=ccrs.PlateCarree()) plot_coarse_coast(ax, plot_box) plt.colorbar() plt.savefig('bckgnd_grid_cell_width' + str(call) + '.png', bbox_inches='tight') plt.close() print(" Done") return (lon_grd, lat_grd, cell_width) # }}}
def cellWidthVsLatLon(): """ Create cell width array for this mesh on a regular latitude-longitude grid. Returns ------- cellWidth : ndarray m x n array, entries are desired cell width in km lat : ndarray latitude, vector of length m, with entries between -90 and 90, degrees lon : ndarray longitude, vector of length n, with entries between -180 and 180, degrees """ dlon = 0.1 dlat = dlon earth_radius = constants['SHR_CONST_REARTH'] nlon = int(360./dlon) + 1 nlat = int(180./dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) cellWidthSouth = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., cellWidthMidLat=45., cellWidthPole=45., latPosEq=7.5, latWidthEq=3.0) # Transition at Equator cellWidthNorth = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., cellWidthMidLat=60., cellWidthPole=60., latPosEq=7.5, latWidthEq=3.0) latTransition = 0.0 latWidthTransition = 2.5 cellWidthVsLat = mdt.mergeCellWidthVsLat( lat, cellWidthSouth, cellWidthNorth, latTransition, latWidthTransition) _, cellWidth = np.meshgrid(lon, cellWidthVsLat) # now, add the high-res region fc = read_feature_collection('high_res_region.geojson') so_signed_distance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) # Equivalent to 20 degrees latitude trans_width = 1600e3 trans_start = -500e3 dx_min = 12. weights = 0.5 * (1 + np.tanh((so_signed_distance - trans_start) / trans_width)) cellWidth = dx_min * (1 - weights) + cellWidth * weights fc = read_feature_collection('north_mid_res_region.geojson') ar_signed_distance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) fc = read_feature_collection('greenland.geojson') gr_signed_distance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) frac = (-ar_signed_distance/(-ar_signed_distance + gr_signed_distance)) frac = np.maximum(0., np.minimum(1., frac)) dx_min = 15. dx_max = 35. arctic_widths = dx_max + (dx_min - dx_max)*frac trans_width = 1000e3 trans_start = 0. weights = 0.5 * (1 + np.tanh((ar_signed_distance - trans_start) / trans_width)) cellWidth = arctic_widths * (1 - weights) + cellWidth * weights return cellWidth, lon, lat
def cellWidthVsLatLon(): """ Create cell width array for this mesh on a regular latitude-longitude grid. Returns ------- cellWidth : ndarray m x n array, entries are desired cell width in km lat : ndarray latitude, vector of length m, with entries between -90 and 90, degrees lon : ndarray longitude, vector of length n, with entries between -180 and 180, degrees """ # To speed up for testing, set following line to 1.0 degrees dlon = 0.1 dlat = dlon earth_radius = constants['SHR_CONST_REARTH'] print('\nCreating cellWidth on a lat-lon grid of: {0:.2f} x {0:.2f} ' 'degrees'.format(dlon,dlat)) print('This can be set higher for faster test generation\n') nlon = int(360. / dlon) + 1 nlat = int(180. / dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) km = 1.0e3 print('plotting ...') fig = plt.figure() plt.clf() fig.set_size_inches(10.0, 14.0) register_sci_viz_colormaps() # Create cell width vs latitude for Atlantic and Pacific basins QU1 = np.ones(lat.size) EC60to30 = mdt.EC_CellWidthVsLat(lat) EC60to30Narrow = mdt.EC_CellWidthVsLat(lat, latPosEq = 8.0, latWidthEq = 3.0) # Expand from 1D to 2D _, cellWidth = np.meshgrid(lon, EC60to30Narrow) plot_cartopy(2, 'narrow EC60to30', cellWidth, '3Wbgy5') plotFrame = 3 # global settings for regionally refines mesh highRes = 14.0 #[km] fileName = 'region_Central_America' transitionWidth = 800.0*km transitionOffset = 0.0 fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset-signedDistance) / (transitionWidth/2.))) cellWidth = 30.0 * mask + cellWidth * (1 - mask) fileName = 'coastline_CUSP' distanceToTransition = 600.0*km # transitionWidth is distance from 0.07 to 0.03 of transition within tanh transitionWidth = 600.0*km transitionOffset = distanceToTransition + transitionWidth/2.0 fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset-signedDistance) / (transitionWidth/2.))) cellWidth = highRes * mask + cellWidth * (1 - mask) plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') plot_cartopy(plotFrame+1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Gulf_of_Mexico' transitionOffset = 600.0*km transitionWidth = 600.0*km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) maskSmooth = 0.5 * (1 + np.tanh((transitionOffset-signedDistance) / (transitionWidth/2.))) maskSharp = 0.5 * (1 + np.sign(-signedDistance)) fc = read_feature_collection('land_mask_Mexico.geojson') signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) landMask = 0.5 * (1 + np.sign(-signedDistance)) mask = maskSharp * landMask + maskSmooth * (1-landMask) cellWidth = highRes * mask + cellWidth * (1 - mask) plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') plot_cartopy(plotFrame+1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Bering_Sea' transitionOffset = 0.0*km transitionWidth = 600.0*km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) maskSmooth = 0.5 * (1 + np.tanh((transitionOffset-signedDistance) / (transitionWidth/2.))) maskSharp = 0.5 * (1 + np.sign(-signedDistance)) fc = read_feature_collection('land_mask_Kamchatka.geojson') signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) landMask = 0.5 * (1 + np.sign(-signedDistance)) mask = maskSharp * landMask + maskSmooth * (1-landMask) cellWidth = highRes * mask + cellWidth * (1 - mask) plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') plot_cartopy(plotFrame+1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Arctic_Ocean' transitionOffset = 0.0*km transitionWidth = 600.0*km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset-signedDistance) / (transitionWidth/2.))) cellWidth = highRes * mask + cellWidth * (1 - mask) plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') plot_cartopy(plotFrame+1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Gulf_Stream_extension' transitionOffset = 0.0*km transitionWidth = 600.0*km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset-signedDistance) / (transitionWidth/2.))) cellWidth = highRes * mask + cellWidth * (1 - mask) plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') plot_cartopy(plotFrame+1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 # save signed distance to a file # da = xarray.DataArray(signedDistance, # dims=['y', 'x'], # coords={'y': lat, 'x': lon}, # name='signedDistance') #cw_filename = 'signedDistance.nc' # da.to_netcdf(cw_filename) ax = plt.subplot(6, 2, 1) ax.plot(lat, EC60to30, label='original EC60to30') ax.plot(lat, EC60to30Narrow, label='narrow EC60to30') ax.grid(True) plt.title('Grid cell size [km] versus latitude') plt.legend(loc="upper left") plt.savefig('mesh_construction.png') return cellWidth, lon, lat
def build_cell_width_lat_lon(self): """ Create cell width array for this mesh on a regular latitude-longitude grid Returns ------- cellWidth : numpy.array m x n array of cell width in km lon : numpy.array longitude in degrees (length n and between -180 and 180) lat : numpy.array longitude in degrees (length m and between -90 and 90) """ dlon = 0.1 dlat = dlon earth_radius = constants['SHR_CONST_REARTH'] nlon = int(360./dlon) + 1 nlat = int(180./dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) cellWidthSouth = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., cellWidthMidLat=45., cellWidthPole=45., latPosEq=7.5, latWidthEq=3.0) cellWidthNorth = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., cellWidthMidLat=60., cellWidthPole=35., latPosEq=7.5, latWidthEq=3.0) # Transition at Equator latTransition = 0.0 latWidthTransition = 2.5 cellWidthVsLat = mdt.mergeCellWidthVsLat( lat, cellWidthSouth, cellWidthNorth, latTransition, latWidthTransition) _, cellWidth = np.meshgrid(lon, cellWidthVsLat) cellWidthAtlantic = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., cellWidthMidLat=30., cellWidthPole=35., latPosEq=7.5, latWidthEq=3.0) cellWidthAtlantic = mdt.mergeCellWidthVsLat( lat, cellWidthSouth, cellWidthAtlantic, latTransition, latWidthTransition) _, cellWidthAtlantic = np.meshgrid(lon, cellWidthAtlantic) fc = read_feature_collection('atlantic.geojson') atlantic_signed_distance = signed_distance_from_geojson( fc, lon, lat, earth_radius, max_length=0.25) trans_width = 400e3 trans_start = 0. weights = 0.5 * (1 + np.tanh((atlantic_signed_distance - trans_start) / trans_width)) cellWidth = cellWidthAtlantic * (1 - weights) + cellWidth * weights fc = read_feature_collection('high_res_region.geojson') so_signed_distance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) # Equivalent to 20 degrees latitude trans_width = 1600e3 trans_start = 500e3 dx_min = 12. weights = 0.5 * (1 + np.tanh((so_signed_distance - trans_start) / trans_width)) cellWidth = dx_min * (1 - weights) + cellWidth * weights return cellWidth, lon, lat
def cellWidthVsLatLon(): """ Create cell width array for this mesh on a regular latitude-longitude grid. Returns ------- cellWidth : ndarray m x n array, entries are desired cell width in km lat : ndarray latitude, vector of length m, with entries between -90 and 90, degrees lon : ndarray longitude, vector of length n, with entries between -180 and 180, degrees """ # To speed up for testing, set following line to 1.0 degrees dlon = 1.0 dlat = dlon earth_radius = constants['SHR_CONST_REARTH'] print('\nCreating cellWidth on a lat-lon grid of: {0:.2f} x {0:.2f} ' 'degrees'.format(dlon, dlat)) print('This can be set higher for faster test generation\n') nlon = int(360. / dlon) + 1 nlat = int(180. / dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) km = 1.0e3 print('plotting ...') fig = plt.figure() plt.clf() fig.set_size_inches(10.0, 10.0) register_sci_viz_colormaps() # Create cell width vs latitude for Atlantic and Pacific basins QU1 = np.ones(lat.size) EC60to30 = mdt.EC_CellWidthVsLat(lat) RRS30to10 = mdt.RRS_CellWidthVsLat(lat, 30, 10) AtlNH = RRS30to10 AtlVsLat = mdt.mergeCellWidthVsLat(lat, EC60to30, AtlNH, 0, 6) PacNH = mdt.mergeCellWidthVsLat(lat, 30 * QU1, RRS30to10, 50, 10) PacVsLat = mdt.mergeCellWidthVsLat(lat, EC60to30, PacNH, 0, 6) # Expand from 1D to 2D _, AtlGrid = np.meshgrid(lon, AtlVsLat) _, PacGrid = np.meshgrid(lon, PacVsLat) # Signed distance of Atlantic region fc = read_feature_collection('Atlantic_region.geojson') signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) # Merge Atlantic and Pacific distrubutions smoothly transitionWidth = 500.0 * km maskSmooth = 0.5 * (1 + np.tanh(signedDistance / transitionWidth)) cellWidthSmooth = PacGrid * maskSmooth + AtlGrid * (1 - maskSmooth) # Merge Atlantic and Pacific distrubutions with step function maskSharp = 0.5 * (1 + np.sign(signedDistance)) cellWidthSharp = PacGrid * maskSharp + AtlGrid * (1 - maskSharp) # Create a land mask that is 1 over land fc = read_feature_collection('Americas_land_mask.geojson') Americas_land_mask = mask_from_geojson(fc, lon, lat) fc = read_feature_collection('Europe_Africa_land_mask.geojson') Europe_Africa_land_mask = mask_from_geojson(fc, lon, lat) landMask = np.fmax(Americas_land_mask, Europe_Africa_land_mask) # Merge: step transition over land, smooth transition over water cellWidth = cellWidthSharp * landMask + cellWidthSmooth * (1 - landMask) ax = plt.subplot(4, 2, 1) ax.plot(lat, AtlVsLat, label='Atlantic') ax.plot(lat, PacVsLat, label='Pacific') ax.grid(True) plt.title('Grid cell size [km] versus latitude') plt.legend() varNames = [ 'signedDistance', 'maskSmooth', 'cellWidthSmooth', 'maskSharp', 'cellWidthSharp', 'landMask', 'cellWidth' ] j = 2 for varName in varNames: plot_cartopy(j, varName, vars()[varName], '3Wbgy5') j += 1 fig.canvas.draw() plt.tight_layout() plt.savefig('mesh_construction.png') return cellWidth, lon, lat
def build_cell_width_lat_lon(self): """ Create cell width array for this mesh on a regular latitude-longitude grid Returns ------- cellWidth : numpy.array m x n array of cell width in km lon : numpy.array longitude in degrees (length n and between -180 and 180) lat : numpy.array longitude in degrees (length m and between -90 and 90) """ dlon = 0.1 dlat = dlon earth_radius = constants['SHR_CONST_REARTH'] print('\nCreating cellWidth on a lat-lon grid of: {0:.2f} x {0:.2f} ' 'degrees'.format(dlon, dlat)) print('This can be set higher for faster test generation\n') nlon = int(360. / dlon) + 1 nlat = int(180. / dlat) + 1 lon = np.linspace(-180., 180., nlon) lat = np.linspace(-90., 90., nlat) km = 1.0e3 print('plotting ...') plt.switch_backend('Agg') fig = plt.figure() plt.clf() fig.set_size_inches(10.0, 14.0) register_sci_viz_colormaps() # Create cell width vs latitude for Atlantic and Pacific basins EC60to30 = mdt.EC_CellWidthVsLat(lat) EC60to30Narrow = mdt.EC_CellWidthVsLat(lat, latPosEq=8.0, latWidthEq=3.0) # Expand from 1D to 2D _, cellWidth = np.meshgrid(lon, EC60to30Narrow) _plot_cartopy(2, 'narrow EC60to30', cellWidth, '3Wbgy5') plotFrame = 3 # global settings for regionally refines mesh highRes = 14.0 # [km] fileName = 'region_Central_America' transitionWidth = 800.0 * km transitionOffset = 0.0 fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) cellWidth = 30.0 * mask + cellWidth * (1 - mask) fileName = 'coastline_CUSP' distanceToTransition = 600.0 * km # transitionWidth is distance from 0.07 to 0.03 of transition within # tanh transitionWidth = 600.0 * km transitionOffset = distanceToTransition + transitionWidth / 2.0 fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) cellWidth = highRes * mask + cellWidth * (1 - mask) _plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') _plot_cartopy(plotFrame + 1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Gulf_of_Mexico' transitionOffset = 600.0 * km transitionWidth = 600.0 * km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) maskSmooth = 0.5 * (1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) maskSharp = 0.5 * (1 + np.sign(-signedDistance)) fc = read_feature_collection('land_mask_Mexico.geojson') signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) landMask = 0.5 * (1 + np.sign(-signedDistance)) mask = maskSharp * landMask + maskSmooth * (1 - landMask) cellWidth = highRes * mask + cellWidth * (1 - mask) _plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') _plot_cartopy(plotFrame + 1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Bering_Sea' transitionOffset = 0.0 * km transitionWidth = 600.0 * km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) maskSmoothEast = 0.5 * ( 1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) fc = read_feature_collection('region_Bering_Sea_reduced.geojson') signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) maskSmoothWest = 0.5 * ( 1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) fc = read_feature_collection('land_mask_Kamchatka.geojson') maskWest = mask_from_geojson(fc, lon, lat) mask = maskSmoothWest * maskWest + maskSmoothEast * (1 - maskWest) cellWidth = highRes * mask + cellWidth * (1 - mask) _plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') _plot_cartopy(plotFrame + 1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Arctic_Ocean' transitionOffset = 0.0 * km transitionWidth = 600.0 * km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) cellWidth = highRes * mask + cellWidth * (1 - mask) _plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') _plot_cartopy(plotFrame + 1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 fileName = 'region_Gulf_Stream_extension' transitionOffset = 0.0 * km transitionWidth = 600.0 * km fc = read_feature_collection('{}.geojson'.format(fileName)) signedDistance = signed_distance_from_geojson(fc, lon, lat, earth_radius, max_length=0.25) mask = 0.5 * (1 + np.tanh((transitionOffset - signedDistance) / (transitionWidth / 2.))) cellWidth = highRes * mask + cellWidth * (1 - mask) _plot_cartopy(plotFrame, fileName + ' mask', mask, 'Blues') _plot_cartopy(plotFrame + 1, 'cellWidth ', cellWidth, '3Wbgy5') plotFrame += 2 ax = plt.subplot(6, 2, 1) ax.plot(lat, EC60to30, label='original EC60to30') ax.plot(lat, EC60to30Narrow, label='narrow EC60to30') ax.grid(True) plt.title('Grid cell size [km] versus latitude') plt.legend(loc="upper left") plt.savefig('mesh_construction.png', dpi=300) return cellWidth, lon, lat
def setspac(): spac_ocn = 30. # regional ocn. km spac_1_m = 2. # sqrt(H) ocn. km spac_lnd = 45. # global land km spac_wbd = 5. # watershed km spac_pfz = 2. # PFZ km elev_pfz = 25. # PFZ elev. thresh dhdx_lim = 0.0625 # |dH/dx| thresh fade_pos = [-75.2316, 39.1269] fade_len = 700. fade_gap = 350. spac = jigsawpy.jigsaw_msh_t() opts = jigsawpy.jigsaw_jig_t() poly = jigsawpy.jigsaw_msh_t() opts.jcfg_file = os.path.join(TDIR, "opts.jig") opts.hfun_file = os.path.join(TDIR, "spac.msh") #------------------------------------ define spacing pattern print("BUILDING MESH SPAC.") print("Loading elevation assets...") data = nc.Dataset( os.path.join("data", "etopo_gebco", "etopo_gebco_tiled.nc"), "r") zlev = np.array(data.variables["z"]) spac.mshID = "ellipsoid-grid" # use elev. grid spac.radii = np.full(+3, FULL_SPHERE_RADIUS, dtype=spac.REALS_t) spac.xgrid = np.array(data.variables["x"][:], dtype=spac.REALS_t) spac.ygrid = np.array(data.variables["y"][:], dtype=spac.REALS_t) spac.xgrid *= np.pi / +180. spac.ygrid *= np.pi / +180. xgrd, ygrd = np.meshgrid(spac.xgrid, spac.ygrid) grid = np.concatenate( ( # to [x, y] list xgrd.reshape((xgrd.size, +1)), ygrd.reshape((ygrd.size, +1))), axis=+1) #------------------------------------ global ocn ec-60-to-30 print("Compute global ocean h(x)...") vals = \ mdt.EC_CellWidthVsLat(spac.ygrid * 180. / np.pi) vals = np.reshape(vals, (spac.ygrid.size, 1)) spac.value = np.array(np.tile(vals, (1, spac.xgrid.size)), dtype=spac.REALS_t) #------------------------------------ region ocn "eddy" halo filename = os.path.join("data", "na_ocean_halo", "na_ocean_halo.geojson") loadgeo(filename, poly) poly.point["coord"] *= np.pi / +180. mask, _ = inpoly2(grid, poly.point["coord"], poly.edge2["index"]) mask = np.reshape(mask, spac.value.shape) mask = np.logical_and(mask, zlev <= +0.0) spac.value[mask] = \ np.minimum(spac_ocn, spac.value[mask]) #------------------------------------ coastal ocn heuristics mask = zlev <= +0.0 hval = np.sqrt(np.maximum(-zlev, +0.0)) hval = np.maximum(spac_1_m, hval / np.sqrt(+1.0) / spac_1_m) dist = sphdist(FULL_SPHERE_RADIUS, grid[:, 0], grid[:, 1], fade_pos[0] * np.pi / 180., fade_pos[1] * np.pi / 180.) dist = np.reshape(dist, spac.value.shape) hval = blender(hval, spac.value, dist, fade_len, fade_gap) spac.value[mask] = \ np.minimum(hval[mask], spac.value[mask]) #------------------------------------ global lnd const. = 45 print("Compute global land h(x)...") halo = +9 # filter islands zmed = median_filter(zlev, size=halo, mode="wrap") spac.value[zmed >= 0.0] = spac_lnd #------------------------------------ push watershed(s) = 5. print("Compute watersheds h(x)...") shed = np.full((grid.shape[0]), False, dtype=bool) filename = os.path.join("data", "NHD_H_0204_HU4_Shape", "Shape", "WBDHU4.shp") loadshp(filename, poly) poly.point["coord"] *= np.pi / +180. mask, _ = inpoly2(grid, poly.point["coord"], poly.edge2["index"]) shed[mask] = True filename = os.path.join("data", "NHD_H_0205_HU4_Shape", "Shape", "WBDHU4.shp") loadshp(filename, poly) poly.point["coord"] *= np.pi / +180. mask, _ = inpoly2(grid, poly.point["coord"], poly.edge2["index"]) shed[mask] = True filename = os.path.join("data", "NHD_H_0206_HU4_Shape", "Shape", "WBDHU4.shp") loadshp(filename, poly) poly.point["coord"] *= np.pi / +180. mask, _ = inpoly2(grid, poly.point["coord"], poly.edge2["index"]) shed[mask] = True filename = os.path.join("data", "NHD_H_0207_HU4_Shape", "Shape", "WBDHU4.shp") loadshp(filename, poly) poly.point["coord"] *= np.pi / +180. mask, _ = inpoly2(grid, poly.point["coord"], poly.edge2["index"]) shed[mask] = True filename = os.path.join("data", "NHD_H_0208_HU4_Shape", "Shape", "WBDHU4.shp") loadshp(filename, poly) poly.point["coord"] *= np.pi / +180. mask, _ = inpoly2(grid, poly.point["coord"], poly.edge2["index"]) shed[mask] = True shed = np.reshape(shed, spac.value.shape) spac.value[shed] = \ np.minimum(spac_wbd, spac.value[shed]) #------------------------------------ partially flooded zone mask = np.logical_and(shed, zlev < elev_pfz) spac.value[mask] = \ np.minimum(spac_pfz, spac.value[mask]) #------------------------------------ push |DH/DX| threshold print("Impose |DH/DX| threshold...") spac.slope = np.full(spac.value.shape, dhdx_lim, dtype=spac.REALS_t) jigsawpy.savemsh(opts.hfun_file, spac, "precision = 9") jigsawpy.cmd.marche(opts, spac) spac.slope = \ np.empty((+0), dtype=spac.REALS_t) return spac