source: TOOLS/MOSAIX/Build_coordinates_mask.ipynb @ 5925

Last change on this file since 5925 was 5925, checked in by snguyen, 3 years ago

Ajout du notebook de génération du fichier coordonnées masks bounds en python

File size: 28.1 KB
Line 
1{
2 "cells": [
3  {
4   "cell_type": "markdown",
5   "id": "10fcba33",
6   "metadata": {},
7   "source": [
8    "# Constructs ```coordinates_mask``` file\n",
9    "The ```coordinates_mask``` file is needed to run MOSAIX, to build interpolation weights for the coupled model"
10   ]
11  },
12  {
13   "cell_type": "markdown",
14   "id": "b1cbb871",
15   "metadata": {},
16   "source": [
17    "Olivier Marti - olivier.marti@lsce.ipsl - 10/06/2021"
18   ]
19  },
20  {
21   "cell_type": "code",
22   "execution_count": 1,
23   "id": "731d770c",
24   "metadata": {},
25   "outputs": [],
26   "source": [
27    "import xarray as xr\n",
28    "import numpy  as np\n",
29    "import nemo\n",
30    "import datetime, os, platform"
31   ]
32  },
33  {
34   "cell_type": "markdown",
35   "id": "26422e3f",
36   "metadata": {},
37   "source": [
38    "# Input files, type of ORCA grid, and output file"
39   ]
40  },
41  {
42   "cell_type": "code",
43   "execution_count": 2,
44   "id": "deb66d3d",
45   "metadata": {},
46   "outputs": [],
47   "source": [
48    "#model   = 'eORCA1.2'\n",
49    "model   = 'ORCA2.3'\n",
50    "#model   = 'ORCA2.4'"
51   ]
52  },
53  {
54   "cell_type": "code",
55   "execution_count": 5,
56   "id": "2475c8b7",
57   "metadata": {},
58   "outputs": [],
59   "source": [
60    "if model == 'eORCA1.2' :\n",
61    "    n_coord = 'eORCA_R1_coordinates_v1.0.nc' \n",
62    "    n_bathy = 'eORCA_R1_bathy_meter_v2.2.nc'\n",
63    "    #n_coord = 'https://vesg.ipsl.upmc.fr/thredds/dodsC/work/p86mart/GRAF/DATA/eORCA_R1_coordinates_v1.0.nc'\n",
64    "    #n_bathy = 'https://vesg.ipsl.upmc.fr/thredds/dodsC/work/p86mart/GRAF/DATA/eORCA_R1_bathy_meter_v2.2.nc'\n",
65    "    nperio  = 6\n",
66    "    n_out   = 'eORCA_R1_coordinates_mask_test.nc'\n",
67    "\n",
68    "if model == 'ORCA2.3' :\n",
69    "    nperio  = 4\n",
70    "    n_coord = 'coordinates_ORCA2_LIM3_PISCES.nc' #'ORCA2.3_coordinates.nc' #'coordinates.nc' # \n",
71    "    n_bathy = 'bathy_meter_ORCA2_LIM3_PISCES.nc' #'ORCA2.3_bathy_meter.nc' #'bathy_meter_closea_topo.nc' # \n",
72    "    n_out   = 'My_test.nc'\n",
73    "    \n",
74    "if model == 'ORCA2.4' :\n",
75    "    nperio  = 4\n",
76    "    n_coord = 'ORCA2.4_coordinates.nc'\n",
77    "    n_bathy = 'ORCA2.4_bathy_meter.nc'\n",
78    "    n_out   = 'ORCA2.4_coordinates_mask_test.nc'"
79   ]
80  },
81  {
82   "cell_type": "markdown",
83   "id": "8cd952a6",
84   "metadata": {},
85   "source": [
86    "## Open input files\n",
87    "Do not decode time which might be buggy in soem files\n",
88    "Suppress singleton dimensions if necessary"
89   ]
90  },
91  {
92   "cell_type": "code",
93   "execution_count": 6,
94   "id": "0b7c7279",
95   "metadata": {
96    "scrolled": false
97   },
98   "outputs": [],
99   "source": [
100    "f_coord = xr.open_dataset (n_coord, decode_times=False).squeeze()\n",
101    "f_bathy = xr.open_dataset (n_bathy, decode_times=False).squeeze()"
102   ]
103  },
104  {
105   "cell_type": "code",
106   "execution_count": 7,
107   "id": "9fb92919",
108   "metadata": {},
109   "outputs": [
110    {
111     "name": "stdout",
112     "output_type": "stream",
113     "text": [
114      "success\n"
115     ]
116    }
117   ],
118   "source": [
119    "# Suppress time if necessary\n",
120    "try    :\n",
121    "    del f_coord['time']\n",
122    "    print ('success')\n",
123    "except :\n",
124    "    pass\n",
125    "    print ('failed to suppress time')"
126   ]
127  },
128  {
129   "cell_type": "markdown",
130   "id": "d61fb6b2",
131   "metadata": {},
132   "source": [
133    "## Creates masks"
134   ]
135  },
136  {
137   "cell_type": "markdown",
138   "id": "299c0a66",
139   "metadata": {},
140   "source": [
141    "### Read bathymetry "
142   ]
143  },
144  {
145   "cell_type": "code",
146   "execution_count": 8,
147   "id": "9dfd90e6",
148   "metadata": {
149    "scrolled": true
150   },
151   "outputs": [
152    {
153     "name": "stdout",
154     "output_type": "stream",
155     "text": [
156      "Exception\n"
157     ]
158    }
159   ],
160   "source": [
161    "Bathymetry = f_bathy['Bathymetry']\n",
162    "\n",
163    "try :\n",
164    "    Bathymetry = Bathymetry.rename ({'nav_lat':'nav_lat_grid_T', 'nav_lon':'nav_lon_grid_T'})\n",
165    "    print ('Normal case')\n",
166    "except : \n",
167    "    print ('Exception')\n",
168    "    nav_lon_grid_T = f_bathy ['nav_lon']\n",
169    "    nav_lat_grid_T = f_bathy ['nav_lat']\n",
170    "    Bathymetry = xr.DataArray (Bathymetry, coords = { \"nav_lat_grid_T\": ([\"y\", \"x\"], nav_lat_grid_T),\n",
171    "                                                      \"nav_lon_grid_T\": ([\"y\", \"x\"], nav_lon_grid_T) } )\n",
172    "    \n",
173    "Bathymetry = Bathymetry.rename ({'y':'y_grid_T', 'x':'x_grid_T'})"
174   ]
175  },
176  {
177   "cell_type": "code",
178   "execution_count": 9,
179   "id": "2606d14b",
180   "metadata": {},
181   "outputs": [],
182   "source": [
183    "if model == 'ORCA2.3' :\n",
184    "    # orca_r2: Gibraltar strait open\n",
185    "    Bathymetry[101,139] = 284.\n",
186    "    # orca_r2: Bab el Mandeb strait open\n",
187    "    Bathymetry[87,159] = 137."
188   ]
189  },
190  {
191   "cell_type": "markdown",
192   "id": "71c9c821",
193   "metadata": {},
194   "source": [
195    "### Determine which periodicity is needed"
196   ]
197  },
198  {
199   "cell_type": "code",
200   "execution_count": 10,
201   "id": "7e7a49d5",
202   "metadata": {},
203   "outputs": [
204    {
205     "name": "stdout",
206     "output_type": "stream",
207     "text": [
208      "nperio specified :  4\n"
209     ]
210    }
211   ],
212   "source": [
213    "jpj, jpi = Bathymetry.shape\n",
214    "try : \n",
215    "    if nperio != None :\n",
216    "        print ('nperio specified : ', nperio)\n",
217    "except :\n",
218    "    nperio = None\n",
219    "    if jpi ==  182 : nperio = 4 # ORCA2. \\!/ We choose legacy orca2\n",
220    "    if jpi ==  362 : nperio = 6 # ORCA1.\n",
221    "    if jpi == 1442 : nperio = 6 # ORCA025.\n",
222    "    #\n",
223    "    if nperio == None :\n",
224    "        sys.exit ('nperio not found, and cannot by guessed' )\n",
225    "    else :\n",
226    "        print ('nperio set as {:d} (deduced from data size {:d} {:d})'.format (nperio, jpj, jpi))"
227   ]
228  },
229  {
230   "cell_type": "code",
231   "execution_count": 11,
232   "id": "34cdcfe4",
233   "metadata": {},
234   "outputs": [],
235   "source": [
236    "Bathymetry = nemo.lbc (Bathymetry, nperio=nperio, cd_type='T')"
237   ]
238  },
239  {
240   "cell_type": "markdown",
241   "id": "0da91538",
242   "metadata": {},
243   "source": [
244    "### Creates ```mask_T```"
245   ]
246  },
247  {
248   "cell_type": "code",
249   "execution_count": 12,
250   "id": "49a654ef",
251   "metadata": {},
252   "outputs": [],
253   "source": [
254    "mask_T = xr.where (Bathymetry - 1. + 0.1 >= 0.0, 1, 0).astype (dtype='int8')"
255   ]
256  },
257  {
258   "cell_type": "markdown",
259   "id": "327d48ea",
260   "metadata": {},
261   "source": [
262    "### Creates other masks"
263   ]
264  },
265  {
266   "cell_type": "code",
267   "execution_count": 14,
268   "id": "f0b656a1",
269   "metadata": {},
270   "outputs": [],
271   "source": [
272    "mask_U = mask_T * mask_T.shift (x_grid_T=-1)\n",
273    "mask_V = mask_T * mask_T.shift (y_grid_T=-1)\n",
274    "mask_F = mask_T * mask_T.shift (y_grid_T=-1) * mask_T.shift (x_grid_T=-1) * mask_T.shift (y_grid_T=-1, x_grid_T=-1)\n",
275    "mask_W = mask_T\n",
276    "\n",
277    "mask_U = nemo.lbc (mask_U, nperio=nperio, cd_type='U', nemo_4U_bug=True).astype (dtype='int8')\n",
278    "mask_V = nemo.lbc (mask_V, nperio=nperio, cd_type='V').astype (dtype='int8')\n",
279    "mask_F = nemo.lbc (mask_F, nperio=nperio, cd_type='F').astype (dtype='int8')\n",
280    "mask_W = nemo.lbc (mask_W, nperio=nperio, cd_type='W').astype (dtype='int8')\n",
281    "\n",
282    "mask_U = mask_U.rename ( {'y_grid_T'      : 'y_grid_U'      , 'x_grid_T'      : 'x_grid_U', \n",
283    "                          'nav_lat_grid_T': 'nav_lat_grid_U', 'nav_lon_grid_T': 'nav_lon_grid_U'} )\n",
284    "mask_V = mask_V.rename ( {'y_grid_T'      : 'y_grid_V'      , 'x_grid_T'      : 'x_grid_V',\n",
285    "                          'nav_lat_grid_T': 'nav_lat_grid_V', 'nav_lon_grid_T': 'nav_lon_grid_V'} )\n",
286    "mask_W = mask_W.rename ( {'y_grid_T'      : 'y_grid_W'      , 'x_grid_T'      : 'x_grid_W',\n",
287    "                          'nav_lat_grid_T': 'nav_lat_grid_W', 'nav_lon_grid_T': 'nav_lon_grid_W'} )\n",
288    "mask_F = mask_F.rename ( {'y_grid_T'      : 'y_grid_F'      , 'x_grid_T'      : 'x_grid_F',\n",
289    "                          'nav_lat_grid_T': 'nav_lat_grid_F', 'nav_lon_grid_T': 'nav_lon_grid_F'} )\n",
290    "\n",
291    "mask_T.name = 'mask_T'\n",
292    "mask_U.name = 'mask_U'\n",
293    "mask_V.name = 'mask_V'\n",
294    "mask_F.name = 'mask_F'\n",
295    "mask_W.name = 'mask_W'"
296   ]
297  },
298  {
299   "cell_type": "markdown",
300   "id": "5cb36da6",
301   "metadata": {},
302   "source": [
303    "### Masks with duplicate points removed"
304   ]
305  },
306  {
307   "cell_type": "code",
308   "execution_count": null,
309   "id": "b9ce5946",
310   "metadata": {},
311   "outputs": [],
312   "source": [
313    "#maskutil_T = nemo.lbc_mask (mask_T, nperio=nperio, cd_type='T')\n",
314    "#maskutil_U = nemo.lbc_mask (mask_U, nperio=nperio, cd_type='U')\n",
315    "#maskutil_V = nemo.lbc_mask (mask_V, nperio=nperio, cd_type='V')\n",
316    "#maskutil_F = nemo.lbc_mask (mask_F, nperio=nperio, cd_type='F')\n",
317    "#maskutil_W = nemo.lbc_mask (mask_W, nperio=nperio, cd_type='W')\n",
318    "\n",
319    "#maskutil_T.name = 'maskutil_T'\n",
320    "#maskutil_U.name = 'maskutil_U'\n",
321    "#maskutil_V.name = 'maskutil_V'\n",
322    "#maskutil_F.name = 'maskutil_F'\n",
323    "#maskutil_W.name = 'maskutil_W'"
324   ]
325  },
326  {
327   "cell_type": "code",
328   "execution_count": 15,
329   "id": "274e4321",
330   "metadata": {},
331   "outputs": [],
332   "source": [
333    "# Plus compact que ci-dessus, mais un peu incompréhensible .... !!!\n",
334    "for cd_type in ['T', 'U', 'V', 'F', 'W'] :\n",
335    "    MaskName = 'mask_'     + cd_type\n",
336    "    UtilName = 'maskutil_' + cd_type\n",
337    "    locals()[UtilName] = nemo.lbc_mask (locals()[MaskName], nperio=nperio, cd_type=cd_type)\n",
338    "    locals()[UtilName].name = UtilName"
339   ]
340  },
341  {
342   "cell_type": "markdown",
343   "id": "69ec3daa",
344   "metadata": {},
345   "source": [
346    "### Add attributes"
347   ]
348  },
349  {
350   "cell_type": "code",
351   "execution_count": 16,
352   "id": "f46e1c93",
353   "metadata": {},
354   "outputs": [],
355   "source": [
356    "mask_T.attrs    ['cell_measures'] = 'area: area_grid_T'\n",
357    "mask_U.attrs    ['cell_measures'] = 'area: area_grid_U'\n",
358    "mask_V.attrs    ['cell_measures'] = 'area: area_grid_V'\n",
359    "mask_W.attrs    ['cell_measures'] = 'area: area_grid_W'\n",
360    "mask_F.attrs    ['cell_measures'] = 'area: area_grid_F'\n",
361    "\n",
362    "maskutil_T.attrs['cell_measures'] = 'area: area_grid_T'\n",
363    "maskutil_U.attrs['cell_measures'] = 'area: area_grid_U'\n",
364    "maskutil_V.attrs['cell_measures'] = 'area: area_grid_V'\n",
365    "maskutil_W.attrs['cell_measures'] = 'area: area_grid_W'\n",
366    "maskutil_F.attrs['cell_measures'] = 'area: area_grid_F'"
367   ]
368  },
369  {
370   "cell_type": "markdown",
371   "id": "580e2776",
372   "metadata": {},
373   "source": [
374    "## Creates grid coordinates and surfaces"
375   ]
376  },
377  {
378   "cell_type": "code",
379   "execution_count": 17,
380   "id": "a7ce1490",
381   "metadata": {},
382   "outputs": [],
383   "source": [
384    "nav_lon_grid_T = nemo.lbc (f_coord ['glamt'], nperio=nperio, cd_type='T')\n",
385    "nav_lat_grid_T = nemo.lbc (f_coord ['gphit'], nperio=nperio, cd_type='T')\n",
386    "nav_lon_grid_U = nemo.lbc (f_coord ['glamu'], nperio=nperio, cd_type='U',nemo_4U_bug=True)\n",
387    "#nav_lon_grid_U = f_coord ['glamu']\n",
388    "nav_lat_grid_U = nemo.lbc (f_coord ['gphiu'], nperio=nperio, cd_type='U',nemo_4U_bug=True)\n",
389    "#nav_lat_grid_U = f_coord ['gphiu']\n",
390    "nav_lon_grid_V = nemo.lbc (f_coord ['glamv'], nperio=nperio, cd_type='V')\n",
391    "nav_lat_grid_V = nemo.lbc (f_coord ['gphiv'], nperio=nperio, cd_type='V')\n",
392    "nav_lon_grid_W = nemo.lbc (f_coord ['glamt'], nperio=nperio, cd_type='W')\n",
393    "nav_lat_grid_W = nemo.lbc (f_coord ['gphit'], nperio=nperio, cd_type='W')\n",
394    "nav_lon_grid_F = nemo.lbc (f_coord ['glamf'], nperio=nperio, cd_type='F')\n",
395    "nav_lat_grid_F = nemo.lbc (f_coord ['gphif'], nperio=nperio, cd_type='F')\n",
396    "\n",
397    "nav_lon_grid_T = nav_lon_grid_T.rename( {'y':'y_grid_T', 'x':'x_grid_T'} )\n",
398    "nav_lat_grid_T = nav_lat_grid_T.rename( {'y':'y_grid_T', 'x':'x_grid_T'} )\n",
399    "nav_lon_grid_U = nav_lon_grid_U.rename( {'y':'y_grid_U', 'x':'x_grid_U'} )\n",
400    "nav_lat_grid_U = nav_lat_grid_U.rename( {'y':'y_grid_U', 'x':'x_grid_U'} )\n",
401    "nav_lon_grid_V = nav_lon_grid_V.rename( {'y':'y_grid_V', 'x':'x_grid_V'} )\n",
402    "nav_lat_grid_V = nav_lat_grid_V.rename( {'y':'y_grid_V', 'x':'x_grid_V'} )\n",
403    "nav_lon_grid_W = nav_lon_grid_W.rename( {'y':'y_grid_W', 'x':'x_grid_W'} )\n",
404    "nav_lat_grid_W = nav_lat_grid_W.rename( {'y':'y_grid_W', 'x':'x_grid_W'} )\n",
405    "nav_lon_grid_F = nav_lon_grid_F.rename( {'y':'y_grid_F', 'x':'x_grid_F'} )\n",
406    "nav_lat_grid_F = nav_lat_grid_F.rename( {'y':'y_grid_F', 'x':'x_grid_F'} )\n",
407    "\n",
408    "for cd_type in ['T', 'U', 'V', 'F', 'W'] :\n",
409    "    for dir_type in ['lat', 'lon'] :\n",
410    "        coord_name = 'nav_' + dir_type + '_grid_' + cd_type\n",
411    "        locals()[coord_name].encoding['_FillValue'] = None\n",
412    "        locals()[coord_name].encoding['missing_value'] = None"
413   ]
414  },
415  {
416   "cell_type": "code",
417   "execution_count": 18,
418   "id": "516b4c5c",
419   "metadata": {},
420   "outputs": [],
421   "source": [
422    "nav_lon_grid_T.name = 'nav_lon_grid_T'\n",
423    "nav_lat_grid_T.name = 'nav_lat_grid_T'\n",
424    "nav_lon_grid_U.name = 'nav_lon_grid_U'\n",
425    "nav_lat_grid_U.name = 'nav_lat_grid_U'\n",
426    "nav_lon_grid_V.name = 'nav_lon_grid_V'\n",
427    "nav_lat_grid_V.name = 'nav_lat_grid_V'\n",
428    "nav_lon_grid_F.name = 'nav_lon_grid_F'\n",
429    "nav_lat_grid_F.name = 'nav_lat_grid_F'\n",
430    "nav_lon_grid_W.name = 'nav_lon_grid_W'\n",
431    "nav_lat_grid_W.name = 'nav_lat_grid_W'"
432   ]
433  },
434  {
435   "cell_type": "markdown",
436   "id": "cffad9b4",
437   "metadata": {},
438   "source": [
439    "### Add attributes"
440   ]
441  },
442  {
443   "cell_type": "code",
444   "execution_count": 27,
445   "id": "de0e6514",
446   "metadata": {},
447   "outputs": [],
448   "source": [
449    "nav_lon_grid_T.attrs['standard_name'] = 'longitude'\n",
450    "nav_lon_grid_T.attrs['long_name']     = 'Longitude'\n",
451    "nav_lon_grid_T.attrs['units']         = 'degrees_east'\n",
452    "nav_lat_grid_T.attrs['standard_name'] = 'latitude'\n",
453    "nav_lat_grid_T.attrs['long_name']     = 'Latitude'\n",
454    "nav_lat_grid_T.attrs['units']         = 'degrees_north'\n",
455    "\n",
456    "nav_lon_grid_U.attrs['standard_name'] = 'longitude'\n",
457    "nav_lon_grid_U.attrs['long_name']     = 'Longitude'\n",
458    "nav_lon_grid_U.attrs['units']         = 'degrees_east'\n",
459    "nav_lat_grid_U.attrs['standard_name'] = 'latitude'\n",
460    "nav_lat_grid_U.attrs['long_name']     = 'Latitude'\n",
461    "nav_lat_grid_U.attrs['units']         = 'degrees_north'\n",
462    "\n",
463    "nav_lon_grid_V.attrs['standard_name'] = 'longitude'\n",
464    "nav_lon_grid_V.attrs['long_name']     = 'Longitude'\n",
465    "nav_lon_grid_V.attrs['units']         = 'degrees_east'\n",
466    "nav_lat_grid_V.attrs['standard_name'] = 'latitude'\n",
467    "nav_lat_grid_V.attrs['long_name']     = 'Latitude'\n",
468    "nav_lat_grid_V.attrs['units']         = 'degrees_north'\n",
469    "\n",
470    "nav_lon_grid_W.attrs['standard_name'] = 'longitude'\n",
471    "nav_lon_grid_W.attrs['long_name']     = 'Longitude'\n",
472    "nav_lon_grid_W.attrs['units']         = 'degrees_east'\n",
473    "nav_lat_grid_W.attrs['standard_name'] = 'latitude'\n",
474    "nav_lat_grid_W.attrs['long_name']     = 'Latitude'\n",
475    "nav_lat_grid_W.attrs['units']         = 'degrees_north'\n",
476    "\n",
477    "nav_lon_grid_F.attrs['standard_name'] = 'longitude'\n",
478    "nav_lon_grid_F.attrs['long_name']     = 'Longitude'\n",
479    "nav_lon_grid_F.attrs['units']         = 'degrees_east'\n",
480    "nav_lat_grid_F.attrs['standard_name'] = 'latitude'\n",
481    "nav_lat_grid_F.attrs['long_name']     = 'Latitude'\n",
482    "nav_lat_grid_F.attrs['units']         = 'degrees_north'\n",
483    "\n",
484    "nav_lon_grid_T.attrs['bounds'] = 'bounds_lon_grid_T'\n",
485    "nav_lat_grid_T.attrs['bounds'] = 'bounds_lat_grid_T'\n",
486    "nav_lon_grid_U.attrs['bounds'] = 'bounds_lon_grid_U'\n",
487    "nav_lat_grid_U.attrs['bounds'] = 'bounds_lat_grid_U'\n",
488    "nav_lon_grid_V.attrs['bounds'] = 'bounds_lon_grid_V'\n",
489    "nav_lat_grid_V.attrs['bounds'] = 'bounds_lat_grid_V'\n",
490    "nav_lon_grid_W.attrs['bounds'] = 'bounds_lon_grid_W'\n",
491    "nav_lat_grid_W.attrs['bounds'] = 'bounds_lat_grid_W'\n",
492    "nav_lon_grid_F.attrs['bounds'] = 'bounds_lon_grid_F'\n",
493    "nav_lat_grid_F.attrs['bounds'] = 'bounds_lat_grid_F'"
494   ]
495  },
496  {
497   "cell_type": "code",
498   "execution_count": 20,
499   "id": "8e4d997c",
500   "metadata": {},
501   "outputs": [],
502   "source": [
503    "# remove zero values from areas\n",
504    "# need to be define for the extended grid south of -80S\n",
505    "# some point are undefined but you need to have e1 and e2 .NE. 0\n",
506    "for cd_type in ['t', 'u', 'v', 'f'] :\n",
507    "    for axis in ['1', '2'] :\n",
508    "        coordName = 'e' + axis + cd_type\n",
509    "        f_coord[coordName]=xr.where(f_coord[coordName] == 0.0, 1.0e2, f_coord[coordName])"
510   ]
511  },
512  {
513   "cell_type": "code",
514   "execution_count": 21,
515   "id": "175bae75",
516   "metadata": {},
517   "outputs": [],
518   "source": [
519    "# Correct areas for straits\n",
520    "if model == 'ORCA2.3' :\n",
521    "    # orca_r2: Gibraltar    : e2u reduced to 20 km\n",
522    "    f_coord['e2u'][101,138:140] = 20.e3\n",
523    "    # orca_r2: Bab el Mandeb: e2u reduced to 30 km\n",
524    "    #                         e1v reduced to 18 km\n",
525    "    f_coord['e1v'][87,159] = 18.e3\n",
526    "    f_coord['e2u'][87,159] = 30.e3\n",
527    "    # orca_r2: Danish Straits : e2u reduced to 10 km\n",
528    "    f_coord['e2u'][115,144:146] = 10.e3\n",
529    "    "
530   ]
531  },
532  {
533   "cell_type": "code",
534   "execution_count": 22,
535   "id": "4f6cfbca",
536   "metadata": {},
537   "outputs": [],
538   "source": [
539    "area_grid_T = nemo.lbc (f_coord ['e1t']*f_coord ['e2t'], nperio=nperio, cd_type='T')\n",
540    "area_grid_U = nemo.lbc (f_coord ['e1u']*f_coord ['e2u'], nperio=nperio, cd_type='U',nemo_4U_bug=True)\n",
541    "#area_grid_U = f_coord ['e1u']*f_coord ['e2u']\n",
542    "area_grid_V = nemo.lbc (f_coord ['e1v']*f_coord ['e2v'], nperio=nperio, cd_type='V')\n",
543    "area_grid_W = nemo.lbc (f_coord ['e1t']*f_coord ['e2t'], nperio=nperio, cd_type='W')\n",
544    "area_grid_F = nemo.lbc (f_coord ['e1f']*f_coord ['e2f'], nperio=nperio, cd_type='F')\n",
545    "\n",
546    "area_grid_T.name = 'area_grid_T'\n",
547    "area_grid_U.name = 'area_grid_U'\n",
548    "area_grid_V.name = 'area_grid_V'\n",
549    "area_grid_F.name = 'area_grid_F'\n",
550    "area_grid_W.name = 'area_grid_W'\n",
551    "\n",
552    "area_grid_T = area_grid_T.rename ({'y':'y_grid_T', 'x':'x_grid_T'})\n",
553    "area_grid_U = area_grid_U.rename ({'y':'y_grid_U', 'x':'x_grid_U'})\n",
554    "area_grid_V = area_grid_V.rename ({'y':'y_grid_V', 'x':'x_grid_V'})\n",
555    "area_grid_W = area_grid_W.rename ({'y':'y_grid_W', 'x':'x_grid_W'})\n",
556    "area_grid_F = area_grid_F.rename ({'y':'y_grid_F', 'x':'x_grid_F'})\n",
557    "\n",
558    "area_grid_T.attrs['standard_name'] = 'cell_area'\n",
559    "area_grid_T.attrs['units']         = 'm2'\n",
560    "area_grid_T.attrs['coordinates']   = 'nav_lat_grid_T nav_lon_grid_T'\n",
561    "area_grid_U.attrs['standard_name'] = 'cell_area'\n",
562    "area_grid_U.attrs['units']         = 'm2'\n",
563    "area_grid_U.attrs['coordinates']   = 'nav_lat_grid_U nav_lon_grid_U'\n",
564    "area_grid_V.attrs['standard_name'] = 'cell_area'\n",
565    "area_grid_V.attrs['units']         = 'm2'\n",
566    "area_grid_V.attrs['coordinates']   = 'nav_lat_grid_V nav_lon_grid_V'\n",
567    "area_grid_W.attrs['standard_name'] = 'cell_area'\n",
568    "area_grid_W.attrs['units']         = 'm2'\n",
569    "area_grid_W.attrs['coordinates']   = 'nav_lat_grid_W nav_lon_grid_W'\n",
570    "area_grid_F.attrs['standard_name'] = 'cell_area'\n",
571    "area_grid_F.attrs['units']         = 'm2'\n",
572    "area_grid_F.attrs['coordinates']   = 'nav_lat_grid_F nav_lon_grid_F'"
573   ]
574  },
575  {
576   "cell_type": "markdown",
577   "id": "3c6f7b08",
578   "metadata": {},
579   "source": [
580    "## Construct bounds"
581   ]
582  },
583  {
584   "cell_type": "code",
585   "execution_count": 23,
586   "id": "69c404d9",
587   "metadata": {},
588   "outputs": [],
589   "source": [
590    "def set_bounds (cdgrd) :\n",
591    "    '''\n",
592    "    Constructs lon/lat bounds\n",
593    "    Bounds are numerated counter clockwise, from bottom left\n",
594    "    See NEMO file OPA_SRC/IOM/iom.F90, ROUTINE set_grid_bounds, for more details\n",
595    "    '''\n",
596    "    # Define offset of coordinate representing bottom-left corner\n",
597    "    if cdgrd in ['T', 'W'] : \n",
598    "        icnr = -1 ; jcnr = -1\n",
599    "        corner_lon = nav_lon_grid_F ; corner_lat = nav_lat_grid_F\n",
600    "    if cdgrd == 'U'        : \n",
601    "        icnr =  0 ; jcnr = -1\n",
602    "        corner_lon = nav_lon_grid_V ; corner_lat = nav_lat_grid_V\n",
603    "    if cdgrd == 'V'        : \n",
604    "        icnr = -1 ; jcnr =  0\n",
605    "        corner_lon = nav_lon_grid_U ; corner_lat = nav_lat_grid_U\n",
606    "    if cdgrd == 'F'        : \n",
607    "        icnr = -1 ; jcnr = -1\n",
608    "        corner_lon = nav_lon_grid_T ; corner_lat = nav_lat_grid_T\n",
609    "\n",
610    "    y_grid, x_grid = corner_lon.shape ; nvertex = 4\n",
611    "    dims = ['y_grid_' + cdgrd, 'x_grid_' + cdgrd, 'nvertex_grid_' + cdgrd]\n",
612    "    \n",
613    "    bounds_lon = xr.DataArray (np.zeros ((y_grid, x_grid, nvertex)), dims=dims)\n",
614    "    bounds_lat = xr.DataArray (np.zeros ((y_grid, x_grid, nvertex)), dims=dims)\n",
615    "    \n",
616    "    idx = [(jcnr,icnr), (jcnr,icnr+1), (jcnr+1,icnr+1), (jcnr+1,icnr)]\n",
617    "    \n",
618    "    # Compute cell vertices that can be defined, \n",
619    "    # and complete with periodicity\n",
620    "    for nn in range (nvertex) :\n",
621    "        bounds_lon[:,:,nn] = np.roll  (corner_lon, shift=(idx[nn]), axis=(-2,-1))\n",
622    "        bounds_lat[:,:,nn] = np.roll  (corner_lat, shift=(idx[nn]), axis=(-2,-1))\n",
623    "        bounds_lon[:,:,nn] = nemo.lbc (bounds_lon[:,:,nn], nperio=nperio, cd_type=cdgrd)\n",
624    "        bounds_lat[:,:,nn] = nemo.lbc (bounds_lat[:,:,nn], nperio=nperio, cd_type=cdgrd)\n",
625    "    \n",
626    "    # Rotate cells at the north fold\n",
627    "    if nperio >= 3 :\n",
628    "        # Working array for location of northfold\n",
629    "        z_fld = nemo.lbc (np.ones ((jpj, jpi)), nperio=nperio, cd_type=cdgrd, psgn=-1. )\n",
630    "        z_fld = (z_fld == -1.0)\n",
631    "        \n",
632    "        for nn in range (nvertex) :\n",
633    "            nr = np.mod (nn+2, 4)\n",
634    "            bounds_lon[:,:,nn] = np.where (z_fld, bounds_lon[:,:,nr], bounds_lon[:,:,nn])\n",
635    "            bounds_lat[:,:,nn] = np.where (z_fld, bounds_lat[:,:,nr], bounds_lat[:,:,nn])\n",
636    "    \n",
637    "    # Invert cells at the symmetric equator\n",
638    "    if nperio == 2 :\n",
639    "        for nn in range (nvertex) :\n",
640    "            nr = np.mod (nn+2, 4)\n",
641    "            bounds_lon [0, :, nn] = bounds_lon [0, :, nr]\n",
642    "            bounds_lat [0, :, nn] = bounds_lat [0, :, nr]\n",
643    "    \n",
644    "    bounds_lon.attrs['coordinates'] = 'nav_lat_grid_' + cdgrd + ' nav_lon_grid_' + cdgrd\n",
645    "    bounds_lat.attrs['coordinates'] = 'nav_lat_grid_' + cdgrd + ' nav_lon_grid_' + cdgrd\n",
646    "    bounds_lon.attrs['units']       = 'degrees_east'\n",
647    "    bounds_lat.attrs['units']       = 'degrees_north'\n",
648    "    bounds_lon.name = 'bounds_lon_grid_' + cdgrd\n",
649    "    bounds_lat.name = 'bounds_lat_grid_' + cdgrd\n",
650    "\n",
651    "    return bounds_lon, bounds_lat"
652   ]
653  },
654  {
655   "cell_type": "code",
656   "execution_count": 24,
657   "id": "87a8f592",
658   "metadata": {},
659   "outputs": [],
660   "source": [
661    "bounds_lon_grid_T, bounds_lat_grid_T = set_bounds ('T')\n",
662    "bounds_lon_grid_U, bounds_lat_grid_U = set_bounds ('U')\n",
663    "bounds_lon_grid_V, bounds_lat_grid_V = set_bounds ('V')\n",
664    "bounds_lon_grid_W, bounds_lat_grid_W = set_bounds ('W')\n",
665    "bounds_lon_grid_F, bounds_lat_grid_F = set_bounds ('F')"
666   ]
667  },
668  {
669   "cell_type": "markdown",
670   "id": "5dbf22b3",
671   "metadata": {},
672   "source": [
673    "## Save Data in a NetCDF file"
674   ]
675  },
676  {
677   "cell_type": "code",
678   "execution_count": 28,
679   "id": "ca87fa1b",
680   "metadata": {},
681   "outputs": [],
682   "source": [
683    "ds = xr.Dataset ({\n",
684    "    'mask_T'      : mask_T     ,\n",
685    "    'mask_U'      : mask_U     ,\n",
686    "    'mask_V'      : mask_V     ,\n",
687    "    'mask_W'      : mask_W     ,\n",
688    "    'mask_F'      : mask_F     ,\n",
689    "    'area_grid_T' : area_grid_T,\n",
690    "    'area_grid_U' : area_grid_U,\n",
691    "    'area_grid_V' : area_grid_V,\n",
692    "    'area_grid_W' : area_grid_W,\n",
693    "    'area_grid_F' : area_grid_F,\n",
694    "    'maskutil_T'  : maskutil_T ,\n",
695    "    'maskutil_U'  : maskutil_U ,\n",
696    "    'maskutil_V'  : maskutil_V ,\n",
697    "    'maskutil_W'  : maskutil_W ,\n",
698    "    'maskutil_F'  : maskutil_F ,\n",
699    "    'bounds_lon_grid_T': bounds_lon_grid_T,\n",
700    "    'bounds_lat_grid_T': bounds_lat_grid_T,\n",
701    "    'bounds_lon_grid_U': bounds_lon_grid_U,\n",
702    "    'bounds_lat_grid_U': bounds_lat_grid_U,\n",
703    "    'bounds_lon_grid_V': bounds_lon_grid_V,\n",
704    "    'bounds_lat_grid_V': bounds_lat_grid_V,\n",
705    "    'bounds_lon_grid_W': bounds_lon_grid_W,\n",
706    "    'bounds_lat_grid_W': bounds_lat_grid_W,\n",
707    "    'bounds_lon_grid_F': bounds_lon_grid_F,\n",
708    "    'bounds_lat_grid_F': bounds_lat_grid_F,\n",
709    "})\n",
710    "for cd_type in ['T', 'U', 'V', 'F', 'W'] :\n",
711    "    for dir_type in ['lat', 'lon'] :\n",
712    "        coord_name = 'nav_' + dir_type + '_grid_' + cd_type\n",
713    "        ds.coords[coord_name]=locals()[coord_name]\n",
714    "\n",
715    "ds.attrs['name']         = 'coordinates_mask'\n",
716    "ds.attrs['description']  = 'coordinates and mask for MOSAIX'\n",
717    "ds.attrs['title']        = 'coordinates_mask'\n",
718    "ds.attrs['source']       = 'IPSL Earth system model'\n",
719    "ds.attrs['group']        = 'ICMC IPSL Climate Modelling Center'\n",
720    "ds.attrs['Institution']  = 'IPSL https.//www.ipsl.fr'\n",
721    "ds.attrs['Model']        = model\n",
722    "ds.attrs['timeStamp']    = '{:%Y-%b-%d %H:%M:%S}'.format (datetime.datetime.now ())\n",
723    "ds.attrs['history']      = 'Build from ' + n_coord + ' and ' + n_bathy\n",
724    "ds.attrs['directory']    = os.getcwd     ()\n",
725    "ds.attrs['user']         = os.getlogin   ()\n",
726    "ds.attrs['HOSTNAME']     = platform.node ()\n",
727    "ds.attrs['Python']       = 'Python version: ' +  platform.python_version ()\n",
728    "ds.attrs['xarray']       = 'xarray version: ' +  xr.__version__\n",
729    "ds.attrs['OS']           = platform.system  ()\n",
730    "ds.attrs['release']      = platform.release ()\n",
731    "ds.attrs['hardware']     = platform.machine ()\n",
732    "\n",
733    "ds.attrs['SVN_Author']   = \"$Author:  $\"\n",
734    "ds.attrs['SVN_Date']     = \"$Date:  $\"\n",
735    "ds.attrs['SVN_Revision'] = \"$Revision:  $\"\n",
736    "ds.attrs['SVN_Id']       = \"$Id: Build_coordinates_mask.py $\"\n",
737    "ds.attrs['SVN_HeadURL']  = \"$HeadURL: http://forge.ipsl.jussieu.fr/igcmg/svn/TOOLS/MOSAIX/Build_coordinates_mask.py $\""
738   ]
739  },
740  {
741   "cell_type": "code",
742   "execution_count": null,
743   "id": "6bfcc709",
744   "metadata": {},
745   "outputs": [],
746   "source": [
747    "# Why is this necessary ?\n",
748    "ds['nav_lon_grid_T'].attrs['bounds'] = nav_lon_grid_T.attrs['bounds']\n",
749    "ds['nav_lat_grid_T'].attrs['bounds'] = nav_lat_grid_T.attrs['bounds']\n",
750    "ds['nav_lon_grid_U'].attrs['bounds'] = nav_lon_grid_U.attrs['bounds']\n",
751    "ds['nav_lat_grid_U'].attrs['bounds'] = nav_lat_grid_U.attrs['bounds']\n",
752    "ds['nav_lon_grid_V'].attrs['bounds'] = nav_lon_grid_V.attrs['bounds']\n",
753    "ds['nav_lat_grid_V'].attrs['bounds'] = nav_lat_grid_V.attrs['bounds']\n",
754    "ds['nav_lon_grid_W'].attrs['bounds'] = nav_lon_grid_W.attrs['bounds']\n",
755    "ds['nav_lat_grid_W'].attrs['bounds'] = nav_lat_grid_W.attrs['bounds']\n",
756    "ds['nav_lon_grid_F'].attrs['bounds'] = nav_lon_grid_F.attrs['bounds']\n",
757    "ds['nav_lat_grid_F'].attrs['bounds'] = nav_lat_grid_F.attrs['bounds']"
758   ]
759  },
760  {
761   "cell_type": "code",
762   "execution_count": 29,
763   "id": "41391c22",
764   "metadata": {},
765   "outputs": [],
766   "source": [
767    "ds.to_netcdf (n_out)"
768   ]
769  },
770  {
771   "cell_type": "markdown",
772   "id": "75143732",
773   "metadata": {},
774   "source": [
775    "# That's all folk's !"
776   ]
777  },
778  {
779   "cell_type": "code",
780   "execution_count": null,
781   "id": "88457886",
782   "metadata": {},
783   "outputs": [],
784   "source": []
785  }
786 ],
787 "metadata": {
788  "kernelspec": {
789   "display_name": "Python 3",
790   "language": "python",
791   "name": "python3"
792  },
793  "language_info": {
794   "codemirror_mode": {
795    "name": "ipython",
796    "version": 3
797   },
798   "file_extension": ".py",
799   "mimetype": "text/x-python",
800   "name": "python",
801   "nbconvert_exporter": "python",
802   "pygments_lexer": "ipython3",
803   "version": "3.8.10"
804  }
805 },
806 "nbformat": 4,
807 "nbformat_minor": 5
808}
Note: See TracBrowser for help on using the repository browser.