• Tidak ada hasil yang ditemukan

8.5 Numerical Implementation

8.5.1 Main

The main filemain.pycontains the calls to the other filePSP_infiltration1D.py, where the solvers for the numerical solution are implemented. This file (described be- low) calls the file used to build the grid (PSP_grid.py) and the file where the soil data structure is implemented (PSP_soil.py).The soil hydraulic parameters are saved in the file soil.txt, which are the parameters for the Campbell, van Genuchten and modified van Genuchten equations. The filesoil.txtis organized in rows and col- umns. Each row corresponds to a soil layer, while the data organized by columns are the soil hydraulic function parameters (the reader should open the file to see how it is struc- tured). In this example, the soil is homogenous and therefore there is only one layer of 1 m depth. However, in the following chapters, numerical solutions for layered soils will also be presented, and the file will have multiple rows, each corresponding to a soil layer.

The selection of the models, printed to the screen, are prompted to the user for se- lection of the hydraulic properties model. The user is asked to select the lower boundary condition, free drainage or constant potential, and the total length of the simulation.

Then the results are plotted and cumulative time, incremental time step, number of iterations per time step and cumulative infiltration are printed.

An example of the iterative prompt is shown below. First the user is asked to select the hydraulic function, in this case the Campbell formulation, and then to select the nu- merical scheme (in this case cell-centred finite volume). The initial degree of saturation of the soil profile is 0.3. The lower boundary condition is free drainage and the number of simulation hours is 5 h.

1 Campbell

2 van Genuchten with m = 1-1/n restriction 3 van Genuchten modified

Select water retention curve: 1 1 Cell-Centered Finite Volume

2 Matric Potential with Newton-Raphson 3 Matric Flux Potential with Newton-Raphson Select solver: 1

Initial degree of saturation ]0-1]: 0.3 1: Free drainage

2: Constant water potential Select lower boundary condition:1 Nr of simulation hours: 5

Numerical Implementation 183 The three numerical schemes were described above. The upper boundary condition is a constant-potential boundary condition. The model also allows for setting up other upper boundary conditions, such as atmospheric boundaries, which are simulated by applying either a prescribed water potential or a prescribed flux. The implementation of atmospheric boundary conditions will be presented in Chapter 15. The lower boundary condition can be chosen as free drainage or constant water potential. The free-drainage boundary condition is a unit vertical water potential gradient boundary condition that can be implemented in the form of a variable-flux boundary condition. The constant potential corresponds to setting the last node at a fixed value of water potential. The program is as follows:

#PSP_main.py from _

˙_future_ _ import print_function, division import matplotlib.pyplot as plt

import PSP_infiltration1D as inf def main():

isSuccess, soil = inf.readSoil("soil.txt") if not isSuccess:

print("warning: wrong soil file.") return

print (inf.CAMPBELL,’ Campbell’)

print (inf.RESTRICTED_VG,’ van Genuchten with m = 1-1/n restriction’)

print (inf.IPPISCH_VG,’ Ippisch-van Genuchten’)

funcType = int(input("Select water retention curve: ")) if (funcType == inf.CAMPBELL):

print()

print (inf.CELL_CENT_FIN_VOL,’ Cell-Centered Finite Volume’) print (inf.NEWTON_RAPHSON_MP,’ Matric Potential with

Newton-Raphson’)

print (inf.NEWTON_RAPHSON_MFP,’ Matric Flux Potential with Newton-Raphson’)

solver = int(input("Select solver: ")) else:

solver = inf.CELL_CENT_FIN_VOL

myStr = "]" + format(soil.VG_thetaR, ’.2f’) myStr += ", " + format(soil.thetaS, ’.2f’) myStr += "] initial water content (m^3 m^-3):"

thetaIni = inf.NODATA print()

while ((thetaIni <= soil.VG_thetaR) or (thetaIni > soil.thetaS)):

thetaIni = float(input(myStr))

184 Transient Water Flow

inf.initializeWater(funcType, soil, thetaIni, solver)

# [J kg^-1] upper boundary condition

ubPotential = inf.airEntryPotential(funcType, soil) print()

print ("1: Free drainage")

print ("2: Constant water potential")

boundary = int(input("Select lower boundary condition:")) if (boundary == 1):

isFreeDrainage = True else:

isFreeDrainage = False

# hours of simulation

simulationLenght = int(input("\nNr of simulation hours:")) endTime = simulationLenght * 3600

maxTimeStep = 600 dt = maxTimeStep / 10 time = 0

sumInfiltration = 0 totalIterationNr = 0 plt.ion()

f, myPlot = plt.subplots(2, figsize=(8, 8), dpi=80) myPlot[0].set_xlim(0, 0.5)

myPlot[1].set_xlim(0, simulationLenght * 3600)

myPlot[1].set_ylabel("Infiltration Rate [kg m$^{-2}$ s$^{-1}$]") myPlot[1].set_xlabel("Time [s]")

while (time < endTime):

dt = min(dt, endTime - time)

if (solver == inf.CELL_CENT_FIN_VOL):

success, nrIterations, flux = inf.cellCentFiniteVolWater (funcType, soil, dt, ubPotential, isFreeDrainage, inf.LOGARITHMIC)

elif (solver == inf.NEWTON_RAPHSON_MP):

success, nrIterations, flux = inf.NewtonRapsonMP(funcType, soil, dt, ubPotential, isFreeDrainage)

elif (solver == inf.NEWTON_RAPHSON_MFP):

success, nrIterations, flux = inf.NewtonRapsonMFP(funcType, soil, dt, ubPotential, isFreeDrainage)

totalIterationNr += nrIterations if success:

for i in range(inf.n+1):

Numerical Implementation 185 inf.oldTheta[i] = inf.theta[i]

sumInfiltration += flux * dt time += dt

print("time =", int(time), "\tdt =", int(dt),

"\tIter. =", int(nrIterations),

"\tInf:", format(sumInfiltration, ’.3f’)) myPlot[0].clear()

myPlot[0].set_xlim(0, 0.5)

myPlot[0].set_xlabel("Water content [m$^3$ m$^{-3}$]") myPlot[0].set_ylabel("Depth [m]")

myPlot[0].plot(inf.theta, -inf.z, ’r-’) myPlot[0].plot(inf.theta, -inf.z, ’yo’) myPlot[1].plot(time, flux, ’ro’)

plt.draw()

if (float(nrIterations/inf.maxNrIterations) < 0.25):

dt = min(dt*2, maxTimeStep) else:

dt = max(dt / 2, 1) for i in range(inf.n+1):

inf.theta[i] = inf.oldTheta[i]

if (solver == inf.NEWTON_RAPHSON_MFP):

inf.psi[i] = inf.MFPFromTheta(soil, inf.theta[i]) else:

inf.psi[i] = inf.waterPotential(funcType, soil, inf.theta[i]) print ("dt =", dt, "No convergence")

print("nr of iterations per hour:", totalIterationNr / simulationLenght)

plt.ioff() plt.show() main()

The algorithm has an adaptive time step. If the ratio between the number of iterations and the maximum number of iterations is less than 0.25, then the selected time step is the minimum value between 2tand the maximum time step. Otherwise, the time step is the maximum value betweendt/2 and 1. The algorithm also has the option of using a linear or a geometric grid, which is generated by the same functions used for solution of gas flow in Chapter 3. The filePSP_grid.pycontains the algorithm.