From be4937669e3222c46327adc45a27a9cb430e8fda Mon Sep 17 00:00:00 2001
From: Anthony <anthony.schrapffer@polytechnique.fr>
Date: Mon, 18 May 2020 23:06:31 +0200
Subject: [PATCH] =?UTF-8?q?Land=20points=20outside=20Hydrosheds=20(>60?=
 =?UTF-8?q?=C2=B0S)=20+=20cleanup=20+=20solving=20res=5Flon/res=5Flat=20is?=
 =?UTF-8?q?sue=20in=20ModelGrid=20when=20nbj=20or=20nbi=20=3D=201?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ModelGrid.py | 150 +++++++++++++++++++++++----------------------------
 RPPtools.py  |  21 ++++++++
 2 files changed, 88 insertions(+), 83 deletions(-)

diff --git a/ModelGrid.py b/ModelGrid.py
index 4490827..0a855c7 100644
--- a/ModelGrid.py
+++ b/ModelGrid.py
@@ -37,90 +37,63 @@ def mindist(coord,lon,lat) :
 #
 def gatherland(lon, lat, land, indP, indFi, indFj) :
     nj,ni=lon.shape
-    coord=[]
-    indF_land=[]
-    indP_land=[]
-    for i in range(ni) :
-        for j in range(nj) :
-            if (land[j,i] > 0 ) :
-                coord.append([lon[j,i],lat[j,i]])
-                indF_land.append([indFi[j,i],indFj[j,i]])
-                indP_land.append([j,i])
+    #
+    indP_land = [[j,i] for i in range(ni) for j in range(nj) if land[j,i] > 0]
+    coord = [[lon[j,i],lat[j,i]] for j,i in indP_land]
+    indF_land = [[indFi[j,i],indFj[j,i]] for j,i in indP_land] 
+    #
     nbland=len(coord)
     #
     # Get the neighbours in the coord list. The same order is used as in ORCHIDEE
     #
-    neighbours=[]
-    for i in range(ni) :
-        for j in range(nj) :
-           if (land[j,i] > 0 ) :
-               ntmp=[]
-               #
-               # Indices of neighbouring points are in C and thus +1 will be performed
-               # For FORTRAN.
-               # -1 will become 0 and indicate point is outside of domain.
-               # -2 will become -1 and indicate ocean.
-               #
-               for r in rose :
-                   nnj=j+r[0]
-                   nni=i+r[1]
-                   if ( nni >= 0 and nni < ni and nnj >= 0 and nnj < nj) :
-                       if land[nnj,nni] > 0 :
-                           ntmp.append(mindist(coord,lon[nnj,nni],lat[nnj,nni]))
-                       else : 
-                           ntmp.append(-2)
-                   else :
-                       ntmp.append(-1)
-               neighbours.append(ntmp)
-               
+    # Indices of neighbouring points are in C and thus +1 will be performed
+    # For FORTRAN.
+    # -1 will become 0 and indicate point is outside of domain.
+    # -2 will become -1 and indicate ocean.
+    #
+    neighbours = [get_neighbours(i,j,ni,nj,land, coord, lon, lat) for j,i in indP_land]
+    #
     return nbland, coord,neighbours,indP_land,indF_land
 #
+def get_neighbours(i,j, ni, nj, land, coord, lon, lat):
+   nn = [[j+r[0], i +r[1]] for r in rose]
+   ntmp = [-1 if (nni < 0 or nni>=ni or nnj <0 or nnj>=nj) else -2 if (land[nnj,nni] == 0) else mindist(coord,lon[nnj,nni],lat[nnj,nni]) for nnj, nni in nn]
+   return ntmp
 #
 #
-def corners(indF, proj, istart, jstart, lon, lat) :
-    cornersll=[]
-    cornerspoly=[]
-    centersll=[]
-    radiusll=[]
-    areas=[]
-    allon=[]
-    allat=[]
+#
+def corners(indF, proj, istart, jstart, lon, lat, res_lon, res_lat) :
     #
-    dlon=int((lon[0,-1]-lon[0,0])/np.abs(lon[0,-1]-lon[0,0]))
-    dlat=int((lat[0,0]-lat[-1,0])/np.abs(lat[0,0]-lat[-1,0]))
+    if lon.shape[1]>1 and lat.shape[0]>1:
+        dlon=int((lon[0,-1]-lon[0,0])/np.abs(lon[0,-1]-lon[0,0]))
+        dlat=int((lat[0,0]-lat[-1,0])/np.abs(lat[0,0]-lat[-1,0]))
+    else:
+        dlon = res_lon
+        dlat = res_lat
+    #
+    # Get the corners and mid-points of segments to completely describe the polygone
+    #
+    Lpolyg = [RPP.boxit([istart+ij[0],jstart+ij[1]], dlon, dlat, 2)  for ij in indF]
+    cornersll = [proj.ijll(polyg) for polyg in Lpolyg]
+    centersll = [proj.ijll([[istart+ij[0],jstart+ij[1]]])[0] for ij in indF]
+    #
+    # Avoid that points have longitude or latitude exactly equal to zero
+    #
+    allon = [[p[0] if p[0]!=0 else 0.0000001 for p in polyll] for polyll in cornersll]
+    allat = [[p[1] if p[1]!=0 else 0.0000001 for p in polyll] for polyll in cornersll]
+    #
+    cornerspoly = [polygon.SphericalPolygon.from_lonlat(lons, lats, center=centll) for lons, lats, centll in zip(allon, allat, centersll)]
+    areas = [(sphpoly.area())*EarthRadius**2 for sphpoly in cornerspoly]
+    radiusll =[RPP.maxradius(centll, lons, lats) for centll, lons, lats in zip(centersll, allon, allat)]
     #
-    for ij in indF :
-        #
-        # Get the corners and mid-points of segments to completely describe the polygone
-        #
-        polyg = RPP.boxit([istart+ij[0],jstart+ij[1]], dlon, dlat, 2)
-        polyll=proj.ijll(polyg)
-        centll=proj.ijll([[istart+ij[0],jstart+ij[1]]])[0]
-        #
-        # Avoid that points have longitude or latitude exactly equal to zero
-        #
-        lons = [p[0] if p[0]!=0 else 0.0000001 for p in polyll]
-        lats = [p[1] if p[1]!=0 else 0.0000001 for p in polyll]
-        #
-        allon.append(lons)
-        allat.append(lats)
-        radiusll.append(RPP.maxradius(centll, lons, lats))
-        #
-        sphpoly=polygon.SphericalPolygon.from_lonlat(lons, lats, center=centll)
-        #
-        areas.append((sphpoly.area())*EarthRadius**2)
-        cornerspoly.append(sphpoly)
-        cornersll.append(polyll)
-        centersll.append(centll)
-
     box=[[np.min(np.array(allon)),np.max(np.array(allon))],[np.min(np.array(allat)),np.max(np.array(allat))]]
-    
+    # 
     return cornersll, cornerspoly, centersll, radiusll, areas, box
 #
 # Extract the coordinates of the grid file. If ni < 0 and nj < 0 then the
 # full grid is read.
 # 
-def getcoordinates(geo, istart, ni, jstart, nj) :
+def getcoordinates(geo, istart, ni, jstart, nj, res = False) :
     #
     # Guess the type of grid
     #
@@ -164,6 +137,8 @@ def getcoordinates(geo, istart, ni, jstart, nj) :
         #
         lon_full=np.copy(geo.variables["XLONG_M"][0,jstart:jstart+nj,istart:istart+ni])
         lat_full=np.copy(geo.variables["XLAT_M"][0,jstart:jstart+nj,istart:istart+ni])
+        return griddesc, lon_full, lat_full
+
     elif griddesc['type'] == "RegLonLat"  :
         # We have a regulat lat/lon grid
         nbi_g = geo.variables["lon"].shape[0]
@@ -184,15 +159,22 @@ def getcoordinates(geo, istart, ni, jstart, nj) :
         #
         # Extract grid
         #
+        res_lon = np.mean(np.gradient(geo.variables["lon"][:]))
+        res_lat = np.mean(np.gradient(geo.variables["lat"][:]))
+        #
         lon_full=np.tile(np.copy(geo.variables["lon"][istart:istart+ni]),(nj,1))
         griddesc['inilon'] = np.copy(geo.variables["lon"][0])
         lat_full=np.transpose(np.tile(np.copy(geo.variables["lat"][jstart:jstart+nj]),(ni,1)))
         griddesc['inilat'] = np.copy(geo.variables["lat"][0])
+        #
+        if res:
+           return griddesc, lon_full, lat_full, res_lon, res_lat
+        else:
+           return griddesc, lon_full, lat_full
+
     else :
         ERROR("Unknown grid type")
         sys.exit()
-    #
-    return griddesc, lon_full, lat_full
 #
 #
 #
@@ -227,11 +209,13 @@ def getland (geo, ist, ni, jst, nj) :
 #
 class ModelGrid :
     def __init__(self, istart, ni, jstart, nj) :
-        #
+        # Uncompatibility with Partition over Iberia_regular
+        """
         if ni < 2 or nj < 2 :
             INFO("Found impossibleDomain too small for ModelGrid to work : "+str(ni)+str(nj))
             ERROR("Domain too small")
             sys.exit()
+        """
         #
         self.source = config.get("OverAll", "ModelGridFile")
         geo=Dataset(self.source,'r')
@@ -244,17 +228,16 @@ class ModelGrid :
         #
         self.land = getland(geo, istart, ni, jstart, nj)
         ind=np.reshape(np.array(range(self.land.shape[0]*self.land.shape[1])),self.land.shape)
-        indFi=[]
-        indFj=[]
-        for j in range(nj) :
-            for i in range(ni) :
-                indFi.append([i+1])
-                indFj.append([j+1])
+        indFi=[[i+1] for j in range(nj) for i in range(ni)]
+        indFj=[[j+1] for j in range(nj) for i in range(ni)]
         #
         # Define some grid variables.
         #
-        self.res_lon = np.mean(np.gradient(self.lon_full, axis=1))
-        self.res_lat = np.mean(np.gradient(self.lat_full, axis=0))
+        if griddesc['type'] == "RegLonLat":
+            griddesc, self.lon_full, self.lat_full, self.res_lon, self.res_lat = getcoordinates(geo, istart, ni, jstart, nj, res = True)
+        else:
+            self.res_lon = np.mean(np.gradient(self.lon_full, axis=1))
+            self.res_lat = np.mean(np.gradient(self.lat_full, axis=0))
         self.nj,self.ni = self.lon_full.shape
         #
         # Gather all land points
@@ -290,7 +273,7 @@ class ModelGrid :
         #
         # Get the bounds of the grid boxes and region.
         #
-        self.polyll, self.polylist, self.centers, self.radius, self.area, self.box_land = corners(indF, proj, istart, jstart, self.lon_full, self.lat_full)
+        self.polyll, self.polylist, self.centers, self.radius, self.area, self.box_land = corners(indF, proj, istart, jstart, self.lon_full, self.lat_full, self.res_lon, self.res_lat)
         #
         self.box=[[np.min(self.lon_full),np.max(self.lon_full)],[np.min(self.lat_full),np.max(self.lat_full)]]
         #
@@ -412,7 +395,6 @@ class GlobalGrid :
 
         lonrange=np.array(config.get("OverAll", "WEST_EAST", fallback="-180., 180.").split(","),dtype=float)
         latrange=np.array(config.get("OverAll", "SOUTH_NORTH", fallback="-90., 90.").split(","),dtype=float)
-        
         self.source=config.get("OverAll", "ModelGridFile")
         INFO("Opening : "+self.source)
         geo=Dataset(self.source,'r')
@@ -427,10 +409,11 @@ class GlobalGrid :
             self.jgstart = 0
             self.igstart = 0
         else :
-            dist=np.sqrt((lon_full-min(lonrange))**2 + (lat_full-min(latrange))**2)
+            dist=np.sqrt(np.power(lon_full-np.min(lonrange),2) + np.power(lat_full-np.min(latrange),2))
             jmin,imin=np.unravel_index(np.argmin(dist, axis=None), dist.shape)
-            dist=np.sqrt((lon_full-max(lonrange))**2 + (lat_full-max(latrange))**2)
+            dist=np.sqrt(np.power(lon_full-np.max(lonrange),2) + np.power(lat_full-np.max(latrange),2))
             jmax,imax=np.unravel_index(np.argmin(dist, axis=None), dist.shape)
+
             self.nj = jmax-jmin+1
             self.jgstart = jmin
             self.ni = imax-imin+1
@@ -441,3 +424,4 @@ class GlobalGrid :
         self.nbland = int(np.sum(self.land))
         #
         geo.close()
+
diff --git a/RPPtools.py b/RPPtools.py
index 5f9bbac..3a5d694 100644
--- a/RPPtools.py
+++ b/RPPtools.py
@@ -122,12 +122,16 @@ class compweights :
         sub_area = []
         sub_lon = []
         sub_lat = []
+        nbpts = len(modelgrid.centers)
         #
         # Only compute the weights if the file does not exist.
         #
         if not os.path.exists(wfile) :
             INFO("Computing weights")
+            nbpts = len(modelgrid.centers)
+            i = 0
             for cell, center, radius, area in zip(modelgrid.polylist, modelgrid.centers, modelgrid.radius, modelgrid.area) :
+                t = time.time()
                 llinside=vector.vector_to_lonlat(cell.polygons[0].inside[0],cell.polygons[0].inside[1],cell.polygons[0].inside[2])
                 area_in=np.zeros((hydrogrid.jjm,hydrogrid.iim), dtype=float)
 
@@ -155,6 +159,12 @@ class compweights :
                 sub_area.append(np.extract(area_in > 0.0, area_in))
                 sub_lon.append(np.extract(area_in > 0.0, hydrogrid.lon))
                 sub_lat.append(np.extract(area_in > 0.0, hydrogrid.lat))
+                t1 = time.time()
+                i += 1
+                with open("./Weight_proc_{0}.txt".format(part.rank), "a") as foo:
+                    foo.write("Pt : {0} / {1};  time: {2} s.\n".format(i, nbpts, int(t1-t)))
+            with open("./Weight_proc_{0}.txt".format(part.rank), "a") as foo:
+                foo.write("Finished !\n")
             #
             # Save information in class variables.
             #
@@ -180,12 +190,16 @@ class compweights :
         else :
             #
             INFO("Reading weights from "+wfile)
+            with open("check.out","a+") as foo:
+               foo.write("Proc {0}, Start reading Weights from {1} points\n".format(part.rank,nbpts))
             t = time.time() 
             self.fetchweight(wfile, part, modelgrid, hydrogrid)
             self.hpts = [l.shape[0] for l in self.lon]
             self.maxhpts = max(self.hpts)
             t1 = time.time()
             INFO("Proc {0}, time : {1}".format(part.rank,round(t1-t,2 ))) 
+            with open("check.out","a+") as foo:
+               foo.write("Proc {0}, time : {1}\n".format(part.rank,round(t1-t,2 )))
             """
             for icell in range(len(self.lon)) :
                 INFO(str(icell)+" Sum of overlap "+str(np.sum(self.area[icell])/modelgrid.area[icell])+
@@ -212,6 +226,7 @@ class compweights :
         locinfile = [int(self.findinfile(pts, gindex)) for pts in landind]
         var = innf.variables["hydro_index"]
         self.hpts = [int(np.array(np.where(var[0,:,i]>= 0)).shape[1]) for i in locinfile ]
+        A = np.where(np.array(self.hpts) == 0)[0]
         t1 = time.time()
 
         if debug_time:INFO("Proc {0}, step 1, time : {1}".format(part.rank,round(t1-t,2 )))
@@ -228,6 +243,12 @@ class compweights :
         innf.close()
         # Find the indicis of the points on the HydroGrid using the coordinates.
         self.index = self.findhindex(hydrogrid)
+        for k in A:
+            if modelgrid.centers[k][1]<-60:
+                self.index[k] = np.array([[-1],[ -1]])
+                self.area[k] = np.array([modelgrid.area[k]])
+                self.lon[k] = np.array([modelgrid.centers[k][0]])
+                self.lat[k] = np.array([modelgrid.centers[k][1]])
         t3 = time.time()
         if debug_time: INFO("Proc {0}, step 3, time : {1}".format(part.rank,round(t3-t2,2 )))
         #
-- 
GitLab