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 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