source: codes/icosagcm/devel/Python/test/py/write_Cartesian_mesh.py @ 719

Last change on this file since 719 was 719, checked in by dubos, 6 years ago

devel/unstructured : write/read Cartesian mesh as an unstructured mesh

File size: 10.0 KB
Line 
1from dynamico.meshes import zeros
2import numpy as np
3import netCDF4 as cdf
4
5#----------------------- Cartesian mesh -----------------------
6
7def concat(x,y):
8    z = np.asarray([x,y])
9    return z.transpose()
10
11# arrays is a list of arrays
12# vals is a list of tuples
13# each tuple is stored in each array
14def put(ij, deg, arrays, vals):
15    k=0
16    for vv in vals: # vv is a tuple of values to be stored in arrays
17        for array,v in zip(arrays,vv):
18            array[ij,k]=v
19        k=k+1
20    deg[ij]=k
21
22class Cartesian_mesh:
23    def __init__(self,nx,ny,llm,nqdyn,Lx,Ly):
24        dx,dy = Lx/nx, Ly/ny
25        self.dx, self.dy = dx,dy
26        self.nx, self.ny, self.llm, self.nqdyn = nx,ny,llm,nqdyn
27        self.field_z = self.field_mass
28        # 1D coordinate arrays
29        x=(np.arange(nx)-nx/2.)*Lx/nx
30        y=(np.arange(ny)-ny/2.)*Ly/ny
31        lev=np.arange(llm)
32        levp1=np.arange(llm+1)
33        self.x, self.y, self.lev, self.levp1 = x,y,lev,levp1
34        # 3D coordinate arrays
35        self.xx,self.yy,self.ll = np.meshgrid(x,y,lev, indexing='ij')
36        self.xxp1,self.yyp1,self.llp1 = np.meshgrid(x,y,levp1, indexing='ij')
37        # beware conventions for indexing
38        # Fortran order : llm,nx*ny,nqdyn  / indices start at 1
39        # Python order : nqdyn,ny,nx,llm   / indices start at 0
40        # indices below follow Fortran while x,y follow Python/C
41        index=lambda x,y : ((x+(nx*(y+2*ny)))%(nx*ny))+1
42        indexu=lambda x,y : 2*index(x,y)-1
43        indexv=lambda x,y : 2*index(x,y)
44        indices = lambda shape : np.zeros(shape,np.int32)
45
46        primal_deg = indices(nx*ny)
47        primal_edge = indices((nx*ny,4))
48        primal_ne = indices((nx*ny,4))
49
50        dual_deg = indices(nx*ny)
51        dual_edge = indices((nx*ny,4))
52        dual_ne = indices((nx*ny,4))
53        primal_vertex = indices((nx*ny,4))
54        dual_vertex = indices((nx*ny,4))
55        Riv2 = np.zeros((nx*ny,4))
56
57        left = indices(2*nx*ny)
58        right = indices(2*nx*ny)
59        up = indices(2*nx*ny)
60        down = indices(2*nx*ny)
61        le_de = np.zeros(2*nx*ny)
62        le = np.zeros(2*nx*ny)
63        de = np.zeros(2*nx*ny)
64        angle_e = np.zeros(2*nx*ny)
65
66        trisk_deg = indices(2*nx*ny)
67        trisk = indices((2*nx*ny,4)) # 4 TRiSK coefs per edge
68        wee = np.zeros((2*nx*ny,4))
69
70        lon_i = indices(nx*ny)
71        lon_v = indices(nx*ny)
72        lon_e = indices(2*nx*ny)
73        lat_i = indices(nx*ny)
74        lat_v = indices(nx*ny)
75        lat_e = indices(2*nx*ny)
76
77        for x in range(nx):
78            for y in range(ny):
79                # NB : Fortran indices start at 1
80                # primal cells
81                put(index(x,y)-1, primal_deg,(primal_edge,primal_vertex,primal_ne),
82                    ((indexu(x,y),index(x,y),1), 
83                    (indexv(x,y),index(x-1,y),1),
84                    (indexu(x-1,y),index(x-1,y-1),-1),
85                    (indexv(x,y-1),index(x,y-1),-1) ))
86                # dual cells
87                put(index(x,y)-1,dual_deg,(dual_edge,dual_vertex,dual_ne,Riv2),
88                   ((indexv(x+1,y),index(x,y),1,.25),
89                    (indexu(x,y+1),index(x+1,y),-1,.25),
90                    (indexv(x,y),index(x+1,y+1),-1,.25),
91                    (indexu(x,y),index(x,y+1),1,.25) ))
92                # edges :
93                # left and right are adjacent primal cells
94                # flux is positive when going from left to right
95                # up and down are adjacent dual cells (vertices)
96                # circulation is positive when going from down to up
97                # u-points
98                ij =indexu(x,y)-1
99                left[ij]=index(x,y)
100                right[ij]=index(x+1,y)
101                down[ij]=index(x,y-1)
102                up[ij]=index(x,y)
103                #le_de[ij]=dy/dx
104                le[ij]=dy
105                de[ij]=dx
106                le_de[ij]=le[ij]/de[ij]
107                angle_e[ij]=0.
108                put(ij,trisk_deg,(trisk,wee),(
109                    (indexv(x,y),.25),
110                    (indexv(x+1,y),.25),
111                    (indexv(x,y-1),.25),
112                    (indexv(x+1,y-1),.25)))
113                # v-points
114                ij = indexv(x,y)-1
115                left[ij]=index(x,y)
116                right[ij]=index(x,y+1)
117                down[ij]=index(x,y)
118                up[ij]=index(x-1,y)
119                #le_de[ij]=dx/dy
120                le[ij]=dx
121                de[ij]=dy
122                le_de[ij]=le[ij]/de[ij]
123                angle_e[ij]=.5*np.pi
124                put(ij,trisk_deg,(trisk,wee),(
125                    (indexu(x,y),-.25),
126                    (indexu(x-1,y),-.25),
127                    (indexu(x,y+1),-.25),
128                    (indexu(x-1,y+1),-.25)))
129                ij = index(x,y)-1
130                lon_i[ij], lat_i[ij] = x, y
131                ij = index(x,y)-1
132                lon_v[ij], lat_v[ij] = x+.5, y+.5
133                ij = indexu(x,y)-1
134                lon_e[ij], lat_e[ij] = x+.5, y
135                ij = indexv(x,y)-1
136                lon_e[ij], lat_e[ij] = x, y+.5
137
138        Aiv=np.zeros(nx*ny)+dx*dy 
139        Ai=Av=np.zeros(nx*ny)+dx*dy
140
141        self.llm=llm
142        self.nqdyn=nqdyn
143        self.nx=nx
144        self.ny=ny
145        self.primal_deg=primal_deg
146        self.primal_edge=primal_edge
147        self.primal_ne=primal_ne
148        self.dual_deg=dual_deg
149        self.dual_edge=dual_edge
150        self.dual_ne=dual_ne
151        self.dual_vertex=dual_vertex
152        self.primal_vertex=primal_vertex
153        self.left=left
154        self.right=right
155        self.down=down
156        self.up=up
157        self.trisk_deg=trisk_deg
158        self.trisk=trisk
159        self.Aiv=Aiv
160        self.Ai=Ai
161        self.Av=Av
162        self.le=le
163        self.de=de
164        self.angle_e=angle_e
165        self.Riv2=Riv2
166        self.wee=wee
167        self.lon_i = lon_i
168        self.lon_v = lon_v
169        self.lon_e = lon_e
170        #self.lon_ev = indices(2*nx*ny)
171        self.lat_i = lat_i
172        self.lat_v = lat_v
173        self.lat_e = lat_e
174        #self.lat_ev = indices(2*nx*ny)
175     
176
177    def field_theta(self,n=1): return zeros((n,self.nqdyn,self.ny,self.nx,self.llm))
178    def field_mass(self,n=1): return zeros((n,self.ny,self.nx,self.llm))
179    def field_z(self,n=1): return zeros((n,self.ny,self.nx,self.llm))
180    def field_w(self,n=1): return zeros((n,self.ny,self.nx,self.llm+1))
181    def field_u(self,n=1):
182        if n==1:
183            return np.zeros((self.ny,2*self.nx,self.llm))
184        else:
185            return np.zeros((n,self.ny,2*self.nx,self.llm))
186    def field_ps(self,n=1): return zeros((n,self.ny,self.nx))
187    def ucomp(self,u): return u[:,range(0,2*self.nx,2),:]
188    def set_ucomp(self,uv,u): uv[:,range(0,2*self.nx,2),:]=u
189    def vcomp(self,u): return u[:,range(1,2*self.nx,2),:]
190
191    print('#NC4: Successfully initialized Cartesian mesh')
192
193    #----------------------------WRITING MESH----------------------
194    def ncwrite(self, name):
195        """The method writes Cartesian mesh on the disc.
196            Args: Mesh parameters"""
197
198        #----------------OPENING NETCDF OUTPUT FILE------------
199
200        try:
201            f = cdf.Dataset(name, 'w', format='NETCDF4')
202        except:
203            print("CartesianMesh.ncwrite : Error occurred while opening new netCDF mesh file")
204            help(self.ncwrite)
205            raise
206
207        #----------------DEFINING DIMENSIONS--------------------
208
209        for dimname, dimsize in [("primal_cell", self.primal_deg.size),
210                                 ("dual_cell", self.dual_deg.size),
211                                 ("edge", self.left.size),
212                                 ("primal_edge_or_vertex", self.primal_edge.shape[1]),
213                                 ("dual_edge_or_vertex", self.dual_edge.shape[1]),
214                                 ("TWO", 2),
215                                 ("trisk_edge", 4)]:
216            f.createDimension(dimname,dimsize)
217
218        #----------------DEFINING VARIABLES---------------------
219       
220        f.description = "Cartesian_mesh"
221        f.nx, f.ny = self.nx, self.ny
222
223        def create_vars(dimname, info):
224            for vname, vtype, vdata in info:
225#                print('create_vars', dimname, vname, vdata.shape)
226                var = f.createVariable(vname,vtype,dimname)
227                var[:] = vdata
228               
229        create_vars("primal_cell", 
230                    [("primal_deg","i4",self.primal_deg), 
231                     ("Ai","f8",self.Aiv),
232                     ("lon_i","f8",self.lon_i),
233                     ("lat_i","f8",self.lat_i)] )
234        create_vars("dual_cell", 
235                    [("dual_deg","i4",self.dual_deg), 
236                     ("Av","f8",self.Aiv),
237                     ("lon_v","f8",self.lon_v),
238                     ("lat_v","f8",self.lat_v),
239                     ] )
240
241        create_vars( ("primal_cell","primal_edge_or_vertex"), 
242                     [("primal_edge", "i4", self.primal_edge),
243                      ("primal_ne", "i4", self.primal_ne),
244                      ("primal_vertex", "i4", self.primal_vertex)] )
245
246        create_vars( ("dual_cell","dual_edge_or_vertex"), 
247                     [("dual_edge", "i4", self.dual_edge),
248                      ("dual_vertex","i4",self.dual_vertex),
249                      ("dual_ne","i4",self.dual_ne),
250                      ("Riv2","f8",self.Riv2)] )
251
252        create_vars("edge",
253                    [("trisk_deg","i4",self.trisk_deg),
254                     ("le","f8",self.le),
255                     ("de","f8",self.de),
256                     ("lon_e","f8", self.lon_e),
257                     ("lat_e","f8", self.lat_e),
258                      ("angle_e","f8", self.angle_e)] )
259
260        create_vars( ("edge","TWO"),
261                     [("edge_left_right","i4", concat(self.left,self.right)),
262                      ("edge_down_up","i4", concat(self.down,self.up))] )
263                     
264
265        create_vars( ("edge","trisk_edge"),
266                    [("trisk","i4",self.trisk),
267                     ("wee","f8",self.wee)] )
268
269        f.close()
270
271
272#--------------------------------- Main program -------------------------------------
273
274nx,ny,llm,nqdyn=128,128,1,1
275Lx,Ly = 8.,8.
276dx,dy=Lx/nx,Ly/ny
277mesh = Cartesian_mesh(nx,ny,llm,nqdyn,Lx,Ly)
278mesh.ncwrite('cart128.nc')
Note: See TracBrowser for help on using the repository browser.