def __init__(self,
                 nx=100,
                 ny=100,
                 value_left=1.,
                 value_right=0.,
                 value_top=0.,
                 value_bottom=0.,
                 q=None):
        """
        ::param nx:: Number of cells in the x direction.
        ::param ny:: Number of cells in the y direction.
        ::param value_left:: Boundary condition on the left face.
        ::param value_right:: Boundary condition on the right face.
        ::param value_top:: Boundary condition on the top face.
        ::param value_bottom:: Boundary condition on the bottom face.
        ::param q:: Source function. 
        """
        #set domain dimensions
        self.nx = nx
        self.ny = ny
        self.dx = 1. / nx
        self.dy = 1. / ny

        #define mesh
        self.mesh = fipy.Grid2D(nx=self.nx, ny=self.ny, dx=self.dx, dy=self.dy)

        #get the location of the middle of the domain
        #cellcenters=np.array(self.mesh.cellCenters).T
        #x=cellcenters[:, 0]
        #y=cellcenters[:, 1]
        x, y = self.mesh.cellCenters
        x_all = x[:self.nx]
        y_all = y[0:-1:self.ny]
        loc1 = x_all[(self.nx - 1) / 2]
        loc2 = y_all[(self.ny - 1) / 2]
        self.loc = np.intersect1d(
            np.where(x == loc1)[0],
            np.where(y == loc2)[0])[0]

        #get facecenters
        X, Y = self.mesh.faceCenters

        #define cell and face variables
        self.phi = fipy.CellVariable(name='$T(x)$', mesh=self.mesh, value=1.)
        self.C = fipy.CellVariable(name='$C(x)$', mesh=self.mesh, value=1.)
        self.source = fipy.CellVariable(name='$f(x)$',
                                        mesh=self.mesh,
                                        value=0.)

        #apply boundary conditions
        #dirichet
        self.phi.constrain(value_left, self.mesh.facesLeft)
        self.phi.constrain(value_right, self.mesh.facesRight)

        #homogeneous Neumann
        self.phi.faceGrad.constrain(value_top, self.mesh.facesTop)
        self.phi.faceGrad.constrain(value_bottom, self.mesh.facesBottom)

        #setup the diffusion problem
        self.eq = -fipy.DiffusionTerm(coeff=self.C) == self.source
Beispiel #2
0
def mesh_and_boundaries(params):
    """Generate a 2D grid appropriate for the parameters

    """
    def fn(f, N):
        '''Root solving kernel for compression factor
        
        Determine f(N), such that $\Delta x \sum_{i=0}^N f^i = 2 \Delta x$
        '''
        return (1 - f**N) / (1 - f) - 2.

    N = 1 + params["compression"]
    compression = fsolve(fn, x0=[.5], args=(N))[0]

    dx = dy = params["cellSize"]
    Nx = int(params["Lx"] / dx)
    Ny = int(params["Ly"] / dx)
    dx_variable = [dx] * (Nx - 2) + [dx * compression**i for i in range(N)]

    dy_variable = [dy] * Ny

    mesh = fp.Grid2D(dx=dx_variable, dy=dy_variable)

    X, Y = mesh.faceCenters

    inlet = mesh.facesLeft
    outlet = mesh.facesRight
    walls = mesh.facesTop | mesh.facesBottom
    top_right = outlet & (Y > params["Ly"] - dy)

    return mesh, inlet, outlet, walls, top_right
Beispiel #3
0
 def _eval(self, xs):
     """
     Solves the advection equation for u and its derivatives for a given 
     source location xs. 
     """
     xs = view_as_column(xs)
     assert xs.shape[0] == 2
     nx = 50
     ny = nx
     dx = 0.1
     dy = dx
     mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
     vx, vy = make_V_field(mesh)
     u = f(xs[:, 0], mesh, vx, vy)
     du1 = df(xs[:, 0], mesh, vx, vy, 1)
     du2 = df(xs[:, 0], mesh, vx, vy, 2)
     d2u11 = df2(xs[:, 0], mesh, vx, vy, 1, 1)
     d2u22 = df2(xs[:, 0], mesh, vx, vy, 1, 1)
     d2u12 = df2(xs[:, 0], mesh, vx, vy, 1, 2)
     dU = np.hstack([view_as_column(du1), view_as_column(du2)])
     d2U = np.hstack([
         view_as_column(d2u11),
         view_as_column(d2u12),
         view_as_column(d2u12),
         view_as_column(d2u22)
     ])
     d2U = d2U.reshape((d2U.shape[0], 2, 2))
     state = {}
     state['f'] = u  #view_as_column(u)
     state['f_grad'] = dU
     state['f_grad_2'] = d2U
     return state
Beispiel #4
0
def main():
    """
	NAME		2DFPE.py
	
	PURPOSE		Integrate time-dependent FPE
	
	EXECUTION	python 2DFPE.py
	
	STARTED		CS 24/09/2015
	"""

    nx = 20
    ny = nx
    dx = 1.
    dy = dx
    L = dx * nx
    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
    y = np.linspace(-ny * dy * 0.5, +ny * dy * 0.5, ny,
                    endpoint=True)[:, np.newaxis]
    X, Y = mesh.faceCenters

    ## phi is pdf; psi is y*pdf for convenience
    phi = fp.CellVariable(mesh=mesh, value=1 / (dx * nx * dy * ny))
    psi = fp.CellVariable(mesh=mesh,
                          value=(y * phi.value.reshape((nx, ny))).flatten())

    diffCoeff = 1.
    diffMatri = [[0., 0.], [0., diffCoeff]]
    convCoeff = np.array([-1., +1.])
    eq = fp.TransientTerm(var=phi) == fp.DiffusionTerm(
        coeff=[diffMatri],
        var=phi) + 0 * fp.ExponentialConvectionTerm(coeff=convCoeff, var=psi)

    ##---------------------------------------------------------------------------------------------------------
    ## BCs
    phi = BC_value_at_boundary(phi, mesh)

    ## Evolution
    timeStepDuration = 0.5 * min(dy**2 / (2. * diffCoeff), dy / (nx * dx))
    steps = 10
    for step in range(steps):
        print np.trapz(np.trapz(phi.value.reshape([nx, ny]), dx=dx), dx=dy)
        psi.value = (y * phi.value.reshape((nx, ny))).flatten()
        eq.solve(var=phi, dt=timeStepDuration)
        print phi.value[5]

    # plot_pdf(phi.value.reshape([nx,ny]),step+1)
    plt.contourf(phi.value.reshape([nx, ny]), extent=(-1, 1, -1, 1))
    plt.colorbar()
    plt.title("Density at timestep " + str(steps))
    plt.xlabel("$x$", fontsize=18)
    plt.ylabel("$\eta$", fontsize=18)
    plt.savefig("fig_FPE/Imp" + str(steps) + ".png")
    plt.show()

    return
Beispiel #5
0
def forward(xs):

    nx = 21
    ny = nx
    dx = 1. / 51
    dy = dx
    rho = 0.05
    q0 = 1. / (np.pi * rho**2)
    T = 0.3
    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)

    time = fp.Variable()
    sourceTerm_1 = fp.CellVariable(name="Source term", mesh=mesh, value=0.)

    for i in range(sourceTerm_1().shape[0]):
        sourceTerm_1()[i] = q0 * np.exp(-(
            (mesh.cellCenters[0]()[i] - xs[0])**2 +
            (mesh.cellCenters[1]()[i] - xs[1])**2) /
                                        (2 * rho**2)) * (time() < T)

    # The equation
    eq = fp.TransientTerm() == fp.DiffusionTerm(
        coeff=1.) + sourceTerm_1  # + sourceTerm_2

    # The solution variable
    phi = fp.CellVariable(name="Concentration", mesh=mesh, value=0.)

    #if __name__ == '__main__':
    #    viewer = fp.Viewer(vars=phi, datamin=0., datamax=3.)
    #    viewer.plot()

    x = np.arange(0, nx) / nx
    y = x

    data = []
    dt = 0.005
    steps = 60
    for step in range(steps):
        time.setValue(time() + dt)
        eq.solve(var=phi, dt=dt)
        #if __name__ == '__main__':
        #    viewer.plot()
        #if step == 14 or step == 29 or step == 44 or  step == 59:
        #    dl = phi()[0]
        #    dr = phi()[nx-1]
        #    ul = phi()[nx**2 - nx]
        #    ur = phi()[nx**2 - 1]
        #    print phi().shape
        #    data = np.hstack([data, np.array([dl, dr, ul, ur])])

    #if __name__ == '__main__':
    #    raw_input("Transient diffusion with source term. Press <return> to proceed")

    return phi().reshape(nx, nx)
 def _eval_u(self, xs):
     """
     Solves only the diffusion equation for u for a given 
     source location xs. 
     """
     xs = view_as_column(xs)
     assert xs.shape[0] == 2
     nx = 25
     ny = nx
     dx = 0.04
     dy = dx
     mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
     u = f(xs[:,0], mesh)
     return u
Beispiel #7
0
 def initialise_mesh(self):
     if self.has_obstacles():
         self.mesh = make_porous_mesh(self.rc, self.Rc, self.dx, self.L)
     elif self.dim == 1:
         self.mesh = fipy.Grid1D(Lx=self.L[0],
                                 dx=self.dx[0],
                                 origin=(-self.L[0] / 2.0, ))
     elif self.dim == 2:
         self.mesh = fipy.Grid2D(Lx=self.L[0],
                                 Ly=self.L[1],
                                 dx=self.dx[0],
                                 dy=self.dx[1],
                                 origin=((-self.L[0] / 2.0, ),
                                         (-self.L[1] / 2.0, )))
Beispiel #8
0
def get_mesh(params):
    """Create the mesh

    Args:
      params: the parameter dict

    Returns:
      the fipy mesh
    """
    return pipe(
        fp.Grid2D(Lx=params["lx"],
                  Ly=params["lx"],
                  nx=params["nx"],
                  ny=params["nx"]),
        lambda x: x - np.array(
            (params["lx"] / 2., params["lx"] / 2.))[:, None],
    )
def df2(xs, mesh, i, j):
    """
    Evaluate the model for the 2nd derivatives at the four corners of the domain
    at times ``t``.

    It returns a flatten version of the system, i.e.:
    y_1(t_1)
    ...
    y_4(t_1)
    ...
    y_1(t_4)
    ...
    y_4(t_4)
    """
    assert i == 1 or i == 2
    assert j == 1 or j == 2
    nx = 25
    ny = nx
    dx = 0.04
    dy = dx
    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
    time = fp.Variable()
    q0 = make_source_der_2(xs, mesh, time, i, j)
    D = 1.
    # Define the equation
    eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=D) + q0
    # Boundary conditions

    # The solution variable
    phi = fp.CellVariable(name="Concentraion", mesh=mesh, value=0.)

    # Solve
    dt = 0.005
    steps = 60
    d2U = []
    for step in range(steps):
        eq.solve(var=phi, dt=dt)
        if step == 14 or step == 29 or step == 44 or step == 59:
            dl = phi()[0]
            #dr = phi()[24]
            ul = phi()[600]
            #ur = phi()[624]
            #d2U = np.hstack([d2U, np.array([dl, dr, ul, ur])])
            d2U = np.hstack([d2U, np.array([dl, ul])])

    return d2U
Beispiel #10
0
    '''Root solving kernel for compression factor
    
    Determine f(N), such that $\Delta x \sum_{i=0}^N f^i = 2 \Delta x$
    '''
    return (1 - f**N) / (1 - f) - 2.
    
N = 1 + args.compression
compression = fsolve(fn, x0=[.5], args=(N))[0]

Nx = int(Lx / dx)
Ny = int(Ly / dy)
dx_variable = [dx] * (Nx - 2) + [dx * compression**i for i in range(N+1)]

dy_variable = [dy] * Ny

mesh = fp.Grid2D(dx=dx_variable, dy=dy_variable)
volumes = fp.CellVariable(mesh=mesh, value=mesh.cellVolumes)

pressure = fp.CellVariable(mesh=mesh, name="$p$")
pressureCorrection = fp.CellVariable(mesh=mesh, name="$p'$")
xVelocity = fp.CellVariable(mesh=mesh, name="$u_x$")
yVelocity = fp.CellVariable(mesh=mesh, name="$u_y$")

velocity = fp.FaceVariable(mesh=mesh, name=r"$\vec{u}$", rank=1)

xVelocityEq = fp.DiffusionTerm(coeff=viscosity) - pressure.grad.dot([1.,0.]) + density * gravity[0]
yVelocityEq = fp.DiffusionTerm(coeff=viscosity) - pressure.grad.dot([0.,1.]) + density * gravity[1]

ap = fp.CellVariable(mesh=mesh, value=1.)
coeff = 1./ ap.arithmeticFaceValue*mesh._faceAreas * mesh._cellDistances
pressureCorrectionEq = fp.DiffusionTerm(coeff=coeff) - velocity.divergence
Beispiel #11
0
    os.makedirs(pathStr + 'ForwardEvo/')
if (not os.path.exists(pathStr + 'ReverseEvoUnupdated/')):
    os.makedirs(pathStr + 'ReverseEvoUnupdated/')
if (not os.path.exists(pathStr + 'ReverseEvoUpdated/')):
    os.makedirs(pathStr + 'ReverseEvoUpdated/')

# Initialize phase-space lattice
# Nx, Dx, XMax, Np, Dp, PMax, and Mesh are Global
Nx = n1 * n2
Np = Nx
Dx = 1. / n1
Dp = Dx
XMax = Dx * Nx
PMax = Dp * Np
comm = fipy.tools.serial
Mesh = fipy.Grid2D(dx=Dx, dy=Dp, nx=2*Nx, ny=2*Np, communicator=comm)\
                + [[-XMax], [-PMax]]
fipy.dump.write(Mesh, filename=pathStr + 'mesh.gz')

# Create and save initial distribution
phi = distributionInitial()
phiInitial = fipy.CellVariable(mesh=Mesh, name=r"\LARGE $\rho_{0}(x,p)$")
phiInitial.setValue(phi.value)
del phi
if (saveResults):
    fipy.tools.dump.write(phiInitial, \
                                filename=pathStr+'initialDistribution.gz')

# Plot initial distribution
genPlots(phiInitial, tStart, saveResults, 'initialDistribution.pdf', pathStr)
import fipy as fp
import glob
import json
import numpy as np
import os
import sys
from fipy.solvers.pysparse import LinearLUSolver as Solver

problem = '1'
domain = 'b'
nx = 200
dx = 1.0

# The first step in implementing any problem in FiPy is to define the mesh. For [Problem 1b]({{ site.baseurl }}/hackathon1/#a.-Square-Periodic) the solution domain is just a square domain with fixed boundary conditions, so a `Grid2D` object is used. No other boundary conditions are required.

mesh = fp.Grid2D(nx=nx, ny=nx, dx=dx, dy=dx)

# The next step is to define the parameters and create a solution variable.
# Constants and initial conditions:
# $c_{\alpha}$ and $c_{\beta}$ are concentrations at which the bulk free energy has minima.
# $\kappa$ is the gradient energy coefficient.
# $\varrho_s$ controls the height of the double-well barrier.

c_alpha = 0.3
c_beta = 0.7
kappa = 2.0
M = 5.0
c_0 = 0.5
epsilon = 0.01
rho_s = 5.0
Beispiel #13
0
def hydrology(solve_mode,
              nx,
              ny,
              dx,
              dy,
              days,
              ele,
              phi_initial,
              catchment_mask,
              wt_canal_arr,
              boundary_arr,
              peat_type_mask,
              httd,
              tra_to_cut,
              sto_to_cut,
              diri_bc=0.0,
              neumann_bc=None,
              plotOpt=False,
              remove_ponding_water=True,
              P=0.0,
              ET=0.0,
              dt=1.0):
    """
    INPUT:
        - ele: (nx,ny) sized NumPy array. Elevation in m above c.r.p.
        - Hinitial: (nx,ny) sized NumPy array. Initial water table in m above c.r.p.
        - catchment mask: (nx,ny) sized NumPy array. Boolean array = True where the node is inside the computation area. False if outside.
        - wt_can_arr: (nx,ny) sized NumPy array. Zero everywhere except in nodes that contain canals, where = wl of the canal.
        - value_for_masked: DEPRECATED. IT IS NOW THE SAME AS diri_bc.
        - diri_bc: None or float. If None, Dirichlet BC will not be implemented. If float, this number will be the BC.
        - neumann_bc: None or float. If None, Neumann BC will not be implemented. If float, this is the value of grad phi.
        - P: Float. Constant precipitation. mm/day.
        - ET: Float. Constant evapotranspiration. mm/day.
    """
    #    dneg = []

    track_WT_drained_area = (239, 166)
    track_WT_notdrained_area = (522, 190)

    ele[~catchment_mask] = 0.
    ele = ele.flatten()
    phi_initial = (phi_initial + 0.0 * np.zeros((ny, nx))) * catchment_mask
    #    phi_initial = phi_initial * catchment_mask
    phi_initial = phi_initial.flatten()

    if len(ele) != nx * ny or len(phi_initial) != nx * ny:
        raise ValueError("ele or Hinitial are not of dim nx*ny")

    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
    phi = fp.CellVariable(
        name='computed H', mesh=mesh, value=phi_initial,
        hasOld=True)  #response variable H in meters above reference level

    if diri_bc != None and neumann_bc == None:
        phi.constrain(diri_bc, mesh.exteriorFaces)

    elif diri_bc == None and neumann_bc != None:
        phi.faceGrad.constrain(neumann_bc * mesh.faceNormals,
                               where=mesh.exteriorFaces)

    else:
        raise ValueError(
            "Cannot apply Dirichlet and Neumann boundary values at the same time. Contradictory values."
        )

    #*******omit areas outside the catchment. c is input
    cmask = fp.CellVariable(mesh=mesh, value=np.ravel(catchment_mask))
    cmask_not = fp.CellVariable(mesh=mesh,
                                value=np.array(~cmask.value, dtype=int))

    # *** drain mask or canal mask
    dr = np.array(wt_canal_arr, dtype=bool)
    dr[np.array(wt_canal_arr, dtype=bool) * np.array(
        boundary_arr, dtype=bool
    )] = False  # Pixels cannot be canals and boundaries at the same time. Everytime a conflict appears, boundaries win. This overwrites any canal water level info if the canal is in the boundary.
    drmask = fp.CellVariable(mesh=mesh, value=np.ravel(dr))
    drmask_not = fp.CellVariable(
        mesh=mesh, value=np.array(~drmask.value, dtype=int)
    )  # Complementary of the drains mask, but with ints {0,1}

    # mask away unnecesary stuff
    #    phi.setValue(np.ravel(H)*cmask.value)
    #    ele = ele * cmask.value

    source = fp.CellVariable(mesh=mesh,
                             value=0.)  # cell variable for source/sink

    #    CC=fp.CellVariable(mesh=mesh, value=C(phi.value-ele))                   # differential water capacity

    def D_value(phi, ele, tra_to_cut, cmask, drmask_not):
        # Some inputs are in fipy CellVariable type
        gwt = phi.value * cmask.value - ele

        d = hydro_utils.peat_map_h_to_tra(
            soil_type_mask=peat_type_mask, gwt=gwt,
            h_to_tra_and_C_dict=httd) - tra_to_cut

        # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that
        # phi is below the impermeable bottom. We allow phi to have those values, but
        # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom).
        d[d < 0] = 1e-3  # Small non-zero value not to wreck the computation

        dcell = fp.CellVariable(
            mesh=mesh, value=d
        )  # diffusion coefficient, transmissivity. As a cell variable.
        dface = fp.FaceVariable(mesh=mesh,
                                value=dcell.arithmeticFaceValue.value
                                )  # THe correct Face variable.

        return dface.value

    def C_value(phi, ele, sto_to_cut, cmask, drmask_not):
        # Some inputs are in fipy CellVariable type
        gwt = phi.value * cmask.value - ele

        c = hydro_utils.peat_map_h_to_sto(
            soil_type_mask=peat_type_mask, gwt=gwt,
            h_to_tra_and_C_dict=httd) - sto_to_cut
        c[c < 0] = 1e-3  # Same reasons as for D

        ccell = fp.CellVariable(
            mesh=mesh, value=c
        )  # diffusion coefficient, transmissivity. As a cell variable.
        return ccell.value

    D = fp.FaceVariable(
        mesh=mesh, value=D_value(phi, ele, tra_to_cut, cmask,
                                 drmask_not))  # THe correct Face variable.
    C = fp.CellVariable(
        mesh=mesh, value=C_value(phi, ele, sto_to_cut, cmask,
                                 drmask_not))  # differential water capacity

    largeValue = 1e20  # value needed in implicit source term to apply internal boundaries

    if plotOpt:
        big_4_raster_plot(
            title='Before the computation',
            raster1=(
                (hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask,
                                               gwt=(phi.value - ele),
                                               h_to_tra_and_C_dict=httd) -
                 tra_to_cut) * cmask.value * drmask_not.value).reshape(ny, nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))
        # for later cross-section plots
        y_value = 270

#        print "first cross-section plot"
#        ele_with_can = copy.copy(ele).reshape(ny,nx)
#        ele_with_can = ele_with_can * catchment_mask
#        ele_with_can[wt_canal_arr > 0] = wt_canal_arr[wt_canal_arr > 0]
#        plot_line_of_peat(ele_with_can, y_value=y_value, title="cross-section", color='green', nx=nx, ny=ny, label="ele")

# ********************************** PDE, STEADY STATE **********************************
    if solve_mode == 'steadystate':
        if diri_bc != None:
            #        diri_boundary = fp.CellVariable(mesh=mesh, value= np.ravel(diri_boundary_value(boundary_mask, ele2d, diri_bc)))

            eq = 0. == (
                fp.DiffusionTerm(coeff=D) + source * cmask * drmask_not -
                fp.ImplicitSourceTerm(cmask_not * largeValue) +
                cmask_not * largeValue * np.ravel(boundary_arr) -
                fp.ImplicitSourceTerm(drmask * largeValue) +
                drmask * largeValue * (np.ravel(wt_canal_arr))
                #                    - fp.ImplicitSourceTerm(bmask_not*largeValue) + bmask_not*largeValue*(boundary_arr)
            )

        elif neumann_bc != None:
            raise NotImplementedError("Neumann BC not implemented yet!")
            cmask_face = fp.FaceVariable(mesh=mesh,
                                         value=np.array(
                                             cmask.arithmeticFaceValue.value,
                                             dtype=bool))
            D[cmask_face.value] = 0.
            eq = 0. == (
                fp.DiffusionTerm(coeff=D) + source * cmask * drmask_not -
                fp.ImplicitSourceTerm(cmask_not * largeValue) +
                cmask_not * largeValue * (diri_bc) -
                fp.ImplicitSourceTerm(drmask * largeValue) +
                drmask * largeValue * (np.ravel(wt_canal_arr))
                #                + fp.DiffusionTerm(coeff=largeValue * bmask_face)
                #                - fp.ImplicitSourceTerm((bmask_face * largeValue *neumann_bc * mesh.faceNormals).divergence)
            )

    elif solve_mode == 'transient':
        if diri_bc != None:
            #        diri_boundary = fp.CellVariable(mesh=mesh, value= np.ravel(diri_boundary_value(boundary_mask, ele2d, diri_bc)))

            eq = fp.TransientTerm(coeff=C) == (
                fp.DiffusionTerm(coeff=D) + source * cmask * drmask_not -
                fp.ImplicitSourceTerm(cmask_not * largeValue) +
                cmask_not * largeValue * np.ravel(boundary_arr) -
                fp.ImplicitSourceTerm(drmask * largeValue) +
                drmask * largeValue * (np.ravel(wt_canal_arr))
                #                        - fp.ImplicitSourceTerm(bmask_not*largeValue) + bmask_not*largeValue*(boundary_arr)
            )
        elif neumann_bc != None:
            raise NotImplementedError("Neumann BC not implemented yet!")

    #********************************************************

    max_sweeps = 10  # inner loop.

    avg_wt = []
    wt_track_drained = []
    wt_track_notdrained = []

    cumulative_Vdp = 0.

    #********Finite volume computation******************
    for d in range(days):
        source.setValue(
            (P[d] - ET[d]) * .001 * np.ones(ny * nx)
        )  # source/sink. P and ET are in mm/day. The factor of 10^-3 converst to m/day. It does not matter that there are 100 x 100 m^2 in one pixel
        print("(d, P - ET) = ", (d, (P[d] - ET[d])))
        if plotOpt and d != 0:
            # print "one more cross-section plot"
            plot_line_of_peat(phi.value.reshape(ny, nx),
                              y_value=y_value,
                              title="cross-section",
                              color='cornflowerblue',
                              nx=nx,
                              ny=ny,
                              label=d)

        res = 0.0

        phi.updateOld()

        D.setValue(D_value(phi, ele, tra_to_cut, cmask, drmask_not))
        C.setValue(C_value(phi, ele, tra_to_cut, cmask, drmask_not))

        for r in range(max_sweeps):
            resOld = res

            res = eq.sweep(var=phi, dt=dt)  # solve linearization of PDE

            #print "sum of Ds: ", np.sum(D.value)/1e8
            #print "average wt: ", np.average(phi.value-ele)

            #print 'residue diference:    ', res - resOld

            if abs(res - resOld) < 1e-7:
                break  # it has reached to the solution of the linear system

        if solve_mode == 'transient':  #solving in steadystate will remove water only at the very end
            if remove_ponding_water:
                s = np.where(
                    phi.value > ele, ele, phi.value
                )  # remove the surface water. This also removes phi in those masked values (for the plot only)
                phi.setValue(s)  # set new values for water table

        if (D.value < 0.).any():
            print("Some value in D is negative!")

        # For some plots
        avg_wt.append(np.average(phi.value - ele))
        wt_track_drained.append(
            (phi.value - ele).reshape(ny, nx)[track_WT_drained_area])
        wt_track_notdrained.append(
            (phi.value - ele).reshape(ny, nx)[track_WT_notdrained_area])
        """ Volume of dry peat calc."""
        not_peat = np.ones(shape=peat_type_mask.shape)  # Not all soil is peat!
        not_peat[peat_type_mask == 4] = 0  # NotPeat
        not_peat[peat_type_mask == 5] = 0  # OpenWater
        peat_vol_weights = utilities.PeatV_weight_calc(
            np.array(~dr * catchment_mask * not_peat, dtype=int))
        dry_peat_volume = utilities.PeatVolume(peat_vol_weights,
                                               (ele - phi.value).reshape(
                                                   ny, nx))
        cumulative_Vdp = cumulative_Vdp + dry_peat_volume
        print("avg_wt  = ", np.average(phi.value - ele))
        #        print "wt drained = ", (phi.value - ele).reshape(ny,nx)[track_WT_drained_area]
        #        print "wt not drained = ", (phi.value - ele).reshape(ny,nx)[track_WT_notdrained_area]
        print("Cumulative vdp = ", cumulative_Vdp)

    if solve_mode == 'steadystate':  #solving in steadystate we remove water only at the very end
        if remove_ponding_water:
            s = np.where(
                phi.value > ele, ele, phi.value
            )  # remove the surface water. This also removes phi in those masked values (for the plot only)
            phi.setValue(s)  # set new values for water table

        # Areas with WT <-1.0; areas with WT >0
#        plot_raster_by_value((ele-phi.value).reshape(ny,nx), title="ele-phi in the end, colour keys", bottom_value=0.5, top_value=0.01)

    if plotOpt:
        big_4_raster_plot(
            title='After the computation',
            raster1=(
                (hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask,
                                               gwt=(phi.value - ele),
                                               h_to_tra_and_C_dict=httd) -
                 tra_to_cut) * cmask.value * drmask_not.value).reshape(ny, nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))

        fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 9), dpi=80)
        x = np.arange(-21, 1, 0.1)
        axes[0, 0].plot(httd[1]['hToTra'](x), x)
        axes[0, 0].set(title='hToTra', ylabel='depth')
        axes[0, 1].plot(httd[1]['C'](x), x)
        axes[0, 1].set(title='C')
        axes[1, 0].plot()
        axes[1, 0].set(title="Nothing")
        axes[1, 1].plot(avg_wt)
        axes[1, 1].set(title="avg_wt_over_time")

        # plot surface in cross-section
        ele_with_can = copy.copy(ele).reshape(ny, nx)
        ele_with_can = ele_with_can * catchment_mask
        ele_with_can[wt_canal_arr > 0] = wt_canal_arr[wt_canal_arr > 0]
        plot_line_of_peat(ele_with_can,
                          y_value=y_value,
                          title="cross-section",
                          nx=nx,
                          ny=ny,
                          label="surface",
                          color='peru',
                          linewidth=2.0)

        plt.show()

#    change_in_canals = (ele-phi.value).reshape(ny,nx)*(drmask.value.reshape(ny,nx)) - ((ele-H)*drmask.value).reshape(ny,nx)
#    resulting_phi = phi.value.reshape(ny,nx)

    phi.updateOld()

    return (phi.value - ele).reshape(ny, nx)
Beispiel #14
0
else:

    class dummyTreant(object):
        categories = dict()

    data = dummyTreant()

data.categories['problem'] = "III-2a"
data.categories['args'] = " ".join(sys.argv)
data.categories['step'] = args.step
data.categories['sweeps'] = args.sweeps
data.categories['dx'] = args.dx
data.categories['commit'] = os.popen('git log --pretty="%H" -1').read().strip()
data.categories['diff'] = os.popen('git diff').read()

mesh = fp.Grid2D(Lx=100., dx=args.dx, Ly=100., dy=args.dx)
volumes = fp.CellVariable(mesh=mesh, value=mesh.cellVolumes)

c = fp.CellVariable(mesh=mesh, name="$c$", hasOld=True)
psi = fp.CellVariable(mesh=mesh, name=r"$\psi$", hasOld=True)
Phi = fp.CellVariable(mesh=mesh, name=r"$\Phi$", hasOld=True)

calpha = 0.3
cbeta = 0.7
kappa = 2.
rho = 5.
M = 5.
k = 0.09
epsilon = 90.

ceq = fp.TransientTerm(var=c) == fp.DiffusionTerm(coeff=M, var=psi)
Beispiel #15
0
def hydrology(mode,
              sensor_positions,
              nx,
              ny,
              dx,
              dy,
              days,
              ele,
              phi_initial,
              catchment_mask,
              wt_canal_arr,
              boundary_arr,
              peat_type_mask,
              peat_bottom_arr,
              transmissivity,
              t0,
              t1,
              t2,
              t_sapric_coef,
              storage,
              s0,
              s1,
              s2,
              s_sapric_coef,
              diri_bc=0.0,
              plotOpt=False,
              remove_ponding_water=True,
              P=0.0,
              ET=0.0,
              dt=1.0):
    """
    INPUT:
        - ele: (nx,ny) sized NumPy array. Elevation in m above c.r.p.
        - Hinitial: (nx,ny) sized NumPy array. Initial water table in m above c.r.p.
        - catchment mask: (nx,ny) sized NumPy array. Boolean array = True where the node is inside the computation area. False if outside.
        - wt_can_arr: (nx,ny) sized NumPy array. Zero everywhere except in nodes that contain canals, where = wl of the canal.
        - value_for_masked: DEPRECATED. IT IS NOW THE SAME AS diri_bc.
        - diri_bc: None or float. If None, Dirichlet BC will not be implemented. If float, this number will be the BC.
        - neumann_bc: None or float. If None, Neumann BC will not be implemented. If float, this is the value of grad phi.
        - P: Float. Constant precipitation. mm/day.
        - ET: Float. Constant evapotranspiration. mm/day.
    """
    #    dneg = []

    # track_WT_drained_area = (239,166)
    # track_WT_notdrained_area = (522,190)

    ele[~catchment_mask] = 0.
    ele = ele.flatten()
    phi_initial = (phi_initial + 0.0 * np.zeros((ny, nx))) * catchment_mask
    #    phi_initial = phi_initial * catchment_mask
    phi_initial = phi_initial.flatten()

    if len(ele) != nx * ny or len(phi_initial) != nx * ny:
        raise ValueError("ele or Hinitial are not of dim nx*ny")

    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
    phi = fp.CellVariable(
        name='computed H', mesh=mesh, value=phi_initial,
        hasOld=True)  #response variable H in meters above reference level

    if diri_bc != None:
        phi.constrain(diri_bc, mesh.exteriorFaces)

    else:
        raise ValueError("Dirichlet boundary conditions must have a value")

    #*******omit areas outside the catchment. c is input
    cmask = fp.CellVariable(mesh=mesh, value=np.ravel(catchment_mask))
    cmask_not = fp.CellVariable(mesh=mesh,
                                value=np.array(~cmask.value, dtype=int))

    # *** drain mask or canal mask
    dr = np.array(wt_canal_arr, dtype=bool)
    dr[np.array(wt_canal_arr, dtype=bool) * np.array(
        boundary_arr, dtype=bool
    )] = False  # Pixels cannot be canals and boundaries at the same time. Everytime a conflict appears, boundaries win. This overwrites any canal water level info if the canal is in the boundary.
    drmask = fp.CellVariable(mesh=mesh, value=np.ravel(dr))
    drmask_not = fp.CellVariable(
        mesh=mesh, value=np.array(~drmask.value, dtype=int)
    )  # Complementary of the drains mask, but with ints {0,1}

    # mask away unnecesary stuff
    #    phi.setValue(np.ravel(H)*cmask.value)
    #    ele = ele * cmask.value

    source = fp.CellVariable(mesh=mesh,
                             value=0.)  # cell variable for source/sink

    #    CC=fp.CellVariable(mesh=mesh, value=C(phi.value-ele))                   # differential water capacity

    def T_value(phi, ele, cmask, peat_bottom_arr):
        # Some inputs are in fipy CellVariable type
        gwt = (phi.value * cmask.value - ele).reshape(ny, nx)

        # T(h) - T(bottom)
        T = transmissivity(gwt, t0, t1, t2, t_sapric_coef) - transmissivity(
            peat_bottom_arr, t0, t1, t2, t_sapric_coef)

        # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that
        # phi is below the impermeable bottom. We allow phi to have those values, but
        # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom).
        T[T < 0] = 1e-3  # Small non-zero value not to wreck the computation

        Tcell = fp.CellVariable(mesh=mesh, value=T.flatten(
        ))  # diffusion coefficient, transmissivity. As a cell variable.
        Tface = fp.FaceVariable(mesh=mesh,
                                value=Tcell.arithmeticFaceValue.value
                                )  # THe correct Face variable.

        return Tface.value

    def S_value(phi, ele, cmask, peat_bottom_arr):
        # Some inputs are in fipy CellVariable type
        gwt = (phi.value * cmask.value - ele).reshape(ny, nx)

        S = storage(gwt, s0, s1, s2, s_sapric_coef) - storage(
            peat_bottom_arr, s0, s1, s2, s_sapric_coef)
        S[S < 0] = 1e-3  # Same reasons as for D

        Scell = fp.CellVariable(mesh=mesh, value=S.flatten(
        ))  # diffusion coefficient, transmissivity. As a cell variable.
        return Scell.value

    T = fp.FaceVariable(mesh=mesh,
                        value=T_value(
                            phi, ele, cmask,
                            peat_bottom_arr))  # THe correct Face variable.
    S = fp.CellVariable(mesh=mesh,
                        value=S_value(
                            phi, ele, cmask,
                            peat_bottom_arr))  # differential water capacity

    largeValue = 1e20  # value needed in implicit source term to apply internal boundaries

    if plotOpt:
        big_4_raster_plot(
            title='Before the computation',
            # raster1=((hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask, gwt=(phi.value - ele), h_to_tra_and_C_dict=httd) - tra_to_cut)*cmask.value *drmask_not.value ).reshape(ny,nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))
        # for later cross-section plots
        y_value = 270
    """
    ###### PDE ######
    """

    if mode == 'steadystate':
        temp = 0.
    elif mode == 'transient':
        temp = fp.TransientTerm(coeff=S)

    if diri_bc != None:
        #        diri_boundary = fp.CellVariable(mesh=mesh, value= np.ravel(diri_boundary_value(boundary_mask, ele2d, diri_bc))
        eq = temp == (
            fp.DiffusionTerm(coeff=T) + source * cmask * drmask_not -
            fp.ImplicitSourceTerm(cmask_not * largeValue) +
            cmask_not * largeValue * np.ravel(boundary_arr) -
            fp.ImplicitSourceTerm(drmask * largeValue) + drmask * largeValue *
            (np.ravel(wt_canal_arr))
            #                        - fp.ImplicitSourceTerm(bmask_not*largeValue) + bmask_not*largeValue*(boundary_arr)
        )

    #********************************************************

    max_sweeps = 10  # inner loop.

    avg_wt = []
    # wt_track_drained = []
    # wt_track_notdrained = []

    cumulative_Vdp = 0.

    #********Finite volume computation******************
    for d in range(days):

        if type(P) == type(ele):  # assume it is a numpy array
            source.setValue(
                (P[d] - ET[d]) * .001 * np.ones(ny * nx)
            )  # source/sink, in mm/day. The factor of 10^-3 takes into account that there are 100 x 100 m^2 in one pixel
            # print("(d,P) = ", (d, (P[d]-ET[d])* 10.))
        else:
            source.setValue((P - ET) * 10. * np.ones(ny * nx))
            # print("(d,P) = ", (d, (P-ET)* 10.))

        if plotOpt and d != 0:
            # print "one more cross-section plot"
            plot_line_of_peat(phi.value.reshape(ny, nx),
                              y_value=y_value,
                              title="cross-section",
                              color='cornflowerblue',
                              nx=nx,
                              ny=ny,
                              label=d)

        res = 0.0

        phi.updateOld()

        T.setValue(T_value(phi, ele, cmask, peat_bottom_arr))
        S.setValue(S_value(phi, ele, cmask, peat_bottom_arr))

        for r in range(max_sweeps):
            resOld = res

            res = eq.sweep(var=phi, dt=dt)  # solve linearization of PDE

            #print "sum of Ds: ", np.sum(D.value)/1e8
            #print "average wt: ", np.average(phi.value-ele)

            #print 'residue diference:    ', res - resOld

            if abs(res - resOld) < 1e-7:
                break  # it has reached to the solution of the linear system

        if remove_ponding_water:
            s = np.where(
                phi.value > ele, ele, phi.value
            )  # remove the surface water. This also removes phi in those masked values (for the plot only)
            phi.setValue(s)  # set new values for water table

        if (T.value < 0.).any():
            print("Some value in D is negative!")

        # For some plots
        avg_wt.append(np.average(phi.value - ele))
        # wt_track_drained.append((phi.value - ele).reshape(ny,nx)[track_WT_drained_area])
        # wt_track_notdrained.append((phi.value - ele).reshape(ny,nx)[track_WT_notdrained_area])
        """ Volume of dry peat calc."""
        not_peat = np.ones(shape=peat_type_mask.shape)  # Not all soil is peat!
        not_peat[peat_type_mask == 4] = 0  # NotPeat
        not_peat[peat_type_mask == 5] = 0  # OpenWater
        peat_vol_weights = utilities.PeatV_weight_calc(
            np.array(~dr * catchment_mask * not_peat, dtype=int))
        dry_peat_volume = utilities.PeatVolume(peat_vol_weights,
                                               (ele - phi.value).reshape(
                                                   ny, nx))
        cumulative_Vdp = cumulative_Vdp + dry_peat_volume

    if plotOpt:
        big_4_raster_plot(
            title='After the computation',
            # raster1=((hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask, gwt=(phi.value - ele), h_to_tra_and_C_dict=httd) - tra_to_cut)*cmask.value *drmask_not.value ).reshape(ny,nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))

        # fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12,9), dpi=80)
        # x = np.arange(-21,1,0.1)
        # axes[0,0].plot(httd[1]['hToTra'](x),x)
        # axes[0,0].set(title='hToTra', ylabel='depth')
        # axes[0,1].plot(httd[1]['C'](x),x)
        # axes[0,1].set(title='C')
        # axes[1,0].plot()
        # axes[1,0].set(title="Nothing")
        # axes[1,1].plot(avg_wt)
        # axes[1,1].set(title="avg_wt_over_time")

        # # plot surface in cross-section
        # ele_with_can = copy.copy(ele).reshape(ny,nx)
        # ele_with_can = ele_with_can * catchment_mask
        # ele_with_can[wt_canal_arr > 0] = wt_canal_arr[wt_canal_arr > 0]
        # plot_line_of_peat(ele_with_can, y_value=y_value, title="cross-section", nx=nx, ny=ny, label="surface", color='peru', linewidth=2.0)

        # plt.show()

#    change_in_canals = (ele-phi.value).reshape(ny,nx)*(drmask.value.reshape(ny,nx)) - ((ele-H)*drmask.value).reshape(ny,nx)
#    resulting_phi = phi.value.reshape(ny,nx)

    wtd = (phi.value - ele).reshape(ny, nx)
    wtd_sensors = [wtd[i] for i in sensor_positions]

    return np.array(wtd_sensors)
Beispiel #16
0
# This example solves a diffusion problem and demonstrates the use of
# applying boundary condition patches.
try:
    import fipy
except ImportError:
    raise ImportError('Problem with FiPy Installation')

from PyAMGSolver import PyAMGSolver

nx = 20
ny = nx
dx = 1.0
dy = dx
L = dx * nx
mesh = fipy.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
phi = fipy.CellVariable(name="solution variable", mesh=mesh, value=0.)

# Apply Dirichlet boundary conditions (else Neumann by default)
valueTopLeft = 0
valueBottomRight = 1
x, y = mesh.getFaceCenters()
facesTopLeft = ((mesh.getFacesLeft() & (y > L / 2)) | (mesh.getFacesTop() &
                                                       (x < L / 2)))
facesBottomRight = ((mesh.getFacesRight() & (y < L / 2)) |
                    (mesh.getFacesBottom() & (x > L / 2)))
BCs = (fipy.FixedValue(faces=facesTopLeft, value=valueTopLeft),
       fipy.FixedValue(faces=facesBottomRight, value=valueBottomRight))

# set solver
# solver = LinearLUSolver(tolerance = 1.e-6, iterations = 100)
MGSetupOpts = {'max_coarse': 10}
import fipy as fp
import glob
import json
import numpy as np
import os
import sys
from fipy.solvers.pysparse import LinearLUSolver as Solver

problem = '1'
domain = 'c'
nx = 100
dx = 1.0

# The first step in implementing any problem in FiPy is to define the mesh. In this case, the T-shaped domain is constructed out of two rectangular `Grid2D` objects. No other boundary conditions are required.

mesh = fp.Grid2D(Lx=20., Ly=100.0, dx=dx, dy=dx) + (
    fp.Grid2D(Ly=20.0, Lx=100.0, dx=dx, dy=dx) + [[-40], [100]])

# The next step is to define the parameters and create a solution variable.
# Constants and initial conditions:
# $c_{\alpha}$ and $c_{\beta}$ are concentrations at which the bulk free energy has minima.
# $\kappa$ is the gradient energy coefficient.
# $\varrho_s$ controls the height of the double-well barrier.

c_alpha = 0.3
c_beta = 0.7
kappa = 2.0
M = 5.0
c_0 = 0.5
epsilon = 0.01
rho_s = 5.0