1 | #!/usr/bin/env python3 |
---|
2 | |
---|
3 | __doc__ = """This python script converts a grid from the OASIS-SCRIP file format to the ESMF-SCRIP file format. |
---|
4 | This format is capable of storing either 2D logically rectangular grids or 2D unstructured grids. |
---|
5 | The grid should be defined in 3 existing input files: grids.nc, masks.nc, areas.nc |
---|
6 | The grid is written in 1 output file: [gridname]_ESMF_ScripFmt.nc |
---|
7 | |
---|
8 | Input: grid name to be converted (first argument of this script) |
---|
9 | Output: netcdf grid file in ESMF-SCRIP format |
---|
10 | netcdf grid file in ESMF unstructured format if the grid is unstructured |
---|
11 | """ |
---|
12 | |
---|
13 | __author__ = "Gabriel Jonville - July 2019 - Updated february 2021" |
---|
14 | |
---|
15 | import os |
---|
16 | import sys |
---|
17 | import numpy as np |
---|
18 | import netCDF4 as nc |
---|
19 | import time |
---|
20 | import subprocess |
---|
21 | |
---|
22 | #print(str(sys.argv)) |
---|
23 | if len(sys.argv) == 3: |
---|
24 | grid = sys.argv[1] |
---|
25 | fgridoasis_path = sys.argv[2] |
---|
26 | else: |
---|
27 | print("USAGE: python ./{} gridname gridpath".format(sys.argv[0])) |
---|
28 | sys.exit() |
---|
29 | |
---|
30 | fgridoasis = 'grids.nc' |
---|
31 | |
---|
32 | ##### TESTER si grid est bien dans fgridoasis |
---|
33 | #if grid not in gridnames: |
---|
34 | # print("STOP! Gridname should be in {}\n".format(gridnames)) |
---|
35 | # sys.exit() |
---|
36 | |
---|
37 | |
---|
38 | def grid_is_unstruct(gr): |
---|
39 | return gr in ("t12e", "icos", "icoh", "bt42", "ssea", "sse7", "t127", "t359","t799") |
---|
40 | |
---|
41 | |
---|
42 | fgridesmf_s=grid+'_ESMF_ScripFmt.nc' |
---|
43 | print("--\nConvert grid {} from OASIS-SCRIP to ESMF-SCRIP format".format(grid)) |
---|
44 | print("Writting in {}\n--".format(fgridesmf_s)) |
---|
45 | |
---|
46 | |
---|
47 | ### OASIS grid |
---|
48 | # Open a netCDF file in read mode |
---|
49 | frnc = nc.Dataset(os.path.join(fgridoasis_path,fgridoasis), 'r') |
---|
50 | # Open a new netCDF file in write mode |
---|
51 | fwnc = nc.Dataset(fgridesmf_s, 'w', format='NETCDF4_CLASSIC') |
---|
52 | # Read netCDF dimension |
---|
53 | x = len(frnc.dimensions['x_'+grid]) |
---|
54 | y = len(frnc.dimensions['y_'+grid]) |
---|
55 | crn = len(frnc.dimensions['crn_'+grid]) |
---|
56 | if y==1: |
---|
57 | rank=1 |
---|
58 | else: |
---|
59 | rank=2 |
---|
60 | # Read netCDF variable |
---|
61 | lat = frnc.variables[grid+'.lat'][:,:] |
---|
62 | lon = frnc.variables[grid+'.lon'][:,:] |
---|
63 | cla = frnc.variables[grid+'.cla'][:,:,:] |
---|
64 | clo = frnc.variables[grid+'.clo'][:,:,:] |
---|
65 | # Close netCDF file |
---|
66 | frnc.close() |
---|
67 | |
---|
68 | |
---|
69 | ### ESMF grid |
---|
70 | # Create netCDF dimension |
---|
71 | grid_size = len(fwnc.createDimension('grid_size',x*y)) |
---|
72 | grid_corners = len(fwnc.createDimension('grid_corners',crn)) |
---|
73 | grid_rank = len(fwnc.createDimension('grid_rank',rank)) |
---|
74 | # Create netCDF variable / Put data / Set attribute |
---|
75 | grid_dims = fwnc.createVariable('grid_dims',np.int32,('grid_rank',)) |
---|
76 | if y==1: |
---|
77 | grid_dims[:] = (x,) |
---|
78 | else: |
---|
79 | grid_dims[:] = (x,y) |
---|
80 | |
---|
81 | grid_center_lat = fwnc.createVariable('grid_center_lat',np.float64,('grid_size',)) |
---|
82 | grid_center_lat[:] = np.reshape(lat, grid_size, order='C') # read/write the elements using C-like index order |
---|
83 | grid_center_lat.units = 'degrees' |
---|
84 | |
---|
85 | grid_center_lon = fwnc.createVariable('grid_center_lon',np.float64,('grid_size',)) |
---|
86 | grid_center_lon[:] = np.reshape(lon, grid_size, order='C') # read/write the elements using C-like index order |
---|
87 | grid_center_lon.units = 'degrees' |
---|
88 | |
---|
89 | grid_corner_lat = fwnc.createVariable('grid_corner_lat',np.float64,('grid_size','grid_corners')) |
---|
90 | grid_corner_lat[:,:] = np.reshape(cla.T,(grid_size, grid_corners), order='F') # read/write the elements using Fortran-like index order |
---|
91 | grid_corner_lat.units = 'degrees' |
---|
92 | |
---|
93 | grid_corner_lon = fwnc.createVariable('grid_corner_lon',np.float64,('grid_size','grid_corners')) |
---|
94 | grid_corner_lon[:,:] = np.reshape(clo.T,(grid_size, grid_corners), order='F') # read/write the elements using Fortran-like index order |
---|
95 | grid_corner_lon.units = 'degrees' |
---|
96 | |
---|
97 | |
---|
98 | ### OASIS mask |
---|
99 | fgridoasis = 'masks.nc' |
---|
100 | # Open a netCDF file in read mode |
---|
101 | frnc = nc.Dataset(os.path.join(fgridoasis_path,fgridoasis), 'r') |
---|
102 | # Read netCDF variable |
---|
103 | msk = frnc.variables[grid+'.msk'][:,:] |
---|
104 | # Close netCDF file |
---|
105 | frnc.close() |
---|
106 | |
---|
107 | |
---|
108 | ### ESMF mask |
---|
109 | # Create netCDF variable / Put data / Set attribute |
---|
110 | grid_imask = fwnc.createVariable('grid_imask',np.int32,('grid_size',)) |
---|
111 | grid_imask[:] = np.reshape(msk, grid_size, order='C') |
---|
112 | grid_imask[:] = np.invert(grid_imask)+2 # invert mask for ESMF format |
---|
113 | grid_imask.masked_value = "0 (land)" |
---|
114 | grid_imask.unmasked_value = "1 (sea)" |
---|
115 | |
---|
116 | |
---|
117 | ### OASIS areas |
---|
118 | #SV fgridoasis = 'areas.nc' |
---|
119 | # Open a netCDF file in read mode |
---|
120 | #SV frnc = nc.Dataset(os.path.join(fgridoasis_path,fgridoasis), 'r') |
---|
121 | # Read netCDF variable |
---|
122 | #SV srf = frnc.variables[grid+'.srf'][:,:] |
---|
123 | # Close netCDF file |
---|
124 | #SV frnc.close() |
---|
125 | |
---|
126 | |
---|
127 | ### ESMF areas |
---|
128 | # Create netCDF variable / Put data / Set attribute |
---|
129 | #SV grid_area = fwnc.createVariable('grid_area',np.float64,('grid_size',)) |
---|
130 | #SV grid_area[:] = np.reshape(srf, grid_size, order='C') |
---|
131 | #SV grid_area.units = 'm^2' |
---|
132 | |
---|
133 | |
---|
134 | # Global netCDF attributes |
---|
135 | fwnc.description = grid+' grid in ESMF-SCRIP format' |
---|
136 | fwnc.history = 'Created '+time.ctime(time.time()) |
---|
137 | fwnc.source = 'netCDF4 python '+sys.argv[0] |
---|
138 | |
---|
139 | ## all of the Dimension instances in the Dataset are stored in a dictionary |
---|
140 | #for dimname in fwnc.dimensions.keys() : |
---|
141 | # dim = fwnc.dimensions[dimname] |
---|
142 | # print(dimname, len(dim)) |
---|
143 | ## all of the variables in the Dataset are stored in a dictionnary |
---|
144 | #for varname in fwnc.variables.keys() : |
---|
145 | # var = fwnc.variables[varname] |
---|
146 | # print(varname, var.dtype, var.dimensions, var.shape) |
---|
147 | |
---|
148 | # Write and close the netCDF file |
---|
149 | fwnc.close() |
---|
150 | |
---|
151 | |
---|
152 | fgridesmf = grid+'_ESMF.nc' |
---|
153 | if os.path.exists(os.path.join('.',fgridesmf)): |
---|
154 | os.remove(os.path.join('.',fgridesmf)) |
---|
155 | |
---|
156 | if grid_is_unstruct(grid): |
---|
157 | fgridesmf_u = grid+'_ESMF_unstruct.nc' |
---|
158 | cmd = 'ESMF_Scrip2Unstruct {} {} 0'.format(fgridesmf_s,fgridesmf_u) |
---|
159 | #from python3.5#subprocess.run(cmd,shell=True) |
---|
160 | subprocess.call(cmd,shell=True) |
---|
161 | os.symlink(os.path.join('.',fgridesmf_u),os.path.join('.',fgridesmf)) |
---|
162 | print("--") |
---|
163 | else: |
---|
164 | os.symlink(os.path.join('.',fgridesmf_s),os.path.join('.',fgridesmf)) |
---|
165 | |
---|