Beispiel #1
0
 def define_facemirrors(
     self, phi_s_initial, phi_e_initial
 ):  # Facemirrors are copies of the variables solved on the axial meshes..
     self.phi_s_facemirror = FaceVariable(
         mesh=self.p2d_mesh, value=phi_s_initial
     )  # ..and applied to the upper face of the p2d mesh in each domain
     self.phi_e_facemirror = FaceVariable(mesh=self.p2d_mesh,
                                          value=phi_e_initial)
     self.j0_facemirror = FaceVariable(mesh=self.p2d_mesh, value=self.j0[0])
Beispiel #2
0
 def Cs_p2d_diffcoeff_function(self):
     self.Cs_p2d_diffCoeff = FaceVariable(
         mesh=self.p2d_mesh, rank=2, value=[[[0., 0.], [0., 0.]]]
     )  # As always with FiPy, diffusion coefficients are defined on the faces (hence facevar)
     self.numerixed_Cs_p2d_diffCoeff = numerix.array(
         self.Cs_p2d_diffCoeff
     )  # Temporarily convert to a NumPy array to edit the values
     (self.numerixed_Cs_p2d_diffCoeff[1][1]) = self.Ds * (
         self.radial_faces**2.0
     ) / self.Rs  # Assign a non-zero value to the diff. coefficient in the y-axis only..
     self.Cs_p2d_diffCoeff = FaceVariable(
         mesh=self.p2d_mesh, rank=2, value=self.numerixed_Cs_p2d_diffCoeff
     )  # ..which constrains diffusion to 1D. Now recreate the facevar with the new value
Beispiel #3
0
 def _genTorque(self):
     """Generate Torque"""
     self.Lambda = FaceVariable(name='Torque at cell faces', mesh=self.mesh, rank=1)
     self.LambdaCell = CellVariable(name='Torque at cell centers', mesh=self.mesh)
     LambdaArr = np.zeros(self.rF.shape)
     LambdaArr[1:] = self.chi*np.power(1.0/(self.rF[1:]*self.gamma-1.0), 4)
     #LambdaArr[self.gap] = 0.0; LambdaArr[self.gap] = LambdaArr.max()
     self.Lambda.setValue(LambdaArr)
     self.LambdaCell.setValue(self.chi*np.power(1.0/(self.r*self.gamma-1.0), 4))
     self.LambdaCell[np.where(self.LambdaCell > LambdaArr.max())] = LambdaArr.max()
Beispiel #4
0
    def Battery_facevariables(self, neg_De_eff, sep_De_eff, pos_De_eff,
                              neg_epsilon_e, sep_epsilon_e, pos_epsilon_e,
                              normalised_neg_length, normalised_sep_length):
        self.De_eff = FaceVariable(
            mesh=self.axial_mesh
        )  # Define effective diffusion coefficient as a FiPy facevariable
        self.De_eff.setValue(
            neg_De_eff,
            where=(self.axial_mesh.faceCenters[0] <= normalised_neg_length)
        )  # Set its value to that for the neg. diff. coefficient in the negative electrode domain
        self.De_eff.setValue(
            sep_De_eff,
            where=((
                normalised_neg_length  # Set its value to the correct value in the separator
                < self.axial_mesh.faceCenters[0]) &
                   (self.axial_mesh.faceCenters[0] <
                    (normalised_neg_length + normalised_sep_length))))
        self.De_eff.setValue(
            pos_De_eff,
            where=(
                self.axial_mesh.faceCenters[
                    0]  # Set its value to the correct value in the positive electrode domain
                >= (normalised_neg_length + normalised_sep_length)))

        self.epsilon_e_eff_facevariable = FaceVariable(
            mesh=self.axial_mesh
        )  # Define electrolyte phase volume fraction as a FiPy facevariable
        self.epsilon_e_eff_facevariable.setValue(
            neg_epsilon_e**self.
            brug,  # Compute eff. value for neg. domain & set it in neg. electrode domain
            where=(self.axial_mesh.faceCenters[0] <= normalised_neg_length))
        self.epsilon_e_eff_facevariable.setValue(
            sep_epsilon_e**self.
            brug,  # Compute eff. value for sep. domain & set it in sep. electrode domain
            where=((normalised_neg_length < self.axial_mesh.faceCenters[0]) &
                   (self.axial_mesh.faceCenters[0] <
                    (normalised_neg_length + normalised_sep_length))))
        self.epsilon_e_eff_facevariable.setValue(
            pos_epsilon_e**self.
            brug,  # Compute eff. value for pos. domain & set it in pos. electrode domain
            where=(self.axial_mesh.faceCenters[0] >=
                   (normalised_neg_length + normalised_sep_length)))
Beispiel #5
0
    def Battery_cellvariables(self, neg_epsilon_e, sep_epsilon_e,
                              pos_epsilon_e, neg_a_s, pos_a_s, nx_neg, nx_sep,
                              nx_pos, j_battery_value, ce_initial,
                              phi_e_initial, neg_L, sep_L, pos_L, neg_De_eff,
                              sep_De_eff, pos_De_eff):
        self.Ce = CellVariable(mesh=self.axial_mesh,
                               value=ce_initial,
                               hasOld=True)
        self.phi_e = CellVariable(mesh=self.axial_mesh, value=phi_e_initial)

        self.epsilon_e_value = numerix.zeros(nx_neg + nx_sep + nx_pos)
        self.epsilon_e_value[0:nx_neg], self.epsilon_e_value[
            nx_neg:nx_neg + nx_sep] = neg_epsilon_e, sep_epsilon_e
        self.epsilon_e_value[nx_neg + nx_sep:] = pos_epsilon_e
        self.epsilon_e = CellVariable(mesh=self.axial_mesh,
                                      value=self.epsilon_e_value)

        self.epsilon_e_eff_value = numerix.zeros(nx_neg + nx_sep + nx_pos)
        self.epsilon_e_eff_value[0:nx_neg] = neg_epsilon_e**self.brug
        self.epsilon_e_eff_value[nx_neg:nx_neg +
                                 nx_sep] = sep_epsilon_e**self.brug
        self.epsilon_e_eff_value[nx_neg + nx_sep:] = pos_epsilon_e**self.brug
        self.epsilon_e_eff = CellVariable(mesh=self.axial_mesh,
                                          value=self.epsilon_e_eff_value)

        self.a_s_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.a_s_value[0:nx_neg] = neg_a_s
        self.a_s_value[nx_neg:nx_neg + nx_sep] = 0.0
        self.a_s_value[nx_neg + nx_sep:] = pos_a_s
        self.a_s = CellVariable(mesh=self.axial_mesh, value=self.a_s_value)

        self.L_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.L_value[0:nx_neg], self.L_value[nx_neg:nx_neg +
                                             nx_sep] = neg_L, sep_L
        self.L_value[nx_neg + nx_sep:] = pos_L
        self.L = CellVariable(mesh=self.axial_mesh, value=self.L_value)

        self.De_eff_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.De_eff_value[0:nx_neg], self.De_eff_value[
            nx_neg:nx_neg + nx_sep], self.De_eff_value[
                nx_neg + nx_sep:] = neg_De_eff, sep_De_eff, pos_De_eff
        self.De_eff = CellVariable(mesh=self.axial_mesh,
                                   value=self.De_eff_value)

        self.j_battery = CellVariable(mesh=self.axial_mesh,
                                      value=j_battery_value)
Beispiel #6
0
 def initializeDiagnostic(self,
                          variable,
                          funpointer,
                          default=0.0,
                          face_variable=False,
                          output_variable=True):
     if not face_variable:
         self.variables[variable] = CellVariable(name=variable,
                                                 mesh=self.mesh.mesh,
                                                 value=default)
     else:
         self.variables[variable] = FaceVariable(name=variable,
                                                 mesh=self.mesh.mesh,
                                                 value=default)
     self.diagnostic_modules[variable] = DiagnosticModule(funpointer, self)
     if output_variable:
         self.variables_store.append(variable)
     self.diagnostic_update_order.append(variable)
Beispiel #7
0
class Battery():
    def __init__(
            self, cell_temperature_celcius, capacity_Ah, bruggeman_coefficient,
            charge_transfer_coefficient, current_collector_cross_section_area,
            electrolyte_diffusivity,
            transference_number):  # Initialises physical properties of cell

        ########################################## Compute & Assign Constants ##################################################
        self.T = 273.0 + cell_temperature_celcius  # Could move into electrode-level later
        self.Q = capacity_Ah * 3600.0
        self.brug = bruggeman_coefficient  # Could move into electrode-level later when electrodes may have unique brug. values
        self.alpha = charge_transfer_coefficient  # Could move into electrode-level later when electrodes may have unique alpha values
        self.A = current_collector_cross_section_area
        self.De = electrolyte_diffusivity
        self.t_plus = transference_number

    def Battery_scale_quantities(self, overall_thickness, kappa_string):
        # self.L = overall_thickness
        self.kappa = lambdify(
            Ce, sympify(kappa_string), "numpy"
        )  # Function to return electrolyte electrical conductivity, given a species concentration
        # NOTE: Consider changing this function's name since it's only the kappa definition now

######################################## Battery-level Mesh Generation #################################################

    def define_global_mesh(self, node_spacing, normalised_domain_thickness
                           ):  # Only Ce & phi_e are solved on this mesh
        self.dx = node_spacing  # node_spacing vector passed can be either uniformly or non-uniformly spaced points
        self.L_normalised = normalised_domain_thickness
        self.axial_mesh = Grid1D(Lx=self.L_normalised, dx=self.dx)

    def Battery_cellvariables(self, neg_epsilon_e, sep_epsilon_e,
                              pos_epsilon_e, neg_a_s, pos_a_s, nx_neg, nx_sep,
                              nx_pos, j_battery_value, ce_initial,
                              phi_e_initial, neg_L, sep_L, pos_L, neg_De_eff,
                              sep_De_eff, pos_De_eff):
        self.Ce = CellVariable(mesh=self.axial_mesh,
                               value=ce_initial,
                               hasOld=True)
        self.phi_e = CellVariable(mesh=self.axial_mesh, value=phi_e_initial)

        self.epsilon_e_value = numerix.zeros(nx_neg + nx_sep + nx_pos)
        self.epsilon_e_value[0:nx_neg], self.epsilon_e_value[
            nx_neg:nx_neg + nx_sep] = neg_epsilon_e, sep_epsilon_e
        self.epsilon_e_value[nx_neg + nx_sep:] = pos_epsilon_e
        self.epsilon_e = CellVariable(mesh=self.axial_mesh,
                                      value=self.epsilon_e_value)

        self.epsilon_e_eff_value = numerix.zeros(nx_neg + nx_sep + nx_pos)
        self.epsilon_e_eff_value[0:nx_neg] = neg_epsilon_e**self.brug
        self.epsilon_e_eff_value[nx_neg:nx_neg +
                                 nx_sep] = sep_epsilon_e**self.brug
        self.epsilon_e_eff_value[nx_neg + nx_sep:] = pos_epsilon_e**self.brug
        self.epsilon_e_eff = CellVariable(mesh=self.axial_mesh,
                                          value=self.epsilon_e_eff_value)

        self.a_s_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.a_s_value[0:nx_neg] = neg_a_s
        self.a_s_value[nx_neg:nx_neg + nx_sep] = 0.0
        self.a_s_value[nx_neg + nx_sep:] = pos_a_s
        self.a_s = CellVariable(mesh=self.axial_mesh, value=self.a_s_value)

        self.L_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.L_value[0:nx_neg], self.L_value[nx_neg:nx_neg +
                                             nx_sep] = neg_L, sep_L
        self.L_value[nx_neg + nx_sep:] = pos_L
        self.L = CellVariable(mesh=self.axial_mesh, value=self.L_value)

        self.De_eff_value = numerix.zeros(nx_neg + nx_pos + nx_sep)
        self.De_eff_value[0:nx_neg], self.De_eff_value[
            nx_neg:nx_neg + nx_sep], self.De_eff_value[
                nx_neg + nx_sep:] = neg_De_eff, sep_De_eff, pos_De_eff
        self.De_eff = CellVariable(mesh=self.axial_mesh,
                                   value=self.De_eff_value)

        self.j_battery = CellVariable(mesh=self.axial_mesh,
                                      value=j_battery_value)

############################# Define Eff. Diff. Coefficients & Volume Fractions ########################################

    def Battery_facevariables(self, neg_De_eff, sep_De_eff, pos_De_eff,
                              neg_epsilon_e, sep_epsilon_e, pos_epsilon_e,
                              normalised_neg_length, normalised_sep_length):
        self.De_eff = FaceVariable(
            mesh=self.axial_mesh
        )  # Define effective diffusion coefficient as a FiPy facevariable
        self.De_eff.setValue(
            neg_De_eff,
            where=(self.axial_mesh.faceCenters[0] <= normalised_neg_length)
        )  # Set its value to that for the neg. diff. coefficient in the negative electrode domain
        self.De_eff.setValue(
            sep_De_eff,
            where=((
                normalised_neg_length  # Set its value to the correct value in the separator
                < self.axial_mesh.faceCenters[0]) &
                   (self.axial_mesh.faceCenters[0] <
                    (normalised_neg_length + normalised_sep_length))))
        self.De_eff.setValue(
            pos_De_eff,
            where=(
                self.axial_mesh.faceCenters[
                    0]  # Set its value to the correct value in the positive electrode domain
                >= (normalised_neg_length + normalised_sep_length)))

        self.epsilon_e_eff_facevariable = FaceVariable(
            mesh=self.axial_mesh
        )  # Define electrolyte phase volume fraction as a FiPy facevariable
        self.epsilon_e_eff_facevariable.setValue(
            neg_epsilon_e**self.
            brug,  # Compute eff. value for neg. domain & set it in neg. electrode domain
            where=(self.axial_mesh.faceCenters[0] <= normalised_neg_length))
        self.epsilon_e_eff_facevariable.setValue(
            sep_epsilon_e**self.
            brug,  # Compute eff. value for sep. domain & set it in sep. electrode domain
            where=((normalised_neg_length < self.axial_mesh.faceCenters[0]) &
                   (self.axial_mesh.faceCenters[0] <
                    (normalised_neg_length + normalised_sep_length))))
        self.epsilon_e_eff_facevariable.setValue(
            pos_epsilon_e**self.
            brug,  # Compute eff. value for pos. domain & set it in pos. electrode domain
            where=(self.axial_mesh.faceCenters[0] >=
                   (normalised_neg_length + normalised_sep_length)))
Beispiel #8
0
#run gmsh gui to produce this mesh (.msh file)
#gmsh infiniteCylinder01.geo
filename = 'infiniteCylinder01.msh'
mesh = Gmsh2D(filename, communicator=serialComm)
del filename

T_initial = 425.08  #deg K

var = CellVariable(mesh=mesh, value=T_initial)

rho = 6980.  #kg/m^3
cp = 227.  #J/kg/K
k = 59.6  #W/m/K
D_thermal = k / rho / cp

D = FaceVariable(mesh=mesh, value=D_thermal)

eq = TransientTerm() == DiffusionTerm(coeff=D)

X_faces, Y_faces = mesh.faceCenters

surfaceFaces = (Y_faces > 0) & (
    (X_faces**2 + Y_faces**2)**.5 > R_outer - cellSize / 10.)

#convectionCoeff=200.  #W/m^2/K
Bi_desired = 10.
convectionCoeff = Bi_desired * k / R_inner
logging.info('convection coefficient is %.2E' % convectionCoeff)

Bi = convectionCoeff * R_inner / k  #Biot number
logging.info('Biot number is %.2E' % Bi)
Beispiel #9
0
nx = 10
ny = 1

valueLeft = 0.
fluxRight = 1.
timeStepDuration = 1.

L = 10.

dx = L / nx
dy = 1.

mesh = Tri2D(dx, dy, nx, ny)

var = CellVariable(name="solution variable", mesh=mesh, value=valueLeft)

diffCoeff = FaceVariable(mesh=mesh, value=1.0)

x = mesh.faceCenters[0]
diffCoeff.setValue(0.1, where=(L / 4. <= x) & (x < 3. * L / 4.))

var.faceGrad.constrain([[1.], [0.]], mesh.facesRight)

var.constrain(valueLeft, mesh.facesLeft)

if __name__ == '__main__':
    import fipy.tests.doctestPlus
    exec(fipy.tests.doctestPlus._getScript())
    input('finished')
Beispiel #10
0
c0[20:50] = 1.0

# mobile domain concentration
cm = CellVariable(name="$c_m$", mesh=m, value=c0)

# immobile domain concentration
cim = CellVariable(name="$c_{im}$", mesh=m, value=0.0)

cm.constrain(0, m.facesLeft)
cm.constrain(0, m.facesRight)

cim.constrain(0, m.facesLeft)
cim.constrain(0, m.facesRight)

# advective flow velocity 
u = FaceVariable(mesh=m, value=(0.0,), rank=1)

# 1D convection diffusion equation (mobile domain)
# version with \frac{\partial c_{im}}{\partial t}
eqM =  (TransientTerm(1.0,var=cm) + TransientTerm(betaT,var=cim) == 
       DiffusionTerm(DR,var=cm) - ExponentialConvectionTerm(u/(Rm*phim),var=cm))

# immobile domain (lumped approach)
eqIM = TransientTerm(Rim*phiim,var=cim) == beta/Rim*(cm - ImplicitSourceTerm(1.0,var=cim))

# couple equations
eqn = eqM & eqIM

viewer = Viewer(vars=(cm,cim), datamin=0.0, datamax=1.0)
viewer.plot()
time = 0.0
Beispiel #11
0
nx = 800
cfl = 0.1
K = 4.
rho = 1.

dx = L / nx
m = Grid1D(nx=nx, dx=dx) + X0
x, = m.cellCenters

q = CellVariable(mesh=m, rank=1, elementshape=(2, ))

q[0, :] = numerix.exp(-50 * (x - 0.3)**2) * numerix.cos(20 * (x - 0.3))
q[0, x > 0.3] = 0.

Ax = FaceVariable(mesh=m,
                  rank=3,
                  value=[((0, K), (1 / rho, 0))],
                  elementshape=(1, 2, 2))

eqn = TransientTerm() + CentralDifferenceConvectionTerm(Ax) == 0

if __name__ == '__main__':
    from fipy import MatplotlibViewer as Viewer
    vi = Viewer((q[0], q[1]))
    vi.plot()

for step in range(500):
    eqn.solve(q, dt=cfl * dx)
    if step % 10 == 0 and __name__ == '__main__':
        vi.plot()

if __name__ == '__main__':
'''.format(cellSize, l1, l2,
           math.tan(beta) * (l2 - l1), l3,
           math.tan(alpha) * l3)

mesh = Gmsh3D(geometryTemplate)

phi = CellVariable(name="Pressure", mesh=mesh, value=P0)

# Berechnete Werte ------------------------------------------------------------

Dx = material["k_x"] * fluid["dichte"]
Dy = material["k_y"] * fluid["dichte"]
Dz = material["k_y"] * fluid["dichte"]

# D ist eine Face Variable, da der Koeffizient für jede Flaeche einzelnd berechenet wird
D = FaceVariable(mesh=mesh, value=((Dx, 0, 0), (0, Dy, 0), (0, 0, Dz)))

# boundry conditions ----------------------------------------------------------

phi.constrain(Pres, where=mesh.physicalFaces["inner"])
phi.constrain(Pamb, where=mesh.physicalFaces["outer"])

# Solving ---------------------------------------------------------------------

eq = DiffusionTerm(coeff=D)
sweep = 0

phi_old = phi.copy()

max_diff = 10e10
Beispiel #13
0
class Circumbinary(object):
    def __init__(self, rmax=1.0e4, ncell=300, dt=1.0e-6, delta=1.0e-100,
                 fudge=1.0e-3, q=1.0, gamma=100, mdisk=0.1, odir='output',
                 bellLin=True, emptydt=0.001, **kargs):
        self.rmax = rmax
        self.ncell = ncell
        self.dt = dt
        self.delta = delta
        self.mDisk = mdisk
        Omega0 = (G*M/(gamma*a)**3)**0.5
        nu0 = alpha*cs**2/Omega0
        self.chi = 2*fudge*q**2*np.sqrt(G*M)/nu0/a*(gamma*a)**1.5
        self.T0 = mu*Omega0/alpha/k*nu0
        self.gamma = gamma
        self.fudge = fudge
        self.q = q
        self.nu0 = nu0
        self.t = 0.0
        self.odir = odir
        self.bellLin = bellLin
        self.emptydt = emptydt
        self._genGrid()
        self.r = self.mesh.cellCenters.value[0]
        self.rF = self.mesh.faceCenters.value[0]
        if self.q > 0.0:
            self.gap = np.where(self.rF < 1.7/gamma)
        else:
            self.gap = np.where(self.rF < 1.0/gamma)
        self._genSigma()
        self._genTorque()
        self._genT(bellLin=self.bellLin, **kargs)
        self._genVr()
        self._buildEq()

    def _genGrid(self, inB=1.0):
        """Generate a logarithmically spaced grid"""
        logFaces = np.linspace(-np.log(self.gamma/inB), np.log(self.rmax), num=self.ncell+1)
        logFacesLeft = logFaces[:-1]
        logFacesRight = logFaces[1:]
        dr = tuple(np.exp(logFacesRight) - np.exp(logFacesLeft))
        self.mesh = CylindricalGrid1D(dr=dr, origin=(inB/self.gamma,))

    def _genSigma(self, width=0.1):
        """Create dependent variable Sigma"""
        # Gaussian initial condition
        value = self.mDisk*M/np.sqrt(2*np.pi)/(self.gamma*a*width)*\
                np.exp(-0.5*np.square(self.r-1.0)/width**2)/(2*np.pi*self.gamma*self.r*a)
        # Make it dimensionless
        value /= self.mDisk*M/(self.gamma*a)**2
        idxs = np.where(self.r < 0.1)
        value[idxs] = 0.0
        value = tuple(value)

        # Create the dependent variable and set the boundary conditions
        # to zero
        self.Sigma = CellVariable(name='Surface density',
                                 mesh=self.mesh, hasOld=True, value=value)
        #self.Sigma.constrain(0, self.mesh.facesLeft)
        #self.Sigma.constrain(0, self.mesh.facesRight)

    def _genTorque(self):
        """Generate Torque"""
        self.Lambda = FaceVariable(name='Torque at cell faces', mesh=self.mesh, rank=1)
        self.LambdaCell = CellVariable(name='Torque at cell centers', mesh=self.mesh)
        LambdaArr = np.zeros(self.rF.shape)
        LambdaArr[1:] = self.chi*np.power(1.0/(self.rF[1:]*self.gamma-1.0), 4)
        #LambdaArr[self.gap] = 0.0; LambdaArr[self.gap] = LambdaArr.max()
        self.Lambda.setValue(LambdaArr)
        self.LambdaCell.setValue(self.chi*np.power(1.0/(self.r*self.gamma-1.0), 4))
        self.LambdaCell[np.where(self.LambdaCell > LambdaArr.max())] = LambdaArr.max()

    def _interpT(self):
        """
        Get an initial guess for T using an interpolation of the solutions for T
        in the various thermodynamic limits.
        """
        Lambda = self.Lambda/self.chi*self.fudge*self.q**2*G*M/a
        LambdaCell = self.LambdaCell/self.chi*self.fudge*self.q**2*G*M/a
        Sigma = self.Sigma*M/(self.gamma*a)**2
        r = self.r*a*self.gamma #In physical units (cgs)
        self.Omega = np.sqrt(G*M/r**3)
        self.TvThin = np.power(9.0/4*alpha*k/sigma/mu/kappa0*self.Omega, 1.0/(3.0+beta))
        self.TtiThin = np.power(1/sigma/kappa0*(OmegaIn-self.Omega)*LambdaCell, 1.0/(4.0+beta))
        self.Ti = np.power(np.square(eta/7*L/4/np.pi/sigma)*k/mu/G/M*r**(-3), 1.0/7)
        self.TvThick = np.power(27.0/64*kappa0*alpha*k/sigma/mu*self.Omega*Sigma**2, 1.0/(3.0-beta))
        self.TtiThick = np.power(3*kappa0/16/sigma*Sigma**2*(OmegaIn-self.Omega)*LambdaCell, 1.0/(4.0-beta))
        #return np.power(self.TvThin**4 + self.TvThick**4 + self.TtiThin**4 + self.TtiThick**4 + self.Ti**4, 1.0/4)/self.T0
        return np.power(self.TvThin**4 + self.TvThick**4 + self.Ti**4, 1.0/4)/self.T0

    def _genT(self, bellLin=True, **kargs):
        """Create a cell variable for temperature"""
        if bellLin:
            @pickle_results(os.path.join(self.odir, "interpolator.pkl"))
            def buildInterpolator(r, gamma, q, fudge, mDisk, **kargs):
                # Keep in mind that buildTemopTable() returns the log10's of the values
                rGrid, SigmaGrid, temp = thermopy.buildTempTable(r*a*gamma, q=q, f=fudge, **kargs)
                # Go back to dimensionless units
                rGrid -= np.log10(a*gamma)
                SigmaGrid -= np.log10(mDisk*M/gamma**2/a**2)
                # Get the range of values for Sigma in the table
                rangeSigma = (np.power(10.0, SigmaGrid.min()), np.power(10.0, SigmaGrid.max()))
                # Interpolate in the log of dimensionless units
                return rangeSigma, RectBivariateSpline(rGrid, SigmaGrid, temp)
            # Pass the radial grid in phsyical units
            # Get back interpolator in logarithmic space
            rangeSigma, log10Interp = buildInterpolator(self.r, self.gamma, self.q, self.fudge, self.mDisk, **kargs)
            rGrid = np.log10(self.r)
            SigmaMin = np.ones(rGrid.shape)*rangeSigma[0]
            SigmaMax = np.ones(rGrid.shape)*rangeSigma[1]
            r = self.r*a*self.gamma #In physical units (cgs)
            self.Omega = np.sqrt(G*M/r**3)
            Ti = np.power(np.square(eta/7*L/4/np.pi/sigma)*k/mu/G/M*r**(-3), 1.0/7)
            T = np.zeros(Ti.shape)
            # Define wrapper function that uses the interpolator and stores the results
            # in an array given as a second argument. It can handle zero or negative
            # Sigma values.
            def func(Sigma):
                good = np.logical_and(Sigma > rangeSigma[0], Sigma < rangeSigma[1])
                badMin = np.logical_and(True, Sigma < rangeSigma[0])
                badMax = np.logical_and(True, Sigma > rangeSigma[1])
                if np.sum(good) > 0:
                    T[good] = np.power(10.0, log10Interp.ev(rGrid[good], np.log10(Sigma[good])))
                if np.sum(badMin) > 0:
                    T[badMin] = np.power(10.0, log10Interp.ev(rGrid[badMin], np.log10(SigmaMin[badMin])))
                if np.sum(badMax) > 0:
                    raise ValueError("Extrapolation to large values of Sigma is not allowed, build a table with a larger Sigmax")
                    T[badMax] = np.power(10.0, log10Interp.ev(rGrid[badMax], np.log10(SigmaMax[badMax])))
                return T
            # Store interpolator as an instance method
            self._bellLinT = func
            # Save the temperature as an operator variable
            self.T = self.Sigma._UnaryOperatorVariable(lambda x: self._bellLinT(x))

        # Initialize T with the interpolation of the various thermodynamic limits
        else:
            self.T = self._interpT()

    def _genVr(self):
        """Generate the face variable that stores the velocity values"""
        r = self.r #In dimensionless units (cgs)
        # viscosity at cell centers in cgs
        self.nu = alpha*k/mu/self.Omega/self.nu0*self.T
        self.visc = r**0.5*self.nu*self.Sigma
        #self.visc.grad.constrain([self.visc/2/self.r[0]], self.mesh.facesLeft)
        #self.Sigma.constrain(self.visc.grad/self.nu*2*self.r**0.5, where=self.mesh.facesLeft)
        # I add the delta to avoid divisions by zero
        self.vrVisc = -3/self.rF**(0.5)/(self.Sigma.faceValue + self.delta)*self.visc.faceGrad
        if self.q > 0.0:
            self.vrTid = self.Lambda*np.sqrt(self.rF)

    def _buildEq(self):
        """
        Build the equation to solve, we can change this method to impelement other
        schemes, e.g. Crank-Nicholson.
        """
        # The current scheme is an implicit-upwind
        if self.q > 0.0:
            self.vr = self.vrVisc + self.vrTid
            self.eq = TransientTerm(var=self.Sigma) == - ExplicitUpwindConvectionTerm(coeff=self.vr, var=self.Sigma)
        else:
            self.vr = self.vrVisc
            mask_coeff = (self.mesh.facesLeft * self.mesh.faceNormals).getDivergence()
            self.eq = TransientTerm(var=self.Sigma) == - ExplicitUpwindConvectionTerm(coeff=self.vr, var=self.Sigma)\
                                                       - mask_coeff*3.0/2*self.nu/self.mesh.x*self.Sigma.old

    def dimensionalSigma(self):
        """
        Return Sigma in dimensional form (cgs)
        """
        return self.Sigma.value*self.mDisk*M/(self.gamma*a)**2

    def dimensionalFJ(self):
        """
        Return the viscous torque in dimensional units (cgs)
        """
        return 3*np.pi*self.nu.value*self.nu0*self.dimensionalSigma()*np.sqrt(G*M*self.r*a*self.gamma)

    def dimensionalTime(self, t=None, mode='yr'):
        """
        Return current time in dimensional units (years or seconds)
        """
        if t == None:
            t = self.t
        if mode == 'yr' or mode == 'years' or mode == 'year':
            return t*(a*self.gamma)**2/self.nu0/(365*24*60*60)
        else:
            return t*(a*self.gamma)**2/self.nu0

    def dimensionlessTime(self, t, mode='yr'):
        """
        Returns the dimensionless value of the time given as an argument
        """
        if mode == 'yr' or mode == 'years' or mode == 'year':
            return t/(a*self.gamma)**2*self.nu0*(365*24*60*60)
        else:
            return t/(a*self.gamma)**2*self.nu0

    def singleTimestep(self, dtMax=0.001, dt=None, update=True, emptyDt=False):
        """
        Evolve the system for a single timestep of size `dt`
        """
        if dt:
            self.dt = dt
        if emptyDt:
            vr = self.vr.value[0]
            if self.q == 0.0:
                vr[0] = -3.0/2*self.nu.faceValue.value[0]/self.rF[0]
            #vr[np.where(self.Sigma.value)] = self.delta
            self.flux = self.rF[1:]*vr[1:]-self.rF[:-1]*vr[:-1]
            self.flux = np.maximum(self.flux, self.delta)
            self.dts = self.mesh.cellVolumes/(self.flux)
            self.dts[np.where(self.Sigma.value == 0.0)] = np.inf
            self.dts[self.gap] = np.inf
            self.dt = self.emptydt*np.amin(self.dts)
        self.dt = min(dtMax, self.dt)
        try:
            self.eq.sweep(dt=self.dt)
            if np.any(self.Sigma.value < 0.0):
                self.singleTimestep(dt=self.dt/2)
            if update:
                self.Sigma.updateOld()
            self.t += self.dt
        except FloatingPointError:
            import ipdb; ipdb.set_trace()

    def evolve(self, deltaTime, **kargs):
        """
        Evolve the system using the singleTimestep method
        """
        tEv = self.t + deltaTime
        while self.t < tEv:
            dtMax = tEv - self.t
            self.singleTimestep(dtMax=dtMax, **kargs)

    def revert(self):
        """
        Revert evolve method if update=False was used, otherwise
        it has no effect.
        """
        self.Sigma.setValue(self.Sigma.old.value)

    def writeToFile(self):
        fName = self.odir + '/t{0}.pkl'.format(self.t)
        with open(fName, 'wb') as f:
            pickle.dump((self.t, self.Sigma.getValue()), f)

    def readFromFile(self, fName):
        with open(fName, 'rb') as f:
            t, Sigma = pickle.load(f)
        self.t = t
        self.Sigma.setValue(Sigma)

    def loadTimesList(self):
        path = self.odir
        files = os.listdir(path)
        if '.DS_Store' in files:
            files.remove('.DS_Store')
        if 'interpolator.pkl' in files:
            files.remove('interpolator.pkl')
        if 'init.pkl' in files:
            files.remove('init.pkl')
        self.times = np.zeros((len(files),))
        for i, f in enumerate(files):
            match = re.match(r"^t((\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)\.pkl", f)
            if match == None:
                print "WARNING: File {0} has an unexepected name".format(f)
                files.remove(f)
                continue
            self.times[i] = float(match.group(1))
        self.times.sort()
        self.files = files

    def loadTime(self, t):
        """
        Load the file with the time closest to `t`
        """
        idx = (np.abs(self.times-t)).argmin()
        fName = self.odir + '/t'+str(self.times[idx]) + '.pkl'
        self.readFromFile(fName)
The diffusion coefficient in the first half of the slab is double that in the second half
"""
from fipy import Variable, FaceVariable, CellVariable, Grid1D, TransientTerm, DiffusionTerm, Viewer
from fipy.tools import numerix

# Setting up a mesh
nx = 50
dx = 0.02
L = nx * dx
mesh = Grid1D(nx=nx, dx=dx)
c = CellVariable(mesh=mesh, name=r"$c$", value=0.0)

# Setting up the spatially varying diffusion coefficient
# Due to the mechanics of the solver, the diffusion coefficient variable must be defined on the mesh face
D = FaceVariable(mesh=mesh, value=2.0)
x = mesh.faceCenters[0]
D.setValue(1.0, where=(x > L / 2.0))

# Boundary conditions
valueLeft = 1.0
valueRight = 0.0
c.constrain(valueLeft, mesh.facesLeft)
c.constrain(valueRight, mesh.facesRight)

#Equation
eq = (TransientTerm() == DiffusionTerm(coeff=D))

dt = 0.001
t = Variable(0.0)
time_stride = 20
Beispiel #15
0
    // create remaining 7/8 inner shells
    t1[] = Rotate {{0,0,1},{0,0,0},Pi/2} {Duplicata{Surface{1};}};
    t2[] = Rotate {{0,0,1},{0,0,0},Pi} {Duplicata{Surface{1};}};
    t3[] = Rotate {{0,0,1},{0,0,0},Pi*3/2} {Duplicata{Surface{1};}};
    t4[] = Rotate {{0,1,0},{0,0,0},-Pi/2} {Duplicata{Surface{1};}};
    t5[] = Rotate {{0,0,1},{0,0,0},Pi/2} {Duplicata{Surface{t4[0]};}};
    t6[] = Rotate {{0,0,1},{0,0,0},Pi} {Duplicata{Surface{t4[0]};}};
    t7[] = Rotate {{0,0,1},{0,0,0},Pi*3/2} {Duplicata{Surface{t4[0]};}};

    // create entire inner and outer shell
    Surface Loop(100)={1,t1[0],t2[0],t3[0],t7[0],t4[0],t5[0],t6[0]};
''', order=2).extrude(extrudeFunc=lambda r: 1.05 * r) # doctest: +GMSH
#

mmag = FaceVariable(name=r"$mmag$", mesh=mesh) # doctest: +GMSH
gridCoor = mesh.cellCenters
print("mesh created")

## Constants
kBoltzmann = 1.38064852e-23
mu0 = numerix.pi * 4.0e-7

## LLG parameters
##gamFac = 1.7608e11 * pi * 4.0e-7
gamFac = 2.2128e5
alphaDamping = 0.01
Temperature = 300
Msat = 500e3
magVolume = 2.0e-9 * (25e-9 * 25e-9) * numerix.pi
D = alphaDamping * gamFac * kBoltzmann * Temperature / ((1 + alphaDamping) * Msat * magVolume)
Beispiel #16
0
filename = 'infiniteCylinder01_solve_dimensionless.msh'
mesh = Gmsh2D(filename, communicator=serialComm)
del filename

#T_initial=425.08  #deg K
T_initial = 0.

var = CellVariable(mesh=mesh, value=T_initial, hasOld=True)

# rho=6980.  #kg/m^3
# cp=227.  #J/kg/K
# k=59.6  #W/m/K
# D_thermal=k/rho/cp

#D=FaceVariable(mesh=mesh,value=D_thermal)
D = FaceVariable(mesh=mesh, value=1.)

eq = TransientTerm() == DiffusionTerm(coeff=D)

X_faces, Y_faces = mesh.faceCenters

surfaceFaces = (Y_faces > 0) & (
    (X_faces**2 + Y_faces**2)**.5 > R_outer - cellSize / 10.)

#convectionCoeff=200.  #W/m^2/K
# Bi_desired=10.
# convectionCoeff=Bi_desired*k/R_inner
# logging.info('convection coefficient is %.2E' % convectionCoeff)

# Bi=convectionCoeff*R_inner/k  #Biot number
Beispiel #17
0
X_faces, Y_faces = mesh.faceCenters

surfaceFaces = (Y_faces > 0) & (
    (X_faces**2 + Y_faces**2)**.5 > R_outer - cellSize / 10.)

#convectionCoeff=200.  #W/m^2/K
Bi_desired = 10.  #SETTING
#Bi_desired=1e5
convectionCoeff = Bi_desired * k / R_inner
logging.info('convection coefficient is %.2E' % convectionCoeff)

Bi = convectionCoeff * R_inner / k  #Biot number
logging.info('Biot number is %.2E' % Bi)

Gamma0 = D_thermal
Gamma = FaceVariable(mesh=mesh, value=Gamma0)
mask = surfaceFaces
Gamma.setValue(0., where=mask)
dPf = FaceVariable(mesh=mesh,
                   value=mesh._faceToCellDistanceRatio *
                   mesh.cellDistanceVectors)
Af = FaceVariable(mesh=mesh, value=mesh._faceAreas)
b = k
#RobinCoeff = (mask * Gamma0 * Af * mesh.faceNormals / (-dPf.dot(a) + b)).divergence  #I changed a sign in the denominator since I suspect a sign error
#a is convectionCoeff times n_hat
#20181211: I am getting same result whichever sign in the denominator I go with; solution is stuck at initial condition
RobinCoeff = (
    mask * Gamma0 * Af * mesh.faceNormals /
    (-convectionCoeff * dPf.dot(mesh.faceNormals) + b)
).divergence  #I changed a sign in the denominator since I suspect a sign error
g = convectionCoeff * T_infinity
surfaceFaces = (Y_faces > 0) & (
    (X_faces**2 + Y_faces**2)**.5 > R_outer - cellSize / 10.)

#convectionCoeff=200.  #W/m^2/K
Bi_desired = 10.  #SETTING
convectionCoeff = Bi_desired * k / R_inner
logging.info('convection coefficient is %.2E' % convectionCoeff)

Bi = convectionCoeff * R_inner / k  #Biot number
logging.info('Biot number is %.2E' % Bi)

#ref: https://github.com/usnistgov/fipy/blob/develop/documentation/USAGE.rst#applying-robin-boundary-conditions
#warning: avoid confusion between convectionCoeff in that fipy documentation, which refers to terms involving "a", and convectionCoeff here, which refers to a heat transfer convection coefficient at a boundary
Gamma0 = D_thermal
Gamma = FaceVariable(mesh=mesh, value=Gamma0)
mask = surfaceFaces
Gamma.setValue(0., where=mask)
dPf = FaceVariable(mesh=mesh,
                   value=mesh._faceToCellDistanceRatio *
                   mesh.cellDistanceVectors)
Af = FaceVariable(mesh=mesh, value=mesh._faceAreas)
#RobinCoeff = (mask * Gamma0 * Af / (dPf.dot(a) + b)).divergence  #a is zero in our case
b = 1.
RobinCoeff = (mask * Gamma0 * Af / b).divergence  #a is zero in our case
#eq = (TransientTerm() == DiffusionTerm(coeff=Gamma) + RobinCoeff * g - ImplicitSourceTerm(coeff=RobinCoeff * mesh.faceNormals.dot(a)))   #a is zero in our case
# g in this formulation is -convectionCoeff/k*var, where var=T-T_infinity
eq = (TransientTerm() == DiffusionTerm(coeff=Gamma) +
      ImplicitSourceTerm(RobinCoeff * -convectionCoeff / k))

# embed()
Beispiel #19
0
valueLeft = 0.
fluxRight = 1.
timeStepDuration = 1.

L = 10.

dx = L / nx
dy = 1.

mesh = Tri2D(dx, dy, nx, ny)

var = CellVariable(
    name = "solution variable",
    mesh = mesh,
    value = valueLeft)

diffCoeff = FaceVariable(mesh = mesh, value = 1.0)

x = mesh.faceCenters[0]
diffCoeff.setValue(0.1, where=(L/4. <= x) & (x < 3. * L / 4.))

var.faceGrad.constrain([[1.], [0.]], mesh.facesRight)

var.constrain(valueLeft, mesh.facesLeft)

if __name__ == '__main__':
    import fipy.tests.doctestPlus
    exec(fipy.tests.doctestPlus._getScript())
    input('finished')