Example #1
0
    def __init__(self, layer, **kwargs):
        super(SimpleFiniteSolver,self).__init__(layer, **kwargs)
        try:
            layers = layer.layers
            if len(layers) == 1:
                self.layer = layers[0]
            else:
                arg = self.__class__.__name__+" can be initialized only from a single layer or a section containing only one layer."
                raise ArgumentError(arg)
        except AttributeError:
            self.layer = layer

        self.analytical_solver = HalfSpaceSolver(layer)

        self.material = self.layer.material
        self.depth = self.layer.thickness
        self.dy = self.layer.grid_spacing
        self.ny = int((self.depth/self.dy).into("dimensionless"))
        self.mesh = F.Grid1D(nx=self.ny, dx=self.dy.into("m"))

        t_min,t_max = (i.into("kelvin") for i in self.constraints)

        self.initial_values = N.empty(self.ny)
        self.initial_values.fill(t_max)

        self.var = F.CellVariable(name="Temperature", mesh=self.mesh, value=self.initial_values)
        self.var.constrain(t_min, self.mesh.facesLeft)
        self.var.constrain(t_max, self.mesh.facesRight)
        coefficient = self.material.diffusivity.into("m**2/s")
        self.equation = F.TransientTerm() == F.DiffusionTerm(coeff=coefficient)
def df2(xs, mesh, vx, vy, i, j):
    """
    Evaluate the model for the 2nd derivatives at the 10 locations of the domain
    at times ``t``.

    It returns a flatten version of the system, i.e.:
    y_1(t_1)
    ...
    y_10(t_1)
    ...
    y_1(t_4)
    ...
    y_10(t_4)
    """
    assert i == 1 or i == 2
    assert j == 1 or j == 2
    ############################################################################
    ############################################################################
    ##### ------------------ Solve the transport equation ---------------- #####
    ############################################################################

    Rd = 2.  # Retardation factor

    convCoeff = fp.CellVariable(mesh=mesh, rank=1)
    convCoeff()[0, :] = vx
    convCoeff()[1, :] = vy
    time = fp.Variable()
    # --- Make Source ---
    q0 = make_source_der_2(xs, mesh, time, i, j)
    # The solution variable
    var = fp.CellVariable(name="variable", mesh=mesh, value=0.)
    # Define the equation
    eqC = fp.TransientTerm(Rd) == -fp.ConvectionTerm(coeff=convCoeff) + q0

    # Solve
    d2U = []
    timeStepDuration = 0.005
    steps = 400
    for step in range(steps):
        time.setValue(time() + timeStepDuration)
        eqC.solve(var=var, dt=timeStepDuration)
        if step == 99 or step == 199 or step == 299 or step == 399:
            d2U = np.hstack([
                d2U,
                np.array([
                    var()[8 * 50 + 14],
                    var()[8 * 50 + 34],
                    var()[18 * 50 + 14],
                    var()[18 * 50 + 34],
                    var()[28 * 50 + 14],
                    var()[28 * 50 + 34],
                    var()[38 * 50 + 14],
                    var()[38 * 50 + 34],
                    var()[48 * 50 + 14],
                    var()[48 * 50 + 34]
                ])
            ])

    return d2U
def solve_DiracIC(saveplot = False, R_from = 0.7, R_to = 1.0, nr = 1000, duration = 0.001, nt = 1000,
                  diracLoc = 0.85, diracCoeff = 1., diracPercentage = 2,
                  conv_file = 'convC.txt', diff_file = 'diffC.txt',  plotcoeff = False,
                  levels = 300, logdiff = 6, ticks = None, figsize=(10,5), hdf5 = False):
    
    dr = (R_to - R_from) / nr  ## distance between the centers of the mesh cells
    dt = duration / nt  ## length of one timestep
    solution = np.zeros((nt,nr,2))
    for j in range(nr):
        solution[:,j,0] = (j * dr) + (dr / 2) + R_from

    mesh = fp.CylindricalGrid1D(dx=dr, nx=nr)  ## 1D mesh based on the radial coordinates 
    mesh = mesh + (R_from,)  ## translation of the mesh to R_from
    n = fp.CellVariable(mesh=mesh)  ## fipy.CellVariable for the density solution in each timestep
    diracWidth = int((nr / 100) * diracPercentage)
    n.setValue(delta_func(mesh.x - diracLoc, diracWidth * dr, diracCoeff))
    conv_data = np.genfromtxt(conv_file, delimiter=',')
    diff_data = np.genfromtxt(diff_file, delimiter=',')
    conv_i = np.zeros((nr, 2))
    diff_i = np.zeros((nr, 2))
    for i in range(conv_i.shape[0]):
        conv_i[i, 0] = R_from + (i * dr) + (dr / 2)

    for i in range(diff_i.shape[0]):
        diff_i[i, 0] = R_from + (i * dr) + (dr / 2)

    conv_i[:,1] = np.interp(conv_i[:,0],conv_data[:,0],conv_data[:,1])
    diff_i[:,1] = np.interp(diff_i[:,0],diff_data[:,0],diff_data[:,1])
    dC = diff_i[:,1]
    diffCoeff = fp.CellVariable(mesh=mesh, value=dC)
    cC = conv_i[:,1]
    convCoeff = fp.CellVariable(mesh=mesh, value=[cC])
    gradLeft = (0.,)  ## density gradient (at the "left side of the radius") - must be a vector
    valueRight = 0.  ## density value (at the "right end of the radius")
    n.faceGrad.constrain(gradLeft, where=mesh.facesLeft)  ## applying Neumann boundary condition
    n.constrain(valueRight, mesh.facesRight)  ## applying Dirichlet boundary condition
    convCoeff.setValue(0, where=mesh.x<(R_from + dr))  ## convection coefficient 0 at the inner edge
    diffCoeff.setValue(0.001, where=mesh.x<(R_from + dr))  ## diffusion coefficient almost 0 at inner edge
    eq = (fp.TransientTerm() == fp.DiffusionTerm(coeff=diffCoeff)
          - fp.ConvectionTerm(coeff=convCoeff))
    for i in range(nt):
        eq.solve(var=n, dt=dt)
        solution[i,0:nr,1]=copy.deepcopy(n.value)

    plot_solution(solution,ticks=ticks,levels=levels,logdiff=logdiff,figsize=figsize,
                  duration=duration, nt=nt, saveplot=saveplot)
    if plotcoeff == True:
        coeff_plot(conv_i=conv_i, diff_i=diff_i)
    else:
        pass
    
    if hdf5 == True:
        hdf5_save(fname="DiracIC",solution=solution, conv=conv_i, diff=diff_i, duration=duration)
    else:
        pass
    
    return solution
Example #4
0
def forwardEvo(phi, tStart, tEnd, path, saveResults):
    # Initialize step counter and evolution time
    step = 0
    tEvo = tStart
    # Extract cell centers and faces from mesh
    X, P = Mesh.cellCenters()
    xFace, pFace = Mesh.faceCenters()
    # Create plot for starting distribution
    target = 'forwardEvo-Step-' + '%05d' % step + '.png'
    genPlots(phi, tEvo, saveResults, target, path)
    # Continue to evolve distribution until specified end time
    while (tEvo < tEnd):
        # Find current spring constant and location of minimum
        kT = springConstant(tEvo)
        zT = potentialMinimum(tEvo)
        # Calculate time step size
        timeStepDuration = (1. /
                            (SubDiv * Nx)) * (1. /
                                              numpy.sqrt(1. / Tau**2 + kT))
        if (tEvo + timeStepDuration > tEnd):
            timeStepDuration = tEnd - tEvo
        # Create Diffusion Term
        gxx = numpy.zeros(X.shape)
        gxp = numpy.zeros(X.shape)
        gpx = numpy.zeros(X.shape)
        gpp = numpy.ones(X.shape) * (2. / Tau)
        dTerm = fipy.DiffusionTerm(
            fipy.CellVariable(mesh=Mesh, value=[[gxx, gxp], [gpx, gpp]]))
        del gxx, gxp, gpx, gpp
        # Create convection term
        uX = pFace
        uP = -kT * (xFace - zT) - (2. / Tau) * pFace
        cCoeff = fipy.FaceVariable(mesh=Mesh, value=[uX, uP])
        cTerm = fipy.ExponentialConvectionTerm(cCoeff)
        del uX, uP, cCoeff
        # Create evolution equation
        eq = fipy.TransientTerm() + cTerm == dTerm
        # Specify solver
        solver = fipy.solvers.pysparse.LinearLUSolver(tolerance=10**-15, \
                                                iterations=1000, precon=None)
        # Evolve system
        eq.solve(var=phi, dt=timeStepDuration, solver=solver)
        tEvo = tEvo + timeStepDuration
        step = step + 1
        # Check normalization for possible errors
        norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp
        if (abs(norm - 1) > 10**(-13)):
            s1 = 'Distribution is no longer normalized.\n'
            s2 = 'Abs(1-Norm) = '
            s3 = repr(norm - 1.)
            raise RuntimeError(s1 + s2 + s3)
        del kT, zT, timeStepDuration, cTerm, eq, norm
        # Create plot of current distribution
        target = 'forwardEvo-Step-' + '%05d' % step + '.png'
        genPlots(phi, tEvo, saveResults, target, path)
    del tEvo, X, P, xFace, pFace
    return phi
Example #5
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
Example #6
0
def solve_fipy_with_given_N(N, params):

    s1 = params[0]
    s2 = params[1]
    t1 = params[2]
    t2 = params[3]

    dx = 100.0 / N
    dt = 1.0

    NDAYS = 10

    f_start_time = time.time()

    mesh = fp.Grid1D(nx=N, dx=dx)

    v_fp = fp.CellVariable(name="v_fp",
                           mesh=mesh,
                           value=INI_VALUE,
                           hasOld=True)

    # BC
    v_fp.constrain(0, where=mesh.facesLeft)  # left BC is always Dirichlet

    # v_fp.faceGrad.constrain(0. * mesh.faceNormals, where=mesh.facesRight) # right: flux=0

    def dif_fp(u):
        b = -4.
        D = (numerix.exp(t1) / t2 *
             (numerix.power(s2 * numerix.exp(-s1) * u + numerix.exp(s2 * b),
                            t2 / s2) - numerix.exp(t2 * b))) / (
                                s2 * u + numerix.exp(s1 + s2 * b))

        return D

    # Boussinesq eq. for theta
    eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=dif_fp(v_fp)) + SOURCE

    MAX_SWEEPS = 10000

    for t in range(NDAYS):
        v_fp.updateOld()

        res = 0.0
        for r in range(MAX_SWEEPS):
            # print(i, res)
            resOld = res
            # res = eq.sweep(var=v_fp, dt=dt, underRelaxation=0.1)
            res = eq.sweep(var=v_fp, dt=dt)
            if abs(res - resOld) < abs_tolerance:
                break  # it has reached to the solution of the linear system

    time_spent = time.time() - f_start_time

    return v_fp.value, time_spent
Example #7
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)
Example #8
0
def get_eqn(mesh, diff):
    """Generate a generic 1D diffusion equation with flux from the left

     Args:
      mesh: the mesh
      diff: the diffusion coefficient

    Returns:
      a tuple of the flux and the equation
    """
    flux = fipy.CellVariable(mesh, value=0.)
    eqn = fipy.TransientTerm() == fipy.DiffusionTerm(
        diff) + fipy.ImplicitSourceTerm(flux * GET_MASK(mesh) / mesh.dx)
    return (flux, eqn)
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
def df(xs, mesh, i):
    """
    Evaluate the model for the 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
    time = fp.Variable()
    q0 = make_source_der(xs, mesh, time, i)
    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
    dU = []
    for step in range(steps):
        eq.solve(var=phi, dt=dt)
        if step == 14 or step == 29 or step == 44 or  step == 59:
            dc = phi()[12]
            #dr = phi()[24]
            uc = phi()[612]
            #ur = phi()[624]
            #dU = np.hstack([dU, np.array([dl, dr, ul, ur])])
            dU = np.hstack([dU, np.array([dc, uc])])
    
    return dU
def f(xs, mesh):
    """
    Evaluate the model for the concentration 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)
    """
    time = fp.Variable()
    q = make_source(xs, mesh, time)
    D = 1.
    # Define the equation
    eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=D) + q
    # Boundary conditions

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

    # Solve
    dt = 0.005
    steps = 60
    U_sol = []
    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]
            #U_sol = np.hstack([U_sol, np.array([dl, dr, ul, ur])])
            U_sol = np.hstack([U_sol, np.array([dl, ul])])

    return U_sol
Example #12
0
def get_eq(params, eta, d2f):
    """Get the equation

    Args:
      params: the parameter dictionary
      eta: the phase field variable
      d2f: the free energy double derivative variable

    Returns:
      a dictionary of the equation and variables
    """
    return pipe(
        fp.CellVariable(mesh=eta.mesh, name="psi"),
        lambda x: (
            fp.TransientTerm(var=eta) == -fp.DiffusionTerm(
                coeff=params["mobility"], var=x) + fp.DiffusionTerm(
                    coeff=params["mobility"] * d2f, var=eta),
            fp.ImplicitSourceTerm(coeff=1.0, var=x) == fp.DiffusionTerm(
                coeff=params["kappa"], var=eta),
        ),
        lambda x: x[0] & x[1],
    )
Example #13
0
def solve_both_withI(saveplot=False,
                     R_from=0.7,
                     R_to=1.0,
                     nr=1000,
                     duration=0.001,
                     nt=1000,
                     conv_file='convC.txt',
                     diff_file='diffC.txt',
                     plotcoeff=False,
                     levels=300,
                     logdiff=5,
                     ticks=None,
                     figsize=(10, 5),
                     hdf5=False):

    dr = (R_to -
          R_from) / nr  ## distance between the centers of the mesh cells
    dt = duration / nt  ## length of one timestep
    solution = np.zeros((nt, nr, 2))
    for j in range(nr):
        solution[:, j, 0] = (j * dr) + (dr / 2) + R_from

    mesh = fp.CylindricalGrid1D(
        dx=dr, nx=nr)  ## 1D mesh based on the radial coordinates
    mesh = mesh + (R_from, )  ## translation of the mesh to R_from
    n = fp.CellVariable(
        mesh=mesh
    )  ## fipy.CellVariable for the density solution in each timestep
    conv_data = np.genfromtxt(conv_file, delimiter=',')
    diff_data = np.genfromtxt(diff_file, delimiter=',')
    conv_i = np.zeros((nr, 2))
    diff_i = np.zeros((nr, 2))
    for i in range(conv_i.shape[0]):
        conv_i[i, 0] = R_from + (i * dr) + (dr / 2)

    for i in range(diff_i.shape[0]):
        diff_i[i, 0] = R_from + (i * dr) + (dr / 2)

    conv_i[:, 1] = np.interp(conv_i[:, 0], conv_data[:, 0], conv_data[:, 1])
    diff_i[:, 1] = np.interp(diff_i[:, 0], diff_data[:, 0], diff_data[:, 1])
    dC = diff_i[:, 1]
    diffCoeff = fp.CellVariable(mesh=mesh, value=dC)
    cC = conv_i[:, 1]
    convCoeff = fp.CellVariable(mesh=mesh, value=[cC])

    n.setValue(0.0)

    idata = np.genfromtxt('island_data.csv', delimiter=',')
    islands_ratio = np.zeros((nr, 2))
    for i in range(nr):
        islands_ratio[i, 0] = R_from + (i * dr) + (dr / 2)

    islands_ratio[:, 1] = np.interp(islands_ratio[:, 0], idata[:, 0], idata[:,
                                                                            1])
    w_length = math.ceil(nr / 20)
    if (w_length % 2) == 0:
        w_length = w_length + 1
    else:
        pass

    islands_ratio[:, 1] = savgol_filter(islands_ratio[:, 1], w_length, 3)
    islands_ratio[islands_ratio < 0] = 0
    re_ratio = islands_ratio[:, 1]
    re_in_islands = re_ratio * n.value

    gradLeft = (
        0.,
    )  ## density gradient (at the "left side of the radius") - must be a vector
    valueRight = 0.  ## density value (at the "right end of the radius")
    n.faceGrad.constrain(
        gradLeft, where=mesh.facesLeft)  ## applying Neumann boundary condition
    n.constrain(valueRight,
                mesh.facesRight)  ## applying Dirichlet boundary condition
    convCoeff.setValue(
        0, where=mesh.x <
        (R_from + dr))  ## convection coefficient 0 at the inner edge
    diffCoeff.setValue(
        0.001, where=mesh.x <
        (R_from + dr))  ## diffusion coefficient almost 0 at inner edge

    modules = MODULE(b"hc_formula_63", False, b"rosenbluth_putvinski", False,
                     False, 1.0, 1.0001)
    electron_temperature = ct.c_double(300.)
    electron_density = ct.c_double(1e20)
    effective_charge = ct.c_double(1.)
    electric_field = ct.c_double(3.66)
    magnetic_field = ct.c_double(1.)
    inv_asp_ratio = ct.c_double(0.30303)
    rate_values = (ct.c_double * 4)(0., 0., 0., 0.)

    eq = (fp.TransientTerm() == fp.DiffusionTerm(coeff=diffCoeff) -
          fp.ConvectionTerm(coeff=convCoeff))
    for i in range(nt):
        for j in range(nr):
            plasma_local = PLASMA(ct.c_double(mesh.x[j]), electron_density,
                                  electron_temperature, effective_charge,
                                  electric_field, magnetic_field,
                                  ct.c_double(n.value[j]))
            n.value[j] = adv_RE_pop(ct.byref(plasma_local), dt, inv_asp_ratio,
                                    ct.c_double(mesh.x[j]), ct.byref(modules),
                                    rate_values)

        print("{:.1f}".format((i / nt) * 100), '%', end='\r')
        eq.solve(var=n, dt=dt)
        if i == 0:
            solution[i, 0:nr, 1] = copy.deepcopy(n.value)
            re_in_islands = re_ratio * copy.deepcopy(n.value)
            n.value = copy.deepcopy(n.value) - re_in_islands
        else:
            re_local = PLASMA(ct.c_double(mesh.x[j]), electron_density,
                              electron_temperature, effective_charge,
                              electric_field, magnetic_field,
                              ct.c_double(re_in_islands[j]))
            re_in_islands[j] = adv_RE_pop(ct.byref(re_local),
                                          dt, inv_asp_ratio,
                                          ct.c_double(mesh.x[j]),
                                          ct.byref(modules), rate_values)

        re_in_islands[nr - 1] = 0
        solution[i, 0:nr, 1] = copy.deepcopy(n.value) + re_in_islands

    plot_solution(solution,
                  ticks=ticks,
                  levels=levels,
                  logdiff=logdiff,
                  figsize=figsize,
                  duration=duration,
                  nt=nt,
                  saveplot=saveplot)
    if plotcoeff == True:
        coeff_plot(conv_i=conv_i, diff_i=diff_i)
    else:
        pass

    if hdf5 == True:
        hdf5_save(fname="Dreicer_and_avalanche",
                  solution=solution,
                  conv=conv_i,
                  diff=diff_i,
                  duration=duration)
    else:
        pass

    return solution
Example #14
0
if parallelComm.procID == 0:
    dt = data.categories["dt_exact"]
else:
    dt = None

dt = parallelComm.bcast(dt)

elapsed = fp.Variable(name="$t$", value=startfrom * dt)

# linearize double-well
m_eta = 2 * (1 - 2 * eta)
dm_eta_deta = -4.
DW = m_eta * eta * (eta - 1)
dDW_deta = dm_eta_deta * eta * (eta - 1) + m_eta * (2 * eta - 1)
eq = (fp.TransientTerm() == (DW - dDW_deta * eta) +
      fp.ImplicitSourceTerm(coeff=dDW_deta) +
      fp.DiffusionTerm(coeff=kappa_fp) + eq_fp(xx, yy, elapsed))

solver = eq.getDefaultSolver()
print "solver:", repr(solver)

for step in range(1, numsteps + 1):
    eta.updateOld()
    for sweep in range(params['sweeps']):
        res = eq.sweep(var=eta, dt=dt, solver=solver)
    elapsed.value = elapsed() + dt

del solver

error = eta - eta_fp(xx, yy, elapsed - dt)
Example #15
0
time = fp.Variable()

var = fp.CellVariable(name="variable", mesh=mesh)

# --- Make source term
rho = 0.35
q0 = 1. / (np.pi * rho**2)
T = 0.3
xs_1 = np.array([1.25, 2.])
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_1[0])**2 +
        (mesh.cellCenters[1]()[i] - xs_1[1])**2) / (2 * rho**2)) * (time() < T)

eqC = fp.TransientTerm(
    Rd) == -fp.ConvectionTerm(coeff=convCoeff) + sourceTerm_1

if __name__ == '__main__':
    viewer = fp.Viewer(vars=var, datamin=0., datamax=2.5)
    viewer.plot()

data = []
timeStepDuration = 0.005
steps = 400
for step in range(steps):
    time.setValue(time() + timeStepDuration)
    eqC.solve(var=var, dt=timeStepDuration)
    if step == 99 or step == 199 or step == 299 or step == 399:
        data = np.hstack([
            data,
            np.array([
def run():
    memory1 = resource.getrusage(
        resource.RUSAGE_SELF).ru_maxrss  #get initial memory peak

    #load in the json parameter file here
    jsonfile = sys.argv[1]

    if jsonfile:
        with open(jsonfile, 'rb') as ff:
            params = json.load(ff)

    else:
        params = dict()

    print 'my params:', params

    #extract the parameters
    N = params.get('N', 20)
    # dx = params.get('dx', 1)
    total_steps = params.get('steps', 2)
    sumatra_label = params.get('sumatra_label', '')

    c, rho_s, c_alpha, c_beta = sympy.symbols("c_var rho_s c_alpha c_beta")
    f_0 = rho_s * (c - c_alpha)**2 * (c_beta - c)**2

    mesh = fp.PeriodicGrid2D(nx=N, ny=N, dx=.5, dy=.5)

    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
    filepath = os.path.join('Data', sumatra_label)

    c_var = fp.CellVariable(mesh=mesh, name=r"$c$", hasOld=True)

    # array of sample c-values: used in f versus c plot
    vals = np.linspace(-.1, 1.1, 1000)

    c_var = fp.CellVariable(mesh=mesh, name=r"$c$", hasOld=True)

    x, y = np.array(mesh.x), np.array(mesh.y)

    out = sympy.diff(f_0, c, 2)

    exec "f_0_var = " + repr(out)

    #f_0_var = -A + 3*B*(c_var - c_m)**2 + 3*c_alpha*(c_var - c_alpha)**2 + 3*c_beta*(c_var - c_beta)**2

    def f_0(c):
        return rho_s * ((c - c_alpha)**2) * ((c_beta - c)**2)

    def f_0_var(c_var):
        return 2 * rho_s * ((c_alpha - c_var)**2 + 4 * (c_alpha - c_var) *
                            (c_beta - c_var) + (c_beta - c_var)**2)

    # free energy
    def f(c):
        return (f_0(c) + .5 * kappa * (c.grad.mag)**2)

    f_data = []
    time_data = []

    def save_data(f, time):
        f_data.append(f.value)
        time_data.append(time)
        np.savetxt(os.path.join(filepath, '1a.txt'), zip(time_data, f_data))

    eqn = fp.TransientTerm(
        coeff=1.) == fp.DiffusionTerm(M * f_0_var(c_var)) - fp.DiffusionTerm(
            (M, kappa))

    elapsed = 0.0
    steps = 0
    dt = 0.01
    total_sweeps = 2
    tolerance = 1e-1
    # duration = 1000.0

    c_var[:] = c_0 + epsilon * (np.cos(0.105 * x) * np.cos(0.11 * y) + \
                                (np.cos(0.13 * x) * np.cos(0.087 * y))**2 + \
                                + np.cos(0.025 * x - 0.15 * y) * np.cos(0.07 * x - 0.02 * y))
    c_var.updateOld()
    solver = Solver()

    while steps < total_steps:
        res0 = eqn.sweep(c_var, dt=dt, solver=solver)

        for sweeps in range(total_sweeps):
            res = eqn.sweep(c_var, dt=dt, solver=solver)

        if (res < (res0 * tolerance)):
            steps += 1
            #       elapsed += dt
            dt *= 1.1
            c_var.updateOld()

            if (steps % (total_steps / 10.0) == 0):
                # record the volume integral of the free energy
                save_data(
                    f_0_var(c_var).cellVolumeAverage * mesh.numberOfCells,
                    elapsed)
                # pickle the data on c as a function of space at this particular time
                fp.dump.write({
                    'time': steps,
                    'var': c_var
                }, os.path.join(filepath, '1a{0}.pkl'.format(steps)))

        else:
            dt *= 0.8
            c_var[:] = c_var.old

    print ' '

    #memory stuff saves
    filepath = os.path.join('Data', sumatra_label)
    #Keep track os how much memory was used and dump into a txt file
    memory2 = resource.getrusage(
        resource.RUSAGE_SELF).ru_maxrss  #final memory peak
    memory_diff = (memory2 - memory1, )
    filename2 = 'memory_usage.txt'
    np.savetxt(os.path.join(filepath, filename2), memory_diff)
cvar_data = []
f_data = []


def save_data(time, cvar, f, step):
    time_data.append(time)
    cvar_data.append(np.array(cvar.value))
    f_data.append(f.value)

    file_name = 'data/1{0}{1}_{2}'.format(domain, nx, str(step).rjust(5, '0'))
    np.savez(file_name, time=time_data, c_var=cvar_data, f=f_data)


# ## Define the Equation

eqn = fp.TransientTerm(
    coeff=1.) == fp.DiffusionTerm(M * f_0_var(c_var)) - fp.DiffusionTerm(
        (M, kappa))

# ## Solve the Equation

# To solve the equation a simple time stepping scheme is used which is decreased or increased based on whether the residual decreases or increases. A time step is recalculated if the required tolerance is not reached. In addition, the time step is kept under 1 unit. The data is saved out every 10 steps.

elapsed = 0.0
steps = 0
dt = 0.01
dt_max = 1.0
total_sweeps = 2
tolerance = 1e-1
total_steps = int(sys.argv[1])
checkpoint = int(sys.argv[2])
duration = 900.0
Example #18
0
dx = Lx / nx
dy = Ly / ny

mesh = fp.PeriodicGrid2DLeftRight(nx=nx, dx=dx, ny=ny, dy=dx)
xx, yy = mesh.cellCenters[0], mesh.cellCenters[1]
XX, YY = mesh.faceCenters[0], mesh.faceCenters[1]

elapsed = fp.Variable(name="$t$", value=0.)

eta = fp.CellVariable(mesh=mesh, name="$eta$", hasOld=True)
eta.constrain(1., where=YY == 0.)
eta.constrain(0., where=YY == 0.5)

eta.value = eta_fp(xx, yy, 0.)

eq = (fp.TransientTerm() == -4 * eta * (eta - 1) * (eta - 0.5) +
      fp.DiffusionTerm(coeff=kappa_fp) + eq_fp(xx, yy, elapsed))

start = time.time()

while elapsed.value <= totaltime:
    eta.updateOld()
    eq.solve(var=eta, dt=dt)
    elapsed.value = elapsed() + dt

end = time.time()

data.categories["solvetime"] = end - start

error = eta - eta_fp(xx, yy, elapsed - dt)
error.name = r"$\Delta\eta$"
Example #19
0
kappa = 2.0
c_m = (c_alpha + c_beta) / 2.
B = A / (c_alpha - c_m)**2
D = D_alpha = D_beta = 2. / (c_beta - c_alpha)
c_0 = 0.45
q = np.sqrt((2., 3.))
epsilon = 0.01

c_var = fp.CellVariable(mesh=mesh, name=r"$c$", hasOld=True)

r = np.array((mesh.x, mesh.y))
c_var[:] = c_0 + epsilon * np.cos((q[:, None] * r).sum(0))

f_0_var = -A + 3*B*(c_var - c_m)**2 + 3*c_alpha*(c_var - c_alpha)**2 + 3*c_beta*(c_var - c_beta)**2

eqn = fp.TransientTerm(coeff=1.) == fp.DiffusionTerm(D * f_0_var) - fp.DiffusionTerm((D, kappa))

elapsed = 0.0
steps = 0
dt = 0.01
total_sweeps = 2
tolerance = 1e-1
#total_steps = 2       #from 1000 to 100

c_var[:] = c_0 + epsilon * np.cos((q[:, None] * r).sum(0))

c_var.updateOld()

from fipy.solvers.pysparse import LinearLUSolver as Solver

solver = Solver()
Example #20
0
 def initialise_food_equation(self):
     self.food_PDE = (
         fipy.TransientTerm() == fipy.DiffusionTerm(coeff=self.D_food) -
         fipy.ImplicitSourceTerm(coeff=self.gamma * self.rho))
Example #21
0
import fipy as fp
import numpy as np
from matplotlib import pyplot as plt

nx = 20
ny = nx
dx = 1.
dy = dx
L = dx * nx
mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)

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

D = 1.
eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=D)

valueTopLeft = 0
valueBottomRight = 1

X, Y = mesh.faceCenters
facesTopLeft = ((mesh.facesLeft & (Y > L / 2)) | (mesh.facesTop & (X < L / 2)))
facesBottomRight = ((mesh.facesRight & (Y < L / 2)) | (mesh.facesBottom &
                                                       (X > L / 2)))

phi.constrain(valueTopLeft, facesTopLeft)
phi.constrain(valueBottomRight, facesBottomRight)

timeStepDuration = 10 * 0.9 * dx**2 / (2 * D)
steps = 10
for step in range(steps):
    eq.solve(var=phi, dt=timeStepDuration)
Example #22
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)
Example #23
0
 def initialise_density_equation(self):
     self.density_PDE = (fipy.TransientTerm() == -self.v_0 *
                         fipy.PowerLawConvectionTerm(coeff=self.p))
Example #24
0
 def create_equation(self, type='implicit'):
     trans = F.TransientTerm()
     diff = self.diffusion_term(type)
     return trans == diff
Example #25
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)
Example #26
0
 def initialise_orientation_equation(self):
     self.orientation_PDE = (fipy.TransientTerm() ==
                             fipy.ImplicitSourceTerm(coeff=-self.D_rot) -
                             (self.v_0 / 2.0) * self.rho.grad / self.rho)
Example #27
0
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)

fchem = rho * (c - calpha)**2 * (cbeta - c)**2
felec = k * c * Phi / 2.
f = fchem + (kappa / 2.) * c.grad.mag**2 + felec
dfchemdc = 2 * rho * (c - calpha) * (cbeta - c) * (calpha + cbeta - 2 * c)
d2fchemd2c = 2 * rho * ((calpha + cbeta - 2 * c)**2 - 2 * (c - calpha) *
                        (cbeta - c))
psieq = (fp.ImplicitSourceTerm(
    coeff=1., var=psi) == fp.ImplicitSourceTerm(coeff=d2fchemd2c, var=c) -
         d2fchemd2c * c + dfchemdc - fp.DiffusionTerm(coeff=kappa, var=c) +
         fp.ImplicitSourceTerm(coeff=k, var=Phi))

stats = []

Phieq = fp.DiffusionTerm(var=Phi) == fp.ImplicitSourceTerm(coeff=-k / epsilon,
Example #28
0
# &= m_\phi \phi_\text{old} (1 - \phi_\text{old}) - S_1 \phi_\text{old}
# \notag \\
# S_1 &\equiv \left.{\frac{\partial S}{\partial \phi}}\right|_\text{old}
# \notag \\
# &= \frac{\partial m_\phi}{\partial \phi} \phi (1 - \phi) + m_\phi (1 - 2\phi)
# \notag
# \end{align}

# In[9]:

mPhi = -2 * (1 - 2 * phi) + 30 * phi * (1 - phi) * Delta_f
dmPhidPhi = 4 + 30 * (1 - 2 * phi) * Delta_f
S1 = dmPhidPhi * phi * (1 - phi) + mPhi * (1 - 2 * phi)
S0 = mPhi * phi * (1 - phi) - S1 * phi

eq = (fp.TransientTerm() == fp.DiffusionTerm(coeff=1.) + S0 +
      fp.ImplicitSourceTerm(coeff=S1))

# ## Calculate total free energy
#
# > \begin{align}
# F[\phi] = \int\left[\frac{1}{2}(\nabla\phi)^2 + g(\phi) - \Delta f p(\phi)\right]\,dV \tag{6}
# \end{align}

# In[10]:

ftot = (0.5 * phi.grad.mag**2 + phi**2 * (1 - phi)**2 - Delta_f * phi**3 *
        (10 - 15 * phi + 6 * phi**2))
volumes = fp.CellVariable(mesh=mesh, value=mesh.cellVolumes)
F = ftot.cellVolumeAverage * volumes.sum()
Example #29
0
# \notag \\
# S_1 &\equiv \left.{\frac{\partial S}{\partial \phi}}\right|_\text{old}
# \notag \\
# &= \frac{\partial m_\phi}{\partial \phi} \phi (1 - \phi) + m_\phi (1 - 2\phi)
# \notag
# \end{align}

# In[8]:


mPhi = -2 * (1 - 2 * phi) + 30 * phi * (1 - phi) * Delta_f
dmPhidPhi = 4 + 30 * (1 - 2 * phi) * Delta_f
S1 = dmPhidPhi * phi * (1 - phi) + mPhi * (1 - 2 * phi)
S0 = mPhi * phi * (1 - phi) - S1 * phi

eq = (fp.TransientTerm() == 
      fp.DiffusionTerm(coeff=1.) + S0 + fp.ImplicitSourceTerm(coeff=S1))


# ## Calculate total free energy
# 
# > \begin{align}
# F[\phi] = \int\left[\frac{1}{2}(\nabla\phi)^2 + g(\phi) - \Delta f p(\phi)\right]\,dV \tag{6}
# \end{align}

# In[9]:


ftot = (0.5 * phi.grad.mag**2
        + phi**2 * (1 - phi)**2
        - Delta_f * phi**3 * (10 - 15 * phi + 6 * phi**2))
Example #30
0
def hydro_1d_fipy(theta_ini, nx, dx, dt, params, ndays, sensor_loc,
                  boundary_values_left, boundary_values_right, precip,
                  evapotra, ele_interp, peat_depth):
    def zeta_from_theta(x, b):
        return np.log(np.exp(s2 * b) + s2 * np.exp(-s1) * x) / s2

    mesh = fp.Grid1D(nx=nx, dx=dx)

    ele = ele_interp(mesh.cellCenters.value[0])
    b = peat_depth + ele.min() - ele

    s1 = params[0]
    s2 = params[1]
    t1 = params[2]
    t2 = params[3]

    source = precip[0] - evapotra[0]

    theta = fp.CellVariable(name="theta",
                            mesh=mesh,
                            value=theta_ini,
                            hasOld=True)

    # Choice of parameterization
    # This is the underlying conductivity: K = exp(t1 + t2*zeta). The
    # transmissivity is derived from this and written in terms of theta
    # This is the underlying storage coeff: S = exp(s1 + s2*zeta)
    # S is hidden in change from theta to h
    # D = (numerix.exp(t1)/t2 * (numerix.power(s2 * numerix.exp(-s1) * theta + numerix.exp(s2*b), t2/s2) - numerix.exp(t2*b))) * np.power(s2 * (theta + numerix.exp(s1 + s2*b)/s2), -1)

    # Boussinesq eq. for theta
    eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=(
        numerix.exp(t1) / t2 *
        (numerix.power(s2 * numerix.exp(-s1) * theta +
                       numerix.exp(s2 * b), t2 / s2) - numerix.exp(t2 * b))
    ) * np.power(s2 * (theta + numerix.exp(s1 + s2 * b) / s2), -1)) + source

    theta_sol_list = []  # returned quantity

    MAX_SWEEPS = 10000

    for day in range(ndays):

        theta.updateOld()

        # BC and Source/sink update
        theta_left = boundary_values_left[day]  # left BC is always Dirichlet
        theta.constrain(theta_left, where=mesh.facesLeft)
        if boundary_values_right == None:  # Pxx sensors. Neuman BC on the right
            theta.faceGrad.constrain(0. * mesh.faceNormals,
                                     where=mesh.facesRight)
        else:
            theta_right = boundary_values_right[day]
            theta.constrain(theta_right, where=mesh.facesRight)

        source = precip[day] - evapotra[day]

        res = 0.0
        for r in range(MAX_SWEEPS):
            resOld = res
            res = eq.sweep(var=theta, dt=dt)
            if abs(res - resOld) < 1e-7:
                break  # it has reached the solution of the linear system

        if r == MAX_SWEEPS:
            raise ValueError(
                'Solution not converging after maximum number of sweeps')

        # Append to list
        theta_sol = theta.value
        theta_sol_sensors = np.array(
            [theta_sol[sl] for sl in sensor_loc[1:]]
        )  # canal sensor is part of the model; cannot be part of the fitness estimation

        theta_sol_list.append(theta_sol_sensors[0])

    b_sensors = np.array([b[sl] for sl in sensor_loc[1:]])
    zeta_from_theta_sol_sensors = zeta_from_theta(np.array(theta_sol_list),
                                                  b_sensors)
    # print(zeta_from_theta_sol_sensors)

    return zeta_from_theta_sol_sensors