Ejemplo n.º 1
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
Ejemplo n.º 2
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())
Ejemplo n.º 3
0
def distributionInitial():
    phi = fipy.CellVariable(mesh=Mesh, name=r"$\rho(x,p)$")
    X, P = Mesh.cellCenters()
    temp = numpy.exp(-(1. / 2) * (X)**2 - (1. / 2) * (P)**2)
    phi.setValue(temp)
    norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp
    phi.setValue(phi.value / norm)
    del temp, norm, X, P
    return phi
Ejemplo n.º 4
0
def to_face_value(mesh, value):
    """Convert an array over cells to an array over faces
    """
    return pipe(
        value,
        lambda x: fp.CellVariable(mesh=mesh, value=value),
        lambda x: x.faceValue,
        np.array,
    )
Ejemplo n.º 5
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
Ejemplo n.º 6
0
 def excess_heating(self, val):
     """
     Similar to radiogenic heat production, but not
     based on the material properties of the forearc.
     """
     if val == 0:
         v = None
     else:
         v = F.CellVariable(mesh=self.mesh, value=val.into('K/s'))
     self._excess = v
Ejemplo n.º 7
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
Ejemplo n.º 8
0
    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
def distributionInitial():
    phi = fipy.CellVariable(mesh=Mesh, name=r"$\rho(x,p)$")
    X, P = Mesh.cellCenters()
    temp = numpy.exp(-(1./2)*(X/.2)**2-(1./2)*((P-4)/.2)**2) \
                + numpy.exp(-(1./2)*(X/.2)**2-(1./2)*((P+4)/.2)**2)
    #mask = (P<-4)|(P>4)
    #temp = temp*mask
    phi.setValue(temp)
    norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp
    phi.setValue(phi.value / norm)
    del temp, norm, X, P
    return phi
Ejemplo n.º 10
0
    def radiogenic_heating(self):
        """Radiogenic heat production varying in space."""

        a, Cp, rho = (self.section.material_property(i)
                      for i in ("heat_generation", "specific_heat", "density"))
        if a.sum().magnitude == 0:
            return None

        arr = (a / Cp / rho).into("K/s")
        assert len(arr) == len(self.mesh.cellCenters[0])

        return F.CellVariable(mesh=self.mesh, value=arr)
Ejemplo n.º 11
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
Ejemplo n.º 12
0
    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
def make_source(xs, mesh, time):
    """
    Makes the source term of the diffusion equation 
    """
    #assert xs.shape[0] == 2
    sourceTerm = fp.CellVariable(name = "Source term", mesh=mesh, value = 0.)
    rho = 0.05
    q0 = 1 / (np.pi * rho ** 2)
    T = 0.3
    for i in range(sourceTerm().shape[0]):
        sourceTerm()[i] = q0 * np.exp( - ((mesh.cellCenters[0]()[i] - xs[0]) ** 2
                                       + (mesh.cellCenters[1]()[i] - xs[1]) ** 2 ) / (2 * rho **2)) * (time() < T)
    return sourceTerm
Ejemplo n.º 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)
Ejemplo n.º 15
0
def impulseResponse(argArray):
    # Extract arguments
    tStart = argArray[0]
    tFinal = argArray[1]
    k = argArray[2]
    # Initialize the impulse distribution
    phi = fipy.CellVariable(mesh=Mesh, name=r"$\rho(x,p)$")
    temp = numpy.zeros(((2 * Nx)**2, ))
    temp[k] = 1.
    norm = Dx * Dp
    phi.setValue(temp / norm)
    # Evolve the distribution
    response = evolution(phi, tStart, tFinal, '', False)
    return response
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
Ejemplo n.º 17
0
def get_var(params, ini, inf):
    """Make a variable with constraint

    Args:
      params: the parameter dictionary
      ini: initial value
      inf: far field value

    Returns:
      the variable
    """
    return pipe(
        params,
        lambda x: get_mesh(x["nx"], x["delta"]),
        lambda x: fipy.CellVariable(x, value=ini, hasOld=True),
        do(lambda x: x.constrain(inf, where=x.mesh.facesRight)),
    )
Ejemplo n.º 18
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)
Ejemplo n.º 19
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
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
    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
Ejemplo n.º 22
0
def get_vars(params, set_eta, mesh):
    """Get the variables

    Args:
      params: the parameter dict
      set_eta: function to set the initial value of the phase field
      mesh: the FiPy mesh

    Returns:
      a dictionary of the variables (eta, d2f)
    """
    return pipe(
        dict(
            eta=fp.CellVariable(mesh=mesh,
                                hasOld=True,
                                value=params["eta0"],
                                name="eta"),
            d2f=fp.FaceVariable(mesh=mesh, name="d2f"),
        ),
        do(set_eta(params, mesh)),
    )
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
Ejemplo n.º 25
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],
    )
Ejemplo n.º 26
0
    def _Execute(self):
        input = self.GetPolyDataInput()

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

        self.speed = fipy.CellVariable(name="speed", mesh=self.mesh, value=0.)
        self.BCs = (fipy.FixedValue(faces=self.mesh.getExteriorFaces(),
                                    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

        output = self.GetPolyDataOutput()
        output.ShallowCopy(input)
        speed = convert.numpy_to_vtk(self.speed.getValue())
        output.GetCellData().SetScalars(speed)
        return
Ejemplo n.º 27
0
    def __init__(self, section, **kwargs):
        BaseFiniteSolver.__init__(self, section, **kwargs)

        self._excess = None

        if not hasattr(section, "layers"):
            # We need to convert a layer to section
            section = Section(section)

        self.section = section

        self.mesh = self.create_mesh()

        self.initial_values = self.section.profile.into("kelvin")
        self.var = F.CellVariable(name="Temperature",
                                  mesh=self.mesh,
                                  value=self.initial_values,
                                  hasOld=(self.type == 'crank-nicholson'))

        self._exterior_flux = 0
        self.create_coefficient()

        if self.constraints is not None:
            self.set_constraints(*self.constraints)

        if self.type == "explicit":
            # Use stable timesteps if we're running explicit finite differences
            if self.time_step is not None:
                warn("For explicit finite differences, the "
                     "timestep is not user-adjustable")
            self.time_step = self.stable_timestep(0.05)

        if self.type == "crank-nicholson":
            eqns = [self.create_equation(i) for i in ("implicit", "explicit")]
            self.__implicit_equation = eqns[0]
            self.equation = sum(eqns)
        else:
            self.equation = self.create_equation(self.type)
Ejemplo n.º 28
0
    # scanf("%g") simulator
    # https://docs.python.org/3/library/re.html#simulating-scanf
    scanf_g = "[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?"
    pattern = ".*t=({g})\.tar\.gz".format(g=scanf_g)
    elapsed = re.match(pattern, params['restart']).group(1)
    elapsed = fp.Variable(name="$t$", value=float(elapsed))
else:
    Lx = params['Lx']
    Ly = params['Ly']

    dx, nx = _dnl(dx=params['dx'], nx=None, Lx=Lx)
    dy, ny = _dnl(dx=params['dx'], nx=None, Lx=Ly)

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

    phi = fp.CellVariable(mesh=mesh, name="$\phi$", value=0., hasOld=True)

    elapsed = fp.Variable(name="$t$", value=0.)
    
x, y = mesh.cellCenters[0], mesh.cellCenters[1]
X, Y = mesh.faceCenters[0], mesh.faceCenters[1]


# In[6]:


if isnotebook:
    viewer = fp.Viewer(vars=phi, datamin=0., datamax=1.)
    viewer.plot()

Ejemplo n.º 29
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)
Ejemplo n.º 30
0
        categories = dict()

    data = dummyTreant()

viscosity = 1
density = 100.
gravity = [params["gx"], params["gy"]]
pressureRelaxation = 0.8
velocityRelaxation = 0.5

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