Example #1
0
    def calculate_potential(depletion_mask=None, y_dep_new=None):
        potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.)
        electrons = fipy.CellVariable(mesh=mesh, name='e-')
        electrons.valence = -1
        charge = electrons * electrons.valence
        charge.name = "charge"

        # Uniform charge distribution by setting a uniform concentration of
        # electrons = 1
        electrons.setValue(rho_scale)

        # A depletion zone within the bulk requires an internal boundary
        # condition. Internal boundary conditions seem to challenge fipy, see:
        # http://www.ctcms.nist.gov/fipy/documentation/USAGE.html#applying-internal-boundary-conditions

        large_value = 1e+10  # Hack for optimizer

        if depletion_mask is not None:
            # FIXME: Generic depletion_mask not working
            # Is overwritten here with a simple 1D depletion mask
            depletion_mask = np.logical_and(potential.mesh.y > y_dep_new[0],
                                            potential.mesh.y > y_dep_new[0])
            potential.equation = (fipy.DiffusionTerm(coeff=epsilon_scaled) +
                                  charge == fipy.ImplicitSourceTerm(
                                      depletion_mask * large_value) -
                                  depletion_mask * large_value * V_bias)
        else:
            potential.equation = (fipy.DiffusionTerm(coeff=epsilon_scaled) +
                                  charge == 0.)

        # Calculate boundaries
        backplane = mesh.getFacesTop()
        readout_plane = mesh.getFacesBottom()

        electrodes = readout_plane
        bcs = [fipy.FixedValue(value=V_bias, faces=backplane)]
        X, _ = mesh.getFaceCenters()
        for pixel in range(n_pixel):
            pixel_position = width * (pixel + 1. / 2.) - width * n_pixel / 2.
            bcs.append(
                fipy.FixedValue(
                    value=V_readout if pixel_position == 0. else 0.,
                    faces=electrodes & (X > pixel_position - pitch / 2.) &
                    (X < pixel_position + pitch / 2.)))

        solver.solve(potential,
                     equation=potential.equation,
                     boundaryConditions=bcs)
        return potential
Example #2
0
 def solveSectionThermal(self, TPrim, hConvPrim, TSec, hConvSec, TExt,
                         hConvExt):
     # Initialize convergence criteria
     res = 1e10
     n = 0
     # Run the non-linear iteration loop
     while (res > self.fvSolverSettings.tolerance
            and n < self.fvSolverSettings.maxNumIterations):
         # Interpolate temperature on faces
         TFaces = self.T.arithmeticFaceValue()
         # Compute thermal conductivity
         self.thermCond.setValue(self.thermCondModel(TFaces))
         # Set up the equation
         ## Diffusion term
         eqT = FP.DiffusionTerm(coeff=self.thermCond)
         ## Source terms (implicit + explicit) emulating boundary conditions
         eqT += -FP.ImplicitSourceTerm(
             self.cPrimCoeff *
             hConvPrim) + self.cPrimCoeff * hConvPrim * TPrim
         eqT += -FP.ImplicitSourceTerm(
             self.cSecCoeff * hConvSec) + self.cSecCoeff * hConvSec * TSec
         eqT += -FP.ImplicitSourceTerm(
             self.cExtCoeff * hConvExt) + self.cExtCoeff * hConvExt * TExt
         # Linear solve
         res = eqT.sweep(
             var=self.T,
             solver=self.linSolver,
             underRelaxation=self.fvSolverSettings.relaxationFactor)
         #print n, res
         n += 1
    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
Example #4
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)
Example #5
0
def calculate_planar_sensor_potential(width, pitch, n_pixel, thickness,
                                      resolution, V_backplane, V_readout=0):
    points, cells = pg.generate_mesh(mesh_planar_sensor(x=width * n_pixel,
                                                        thickness=thickness,
                                                        resolution=resolution))

    mio.write('sensor.msh', points, cells)
    mesh = fipy.GmshImporter2D('sensor.msh')

    potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.)
    permittivity = 1.
    potential.equation = (fipy.DiffusionTerm(coeff=permittivity) == 0.)

    # Calculate boundaries
    V_backplane = V_backplane
    backplane = mesh.getFacesTop()

    V_readout = V_readout
    readout_plane = mesh.getFacesBottom()

    electrodes = readout_plane
    bcs = [fipy.FixedValue(value=V_backplane, faces=backplane)]
    X, _ = mesh.getFaceCenters()
    for pixel in range(n_pixel):
        pixel_position = width * (pixel + 1. / 2.) - width * n_pixel / 2.
        bcs.append(fipy.FixedValue(value=V_readout,
                                   faces=electrodes &
                                   (X > pixel_position - pitch / 2.) &
                                   (X < pixel_position + pitch / 2.)))

    potential.equation.solve(var=potential, boundaryConditions=bcs)
    return potential
Example #6
0
    def _Execute(self):
        input = self.GetPolyDataInput()

        self.mesh = FiPyTriangleMesher(input).GetMesh()

        self.speed = fipy.CellVariable(name="speed", mesh=self.mesh, value=0.)
        self.speed.constrain(0., where=self.mesh.exteriorFaces)
        #        self.BCs = (fipy.FixedValue(faces=self.mesh.exteriorFaces, value=0),)

        self.equation = fipy.DiffusionTerm() + 1. == 0.

        self.equation.solve(var=self.speed)  #, boundaryConditions=self.BCs)
        # FiPy API doesn't seem to have an integrate method
        #volumeFlux = self.speed.getCellVolumeAverage() * self.speed.mesh.getCellVolumes().sum()
        # Scale such that the flux will be unity
        #self.speed /= volumeFlux
        self.speed /= self.speed.mesh.getCellVolumes().sum()

        #print self.speed
        #print self.speed.getCellVolumeAverage(), self.speed.mesh.getCellVolumes().sum()

        output = self.GetPolyDataOutput()
        output.ShallowCopy(input)
        speed = convert.numpy_to_vtk(self.speed.getValue())
        output.GetCellData().SetScalars(speed)
        return
Example #7
0
def calculate_3D_sensor_potential(pitch_x, pitch_y, n_pixel_x, n_pixel_y, radius, resolution, V_readout, V_bias, nD=2):
    points, cells = pg.generate_mesh(mesh_3D_sensor(x=pitch_x,
                                                        y=pitch_y,
                                                        n_pixel_x=n_pixel_x, 
                                                        n_pixel_y=n_pixel_y,
                                                        radius=radius,
                                                        nD=nD,
                                                        resolution=resolution))
                                     
    mio.write('sensor.msh', points, cells)
    mesh = fipy.GmshImporter2D('sensor.msh')
    
    plot.plot_mesh(mesh)
    
    potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.)
    permittivity = 1.
    potential.equation = (fipy.DiffusionTerm(coeff=permittivity) == 0.)
    
    bcs = []
    allfaces = mesh.getExteriorFaces()
    X,Y =  mesh.getFaceCenters()
    
    # Readout pillars
    for pillar in range(nD):
        position = pitch_x / nD * (pillar + 1. / 2.) - pitch_x / 2.
        ring = allfaces & ( (X-position)**2+(Y)**2 < (radius)**2) 
        bcs.append(fipy.FixedValue(value=V_readout,faces=ring))
        
    # Bias pillars
    # Edges
    positions = [(- pitch_x / 2., - pitch_y / 2.),
                 (+ pitch_x / 2., - pitch_y / 2.),
                 (+ pitch_x / 2., + pitch_y / 2.),
                 (- pitch_x / 2., + pitch_y / 2.)]
    # Sides
    positions += [(0, - pitch_y / 2.),
                 (0, + pitch_y / 2.)]

    for pos_x, pos_y in positions:
        ring = allfaces & ( (X-pos_x)**2+(Y-pos_y)**2 < (radius)**2) 
        bcs.append(fipy.FixedValue(value=V_bias, faces=ring))

#     # Calculate boundaries
#     p_pillars = mesh.getFaces()
#     n_pillars = mesh.getFacesTop()
# 
#     electrodes = readout_plane
#     bcs = [fipy.FixedValue(value=V_backplane, faces=backplane)]
#     
#     for pixel in range(n_pixel):
#         pixel_position = width * (pixel + 1. / 2.) - width * n_pixel / 2.
#         bcs.append(fipy.FixedValue(value=V_readout,
#                                    faces=electrodes &
#                                    (X > pixel_position - pitch / 2.) &
#                                    (X < pixel_position + pitch / 2.)))

    potential.equation.solve(var=potential, boundaryConditions=bcs)
    return potential
Example #8
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
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 #10
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 #11
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 #12
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 #13
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 #14
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
Example #16
0
    def solve(self):
        sideFaceFactor = fp.CellVariable(
            name="sideFaceFactor",
            mesh=self.mesh,
            value=self.areaExtFaces / (self.AcsMult * self.mesh.cellVolumes))
        # Create variables
        self.TCore = fp.CellVariable(name="coreTemperature",
                                     mesh=self.mesh,
                                     value=self.TAmb)
        self.TSurface = fp.CellVariable(name="surfaceTemperature",
                                        mesh=self.mesh,
                                        value=self.TAmb)
        # Apply boundary conditions:
        self.applyBC(self.mesh.facesLeft(), self.BC[0],
                     self.mesh.scaledFaceAreas[0] * self.AcsMult)
        self.applyBC(self.mesh.facesRight(), self.BC[1],
                     self.mesh.scaledFaceAreas[-1] * self.AcsMult)

        # Create linear solver
        linSolver = LinearLUSolver(tolerance=1e-10)

        # Create base equation (thermal conduction):
        eq = fp.DiffusionTerm(coeff=self.thermalConductivity, var=self.TCore)
        if (self.jouleHeating['active']):
            eq += self.jouleHeating['j']**2 * self.jouleHeating['eResistivity']

        if (self.radiation['active']):
            raise NotImplementedError('Radiation not implemented yet!')
        else:
            if (self.convection['active']):
                RAmb = 1. / self.convection['coefficient']
                if (self.insulation['active']):
                    RAmb += self.insulation['thickness'] / self.insulation[
                        'thermConductivity']
                eq += 1. / RAmb * (sideFaceFactor * self.TAmb -
                                   fp.ImplicitSourceTerm(coeff=sideFaceFactor,
                                                         var=self.TCore))
            eq.solve(var=self.TCore, solver=linSolver)
            if (self.convection['active'] and self.insulation['active']):
                # 0 - limited by conduction, 1 - limited by convection
                a1 = 1. / (RAmb * self.convection['coefficient'])
                self.TSurface.setValue(a1 * self.TCore() +
                                       (1 - a1) * self.TAmb)
            else:
                self.TSurface.setValue(self.TCore())
Example #17
0
	def solve(self):
		sideFaceFactor = fp.CellVariable(name = "sideFaceFactor",
			mesh = self.mesh, value = self.sideFaceAreas / (self.areaMult * self.mesh.cellVolumes))

		# Initial conditions
		self.T.setValue(self.TAmb)
		# Run solverSettings
		solver = LinearLUSolver(tolerance=1e-10)
		if (self.solverSettings['nonlinear']):
			res = 1
			sweep = 0
			self.resVector = []
			TFaces = self.T.arithmeticFaceValue()
			self.TLeft = []
			self.TRight = []
			self.QLeft = []
			self.QRight = []
			while (res > self.solverSettings['tolerance'] and sweep < self.solverSettings['maxIterations']):
				# Compute temperature dependent thermal conductivity 
				self.thermCond.setValue(self.conduction['model'](TFaces))
				# Add the conductivity term to the equation					
				eqX = fp.DiffusionTerm(coeff = self.thermCond)
				if (self.radiation['active']):
					# Compute temperature dependent emissivity
					self.emissivity.setValue(self.emissivityCalculator(self.T()))
					# Add radiation term to the equation
					radMultiplier = sigmaSB * self.emissivity * sideFaceFactor
					eqX = eqX + radMultiplier * (self.TAmb**4 - self.T**4)
				# Perform iteration
				res = eqX.sweep(var = self.T, solver = solver, underRelaxation = self.solverSettings['relaxationFactor'])
				# Save residual
				self.resVector.append(res)
				# Save temperature and fluxes at the ends
				TFaces = self.T.arithmeticFaceValue()
				self.TLeft.append(TFaces[0])
				self.TRight.append(TFaces[-1])
				self.QLeft.append(self.QAx[0])
				self.QRight.append(self.QAx[-1])
							
				sweep += 1
		else:
			eqX.solve(var = self.T)
Example #18
0
def calculate_planar_sensor_w_potential(mesh, width, pitch, n_pixel,
                                        thickness):
    ''' Calculates the weighting field of a planar sensor.
    '''
    _LOGGER.info('Calculating weighting potential')
    # Mesh validity check
    mesh_width = mesh.getFaceCenters()[0, :].max() - mesh.getFaceCenters()[
        0, :].min()

    if mesh_width != width * n_pixel:
        raise ValueError(
            'The provided mesh width does not correspond to the sensor width')

    if mesh.getFaceCenters()[1, :].min() != 0:
        raise ValueError('The provided mesh does not start at 0.')

    if mesh.getFaceCenters()[1, :].max() != thickness:
        raise ValueError('The provided mesh does not end at sensor thickness.')

    potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.)
    permittivity = 1.
    potential.equation = (fipy.DiffusionTerm(coeff=permittivity) == 0.)

    # Calculate boundaries
    backplane = mesh.getFacesTop()
    readout_plane = mesh.getFacesBottom()

    electrodes = readout_plane
    bcs = [fipy.FixedValue(value=0., faces=backplane)]
    X, _ = mesh.getFaceCenters()
    for pixel in range(n_pixel):
        pixel_position = width * (pixel + 1. / 2.) - width * n_pixel / 2.
        bcs.append(
            fipy.FixedValue(value=1.0 if pixel_position == 0. else 0.,
                            faces=electrodes &
                            (X > pixel_position - pitch / 2.) &
                            (X < pixel_position + pitch / 2.)))

    solver.solve(potential,
                 equation=potential.equation,
                 boundaryConditions=bcs)
    return potential
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
Example #20
0
def calculate_potential(mesh, rho, epsilon, V_read, V_bias, x_dep):
    r''' Calculate the potential with a given space charge distribution.

    If the depletion width is too large the resulting potential will have
    a minimum < bias voltage. This is unphysical.
    '''

    # The field scales with rho / epsilon, thus scale to proper value to
    # counteract numerical instabilities
    epsilon_scaled = 1.
    rho_scale = rho / epsilon

    potential = fipy.CellVariable(mesh=mesh, name='potential', value=0.)

    electrons = fipy.CellVariable(mesh=mesh, name='e-')
    electrons.valence = -1

    electrons.setValue(rho_scale)

    charge = electrons * electrons.valence
    charge.name = "charge"

    # A depletion zone within the bulk requires an internal boundary condition
    # Internal boundary conditions seem to challenge fipy, see:
    # http://www.ctcms.nist.gov/fipy/documentation/USAGE.html#applying-internal-boundary-conditions

    large_value = 1e+15  # Hack for optimizer

    mask = mesh.x > x_dep
    potential.equation = (fipy.DiffusionTerm(coeff=epsilon_scaled) -
                          fipy.ImplicitSourceTerm(mask * large_value) +
                          mask * large_value * V_bias + charge == 0)

    potential.constrain(V_read, mesh.facesLeft)
    potential.constrain(V_bias, mesh.facesRight)

    solver.solve(potential, equation=potential.equation)

    return potential
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 #22
0
def test_steady_state():
    """
    Test that we can create a steady-state model using
    FiPy that is similar to that given by our 'naive' solver
    """
    continental_crust.heat_generation = u(1, 'mW/m^3')
    _ = continental_crust.to_layer(u(3000, 'm'))
    section = Section([_])

    heatflow = u(15, 'mW/m^2')
    surface_temperature = u(0, 'degC')

    m = continental_crust
    q = heatflow
    k = m.conductivity
    a = m.heat_generation
    Cp = m.specific_heat
    rho = m.density

    def simple_heat_flow(x):
        # Density and heat capacity matter don't matter in steady-state
        T0 = surface_temperature
        return T0.to('K') + q * x / k + a / (2 * k) * x**2

    p = simple_heat_flow(section.cell_centers)
    dx = section.cell_sizes[0]
    test_profile = p.into('degC')

    grad = (-q / k).into('K/m')
    # Divergence
    div = (-a / k).into('K/m^2')

    a_ = -N.gradient(N.gradient(test_profile, dx), dx)
    assert all(a_ < 0)
    assert N.allclose(a_.min(), div)

    res = steady_state(section, heatflow, surface_temperature)
    profile = res.profile.into('degC')

    assert N.allclose(test_profile, profile)

    solver = FiniteSolver(_)
    solver.constrain(surface_temperature, None)
    solver.constrain(heatflow, None)

    res2 = solver.steady_state()
    # Make sure it's nonlinear and has constant 2nd derivative
    arr = solver.var.faceGrad.divergence.value
    assert N.allclose(sum(arr - arr[0]), 0)
    assert N.allclose(arr.mean(), div)

    # Test simple finite element model
    mesh = F.Grid1D(nx=section.n_cells, dx=section.cell_sizes[0].into('m'))
    T = F.CellVariable(name="Temperature", mesh=mesh)
    T.constrain(surface_temperature.into("K"), mesh.facesLeft)
    A = F.FaceVariable(mesh=mesh, value=m.diffusivity.into("m**2/s"))
    rad_heat = F.CellVariable(mesh=mesh, value=(a / Cp / rho).into("K/s"))

    D = F.DiffusionTerm(coeff=A) + F.ImplicitSourceTerm(coeff=rad_heat)
    sol = D.solve(var=T)
    val = T.faceGrad.divergence.value
    arr = T.value - 273.15
    #assert N.allclose(val.mean(), div)
    assert N.allclose(test_profile, arr)

    P = res2.profile.into('degC')
    assert N.allclose(test_profile, P)
Example #23
0
# 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))
volumes = fp.CellVariable(mesh=mesh, value=mesh.cellVolumes)
Example #24
0
meshmodule = import_module("mesh{}".format(params["problem"]))

(mesh, inlet, outlet, walls,
 top_right) = meshmodule.mesh_and_boundaries(params)

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

x, y = mesh.cellCenters
top_right_cell = fp.CellVariable(mesh=mesh,
                                 value=(x > max(x) - params["cellSize"]) &
                                 (y > max(y) - params["cellSize"]))

large_value = 1e10
pressureCorrectionEq = (
    fp.DiffusionTerm(coeff=coeff) - velocity.divergence -
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 #26
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 #27
0
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 #28
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 #29
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 #30
0
coeffD = D() * fp.numerix.exp(0.01 * phi)

# --- Assign boundary conditions
valueTop = -1.5
valueGradBottom = 0.

phi.constrain(valueTop, where=mesh.facesTop)
phi.constrain(valueGradBottom, where=mesh.facesBottom)

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

# --- Solve steady state groundwater flow equation
eqSteady = (fp.DiffusionTerm(coeff=D() * fp.numerix.exp(0.01 * phi)) +
            np.gradient(coeffD())[0])
eqSteady.solve(var=phi)
print phi()
if __name__ == '__main__':
    viewer.plot()

if __name__ == '__main__':
    raw_input("Implicit steady-state diffusion. Press <return> to proceed...")

################################################################################
################################################################################
##### -------------------- Solve the transport equation ------------------ #####
################################################################################

theta = 0.4  # Effective porosity