# -*- Mode: python -*- import netCDF4 import numpy as np import nemo from scipy import ndimage import sys, os, platform, argparse, textwrap, time zero = np.dtype('float64').type(0.0) zone = np.dtype('float64').type(1.0) epsfrac = np.dtype('float64').type(1.0E-10) pi = np.pi rad = pi/np.dtype('float64').type(180.0) ra = np.dtype('float64').type(6400000.0) # Earth radius def geodist (plon1, plat1, plon2, plat2) : """Distance between two points (on sphere)""" zs = np.sin (rad*plat1) * np.sin (rad*plat2) + np.cos (rad*plat1) * np.cos (rad*plat2) * np.cos(rad*(plon2-plon1)) zs = np.maximum (-zone, np.minimum (zone, zs)) geodist = np.arccos (zs) return geodist ### ### A partir d'un fichier de poids, complete avec les rivieres et ### les poids pour le run off ### On met a zero les poids sur les points non cotiers, et on renormalise ### ### Lecture de la ligne de comande # SVN information __Author__ = "$Author: omamce $" __Date__ = "$Date: 2018-10-25 17:59:40 +0200 (Thu, 25 Oct 2018) $" __Revision__ = "$Revision: 4097 $" __Id__ = "$Id: CalvingWeights.py 4097 2018-10-25 15:59:40Z omamce $" __HeadURL__ = "$HeadURL: http://forge.ipsl.jussieu.fr/igcmg/svn/TOOLS/MOSAIX/CalvingWeights.py $" __SVN_Date__ = "$SVN_Date: $" ### ### ===== Handling command line parameters ================================================== # Creating a parser parser = argparse.ArgumentParser ( description = """Compute calving weights""", epilog='-------- This is the end of the help message --------') # Adding arguments parser.add_argument ('--oce' , help='oce model name', type=str, default='eORCA1.2', choices=['ORCA2.3', 'eORCA1.2', 'eORCA025'] ) parser.add_argument ('--atm' , help='atm model name (LMD*)', type=str, default='LMD9695' ) parser.add_argument ('--atmCoastWidth', help='width of the coastal band in atmosphere (in grid points)', default=1 ) parser.add_argument ('--oceCoastWidth', help='width of the coastal band in ocean (in grid points)', default=1 ) parser.add_argument ('--grids', help='grids file name', default='grids.nc' ) parser.add_argument ('--areas', help='masks file name', default='areas.nc' ) parser.add_argument ('--masks', help='areas file name', default='masks.nc' ) parser.add_argument ('--o2a' , help='o2a file name', default='o2a.nc' ) parser.add_argument ('--output', help='output rmp file name', default='rmp_tlmd_to_torc_runoff.nc' ) # Parse command line myargs = parser.parse_args() # grids = myargs.grids areas = myargs.areas masks = myargs.masks o2a = myargs.o2a # Model Names atm_Name = myargs.atm oce_Name = myargs.oce # Largeur de la bande cotiere cote atm atmCoastWidth = myargs.atmCoastWidth # Largeur de la bande cotiere cote oce oceCoastWidth = myargs.oceCoastWidth ### Read coordinates of all models ### diaFile = netCDF4.Dataset ( o2a ) gridFile = netCDF4.Dataset ( grids ) areaFile = netCDF4.Dataset ( areas ) maskFile = netCDF4.Dataset ( masks ) o2aFrac = diaFile ['field01_dst'][:].filled() o2aFrac = np.where ( np.abs(o2aFrac) < 1E10, o2aFrac, 0.0) atm_grid_center_lat = gridFile['tlmd.lat'][:].filled() atm_grid_center_lon = gridFile['tlmd.lon'][:].filled() atm_grid_corner_lat = gridFile['tlmd.cla'][:].filled() atm_grid_corner_lon = gridFile['tlmd.clo'][:].filled() atm_grid_area = areaFile['tlmd.srf'][:].filled() atm_grid_imask = 1-maskFile['tlmd.msk'][:].squeeze().filled() atm_grid_dims = atm_grid_area.shape (atm_nvertex, atm_jpj, atm_jpi) = atm_grid_corner_lat.shape if atm_jpi == 1 : atm_perio = 0 # Icosahedre else : atm_perio = 1 # atm_grid_pmask = nemo.lbc_mask (atm_grid_imask, 'T', atm_perio) atm_address = np.reshape ( np.arange(atm_jpj*atm_jpi), (atm_jpj, atm_jpi) ) atm_grid_size = atm_jpj*atm_jpi oce_grid_center_lat = gridFile['torc.lat'][:].filled() oce_grid_center_lon = gridFile['torc.lon'][:].filled() oce_grid_corner_lat = gridFile['torc.cla'][:].filled() oce_grid_corner_lon = gridFile['torc.clo'][:].filled() oce_grid_area = areaFile['torc.srf'][:].filled() oce_grid_imask = 1-maskFile['torc.msk'][:].filled() oce_grid_dims = oce_grid_area.shape (oce_nvertex, oce_jpj, oce_jpi) = oce_grid_corner_lat.shape ; jpon=oce_jpj*oce_jpj if oce_jpi == 182 : oce_perio = 4 # ORCA 2 if oce_jpi == 362 : oce_perio = 6 # ORCA 1 if oce_jpi == 1442 : oce_perio = 6 # ORCA 025 oce_grid_pmask = nemo.lbc_mask (oce_grid_imask, 'T', oce_perio) oce_address = np.reshape ( np.arange(oce_jpj*oce_jpi), (oce_jpj, oce_jpi) ) oce_grid_size = oce_jpj*oce_jpi print ('Calculs points terre/oce/cote sur grille atmosphere' ) # Fill closed sea with image processing library oce_grid_imask = nemo.lbc_mask ( 1-ndimage.binary_fill_holes (1-nemo.lbc(oce_grid_imask, nperio=oce_perio, cd_type='T')), nperio=oce_perio, cd_type='T' ) print ("Determination d'une bande cotiere ocean") oceLand = np.where (oce_grid_imask[:] < 0.5, True, False) oceOcean = np.where (oce_grid_imask[:] > 0.5, True, False) oceCoast = np.where (ndimage.uniform_filter(oceOcean.astype(float), size=1+2*oceCoastWidth)<1.0,True,False) & oceOcean oceCoast = nemo.lbc_mask (oceCoast, oce_perio, 'T') print ('Nombre de point oceLand : ' + str(oceLand.sum()) ) print ('Nombre de point oceOcean : ' + str(oceOcean.sum()) ) print ('Nombre de point oceCoast : ' + str(oceCoast.sum()) ) # Faire une liste de ces points oceCoast_grid_center_lon = oce_grid_center_lon[oceCoast] oceCoast_grid_center_lat = oce_grid_center_lat[oceCoast] oceCoast_grid_area = oce_grid_area [oceCoast] oceCoast_grid_imask = oce_grid_imask [oceCoast] oceCoast_grid_pmask = oce_grid_pmask [oceCoast] oceCoast_address = oce_address [oceCoast] print ("Determination d'une bande cotiere atmosphere " ) atmLand = np.where (o2aFrac[:] < epsfrac, True, False) atmFrac = np.where (o2aFrac[:] < epsfrac, True, False) & np.where (o2aFrac[:] < (zone-epsfrac), True, False) atmOcean = np.where (o2aFrac[:] < (zone-epsfrac), True, False) atmCoast = np.where (ndimage.uniform_filter(atmLand.astype(float), size=1+2*atmCoastWidth)<1.0,True,False) & atmLand atmCoast = nemo.lbc_mask (atmCoast, 1, 'T') print ('Nombre de point atmLand : ' + str(atmLand.sum()) ) print ('Nombre de point atmOcean : ' + str(atmOcean.sum()) ) print ('Nombre de point atmCoast : ' + str(atmCoast.sum()) ) # Faire une liste de ces points atmCoast_grid_center_lon = atm_grid_center_lon[atmCoast] atmCoast_grid_center_lat = atm_grid_center_lat[atmCoast] atmCoast_grid_area = atm_grid_area [atmCoast] atmCoast_grid_imask = atm_grid_imask [atmCoast] atmCoast_grid_pmask = atm_grid_pmask [atmCoast] atmCoast_address = atm_address [atmCoast] remap_matrix = np.empty ( shape=(0), dtype=np.float64 ) atm_address = np.empty ( shape=(0), dtype=np.int32 ) oce_address = np.empty ( shape=(0), dtype=np.int32 ) for ja in np.arange(len(atmCoast_grid_pmask)) : z_dist = geodist ( atmCoast_grid_center_lon[ja], atmCoast_grid_center_lat[ja], oceCoast_grid_center_lon, oceCoast_grid_center_lat) z_mask = np.where ( z_dist*ra < 600000.0, True, False) num_links = z_mask.sum() if num_links == 0 : continue z_area = oceCoast_grid_area[z_mask].sum() poids = 1.0 / z_area print ( num_links, z_mask.sum(), z_area ) # matrix_local = np.ones ((num_links),dtype=np.float64) * poids # address on source grid : all links points to the same LMDZ point. atm_address_local = np.ones(num_links, dtype=np.int32 ) * atmCoast_address[ja] # address on destination grid oce_address_local = oceCoast_address[z_mask] # Append to global tabs remap_matrix = np.append ( remap_matrix, matrix_local ) atm_address = np.append ( atm_address , atm_address_local ) oce_address = np.append ( oce_address , oce_address_local ) print ('fini') num_links = remap_matrix.shape[0] # Output file runoff = myargs.output f_runoff = netCDF4.Dataset ( runoff, 'w', format='NETCDF3_64BIT' ) print ('Output file: ' + runoff ) f_runoff.Conventions = "CF-1.6" f_runoff.source = "IPSL Earth system model" f_runoff.group = "ICMC IPSL Climate Modelling Center" f_runoff.Institution = "IPSL https.//www.ipsl.fr" f_runoff.Ocean = oce_Name + " https://www.nemo-ocean.eu" f_runoff.Atmosphere = atm_Name + " http://lmdz.lmd.jussieu.fr" f_runoff.associatedFiles = grids + " " + areas + " " + masks f_runoff.directory = os.getcwd () f_runoff.description = "Generated with ???" f_runoff.title = runoff f_runoff.Program = "Generated by " + sys.argv[0] + " with flags " + str(sys.argv[1:]) f_runoff.timeStamp = time.asctime() f_runoff.uuid = areaFile.uuid f_runoff.HOSTNAME = platform.node() #f_runoff.LOGNAME = os.getlogin() f_runoff.Python = "Python version " + platform.python_version() f_runoff.OS = platform.system() f_runoff.release = platform.release() f_runoff.hardware = platform.machine() f_runoff.Comment = "Preliminary attempt - Do not trust !" f_runoff.conventions = "SCRIP" f_runoff.source_grid = "curvilinear" f_runoff.dest_grid = "curvilinear" f_runoff.Model = "IPSL CM6" f_runoff.SVN_Author = "$Author: $" f_runoff.SVN_Date = "$Date: $" f_runoff.SVN_Revision = "$Revision: $" f_runoff.SVN_Id = "$Id: $" f_runoff.SVN_HeadURL = "$HeadURL: $" num_links = f_runoff.createDimension ('num_links' , num_links ) num_wgts = f_runoff.createDimension ('num_wgts' , 1 ) atm_grid_size = f_runoff.createDimension ('src_grid_size' , atm_grid_size ) atm_grid_corners = f_runoff.createDimension ('src_grid_corners', atm_grid_corner_lon.shape[0] ) atm_grid_rank = f_runoff.createDimension ('src_grid_rank' , 2 ) oce_grid_size = f_runoff.createDimension ('dst_grid_size' , oce_grid_size ) oce_grid_corners = f_runoff.createDimension ('dst_grid_corners', oce_grid_corner_lon.shape[0] ) oce_grid_rank = f_runoff.createDimension ('dst_grid_rank' , 2 ) v_remap_matrix = f_runoff.createVariable ( 'remap_matrix', 'f8', ('num_links', 'num_wgts') ) v_atm_address = f_runoff.createVariable ( 'src_address' , 'i4', ('num_links',) ) v_oce_address = f_runoff.createVariable ( 'dst_address' , 'i4', ('num_links',) ) v_remap_matrix[:] = remap_matrix v_atm_address [:] = atm_address v_oce_address [:] = oce_address v_atm_grid_dims = f_runoff.createVariable ( 'src_grid_dims' , 'i4', ('src_grid_rank',) ) v_atm_grid_center_lon = f_runoff.createVariable ( 'src_grid_center_lon', 'i4', ('src_grid_size',) ) v_atm_grid_center_lat = f_runoff.createVariable ( 'src_grid_center_lat', 'i4', ('src_grid_size',) ) v_atm_grid_center_lon.units='degrees_east' ; v_atm_grid_center_lon.long_name='Longitude' ; v_atm_grid_center_lon.long_name='longitude' ; v_atm_grid_center_lon.bounds="src_grid_corner_lon" v_atm_grid_center_lat.units='degrees_north' ; v_atm_grid_center_lat.long_name='Latitude' ; v_atm_grid_center_lat.long_name='latitude ' ; v_atm_grid_center_lat.bounds="src_grid_corner_lat" v_atm_grid_corner_lon = f_runoff.createVariable ( 'src_grid_corner_lon', 'f8', ('src_grid_size', 'src_grid_corners') ) v_atm_grid_corner_lat = f_runoff.createVariable ( 'src_grid_corner_lat', 'f8', ('src_grid_size', 'src_grid_corners') ) v_atm_grid_corner_lon.units="degrees_east" v_atm_grid_corner_lat.units="degrees_north" v_atm_grid_area = f_runoff.createVariable ( 'src_grid_area' , 'f8', ('src_grid_size',) ) v_atm_grid_area.long_name="Grid area" ; v_atm_grid_area.standard_name="cell_area" ; v_atm_grid_area.units="m2" v_atm_grid_imask = f_runoff.createVariable ( 'src_grid_imask' , 'f8', ('src_grid_size',) ) v_atm_grid_imask.long_name="Land-sea mask" ; v_atm_grid_imask.units="Land:1, Ocean:0" v_atm_grid_dims [:] = atm_grid_dims v_atm_grid_center_lon[:] = atm_grid_center_lon[:].ravel() v_atm_grid_center_lat[:] = atm_grid_center_lat[:].ravel() v_atm_grid_corner_lon[:] = atm_grid_corner_lon.reshape( (atm_jpi*atm_jpj, atm_grid_corners.__len__()) ) v_atm_grid_corner_lat[:] = atm_grid_corner_lat.reshape( (atm_jpi*atm_jpj, atm_grid_corners.__len__()) ) v_atm_grid_area [:] = atm_grid_area[:].ravel() v_atm_grid_imask [:] = atm_grid_imask[:].ravel() # -- v_oce_grid_dims = f_runoff.createVariable ( 'dst_grid_dims' , 'i4', ('dst_grid_rank',) ) v_oce_grid_center_lon = f_runoff.createVariable ( 'dst_grid_center_lon', 'i4', ('dst_grid_size',) ) v_oce_grid_center_lat = f_runoff.createVariable ( 'dst_grid_center_lat', 'i4', ('dst_grid_size',) ) v_oce_grid_center_lon.units='degrees_east' ; v_oce_grid_center_lon.long_name='Longitude' ; v_oce_grid_center_lon.long_name='longitude' ; v_oce_grid_center_lon.bounds="dst_grid_corner_lon" v_oce_grid_center_lat.units='degrees_north' ; v_oce_grid_center_lat.long_name='Latitude' ; v_oce_grid_center_lat.long_name='latitude' ; v_oce_grid_center_lat.bounds="dst_grid_corner_lat" v_oce_grid_corner_lon = f_runoff.createVariable ( 'oce_grid_corner_lon', 'f8', ('dst_grid_size', 'dst_grid_corners') ) v_oce_grid_corner_lat = f_runoff.createVariable ( 'dst_grid_corner_lat', 'f8', ('dst_grid_size', 'dst_grid_corners') ) v_oce_grid_corner_lon.units="degrees_east" v_oce_grid_corner_lat.units="degrees_north" v_oce_grid_area = f_runoff.createVariable ( 'dst_grid_area' , 'f8', ('dst_grid_size',) ) v_oce_grid_area.long_name="Grid area" ; v_oce_grid_area.standard_name="cell_area" ; v_oce_grid_area.units="m2" v_oce_grid_imask = f_runoff.createVariable ( 'dst_grid_imask' , 'f8', ('dst_grid_size',) ) v_oce_grid_imask.long_name="Land-sea mask" ; v_oce_grid_imask.units="Land:1, Ocean:0" v_oce_grid_dims [:] = oce_grid_dims v_oce_grid_center_lon[:] = oce_grid_center_lon[:].ravel() v_oce_grid_center_lat[:] = oce_grid_center_lat[:].ravel() v_oce_grid_corner_lon[:] = oce_grid_corner_lon.reshape( (oce_jpi*oce_jpj, oce_grid_corners.__len__()) ) v_oce_grid_corner_lat[:] = oce_grid_corner_lon.reshape( (oce_jpi*oce_jpj, oce_grid_corners.__len__()) ) v_oce_grid_area [:] = oce_grid_area[:].ravel() v_oce_grid_imask [:] = oce_grid_imask[:].ravel() # For diags v_atm_lon_addressed = f_runoff.createVariable ( 'src_lon_addressed', 'f8', ('num_links',) ) v_atm_lat_addressed = f_runoff.createVariable ( 'src_lat_addressed', 'f8', ('num_links',) ) v_oce_lon_addressed = f_runoff.createVariable ( 'dst_lon_addressed', 'f8', ('num_links',) ) v_oce_lat_addressed = f_runoff.createVariable ( 'dst_lat_addressed', 'f8', ('num_links',) ) v_atm_lon_addressed.long_name="Longitude" ; v_atm_lon_addressed.standard_name="longitude" ; v_atm_lon_addressed.units="degrees_east" v_atm_lat_addressed.long_name="Latitude" ; v_atm_lat_addressed.standard_name="latitude" ; v_atm_lat_addressed.units="degrees_east" v_atm_lon_addressed [:] = atm_grid_center_lon.ravel()[atm_address].ravel() v_atm_lat_addressed [:] = atm_grid_center_lat.ravel()[atm_address].ravel() v_oce_lon_addressed.long_name="Longitude" ; v_oce_lon_addressed.standard_name="longitude" ; v_oce_lon_addressed.units="degrees_east" v_oce_lat_addressed.long_name="Latitude" ; v_oce_lat_addressed.standard_name="latitude" ; v_oce_lat_addressed.units="degrees_east" v_oce_lon_addressed [:] = oce_grid_center_lon.ravel()[oce_address].ravel() v_oce_lat_addressed [:] = oce_grid_center_lat.ravel()[oce_address].ravel() f_runoff.close ()