コード例 #1
0
    def phis_mats(self, ):
        """
        Solid phase parameters and j vector matrices
        """
        p = self.p

        self.A_ps_a = batteqns.flux_mat_builder(p.Na, p.x_m_a,
                                                numpy.ones_like(p.vols_a),
                                                p.sig_a_eff)
        self.A_ps_c = batteqns.flux_mat_builder(p.Nc, p.x_m_c,
                                                numpy.ones_like(p.vols_c),
                                                p.sig_c_eff)

        Baps = numpy.array(
            [asa * p.F * dxa for asa, dxa in zip(p.as_a, p.vols_a)], dtype='d')
        Bcps = numpy.array(
            [asc * p.F * dxc for asc, dxc in zip(p.as_c, p.vols_c)], dtype='d')

        self.B_ps_a = numpy.diag(Baps)
        self.B_ps_c = numpy.diag(Bcps)

        self.B2_ps_a = numpy.zeros(p.Na, dtype='d')
        self.B2_ps_a[0] = -1.
        self.B2_ps_c = numpy.zeros(p.Nc, dtype='d')
        self.B2_ps_c[-1] = -1.
コード例 #2
0
    def update_cs_mats(self, csa, csc, csa_ss, csc_ss, csa_o, csc_o):
        """
        FVM discretization of the concentration flux term for the solid
        particle diffusion equation.
        A matrix is generated for each particle that exists at each node point
        along the mesh in the thickness of each electrode.

        In general, the diffusivity is a function of concentration, and
        therefore these matrices are different for each particle, and change
        through time.
        If, Ds(cs) is constant, then this only needs to be initialized and
        then may be left constat during the simulation.
        """
        p = self.p

        Acsa_list = [[] for i in range(p.Na)]
        Acsc_list = [[] for i in range(p.Nc)]

        Dsa_ss = [0. for i in range(p.Na)]
        Dsc_ss = [0. for i in range(p.Nc)]

        for ia in range(p.Na):

            csa_m = csa[ia * p.Nra:(ia + 1) * p.Nra]
            csa_e = numpy.array(
                [csa_o[ia]] +
                [0.5 * (csa_m[i + 1] + csa_m[i])
                 for i in range(p.Nra - 1)] + [csa_ss[ia]])
            Ua_e = p.uref_a(csa_e / p.csa_max)
            Dsa_e = p.Dsa_intp(Ua_e)

            Acsa_list[ia] = batteqns.flux_mat_builder(p.Nra, p.r_m_a,
                                                      p.vols_ra_m,
                                                      Dsa_e * (p.r_e_a**2))

            Dsa_ss[ia] = Dsa_e[-1]

        for ic in range(p.Nc):

            csc_m = csc[ic * p.Nrc:(ic + 1) * p.Nrc]
            csc_e = numpy.array(
                [csc_o[ic]] +
                [0.5 * (csc_m[i + 1] + csc_m[i])
                 for i in range(p.Nrc - 1)] + [csc_ss[ic]])
            Uc_e = p.uref_c(csc_e / p.csc_max)
            Dsc_e = p.Dsc_intp(Uc_e)

            Acsc_list[ic] = batteqns.flux_mat_builder(p.Nrc, p.r_m_c,
                                                      p.vols_rc_m,
                                                      Dsc_e * (p.r_e_c**2))

            Dsc_ss[ic] = Dsc_e[-1]

        self.A_cs_a = scipy.linalg.block_diag(*Acsa_list)
        self.A_cs_c = scipy.linalg.block_diag(*Acsc_list)

        self.D_cs_a = numpy.diag(-1.0 / (numpy.array(Dsa_ss) * self.c_n_a))
        self.D_cs_c = numpy.diag(-1.0 / (numpy.array(Dsc_ss) * self.c_n_c))
コード例 #3
0
    def build_Ace_mat(self, c, T):
        """
        FVM discretization of the concentration flux term for the elyte
        diffusion equation.
        """
        p = self.p

        D_eff = self.Diff_ce(c, T)

        A = p.K_m.dot(batteqns.flux_mat_builder(p.N, p.x_m, p.vols, D_eff))

        return A
コード例 #4
0
    def build_Ape_mat(self, c, T):
        """
        FVM discretization of the potential flux term for the elyte potential
        equation.
        """
        p = self.p

        k_eff = self.kapp_ce(c, T)

        A = batteqns.flux_mat_builder(p.N, p.x_m, p.vols, k_eff)

        A[-1, -1] = 2 * A[-1, -1]  # BC update for phi_e = 0

        return A
コード例 #5
0
    def build_Bpe_mat(self, c, T):
        """
        FVM discretization of the concentration flux term for the elyte
        potential equation.
        """
        p = self.p

        gam = 2. * (1. - p.t_plus) * p.R_gas * T / p.F

        k_eff = self.kapp_ce(c, T)

        c_edge = batteqns.mid_to_edge(c, p.x_e)

        B1 = batteqns.flux_mat_builder(p.N, p.x_m, p.vols,
                                       k_eff * gam / c_edge)

        return B1
コード例 #6
0
    def cs_mats(self, ):
        """
        Intiliaze the solid phase diffusion model matrices.
        """
        p = self.p

        # 1D spherical diffusion model
        # A_cs pre build
        self.A_csa_single = batteqns.flux_mat_builder(p.Nra, p.r_m_a,
                                                      p.vols_ra_m,
                                                      p.Dsa * (p.r_e_a**2))
        self.A_csc_single = batteqns.flux_mat_builder(p.Nrc, p.r_m_c,
                                                      p.vols_rc_m,
                                                      p.Dsc * (p.r_e_c**2))

        # A_cs build up to the stacked full cs size (Nr and Nx)
        b = [self.A_csa_single] * p.Na
        self.A_cs_a = scipy.linalg.block_diag(*b)
        b = [self.A_csc_single] * p.Nc
        self.A_cs_c = scipy.linalg.block_diag(*b)

        # B_cs and C_cs are constant (i.e., are not state-dependent)
        self.B_csa_single = numpy.array(
            [0. for i in range(p.Nra - 1)] +
            [-1. * p.r_e_a[-1]**2 / p.vols_ra_m[-1]],
            dtype='d')
        self.B_csc_single = numpy.array(
            [0. for i in range(p.Nrc - 1)] +
            [-1. * p.r_e_c[-1]**2 / p.vols_rc_m[-1]],
            dtype='d')

        b = [self.B_csa_single] * p.Na
        self.B_cs_a = scipy.linalg.block_diag(*b).T
        b = [self.B_csc_single] * p.Nc
        self.B_cs_c = scipy.linalg.block_diag(*b).T

        # Particle surface concentration
        h_na = p.r_e_a[-1] - p.r_m_a[-1]
        h_n1a = p.r_m_a[-1] - p.r_m_a[-2]

        h_nc = p.r_e_c[-1] - p.r_m_c[-1]
        h_n1c = p.r_m_c[-1] - p.r_m_c[-2]

        self.a_n_a, self.b_n_a, self.c_n_a = batteqns.right_side_coeffs(
            h_na, h_n1a)
        self.a_n_c, self.b_n_c, self.c_n_c = batteqns.right_side_coeffs(
            h_nc, h_n1c)

        self.C_cs_a_single = numpy.array(
            [0. for i in range(p.Nra - 2)] +
            [-self.a_n_a / self.c_n_a, -self.b_n_a / self.c_n_a],
            dtype='d')
        self.C_cs_c_single = numpy.array(
            [0. for i in range(p.Nrc - 2)] +
            [-self.a_n_c / self.c_n_c, -self.b_n_c / self.c_n_c],
            dtype='d')

        self.C_cs_a = scipy.linalg.block_diag(*[self.C_cs_a_single] * p.Na)
        self.C_cs_c = scipy.linalg.block_diag(*[self.C_cs_c_single] * p.Nc)

        self.C_cs_a_avg = scipy.linalg.block_diag(
            *[1. / ((1. / 3.) * p.Rp_a**3) * p.vols_ra_m] * p.Na)
        self.C_cs_c_avg = scipy.linalg.block_diag(
            *[1. / ((1. / 3.) * p.Rp_c**3) * p.vols_rc_m] * p.Nc)

        self.C_cs_a_mean = 1. / p.La * p.vols_a.dot(self.C_cs_a_avg)
        self.C_cs_c_mean = 1. / p.Lc * p.vols_c.dot(self.C_cs_c_avg)

        # Particle core concentration
        h_na = p.r_e_a[0] - p.r_m_a[0]
        h_n1a = p.r_m_a[1] - p.r_m_a[0]

        h_nc = p.r_e_c[0] - p.r_m_c[0]
        h_n1c = p.r_m_c[1] - p.r_m_c[0]

        a_n_a, b_n_a, c_n_a = batteqns.left_side_coeffs(h_na, h_n1a)
        a_n_c, b_n_c, c_n_c = batteqns.left_side_coeffs(h_nc, h_n1c)

        C_cso_a_single = numpy.array([-b_n_a / a_n_a, -c_n_a / a_n_a] +
                                     [0. for i in range(p.Nra - 2)],
                                     dtype='d')
        C_cso_c_single = numpy.array([-b_n_c / a_n_c, -c_n_c / a_n_c] +
                                     [0. for i in range(p.Nrc - 2)],
                                     dtype='d')

        self.C_cso_a = scipy.linalg.block_diag(*[C_cso_a_single] * p.Na)
        self.C_cso_c = scipy.linalg.block_diag(*[C_cso_c_single] * p.Nc)

        # D_cs prelim values, note this is Ds(cs) dependent and therefore
        # requires updating for state dependent Ds
        self.D_cs_a = -1.0 / (p.Dsa * self.c_n_a) * numpy.eye(p.Na)
        self.D_cs_c = -1.0 / (p.Dsc * self.c_n_c) * numpy.eye(p.Nc)