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

        self.analytical_solver = HalfSpaceSolver(layer)

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

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

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

        self.var = F.CellVariable(name="Temperature", mesh=self.mesh, value=self.initial_values)
        self.var.constrain(t_min, self.mesh.facesLeft)
        self.var.constrain(t_max, self.mesh.facesRight)
        coefficient = self.material.diffusivity.into("m**2/s")
        self.equation = F.TransientTerm() == F.DiffusionTerm(coeff=coefficient)
Ejemplo n.º 2
0
	def createLinearMesh(self, sections, Acs, As): 
		""" Define mesh """
		# Cross sectional area
		self.AcsMult = Acs
		# Area multiplier for face area
		self.areaMult = Acs
		# Surface area per unit length
		self.As = As
		# Create the meshes and emissivity calculator for each segment
		self.emissivityCalculator = sm.SectionCalculator()
		dx = []		
		i = 0
		for sec in sections:
			numElements = np.ceil(sec['length'] / sec['meshSize'])			
			self.emissivityCalculator.addSection(
					(i, i + numElements - 1), 
					sm.Interpolator1D([sec['temperature1'], sec['temperature2']], [sec['emissivity1'], sec['emissivity2']])
			)
			dx += [sec['length'] / numElements] * numElements
			i += numElements
		self.radiation['emissivity'] = np.zeros((len(dx)))
		self.mesh = fp.Grid1D(dx = dx)
		self.meshType = 'Linear'
		# Define variable
		self.T = fp.CellVariable(name = "temperature",
			mesh = self.mesh, value = 0.)
		self.thermCond = fp.FaceVariable(mesh = self.mesh)
		self.emissivity = fp.CellVariable(mesh = self.mesh)
Ejemplo n.º 3
0
    def test_linear_poison_solver(self):
        ''' Compare the result of the poison solution with
            analytical result.
        '''

        # Electrical properties
        n_eff = 5e12  # Effective doping concentration
        rho = constants.elementary_charge * n_eff * (
            1e-4)**3  # Charge density in C / um3
        epsilon = constant.epsilon_s * 1e-6  # Permitticity of silicon in F/um

        # External voltages in V
        V_read = -0

        # Geometry
        dx = 0.01  # Grid spacing / resolution
        L = 200.  # Length of simulation domain / width of sensor in um

        # Create mesh
        nx = L / dx  # Number of space points
        mesh = fipy.Grid1D(dx=np.ones((int(nx), )) * dx, nx=nx)
        X = np.array(mesh.getFaceCenters()[0, :])

        for V_bias in range(-10, -200, -20):
            # Get 1D potential with numerical solver
            potential = potential_1D.get_potential(mesh, rho, epsilon, L,
                                                   V_read, V_bias)

            # Get correct analytical solution
            potential_a = fields.get_potential_planar_analytic_1D(
                X, V_bias=V_bias, V_readout=V_read, n_eff=n_eff, D=L)

            self.assertTrue(np.allclose(potential, potential_a[:-1],
                                        atol=1e-1))
Ejemplo n.º 4
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.º 5
0
def get_mesh(ncells, delta):
    """Make the mesh

    Args:
      ncells: number of cells
      delta: the domain size

    Returns:
      the mesh
    """
    return fipy.Grid1D(nx=ncells, dx=delta / ncells)
Ejemplo n.º 6
0
 def initialise_mesh(self):
     if self.has_obstacles():
         self.mesh = make_porous_mesh(self.rc, self.Rc, self.dx, self.L)
     elif self.dim == 1:
         self.mesh = fipy.Grid1D(Lx=self.L[0],
                                 dx=self.dx[0],
                                 origin=(-self.L[0] / 2.0, ))
     elif self.dim == 2:
         self.mesh = fipy.Grid2D(Lx=self.L[0],
                                 Ly=self.L[1],
                                 dx=self.dx[0],
                                 dy=self.dx[1],
                                 origin=((-self.L[0] / 2.0, ),
                                         (-self.L[1] / 2.0, )))
Ejemplo n.º 7
0
def create_1D_planar_sensor():
    # Electrical properties
    n_eff = 5e12  # Effective doping concentration
    rho = constants.elementary_charge * n_eff * \
        (1e-4) ** 3  # Charge density in C / um3
    epsilon = constant.epsilon_s * 1e-6  # Permitticity of silicon in F/um

    # External voltages in V
    V_bias = -200.
    V_read = -0

    # Geometry
    dx = 0.01  # Grid spacing / resolution
    L = 200.  # Length of simulation domain / width of sensor in um

    # Create mesh
    nx = L / dx  # Number of space points
    mesh = fipy.Grid1D(dx=np.ones((int(nx), )) * dx, nx=nx)
    X = np.array(mesh.getFaceCenters()[0, :])

    # Get 1D potential with numerical solver
    potential = get_potential(mesh, rho, epsilon, L, V_read, V_bias)

    # Get correct analytical solution
    potential_a = fields.get_potential_planar_analytic_1D(
        X, V_bias=V_bias, V_readout=V_read, n_eff=n_eff, D=L)

    # Get depletion width from empiric formular in um
    x_dep = silicon.get_depletion_depth(
        abs(V_bias), n_eff, temperature=300) * 1e6

    # Plot result
    plt.plot(X, potential_a, '--', linewidth=2, label='Analytic solution')
    plt.plot(np.array(mesh.getFaceCenters()[0, :]), np.array(
        potential.arithmeticFaceValue()), '-', label='Numeric solution')
    plt.plot([x_dep, x_dep], plt.ylim(), '--',
             linewidth=2., label='Depletion zone')
    plt.plot(plt.xlim(), [V_bias, V_bias], '--',
             linewidth=2., label='Bias voltage')
    plt.xlabel('Position [um]')
    plt.ylabel('Potential [V]')
    plt.grid()
    plt.legend(loc=0)
    plt.title('Potential of a %sfully depleted planar silicon sensor\
                with full fill factor' % ('not ' if x_dep < L else ''))
    plt.show()
Ejemplo n.º 8
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.º 9
0
 def createLinearMesh(self, L, n=100):
     """ Creates 1D mesh """
     dx = float(L) / n
     self.mesh = fp.Grid1D(nx=n, dx=dx)
     self.meshType = 'Linear'
Ejemplo n.º 10
0
def hydro_1d_fipy(theta_ini, nx, dx, dt, params, ndays, sensor_loc,
                  boundary_values_left, boundary_values_right, precip,
                  evapotra, ele_interp, peat_depth):
    def zeta_from_theta(x, b):
        return np.log(np.exp(s2 * b) + s2 * np.exp(-s1) * x) / s2

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

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

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

    source = precip[0] - evapotra[0]

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

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

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

    theta_sol_list = []  # returned quantity

    MAX_SWEEPS = 10000

    for day in range(ndays):

        theta.updateOld()

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

        source = precip[day] - evapotra[day]

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

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

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

        theta_sol_list.append(theta_sol_sensors[0])

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

    return zeta_from_theta_sol_sensors
Ejemplo n.º 11
0
#   5) Solve Boussinesq eq in both forms and compare results


"""
Choice: theta(h) = exp(s0 + s1*h)
"""
#   1) theta(h) = exp(a + b*h); T(h) = t0 + exp(t1*h**t2)
#   2) S(h) = s1*exp(s0 + s1*h)
#   3) S(theta) = s1*theta
#   4) D(theta) = t0/s1 * exp(t1* ((ln(theta) -s0)/s1)**t2 - ln(theta))

nx = 300
dx = 1
dt = 10.

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

s0 = 0.1; s1 = 0.2
t0 = 1.; t1 = 0.01; t2 = 1.1

# IC
hini = 1.

h = fp.CellVariable(name="head", mesh=mesh, value=hini, hasOld=True)
h_implicit_source = fp.CellVariable(name="head_implicit_source", mesh=mesh, value=hini, hasOld=True)
h_convection = fp.CellVariable(name="head_convection", mesh=mesh, value=hini, hasOld=True)
theta = fp.CellVariable(name="theta", mesh=mesh, value=numerix.exp(s0 + s1*h.value), hasOld=True)

T = t0 * numerix.exp(t1 * h**t2)
S = s1 * numerix.exp(s0 + s1 * h) # and S_theta = s1 * theta
D = t0/s1 * numerix.exp(t1* ((numerix.log(theta) -s0)/s1)**t2)/ theta