source: TOOLS/MOSAIX/RunoffWeights.py @ 6446

Last change on this file since 6446 was 6314, checked in by omamce, 16 months ago

O.M. : MOSAIX - RunOffWeight?.

Correct a small typo in auxiliary variable name.

  • Property svn:keywords set to Date Revision HeadURL Author Id
File size: 24.3 KB
Line 
1# -*- Mode: python -*-
2#!/usr/bin/env python3
3### ===========================================================================
4###
5### Compute runoff weights.
6### For LMDZ only. Not suitable for DYNAMICO
7###
8### ===========================================================================
9##
10##  MOSAIX is under CeCILL_V2 licence. See "Licence_CeCILL_V2-en.txt"
11##  file for an english version of the licence and
12##  "Licence_CeCILL_V2-fr.txt" for a french version.
13##
14##  Permission is hereby granted, free of charge, to any person or
15##  organization obtaining a copy of the software and accompanying
16##  documentation covered by this license (the "Software") to use,
17##  reproduce, display, distribute, execute, and transmit the
18##  Software, and to prepare derivative works of the Software, and to
19##  permit third-parties to whom the Software is furnished to do so,
20##  all subject to the following:
21##
22##  Warning, to install, configure, run, use any of MOSAIX software or
23##  to read the associated documentation you'll need at least one (1)
24##  brain in a reasonably working order. Lack of this implement will
25##  void any warranties (either express or implied).  Authors assumes
26##  no responsability for errors, omissions, data loss, or any other
27##  consequences caused directly or indirectly by the usage of his
28##  software by incorrectly or partially configured
29##
30##
31# SVN information
32__Author__   = "$Author$"
33__Date__     = "$Date$"
34__Revision__ = "$Revision$"
35__Id__       = "$Id$"
36__HeadURL__  = "$HeadURL$"
37__SVN_Date__ = "$SVN_Date: $"
38##
39
40## Modules
41import numpy as np, xarray as xr
42import nemo
43from scipy import ndimage
44import sys, os, platform, argparse, textwrap, time
45
46## Useful constants
47zero    = np.dtype('float64').type(0.0)
48zone    = np.dtype('float64').type(1.0)
49epsfrac = np.dtype('float64').type(1.0E-10)
50pi      = np.pi
51rad     = pi/np.dtype('float64').type(180.0)  # Conversion from degrees to radian
52ra      = np.dtype('float64').type(6371229.0) # Earth radius
53
54## Functions
55def geodist (plon1, plat1, plon2, plat2) :
56      """Distance between two points (on sphere)"""
57      zs = np.sin (rad*plat1) * np.sin (rad*plat2) +  np.cos (rad*plat1) * np.cos (rad*plat2) * np.cos(rad*(plon2-plon1))
58      zs = np.maximum (-zone, np.minimum (zone, zs))
59      geodist =  np.arccos (zs)
60      return geodist
61
62### ===== Reading command line parameters ==================================================
63# Creating a parser
64parser = argparse.ArgumentParser (
65    description = """Compute calving weights""",
66    epilog='-------- End of the help message --------')
67
68# Adding arguments
69parser.add_argument ('--oce'          , help='oce model name', type=str, default='eORCA1.2',
70                         choices=['ORCA2.3',  'ORCA1.0', 'ORCA1.1', 'ORCA1_CNRM', 'eORCA1.2', 'eORCA1.4', 'eORCA1.4.2', 'eORCA025', 'eORCA025.1', 'eORCA025.4'] )
71parser.add_argument ('--atm'          , help='atm model name', type=str, default='LMD9695'    )
72parser.add_argument ('--atmCoastWidth', help='width of the coastal band in atmosphere (in grid points)', type=int, default=1 )
73parser.add_argument ('--oceCoastWidth', help='width of the coastal band in ocean (in grid points)'     , type=int, default=2 )
74parser.add_argument ('--atmQuantity'  , help='Quantity if atm provides quantities (m/s), Surfacic if atm provided flux (m/s/m2)' , type=str,
75                         default='Quantity', choices=['Quantity', 'Surfacic'] )
76parser.add_argument ('--oceQuantity'  , help='Quantity if oce requires quantities (ks/s), Surfacic if oce requires flux (m/s/m2)', type=str,
77                         default='Surfacic', choices=['Quantity', 'Surfacic'] )
78parser.add_argument ('--searchRadius' , help='max distance to connect a land point to an ocean point (in km)', type=float, default=600.0 )
79parser.add_argument ('--grids' , help='grids file name', default='grids.nc' )
80parser.add_argument ('--areas' , help='masks file name', default='areas.nc' )
81parser.add_argument ('--masks' , help='areas file name', default='masks.nc' )
82parser.add_argument ('--o2a'   , help='o2a file name'  , default='o2a.nc'   )
83parser.add_argument ('--output', help='output rmp file name', default='rmp_tlmd_to_torc_runoff.nc' )
84parser.add_argument ('--fmt'   , help='NetCDF file format, using nco syntax', default='netcdf4',
85                         choices=['classic', 'netcdf3', '64bit', '64bit_data', '64bit_data', 'netcdf4', 'netcdf4_classsic'] )
86parser.add_argument ('--ocePerio'   , help='periodicity of ocean grid', type=float, default=0, choices=nemo.nperio_valid_range)
87
88# Parse command line
89myargs = parser.parse_args()
90
91#
92grids = myargs.grids
93areas = myargs.areas
94masks = myargs.masks
95o2a   = myargs.o2a
96
97# Model Names
98atm_Name = myargs.atm
99oce_Name = myargs.oce
100# Width of the coastal band (land points) in the atmopshere
101atmCoastWidth = myargs.atmCoastWidth
102# Width of the coastal band (ocean points) in the ocean
103oceCoastWidth = myargs.oceCoastWidth
104searchRadius  = myargs.searchRadius * 1000.0 # From km to meters
105# Netcdf format
106if myargs.fmt == 'classic'         : FmtNetcdf = 'CLASSIC'
107if myargs.fmt == 'netcdf3'         : FmtNetcdf = 'CLASSIC'
108if myargs.fmt == '64bit'           : FmtNetcdf = 'NETCDF3_64BIT_OFFSET'
109if myargs.fmt == '64bit_data'      : FmtNetcdf = 'NETCDF3_64BIT_DATA'
110if myargs.fmt == '64bit_offset'    : FmtNetcdf = 'NETCDF3_64BIT_OFFSET'
111if myargs.fmt == 'netcdf4'         : FmtNetcdf = 'NETCDF4'
112if myargs.fmt == 'netcdf4_classic' : FmtNetcdf = 'NETCDF4_CLASSIC'
113
114#
115if atm_Name.find('LMD') >= 0 : atm_n = 'lmd' ; atmDomainType = 'rectilinear'
116if atm_Name.find('ICO') >= 0 : atm_n = 'ico' ; atmDomainType = 'unstructured'
117
118print ('atmQuantity : ' + str (myargs.atmQuantity) )
119print ('oceQuantity : ' + str (myargs.oceQuantity) )
120
121# Ocean grid periodicity
122oce_perio = myargs.ocePerio
123
124### Read coordinates of all models
125###
126
127diaFile    = xr.open_dataset ( o2a   )
128gridFile   = xr.open_dataset ( grids )
129areaFile   = xr.open_dataset ( areas )
130maskFile   = xr.open_dataset ( masks )
131
132o2aFrac             = diaFile ['OceFrac'].squeeze()
133o2aFrac = np.where ( np.abs(o2aFrac) < 1E10, o2aFrac, 0.0)
134
135(atm_nvertex, atm_jpj, atm_jpi) = gridFile['t'+atm_n+'.clo'][:].shape
136atm_grid_size = atm_jpj*atm_jpi
137atm_grid_rank = len(gridFile['t'+atm_n+'.lat'][:].shape)
138
139atm_grid_center_lat = gridFile['t'+atm_n+'.lat'].squeeze()
140atm_grid_center_lon = gridFile['t'+atm_n+'.lon'].squeeze()
141atm_grid_corner_lat = gridFile['t'+atm_n+'.cla'].squeeze()
142atm_grid_corner_lon = gridFile['t'+atm_n+'.clo'].squeeze()
143atm_grid_area       = areaFile['t'+atm_n+'.srf'].squeeze()
144atm_grid_imask      = 1-maskFile['t'+atm_n+'.msk'][:].squeeze()
145atm_grid_dims       = gridFile['t'+atm_n+'.lat'][:].shape
146
147if atmDomainType == 'unstructured' :
148    atm_grid_center_lat = atm_grid_center_lat.rename ({'ycell':'cell'})
149    atm_grid_center_lon = atm_grid_center_lon.rename ({'ycell':'cell'})
150    atm_grid_corner_lat = atm_grid_corner_lat.rename ({'ycell':'cell'})
151    atm_grid_corner_lon = atm_grid_corner_lon.rename ({'ycell':'cell'})
152    atm_grid_area       = atm_grid_area.rename  ({'ycell':'cell'})
153    atm_grid_imask      = atm_grid_imask.rename ({'ycell':'cell'})
154   
155if atmDomainType == 'rectilinear' :
156    atm_grid_center_lat = atm_grid_center_lat.stack (cell=['y', 'x'])
157    atm_grid_center_lon = atm_grid_center_lon.stack (cell=['y', 'x'])
158    atm_grid_corner_lat = atm_grid_corner_lat.stack (cell=['y', 'x']).rename({'nvertex_lmd':'nvertex'})
159    atm_grid_corner_lon = atm_grid_corner_lon.stack (cell=['y', 'x']).rename({'nvertex_lmd':'nvertex'})
160    atm_grid_area       = atm_grid_area.stack       (cell=['y', 'x'])
161    atm_grid_imask      = atm_grid_imask.stack      (cell=['y', 'x'])
162
163atm_perio = 0
164atm_grid_pmask = atm_grid_imask
165
166
167atm_address = np.arange(atm_jpj*atm_jpi)
168
169(oce_nvertex, oce_jpj, oce_jpi) = gridFile['torc.cla'][:].shape ; jpon=oce_jpj*oce_jpj
170oce_grid_size = oce_jpj*oce_jpi
171oce_grid_rank = len(gridFile['torc.lat'][:].shape)
172
173oce_grid_center_lat = gridFile['torc.lat'].stack(oce_grid_size=['y_grid_T', 'x_grid_T'])
174oce_grid_center_lon = gridFile['torc.lon'].stack(oce_grid_size=['y_grid_T', 'x_grid_T'])
175oce_grid_corner_lat = gridFile['torc.cla'].squeeze().stack(oce_grid_size=['y_grid_T', 'x_grid_T'])
176oce_grid_corner_lon = gridFile['torc.clo'].squeeze().stack(oce_grid_size=['y_grid_T', 'x_grid_T'])
177oce_grid_area       = areaFile['torc.srf'].stack(oce_grid_size=['y_grid_T', 'x_grid_T'])
178oce_grid_imask      = 1-maskFile['torc.msk'].stack(oce_grid_size=['y_grid_T', 'x_grid_T'])
179oce_grid_dims       = gridFile['torc.lat'][:].shape
180
181# imask : includes periodicity point
182# pmask : exclude periodicity points
183
184#if oce_perio == 0 :
185#    if oce_jpi ==  182 : oce_perio = 4 # ORCA 2
186#    if oce_jpi ==  362 : oce_perio = 6 # ORCA 1
187#    if oce_jpi == 1442 : oce_perio = 6 # ORCA 025
188oce_preio = nemo.__guessNperio__ (oce_jpj, oce_jpi, nperio=oce_perio)
189
190print ("Oce NPERIO parameter : {:}".format(oce_perio))
191oce_grid_imask = nemo.lbc      (np.reshape(oce_grid_imask.values, (oce_jpj,oce_jpi)), nperio=oce_perio, cd_type='T'        ).ravel()
192oce_grid_pmask = nemo.lbc_mask (np.reshape(oce_grid_imask       , (oce_jpj,oce_jpi)), nperio=oce_perio, cd_type='T', sval=0).ravel()
193oce_address = np.arange(oce_jpj*oce_jpi)
194
195print ("Fill closed seas with image processing library")
196oce_grid_imask2D = np.reshape (oce_grid_imask, (oce_jpj,oce_jpi))
197oce_grid_imask2D = 1-nemo.fill_closed_seas (1-oce_grid_imask2D, nperio=oce_perio, cd_type='T')
198#oce_grid_imask2D = nemo.lbc ( 1-ndimage.binary_fill_holes (1-nemo.lbc(oce_grid_imask2D, nperio=oce_perio, cd_type='T')),
199#                                       nperio=oce_perio, cd_type='T' )
200oce_grid_imask = oce_grid_imask2D.ravel ()
201
202##
203print ("Computes an ocean coastal band with image processing library")
204oceLand2D  = np.reshape ( np.where (oce_grid_imask < 0.5, True, False), (oce_jpj, oce_jpi) )
205oceOcean2D = np.reshape ( np.where (oce_grid_imask > 0.5, True, False), (oce_jpj, oce_jpi) )
206
207NNocean = 1+2*oceCoastWidth
208oceOceanFiltered2D = ndimage.uniform_filter (oceOcean2D.astype(float), size=NNocean)
209oceCoast2D = np.where (oceOceanFiltered2D<(1.0-0.5/(NNocean**2)),True,False) & oceOcean2D
210oceCoast2D = nemo.lbc_mask (np.reshape(oceCoast2D, (oce_jpj,oce_jpi)), nperio=oce_perio, cd_type='T', sval=0.).ravel()
211
212oceOceanFiltered = oceOceanFiltered2D.ravel()
213oceLand  = oceLand2D.ravel ()
214oceOcean = oceOcean2D.ravel()
215oceCoast = oceCoast2D.ravel()
216
217print ('Number of points in oceLand  : {:8d}'.format (oceLand.sum())  )
218print ('Number of points in oceOcean : {:8d}'.format (oceOcean.sum()) )
219print ('Number of points in oceCoast : {:8d}'.format (oceCoast.sum()) )
220
221# Arrays with coastal points only
222oceCoast_grid_center_lon = oce_grid_center_lon[oceCoast]
223oceCoast_grid_center_lat = oce_grid_center_lat[oceCoast]
224oceCoast_grid_area       = oce_grid_area      [oceCoast]
225oceCoast_grid_imask      = oce_grid_imask     [oceCoast]
226oceCoast_grid_pmask      = oce_grid_pmask     [oceCoast]
227oceCoast_address         = oce_address        [oceCoast]
228
229print ("Computes an atmosphere coastal band" )
230atmLand      = np.where (o2aFrac[:] < epsfrac       , True, False)
231atmLandFrac  = np.where (o2aFrac[:] < zone-epsfrac  , True, False)
232atmFrac      = np.where (o2aFrac[:] > epsfrac       , True, False) & np.where (o2aFrac[:] < (zone-epsfrac), True, False)
233atmOcean     = np.where (o2aFrac[:] < (zone-epsfrac), True, False)
234atmOceanFrac = np.where (o2aFrac[:] > epsfrac       , True, False)
235
236## For LMDZ only !!
237if atmDomainType == 'rectilinear' :
238    print ("Extend coastal band " )
239    NNatm = 1+2*atmCoastWidth
240    atmLand2D = np.reshape ( atmLand, ( atm_jpj, atm_jpi) )
241
242    atmLandFiltered2D = ndimage.uniform_filter(atmLand2D.astype(float), size=NNatm)
243    atmCoast2D = np.where (atmLandFiltered2D<(1.0-0.5/(NNatm**2)),True,False) & atmLandFrac
244   
245    atmLandFiltered = atmLandFiltered2D.ravel()
246    atmCoast = atmCoast2D.ravel()
247
248    print ('Number of points in atmLand  : {:8d}'.format (atmLand.sum())  )
249    print ('Number of points in atmOcean : {:8d}'.format (atmOcean.sum()) )
250    print ('Number of points in atmCoast : {:8d}'.format (atmCoast.sum()) )
251
252else :
253    atmCoast = atmFrac
254   
255   
256# Arrays with coastal points only
257atmCoast_grid_center_lon = atm_grid_center_lon[atmCoast]
258atmCoast_grid_center_lat = atm_grid_center_lat[atmCoast]
259atmCoast_grid_area       = atm_grid_area      [atmCoast]
260atmCoast_grid_imask      = atm_grid_imask     [atmCoast]
261atmCoast_grid_pmask      = atm_grid_pmask     [atmCoast]
262atmCoast_address         = atm_address        [atmCoast]
263
264# Initialisations before the loop
265remap_matrix = np.empty ( shape=(0), dtype=np.float64 )
266atm_address  = np.empty ( shape=(0), dtype=np.int32   )
267oce_address  = np.empty ( shape=(0), dtype=np.int32   )
268
269## Loop on atmosphere coastal points
270if searchRadius > 0. :
271    print ("Loop on atmosphere coastal points")
272    for ja in np.arange (len(atmCoast_grid_pmask)) :
273        z_dist = geodist ( atmCoast_grid_center_lon[ja], atmCoast_grid_center_lat[ja], oceCoast_grid_center_lon, oceCoast_grid_center_lat)
274        z_mask = np.where (z_dist*ra < searchRadius, True, False)
275        num_links = int (z_mask.sum())
276        if num_links == 0 : continue
277        z_area = oceCoast_grid_area[z_mask].sum().values
278        poids = np.ones ((num_links),dtype=np.float64) / z_area
279        if myargs.atmQuantity == 'Surfacic' : poids = poids * atm_grid_area[ja]
280        if myargs.oceQuantity == 'Quantity' : poids = poids * oceCoast_grid_area[z_mask]
281        if  ja % (len(atmCoast_grid_pmask)//50) == 0 : # Control print
282            print ( 'ja:{:8d}, num_links:{:8d},  z_area:{:8.4e},  atm area:{:8.4e},  weights sum:{:8.4e}  '
283                        .format(ja, num_links, z_area, atm_grid_area[ja].values, poids.sum() ) )
284        #
285        matrix_local = poids
286        atm_address_local = np.ones (num_links, dtype=np.int32 ) * atmCoast_address[ja]
287        # Address on destination grid
288        oce_address_local = oceCoast_address [z_mask]
289        # Append to global arrays
290        remap_matrix = np.append ( remap_matrix, matrix_local      )
291        atm_address  = np.append ( atm_address , atm_address_local )
292        oce_address  = np.append ( oce_address , oce_address_local )
293
294    print ('End of loop')
295
296num_links = remap_matrix.shape[0]
297
298print ("Write output file")
299runoff = myargs.output
300print ('Output file: ' + runoff )
301
302
303remap_matrix = xr.DataArray ( np.reshape(remap_matrix, (num_links, 1)), dims = ['num_links', 'num_wgts'] )
304
305# OASIS uses Fortran style indexing, starting at one
306src_address  = xr.DataArray ( atm_address.astype(np.int32)+1, dims = ['num_links'],
307                                 attrs={"convention": "Fortran style addressing, starting at 1"}) 
308dst_address  = xr.DataArray ( oce_address.astype(np.int32)+1, dims = ['num_links'],
309                                 attrs={"convention": "Fortran style addressing, starting at 1"})
310
311src_grid_dims       = xr.DataArray (np.array(atm_grid_dims, dtype=np.int32), dims = ['src_grid_rank',] )
312src_grid_center_lon = xr.DataArray (atm_grid_center_lon.values , dims = ['src_grid_size',] )
313src_grid_center_lat = xr.DataArray (atm_grid_center_lat.values , dims = ['src_grid_size',] )
314
315src_grid_center_lon.attrs['units']='degrees_east'  ; src_grid_center_lon.attrs['long_name']='Longitude'
316src_grid_center_lon.attrs['long_name']='longitude' ; src_grid_center_lon.attrs['bounds']="src_grid_corner_lon"
317src_grid_center_lat.attrs['units']='degrees_north' ; src_grid_center_lat.attrs['long_name']='Latitude'
318src_grid_center_lat.attrs['long_name']='latitude ' ; src_grid_center_lat.attrs['bounds']="src_grid_corner_lat"
319 
320src_grid_corner_lon = xr.DataArray (atm_grid_corner_lon.values.transpose(), dims = [ 'src_grid_size', 'src_grid_corners'] )
321src_grid_corner_lat = xr.DataArray (atm_grid_corner_lat.values.transpose(), dims = [ 'src_grid_size', 'src_grid_corners'] )
322src_grid_corner_lon.attrs['units']="degrees_east"
323src_grid_corner_lat.attrs['units']="degrees_north"
324
325src_grid_area       =  xr.DataArray (atm_grid_area.values, dims = ['src_grid_size',] ) 
326src_grid_area.attrs['long_name']="Grid area" ; src_grid_area.attrs['standard_name']="cell_area" ; src_grid_area.attrs['units']="m2"
327
328src_grid_imask      =  xr.DataArray (atm_grid_imask.values, dims = ['src_grid_size',] ) 
329src_grid_imask.attrs['long_name']="Land-sea mask" ; src_grid_imask.attrs['units']="Land:1, Ocean:0"
330
331src_grid_pmask      =  xr.DataArray (atm_grid_pmask.values, dims = ['src_grid_size',] ) 
332src_grid_pmask.attrs['long_name']="Land-sea mask (periodicity removed)" ; src_grid_pmask.attrs['units']="Land:1, Ocean:0"
333
334# --
335dst_grid_dims       = xr.DataArray (np.array(oce_grid_dims, dtype=np.int32), dims = ['dst_grid_rank',] )
336dst_grid_center_lon = xr.DataArray (oce_grid_center_lon.values, dims = ['dst_grid_size',] )
337dst_grid_center_lat = xr.DataArray (oce_grid_center_lat.values, dims = ['dst_grid_size',] )
338
339dst_grid_center_lon.attrs['units']='degrees_east'  ; dst_grid_center_lon.attrs['long_name']='Longitude'
340dst_grid_center_lon.attrs['long_name']='longitude' ; dst_grid_center_lon.attrs['bounds']="dst_grid_corner_lon"
341dst_grid_center_lat.attrs['units']='degrees_north' ; dst_grid_center_lat.attrs['long_name']='Latitude'
342dst_grid_center_lat.attrs['long_name']='latitude ' ; dst_grid_center_lat.attrs['bounds']="dst_grid_corner_lat"
343
344dst_grid_corner_lon = xr.DataArray (np.transpose(oce_grid_corner_lon.values), dims = [ 'dst_grid_size', 'dst_grid_corners'] )
345dst_grid_corner_lat = xr.DataArray (np.transpose(oce_grid_corner_lat.values), dims = [ 'dst_grid_size', 'dst_grid_corners'] )
346dst_grid_corner_lon.attrs['units']="degrees_east"
347dst_grid_corner_lat.attrs['units']="degrees_north"
348
349dst_grid_area       =  xr.DataArray (oce_grid_area.values, dims = ['dst_grid_size',] ) 
350dst_grid_area.attrs['long_name']="Grid area" ; dst_grid_area.attrs['standard_name']="cell_area" ; dst_grid_area.attrs['units']="m2"
351
352dst_grid_imask      =  xr.DataArray (oce_grid_imask.astype(np.int32), dims = ['dst_grid_size',] ) 
353dst_grid_imask.attrs['long_name']="Land-sea mask" ; dst_grid_imask.attrs['units']="Land:1, Ocean:0"
354
355dst_grid_pmask      =  xr.DataArray (oce_grid_pmask, dims = ['dst_grid_size',] ) 
356dst_grid_pmask.attrs['long_name']="Land-sea mask (periodicity removed)" ; dst_grid_pmask.attrs['units']="Land:1, Ocean:0"
357
358src_lon_addressed   =  xr.DataArray (atm_grid_center_lon.values[atm_address]                  , dims = ['num_links'] )
359src_lat_addressed   =  xr.DataArray (atm_grid_center_lat.values[atm_address]                  , dims = ['num_links'] )
360src_area_addressed  =  xr.DataArray (atm_grid_area      .values[atm_address]                  , dims = ['num_links'] )
361src_imask_addressed =  xr.DataArray (1-atm_grid_imask   .values[atm_address].astype(np.int32) , dims = ['num_links'] )
362src_pmask_addressed =  xr.DataArray (1-atm_grid_pmask   .values[atm_address].astype(np.int32) , dims = ['num_links'] )
363
364dst_lon_addressed   =  xr.DataArray (oce_grid_center_lon.values[atm_address], dims = ['num_links'] )
365dst_lat_addressed   =  xr.DataArray (oce_grid_center_lat.values[oce_address], dims = ['num_links'] )
366dst_area_addressed  =  xr.DataArray (oce_grid_area.values[oce_address].astype(np.int32)      , dims = ['num_links'] )
367dst_imask_addressed =  xr.DataArray (1-oce_grid_imask[oce_address].astype(np.int32)   , dims = ['num_links'] )
368dst_pmask_addressed =  xr.DataArray (1-oce_grid_pmask[oce_address].astype(np.int32)   , dims = ['num_links'] )
369
370src_lon_addressed.attrs['long_name']="Longitude" ; src_lon_addressed.attrs['standard_name']="longitude" ; src_lon_addressed.attrs['units']="degrees_east"
371src_lat_addressed.attrs['long_name']="Latitude"  ; src_lat_addressed.attrs['standard_name']="latitude"  ; src_lat_addressed.attrs['units']="degrees_north"
372
373dst_lon_addressed.attrs['long_name']="Longitude" ; dst_lon_addressed.attrs['standard_name']="longitude" ; dst_lon_addressed.attrs['units']="degrees_east"
374dst_lat_addressed.attrs['long_name']="Latitude"  ; dst_lat_addressed.attrs['standard_name']="latitude"  ; dst_lat_addressed.attrs['units']="degrees_north"
375
376if atmDomainType == 'rectilinear' :
377    atmLand         = xr.DataArray ( atmLand.ravel()     , dims = ['src_grid_size',] )
378    atmLandFiltered = xr.DataArray ( atmLandFrac.ravel() , dims = ['src_grid_size',] )
379    atmLandFrac     = xr.DataArray ( atmFrac.ravel()     , dims = ['src_grid_size',] )
380    atmFrac         = xr.DataArray ( atmFrac.ravel()     , dims = ['src_grid_size',] )
381    atmOcean        = xr.DataArray ( atmOcean.ravel()    , dims = ['src_grid_size',] )
382    atmOceanFrac    = xr.DataArray ( atmOceanFrac.ravel(), dims = ['src_grid_size',] )
383
384atmCoast         = xr.DataArray (atmCoast.astype(np.int32)          , dims = ['src_grid_size',])
385oceLand          = xr.DataArray (oceLand.astype(np.int32)           , dims = ['dst_grid_size',])
386oceOcean         = xr.DataArray (oceOcean.astype(np.int32)          , dims = ['dst_grid_size',])
387oceOceanFiltered = xr.DataArray (oceOceanFiltered.astype(np.float32), dims = ['dst_grid_size',])
388oceCoast         = xr.DataArray (oceCoast.astype(np.int32)          , dims = ['dst_grid_size',])
389
390
391f_runoff = xr.Dataset ( {
392    'remap_matrix'            : remap_matrix,
393        'src_address'         : src_address,
394        'dst_address'         : dst_address,
395        'src_grid_dims'       : src_grid_dims,
396        'src_grid_center_lon' : src_grid_center_lon,
397        'src_grid_center_lat' : src_grid_center_lat,
398    'src_grid_corner_lon' : src_grid_corner_lon,
399    'src_grid_corner_lat' : src_grid_corner_lat,
400        'src_grid_area'       : src_grid_area,
401        'src_grid_area'       : src_grid_area,
402        'src_grid_imask'      : src_grid_imask,
403        'src_grid_pmask'      : src_grid_pmask,
404        'dst_grid_dims'       : dst_grid_dims,
405        'dst_grid_center_lon' : dst_grid_center_lon,
406        'dst_grid_center_lat' : dst_grid_center_lat,
407        'dst_grid_corner_lon' : dst_grid_corner_lon,
408        'dst_grid_corner_lat' : dst_grid_corner_lat,
409        'dst_grid_area'       : dst_grid_area,
410        'dst_grid_imask'      : dst_grid_imask,
411        'dst_grid_pmask'      : dst_grid_pmask,
412        'src_lon_addressed'   : src_lon_addressed,
413        'src_lat_addressed'   : src_lat_addressed,
414        'src_area_addressed'  : src_area_addressed,
415        'dst_lon_addressed'   : dst_lon_addressed,
416        'dst_lat_addressed'   : dst_lat_addressed,
417        'dst_area_addressed'  : dst_area_addressed,
418        'dst_imask_addressed' : dst_imask_addressed,
419        'dst_pmask_addressed' : dst_pmask_addressed,
420        'atmCoast'            : atmCoast,
421        'oceLand'             : oceLand,
422        'oceOcean'            : oceOcean,
423        'oceOceanFiltered'    : oceOceanFiltered,
424        'oceCoast'            : oceCoast
425    } )
426
427f_runoff.attrs['Conventions']     = "CF-1.6"
428f_runoff.attrs['source']          = "IPSL Earth system model"
429f_runoff.attrs['group']           = "ICMC IPSL Climate Modelling Center"
430f_runoff.attrs['Institution']     = "IPSL https.//www.ipsl.fr"
431f_runoff.attrs['Ocean']           = oce_Name + " https://www.nemo-ocean.eu"
432f_runoff.attrs['Atmosphere']      = atm_Name + " http://lmdz.lmd.jussieu.fr"
433f_runoff.attrs['associatedFiles'] = grids + " " + areas + " " + masks
434f_runoff.attrs['description']     = "Generated with RunoffWeights.py"
435f_runoff.attrs['title']           = runoff
436f_runoff.attrs['Program']         = "Generated by " + sys.argv[0] + " with flags " + ' '.join (sys.argv[1:]) 
437f_runoff.attrs['atmCoastWidth']   = "{:d} grid points".format(atmCoastWidth)
438f_runoff.attrs['oceCoastWidth']   = "{:d} grid points".format(oceCoastWidth)
439f_runoff.attrs['searchRadius']    = "{:.0f} km".format(searchRadius/1000.)
440f_runoff.attrs['atmQuantity']     = myargs.atmQuantity
441f_runoff.attrs['oceQuantity']     = myargs.oceQuantity
442f_runoff.attrs['gridsFile']       = grids
443f_runoff.attrs['areasFile']       = areas
444f_runoff.attrs['masksFile']       = masks
445f_runoff.attrs['o2aFile']         = o2a
446f_runoff.attrs['timeStamp']       = time.asctime ()
447try    : f_calving.attrs['directory'] = os.getcwd ()
448except : pass
449try    : f_runoff.attrs['HOSTNAME'] = platform.node ()
450except : pass
451try    : f_runoff.attrs['LOGNAME']  = os.getlogin ()
452except : pass
453try    : f_runoff.attrs['Python']   = "Python version " +  platform.python_version ()
454except : pass
455try    : f_runoff.attrs['OS']       = platform.system ()
456except : pass
457try    : f_runoff.attrs['release']  = platform.release ()
458except : pass
459try    : f_runoff.attrs['hardware'] = platform.machine ()
460except : pass
461f_runoff.attrs['conventions']     = "SCRIP"
462f_runoff.attrs['source_grid']     = "curvilinear"
463f_runoff.attrs['dest_grid']       = "curvilinear"
464f_runoff.attrs['Model']           = "IPSL CM6"
465f_runoff.attrs['SVN_Author']      = "$Author$"
466f_runoff.attrs['SVN_Date']        = "$Date$"
467f_runoff.attrs['SVN_Revision']    = "$Revision$"
468f_runoff.attrs['SVN_Id']          = "$Id$"
469f_runoff.attrs['SVN_HeadURL']     = "$HeadURL$"
470
471f_runoff.to_netcdf ( runoff, mode='w', format=FmtNetcdf )
472f_runoff.close ()
473
474##
475
476print ('That''s all folks !')
477## ======================================================================================
Note: See TracBrowser for help on using the repository browser.