Final version of code of gully erosion

From GeoMod

Jump to: navigation, search
from visual import *
from random import *
from SAREA_6_tmp import *
from visual.graph import *
import math



# Define parameters for creating the hypothetical topography
nx = 25
lx = 25.0
ny = 25
ly = 25.0

dx = lx/nx  # Width of each cell in x direction
dy = ly/ny  # Width of each cell in y direction

# creating land area as per the parameters defined
sourceArea = area (nx, ny, dx, dy)

# Defining general slope to the topography
sourceArea.slope(dydz=0.5)


tt  = 16 # Total number of times the code will execute 
while tt<>0:
    rate(1) # Specifying the slow down rate 
    sourceArea.update_topo() # To update the elevation of the topography
    
    sourceArea.catchment(tt) # To compute the lowest elevation cell in a array of 3x3

    sourceArea.watershed(tt) # To compute the watershed basin for all cells

    sourceArea.localSlope() # To compute the local slope for all cells
    
    sourceArea.sediTrans(tt) # To compute the sediment transport capacity of all cells

    sourceArea.eroht1() # To compute the erosion height from all cells

    sourceArea.chgele() # To substract the erosion height from original elevation value 

    sourceArea.diffusion() # To compute the diffusion for all the cells 

    if (tt == 1):
        
        sourceArea.newdisp(p=1) # To create the new display for the final topography 

        sourceArea.newdisp(p=0) # To create the new display for the total erosion from all cells

    tt= tt-1 

The code for class SAREA_6_tmp is as follows:

from visual import *
from random import *
from visual.graph import *

class area:
    '''This class will create a source area'''
    def __init__(self, nx, ny, dx, dy):
        self.nx=nx # Number of rows
        self.ny=ny # Number of columns
        self.dx=dx # Unit size in x direction
        self.dy=dy # Unit size in z direction
        self.xmin = 0 # The area starting from zero x cord
        self.ymax = nx*dx # The y cord is number of rows multiply by distance between two cells being top left corner as start of area
        self.Elev=zeros((nx,ny), Float) # Initializing the array for elevation of all cells before providing slope 
        self.ElevT=zeros((nx*ny), Float) # Initializing the array for initial elevation of all cells
        self.ElevS=zeros((nx,ny), Float) # Initializing the array for elevation of cells after providing slope
        self.initElevS = zeros((nx,ny), Float) # Initializing the array as the initial elevation of cells after providing slope

        self.land = [] # List for creating the different cells in the topography
        seed(1000) # To make sure that every time same random numbers will be called by the program
        for i in range(nx):
            for j in range(ny):
                self.land.append(box(length=dx, height=dy,  # Appending the cell 
                                     width = (uniform(0.1,.5)),
                                     color = (uniform(0.7,1),0.8,0.4)))
                                     #up=(0,1.5,-0.26)))
                self.land[-1].pos.z = self.land[-1].width / 2.0
                self.land[-1].x=i*dx
                self.land[-1].y=j*dy
                self.Elev[i,j] = self.land[-1].width
             
        print 'the elevation', self.Elev

        '''For better visual display changing the display characteristics'''
        scene.center = (self.dx * (self.nx/2), self.dy * (self.ny/2), 0)
        scene.forward = vector (1,0,0)
        scene.up = vector (0,0,1)
        scene.forward = vector(0,1,0)
        scene.up = vector(0,0,1)


    '''The following function is to provide slope to the flat topography'''    
    def slope(self, dxdz = 0, dydz = 0):
        k=0
        for i in self.land:
            de = dxdz * i.pos.x
            i.width = i.width + de
            de = dydz * i.pos.y
            i.width = i.width + de
            i.pos.z = i.width / 2.0
            self.ElevT[k] = i.width
            k=k+1
        hp=0
        for i in range(self.nx):
            for j in range(self.ny):
                self.ElevS[i,j] = self.ElevT[hp]
                self.initElevS [i,j]= self.ElevT[hp]
                hp=hp+1

        print 'The elevation after slope'
        print self.ElevS

            
    '''The following function is to give the value of number for given row and column'''
    def ij_number(self,r=0,c=0):
        Num = zeros((self.nx,self.ny))
        num = 0
        for i in range(self.nx):
            for j in range(self.ny):
                Num[i,j] = num
                num=num+1
        return Num[r,c]


    '''The following function is to give the i and j value if number of that cell is provided'''                
    def number_ij(self,number):
        T = number/self.nx
        print 'T', T
        if T <=1:
            i = 0
            j = number-1
        if (T > 1 and T <=2):
            i = 1
            j = number-self.nx-1
        if (T >2 and T<=3):
            i = 2
            j = number - 2*self.nx-1
        if (T >3 and T<=4):
            i=3
            j = number - 3*self.nx-1
        if (T >4 and T<=5):
            i = 4
            j = number -4*self.nx-1
        if (T>5 and T<=6):
            i=5
            j = number -5*self.nx-1
        if (T>6 and T<=7):
            i=6
            j = number -6*self.nx-1
        if (T>7 and T<=8):
            i=7
            j = number - 7*self.nx-1
        if (T>8 and T<=9):
            i=8
            j = number -8*self.nx-1
        if (T>9 and T<=10):
            i=9
            j = number - 9*self.nx-1
        print 'The i or Row is', i
        print 'The j or Column is', j

    '''The following function is to provide the x and y co-ordinate for given R and C'''
    def rc_xy(self,R,C):
        self.x=self.xmin+self.dx/2.0+((self.dx)*C)
        self.y=self.ymax-self.dx/2.0-((self.dx)*R)
        return self.x, self.y
        
    '''The following function is the subroutine for the function 'catchment' it calculates the
        lowest value in that array of pixels '''
    def LowRC(self): 
        Low = self.ElevS[self.PosR,self.PosC]
        self.PosRL = self.PosR
        self.PosCL = self.PosC
        temp =0
        for i in range(self.PosR-1,self.PosR+2):
            for j in range(self.PosC-1,self.PosC+2):
                if Low > self.ElevS[i,j]:
                     Low = self.ElevS[i,j]
                     self.PosRL = i
                     self.PosCL = j
                   
        return (self.PosRL, self.PosCL, Low)
        
    '''The following function is also the subroutine for the function 'catchment' it sends the array for 3x3
    surronding the given cell to function 'LowRC'''
    def LowTrace(self,r,c): # 
        self.PosR = r
        self.PosC = c
        (LowRow, LowCol, Low) = self.LowRC()
        self.cr_out[r,c] = self.ElevS[LowRow, LowCol]
        self.c_out[r,c] = LowCol
        self.r_out[r,c] = LowRow
        
    '''The following function is to calculate the stream network i.e., the water flow through the system'''
    def stream_network(self):
        for i in range(1,self.nx-1):
            for j in range(1,self.ny-1):
                tr = curve(color=(uniform(0.1,1),0.1,0.7), radius = 0.13)
                tmpr = i
                tmpc = j
                tr.append(pos=(i,j,self.ElevS[i,j]))

                while not(self.c_out[tmpr,tmpc] == tmpc and self.r_out[tmpr,tmpc] == tmpr):
                    tmpc2 = self.c_out[tmpr, tmpc]
                    tmpr2 = self.r_out[tmpr, tmpc]
                    tmpc = tmpc2
                    tmpr = tmpr2
                    if not (tmpr == 0 and tmpc == 0):
                        tr.append(pos=(tmpr,tmpc,self.ElevS[tmpr,tmpc]))


    '''The following function is to give the lowest elevation value adjacent to the given cell'''
    def catchment(self,tt):

        self.c_out = zeros((self.ny,self.nx))
        self.r_out = zeros((self.nx,self.ny))
        self.cr_out = zeros((self.nx,self.ny), Float)
        for i in range(1,self.nx-1):
            for j in range(1,self.ny-1):
                self.LowTrace(i,j)
        print 'self.c_out', self.c_out
        print 'self.r_out', self.r_out
        print 'self.cr_out', self.cr_out

  
    '''The following function calculates the watershed area i.e, number of the cells contributing to the given cell'''
    def watershed(self,tt):
        self.counter = ones((self.nx, self.ny))
       
        seed(1000)
        l_loop = 1
        while l_loop == 1:
            l_loop =0
            for i in range(1,self.nx-1):
                for j in range(1,self.ny-1):
                    temp = 1

                    for k in range(i-1,i+2):
                        for m in range(j-1,j+2):
                             if ((self.c_out[k,m] == j and self.r_out[k,m] == i) and not(k==i and m ==j)):
                                temp = temp +self.counter[k,m]
                    if temp <> self.counter[i,j]:
                        self.counter[i,j] = temp
                        l_loop = 1
                        (x,y) = self.rc_xy(i,j)
                                                    
        print 'The catchment watershed area of area is',
        print self.counter


    '''The following function calculates the local slope between the given cell and the lowest elevation cell'''    
    def localSlope(self):
        self.Slope = zeros((self.nx,self.ny), Float)
        for i in range(1,self.nx-1):
            for j in range(1,self.ny-1):
                self.Slope[i,j] = abs((self.cr_out[i,j]- self.ElevS[i,j])/self.dx)
                        
        print 'the local slope is',
        print self.Slope

    
    '''The following function calculates the sediment transport of all the cells'''        
    def sediTrans(self,tt):
####      '''The general sediment transport capacity is given as
####        Qs = (self.K* inv(self.ChiC)* self.ChiW* self.ChiT ^ self.P *
####              self.d ^ (1.5-self.P)* (1 - self.Tou* inv(self.ChiT) * (self.R*self.A)^ -self.MTou
####              * self.Slope^ -self.NTou) ^ self.P)* (self.R*self.A)^ -self.M * self.Slope^ -self.N'''

            
        self.Qs = zeros((self.nx, self.ny), Float)
        self.K = 20 # The calibration parameter
        self.g = 9.81 # Acceleration due to gravity
        self.P = 3 # Another calibration parameter
        self.D = 0.003 # dominant grain size
        self.TouCS = 0.045 # Dimensionless critical shear stress
        self.R = .035 # Runoff rate in mm/hr
        self.T = 0.25 # time for gully incision in hr
        self.s = 2.65 # quartz specific gravity
        self.RowW = 1000 # Water density
        self.MTou = 0.6 # Exponent m
        self.NTou = 0.8125 # Exponent n
        self.M = 2.1 # Exponent M
        self.N = 2.25 # Exponent N
        Ks = 1.73
        Kn = 0.08
        C = 0.346
        Ngc = 0.025

     
        self.Qs = zeros((self.nx, self.ny), Float)
        
        self.ChiC = pow (self.RowW,self.P) * pow((self.g* (self.s -1)), (self.P -0.5))
        
        self.TouC = self.TouCS * (self.s-1) * self.D * self.RowW * self.g

        self.ChiW = Ks*pow(Kn,0.375)*pow(C,-0.25)
        
        self.ChiT = self.RowW*self.g*pow(C,0.75)*pow(Kn,-1.13)*pow(Ngc,1.5)

        for i in range(1,self.nx-1):
            for j in range(1,self.ny-1):
                if ((self.counter[i,j] > 2) and (self.Slope[i,j] <> 0.0)):

                    self.A = self.counter[i,j]
                    self.Qs[i,j] = (self.K * (1/self.ChiC) * self.ChiW * pow(self.ChiT,self.P) * pow ( self.D, (1.5-self.P)) * pow((1 - self.TouC*(1/self.ChiT)* pow ((self.R * self.A), -self.MTou) * pow (self.Slope[i,j], -self.NTou)), self.P)) * pow ((self.R * self. A),self.M) * pow ((self.Slope[i,j]), self.N)
                    self.land[self.ij_number(i,j)].color = color.red
              
        print 'The sediment capacity of different cells are',
        print self.Qs
        
    '''The following function gives the erosion height of all cells depending upon the sediment capacity and time for gully incision'''        
    def eroht1(self):
        AreaC = self.dx * self.dy
        self.eroht = zeros((self.nx, self.ny), Float)
        for i in range(self.nx):
            for j in range(self.ny):
                self.eroht[i,j] = (self.Qs[i,j]/AreaC)*self.T
        print 'erosion height of all cells', self.eroht


    '''The following function computes the new elevation after substracting the erosion height'''                
    def chgele(self):
        self.ChgElv = zeros((self.nx, self.ny), Float)
        for i in range(1,self.nx-1):
            for j in range(1,self.ny-1):
                if self.eroht[i,j] > self.cr_out[i,j]:
                    self.eroht[i,j] = self.cr_out[i,j]
                    self.ChgElv[i,j] = self.ElevS[i,j]-self.eroht[i,j]
                else:
                    self.ChgElv[i,j] = self.ElevS[i,j]-self.eroht[i,j]
        print 'change elevation', self.ChgElv
        
        for i in range(1,self.nx-1):
            for j in range(1,self.ny-1):
                self.ElevS[i,j] = self.ChgElv[i,j]
        print 'final elev.',
        print self.ElevS
        

    '''The following function is diffusion equation for all the cells'''        
    def diffusion(self):
        '''Inflow is positive and outflow is negative'''
        self.Qinx = zeros((self.nx, self.ny), Float)
        self.Qoutx = zeros((self.nx, self.ny), Float)
        self.Qiny = zeros((self.nx, self.ny), Float)
        self.Qouty = zeros((self.nx, self.ny), Float)
        self.deltaV = zeros((self.nx, self.ny), Float)
        self.constant = .10
        self.temp = zeros((self.nx, self.ny), Float)
        
        for i in range(1, self.nx-1):
            for j in range(1, self.ny-1):
                self.Qinx[i,j] = self.constant* ((self.ElevS[i,j-1] - self.ElevS[i,j])/self.dx)
                self.Qoutx[i,j] = -self.constant* ((self.ElevS[i,j] - self.ElevS[i,j+1])/self.dx)
                self.Qiny[i,j] = self.constant* ((self.ElevS[i-1,j] - self.ElevS[i,j])/self.dx)
                self.Qouty[i,j] = -self.constant* ((self.ElevS[i,j] - self.ElevS[i+1,j])/self.dx)
        self.deltaV = self.Qinx + self.Qoutx + self.Qiny + self.Qouty
        print 'the deltaV', self.deltaV
        
        for i in range(1, self.nx-1):
            for j in range(1, self.ny-1):
                self.temp[i,j] = self.deltaV[i,j]/ (self.dx*self.dy)
                self.ElevS[i,j] = self.ElevS[i,j] + self.temp[i,j]
        print 'ele in diffusion'
        print self.ElevS

    '''The following function is to update the elevation of topography'''        
    def update_topo(self):
      
        for i in range(self.nx):
            for j in range(self.ny):
                self.land[self.ij_number(i,j)].width = self.ElevS[i,j]
                self.land[self.ij_number(i,j)].pos.z = self.land[self.ij_number(i,j)].width / 2.0
 
    '''The following function is to create new display for showing the final topography and erosion height '''       
    def newdisp(self,p):
        if p ==1:  # To show final eroded surface
            tp = self.ElevS
        else:  # To show the diff. in elevation
            tp = self.initElevS-self.ElevS

        dispa = display ( x =0, y = 0, width= 640,height = 480)
        for i in range(self.nx):
            for j in range(self.ny):
                self.land.append(box(length=self.dx, height=self.dy,
                                     width = (uniform(0.1,.5))))
                
                self.land[-1].x=i*self.dx
                self.land[-1].y=j*self.dy
                self.land[-1].width = tp[i,j]
                self.land[-1].pos.z = self.land[-1].width / 2.0
    
                if ((abs(self.temp[i,j]) > 0.09) and (p == 1)):

                   self.land[-1].color = color.blue
                
                if (p ==0):
                    if tp[i,j] > 0:
                        self.land[-1].color = color.green
                
        '''The following statements is for better display for the new display'''
        dispa.center = (self.dx * (self.nx/2), self.dy * (self.ny/2), 0)    
        dispa.forward = vector (1,0,0)
        dispa.up = vector (0,0,1)
        
        dispa.forward = vector(0,1,0)
        dispa.up = vector(0,0,1)

--Ekta2 15:34, 23 Nov 2005 (CST)

Personal tools