From eedd88162120cdace73c029c6ed2fd57b393ba5e Mon Sep 17 00:00:00 2001
From: Anthony <anthony.schrapffer@polytechnique.fr>
Date: Wed, 15 Apr 2020 13:56:04 +0200
Subject: [PATCH] Add the inflows information in dumpnetcdf and simplify the
 dumpnetcdf by using functions

---
 F90subroutines/routing_interface.f90 |  48 +++++++
 Interface.py                         | 191 +++++++++++----------------
 2 files changed, 128 insertions(+), 111 deletions(-)

diff --git a/F90subroutines/routing_interface.f90 b/F90subroutines/routing_interface.f90
index d9cef5e..c55e738 100644
--- a/F90subroutines/routing_interface.f90
+++ b/F90subroutines/routing_interface.f90
@@ -496,6 +496,54 @@ SUBROUTINE finish_truncate(nbpt, nbxmax_in, nbasmax, nwbas, num_largest, gridare
 END SUBROUTINE finish_truncate
 
 
+SUBROUTINE finish_inflows(nbpt,nbxmax_in, nbasmax, inf_max, basin_count, inflow_number, inflow_grid, inflow_basin,&
+       & route_innum, route_ingrid, route_inbasin)
+  !
+  USE ioipsl
+  USE grid
+  USE routing_tools
+  USE routing_reg
+  !
+  ! Arguments
+  !
+  INTEGER(i_std), INTENT (in) :: nbpt !! Domain size (unitless)
+  INTEGER(i_std), INTENT (in) :: nbxmax_in, nbasmax
+  INTEGER(i_std), INTENT (in) :: inf_max !!
+  !
+  INTEGER(i_std), DIMENSION(nbpt), INTENT(inout)       :: basin_count !!
+  INTEGER(i_std), DIMENSION(nbpt,nbxmax_in), INTENT(in)          :: inflow_number !!
+  INTEGER(i_std), DIMENSION(nbpt,nbxmax_in,inf_max), INTENT(in) :: inflow_basin !!
+  INTEGER(i_std), DIMENSION(nbpt,nbxmax_in,inf_max), INTENT(in) :: inflow_grid !!
+  !
+  REAL(r_std), DIMENSION(nbpt,nbasmax), INTENT(out)    :: route_innum
+  REAL(r_std), DIMENSION(nbpt,nbasmax,inf_max), INTENT(out)    :: route_ingrid
+  REAL(r_std), DIMENSION(nbpt,nbasmax,inf_max), INTENT(out)    :: route_inbasin
+  !
+  !
+  !
+  ! inflow_number -> route_innum
+  route_innum(:,:) = 0
+  DO ig=1,nbpt
+    nbas = basin_count(ig)
+    route_innum(ig,:nbas) = inflow_number(ig,:nbas)
+  END DO
+
+  ! inflow_grid -> route_ingrid
+  ! inflow_basin -> route_inbasin
+  route_ingrid(:,:,:) = 0
+  route_inbasin(:,:,:) = 0
+  DO ig=1,nbpt
+    nbas = basin_count(ig)
+    DO ib=1,nbas
+      nin = route_innum(ig,ib)
+      route_ingrid(ig,ib,:nin) = inflow_grid(ig,ib,:nin)
+      route_inbasin(ig,ib,:nin) = inflow_basin(ig,ib,:nin)
+    END DO
+  END DO
+
+END SUBROUTINE finish_inflows
+
+
 SUBROUTINE killbas(nbpt, nbxmax_in, nbasmax, nwbas,ops, tokill, totakeover, numops, basin_count, basin_area, &
      & basin_cg, basin_topoind, fetch_basin, basin_id, basin_coor, basin_type, basin_flowdir, outflow_grid, outflow_basin, &
      & inflow_number, inflow_grid, inflow_basin)
diff --git a/Interface.py b/Interface.py
index 827855a..66a9767 100644
--- a/Interface.py
+++ b/Interface.py
@@ -529,7 +529,35 @@ class HydroGraph :
         self.num_largest = routing_interface.finalrivclass(part.landcorelist, self.route_togrid, self.route_tobasin, self.routing_fetch, \
                       hydrosuper.largest_rivarea)
         #
+        # Inflows
+        self.max_inflow = part.domainmax(np.max(hydrosuper.inflow_number))
+        gingrid = part.l2glandindex( hydrosuper.inflow_grid[:,:,:self.max_inflow])
+        self.route_innum, self.route_ingrid, self.route_inbasin = routing_interface.finish_inflows(nbpt = self.nbpt, nbxmax_in = nbxmax_in, nbasmax = nbasmax, inf_max = self.max_inflow, basin_count = hydrosuper.basin_count, inflow_number = hydrosuper.inflow_number, inflow_grid = gingrid, inflow_basin = hydrosuper.inflow_basin[:,:,:self.max_inflow])
+
+
+    
         return
+
+    #
+    #
+    #
+    def add_variable(self,outnf, procgrid, NCFillValue, part, coord, name, title, units, data, vtyp, orig_type = "float"):
+        var = procgrid.landscatter(data.astype(vtyp), order='F')
+
+        if orig_type == "float":
+            var[np.isnan(var)] = NCFillValue
+        elif orig_type == "int":
+            var[var>=RPP.IntFillValue] = NCFillValue
+
+        if part.rank == 0:
+            ncvar = outnf.createVariable(name, vtyp, coord, fill_value=NCFillValue)
+            ncvar.title = title
+            ncvar.units = units
+        else :
+            ncvar = np.zeros((1,1,1))
+        ncvar[:] = part.gather(var)
+    #    
+    #
     #
     def dumpnetcdf(self, filename, globalgrid, procgrid, part) :
         #
@@ -546,14 +574,23 @@ class HydroGraph :
             outnf.createDimension('land', len(procgrid.area))
             outnf.createDimension('htu', self.nbasmax)
             outnf.createDimension('bnd', nbcorners)
+            outnf.createDimension('inflow', self.max_inflow)
         else :
             outnf = None
         #
         addcoordinates(outnf, globalgrid, procgrid, part, vtyp, NCFillValue, nbcorners, cornerind)
         addenvironment(outnf, procgrid, part, vtyp, NCFillValue, self.nbpt)
         #
-        # The field route_togrid is with indices on the local grid. That needs to be converted to the global grid.
+        # land grid index -> to facilitate the analyses of the routing
+        # 
+        nbpt_loc = np.zeros((self.nbpt,1)).astype(np.int32)
+        nbpt_loc[:,0] = np.arange(1, self.nbpt+1)
+        nbpt_glo = part.l2glandindex(nbpt_loc)
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('y','x'), "nbpt_glo", "Grid point Global", "-", nbpt_glo[:,0], vtyp)
         #
+        ################
+        # 
+        # TEST: l2glandindex
         itarget=-1
         for il in range(procgrid.nbland) :
             lo = procgrid.lon_full[procgrid.indP[il][0],procgrid.indP[il][1]]
@@ -564,130 +601,62 @@ class HydroGraph :
                 
         if itarget >+ 0 :
             print(part.rank, itarget, " Before route_togrid = ", self.route_togrid[itarget,:])
+        # Conversion 
         grgrid = part.l2glandindex(self.route_togrid[:,:])
         if itarget >+ 0 :
             print(part.rank, itarget, " After route_togrid = ", self.route_togrid[itarget,:])
-        rgrid = procgrid.landscatter(grgrid.astype(vtyp), order='F')
-        rgrid[rgrid >= RPP.IntFillValue] = NCFillValue
-        if part.rank == 0 :
-            routetogrid = outnf.createVariable("routetogrid", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            routetogrid.title = "Grid into which the basin flows"
-            routetogrid.units = "-"
-        else :
-            routetogrid = np.zeros((1,1,1))    
-        routetogrid[:,:,:] = part.gather(rgrid)
-        #
-        rtobasin = procgrid.landscatter(self.route_tobasin[:,:].astype(vtyp), order='F')
-        rtobasin = rtobasin.astype(vtyp, copy=False)
-        rtobasin[rtobasin >= RPP.IntFillValue] = NCFillValue
-        if part.rank == 0 :
-            routetobasin = outnf.createVariable("routetobasin", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            routetobasin.title = "Basin in to which the water goes"
-            routetobasin.units = "-"
-        else :
-            routetobasin = np.zeros((1,1,1))
-        routetobasin[:,:,:] = part.gather(rtobasin)
-        #
-        rid = procgrid.landscatter(self.global_basinid[:,:].astype(vtyp), order='F')
-        rid[rid >= RPP.IntFillValue] = NCFillValue
-        if part.rank == 0 :                           
-            basinid = outnf.createVariable("basinid", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            basinid.title = "ID of basin"
-            basinid.units = "-"
-        else :
-            basinid = np.zeros((1,1,1))
-        basinid[:,:,:] = part.gather(rid)
-        #
-        rintobas = procgrid.landscatter(self.route_nbintobas[:].astype(vtyp))
-        rintobas[rintobas >= RPP.IntFillValue] = NCFillValue
-        if part.rank == 0 : 
-            routenbintobas = outnf.createVariable("routenbintobas", vtyp, ('y','x'), fill_value=NCFillValue)
-            routenbintobas.title = "Number of basin into current one"
-            routenbintobas.units = "-"
-        else :
-            routenbintobas = np.zeros((1,1))
-        routenbintobas[:,:] = part.gather(rintobas)
-        #
-        onbintobas = procgrid.landscatter(self.origin_nbintobas[:].astype(vtyp))
-        onbintobas[onbintobas >= RPP.IntFillValue] = NCFillValue
-        if part.rank == 0 :
-            originnbintobas = outnf.createVariable("originnbintobas", vtyp, ('y','x'), fill_value=NCFillValue)
-            originnbintobas.title = "Number of sub-grid basin into current one before truncation"
-            originnbintobas.units = "-"
-        else :
-            originnbintobas = np.zeros((1,1))
-        originnbintobas[:,:] = part.gather(onbintobas)
+        ################
+        #
+        # The field route_togrid is with indices on the local grid. That needs to be converted to the global grid.        
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu', 'y','x'), "routetogrid", "Grid into which the basin flows", "-", grgrid, vtyp, "int")
+        # route to basin
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu', 'y','x'), "routetobasin", "Basin in to which the water goes", "-", self.route_tobasin[:,:], vtyp, "int")
+        # basin id
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu', 'y','x'), "basinid", "ID of basin", "-", self.global_basinid[:,:], vtyp, "int")
+        #
+        # basin area
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu', 'y','x'), "basin_area", "area of basin", "m^2", self.routing_area[:,:], vtyp, "float")
+        # route number into basin
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('y','x'), "routenbintobas", "Number of basin into current one", "-", self.route_nbintobas[:], vtyp, "int")
+        # 
+        # original number into basin
+        self.add_variable(outnf, procgrid, NCFillValue, part, ( 'y','x'), "originnbintobas", "Number of sub-grid basin into current one before truncation", "-", self.origin_nbintobas[:], vtyp, "int")
+        # 
+        # latitude of outlet
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "outletlat", "Latitude of Outlet", "degrees north", self.route_outlet[:,:,0], vtyp, "float")
+        # longitude of outlet
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "outletlon", "Longitude of Outlet", "degrees east", self.route_outlet[:,:,1], vtyp, "float")
+        # type of outlet
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "outlettype", "Type of outlet", "code", self.route_type[:,:], vtyp, "float")   
         #
-        olat = procgrid.landscatter(self.route_outlet[:,:,0].astype(vtyp), order='F')
-        olat[np.isnan(olat)] = NCFillValue
-        if part.rank == 0 :
-            outletlat = outnf.createVariable("outletlat", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            outletlat.title = "Latitude of Outlet"
-            outletlat.title = "degrees north"
-        else :
-            outletlat = np.zeros((1,1,1))
-        outletlat[:,:,:] = part.gather(olat)
+        # topographic index
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "topoindex", "Topographic index of the retention time", "m", self.topo_resid[:,:], vtyp, "float")
         #
-        olon = procgrid.landscatter(self.route_outlet[:,:,1].astype(vtyp), order='F')
-        olon[np.isnan(olon)] = NCFillValue
-        if part.rank == 0 :
-            outletlon = outnf.createVariable("outletlon", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            outletlon.title = "Longitude of outlet"
-            outletlon.units = "degrees east"
-        else :
-            outletlon = np.zeros((1,1,1))
-        outletlon[:,:,:] = part.gather(olon)
+        
+        # Inflow number
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "route_innum", "Number of inflow", "-", self.route_innum[:,:], vtyp, "int")
         #
-        otype = procgrid.landscatter(self.route_type[:,:].astype(vtyp), order='F')
-        otype[np.isnan(otype)] = NCFillValue
-        if part.rank == 0 :
-            outlettype = outnf.createVariable("outlettype", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            outlettype.title = "Type of outlet"
-            outlettype.units = "code"
-        else :
-            outlettype = np.zeros((1,1,1))
-        outlettype[:,:,:] = part.gather(otype)
+        # Inflow grid
+        #gingrid = part.l2glandindex(self.inflow_grid[:,:,:inflow_size])
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('inflow', 'htu','y','x'), "route_ingrid", "Grid from which the water flows", "-", self.route_ingrid[:,:,:], vtyp, "int")
         #
-        tind = procgrid.landscatter(self.topo_resid[:,:].astype(vtyp), order='F')
-        tind[np.isnan(tind)] = NCFillValue
-        if part.rank == 0 :
-            topoindex = outnf.createVariable("topoindex", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            topoindex.title = "Topographic index of the retention time"
-            topoindex.units = "m"
-        else :
-            topoindex = np.zeros((1,1,1))
-        topoindex[:,:,:] = part.gather(tind)
+        # Inflow basin
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('inflow', 'htu','y','x'), "route_inbasin", "Basin from which the water flows", "-", self.route_inbasin[:,:,:], vtyp, "int")
+        
         #
         # Save centre of gravity of HTU
         #
-        cg = procgrid.landscatter(self.routing_cg[:,:,:].astype(vtyp), order='F')
-        cg[np.isnan(cg)] = NCFillValue
-        if part.rank == 0 :
-            CG_lon = outnf.createVariable("CG_lon", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            CG_lon.title = "Longitude of centre of gravity of HTU"
-            CG_lon.units = "degrees east"
-            CG_lat = outnf.createVariable("CG_lat", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            CG_lat.title = "Latitude of centre of gravity of HTU"
-            CG_lat.units = "degrees north"
-        else :
-            CG_lon = np.zeros((1,1,1))
-            CG_lat = np.zeros((1,1,1))
-        CG_lon[:,:,:] = part.gather(cg[1,:,:,:])
-        CG_lat[:,:,:] = part.gather(cg[0,:,:,:])
+        # Check if it works
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "CG_lon", "Longitude of centre of gravity of HTU", "degrees east", self.routing_cg[:,:,1], vtyp, "float")
+ 
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "CG_lat", "Latitude of centre of gravity of HTU", "degrees north", self.routing_cg[:,:,0], vtyp, "float") 
         #
         # Save the fetch of each basin
         #
-        fe =  procgrid.landscatter(self.routing_fetch[:,:].astype(vtyp), order='F')
-        fe[np.isnan(fe)] = NCFillValue
-        if part.rank == 0 :
-            fetch = outnf.createVariable("fetch", vtyp, ('htu','y','x'), fill_value=NCFillValue)
-            fetch.title = "Fetch contributing to each HTU"
-            fetch.units = "m^2"
-        else :
-            fetch = np.zeros((1,1,1))
-        fetch[:,:,:] = part.gather(fe)
+        self.add_variable(outnf, procgrid, NCFillValue, part, ('htu','y','x'), "fetch", "Fetch contributing to each HTU", "m^2", self.routing_fetch[:,:], vtyp, "float")
         #
-        if part.rank == 0 :
+        # Close the file
+        if part.rank == 0:
             outnf.close()
         #
         return
-- 
GitLab