Esempio n. 1
0
def alpha_prime_approx(ci, ci_1, EC_scheme, c_cutoff):
    if EC_scheme == "NL1":
        return (ci-ci_1)*(alpha(ci)-alpha(ci_1))/((ci-ci_1)**2+0.001)
    elif EC_scheme == "NL2":
        return alpha_c(ci)
    elif EC_scheme == "L1":
        return alpha_c(ci_1) + 0.5*alpha_cc(ci_1)*(ci-ci_1)
    elif EC_scheme == "L2":
        return alpha_c_reg(ci_1, c_cutoff) + 0.5*alpha_cc(c_cutoff)*(ci-ci_1)
Esempio n. 2
0
def equilibrium_EC(w_, test_functions,
                   solutes,
                   permittivity,
                   dx, ds, normal,
                   dirichlet_bcs, neumann_bcs, boundary_to_mark,
                   use_iterative_solvers,
                   V_lagrange,
                   **namespace):
    """ Electrochemistry equilibrium solver. Nonlinear! """
    num_solutes = len(solutes)

    cV = df.split(w_["EC"])
    c, V = cV[:num_solutes], cV[num_solutes]
    if V_lagrange:
        V0 = cV[-1]

    b = test_functions["EC"][:num_solutes]
    U = test_functions["EC"][num_solutes]
    if V_lagrange:
        U0 = test_functions["EC"][-1]

    z = []  # Charge z[species]
    K = []  # Diffusivity K[species]

    for solute in solutes:
        z.append(solute[1])
        K.append(solute[2])

    rho_e = sum([c_e*z_e for c_e, z_e in zip(c, z)])

    veps = permittivity[0]

    F_c = []
    for ci, bi, Ki, zi in zip(c, b, K, z):
        grad_g_ci = df.grad(alpha_c(ci) + zi*V)
        F_ci = Ki*max_value(ci, 0.)*df.dot(grad_g_ci, df.grad(bi))*dx
        F_c.append(F_ci)

    F_V = veps*df.dot(df.grad(V), df.grad(U))*dx
    for boundary_name, sigma_e in neumann_bcs["V"].iteritems():
        F_V += -sigma_e*U*ds(boundary_to_mark[boundary_name])
    if rho_e != 0:
        F_V += -rho_e*U*dx
    if V_lagrange:
        F_V += veps*V0*U*dx + veps*V*U0*dx

    F = sum(F_c) + F_V
    J = df.derivative(F, w_["EC"])

    problem = df.NonlinearVariationalProblem(F, w_["EC"],
                                             dirichlet_bcs["EC"], J)
    solver = df.NonlinearVariationalSolver(problem)

    solver.parameters["newton_solver"]["relative_tolerance"] = 1e-7
    if use_iterative_solvers:
        solver.parameters["newton_solver"]["linear_solver"] = "bicgstab"
        if not V_lagrange:
            solver.parameters["newton_solver"]["preconditioner"] = "hypre_amg"

    solver.solve()
Esempio n. 3
0
def setup(test_functions, trial_functions, w_, w_1,
          ds, dx, normal,
          dirichlet_bcs, neumann_bcs, boundary_to_mark,
          permittivity, density, viscosity,
          solutes, enable_EC, enable_NS,
          dt,
          grav_const,
          grav_dir,
          use_iterative_solvers,
          EC_scheme,
          c_cutoff,
          q_rhs,
          mesh,
          reactions,
          density_per_concentration,
          viscosity_per_concentration,
          V_lagrange, p_lagrange,
          **namespace):
    """ Set up problem. """
    # Constant
    grav = df.Constant(tuple(grav_const*np.array(grav_dir)))
    veps = df.Constant(permittivity[0])

    mu_0 = df.Constant(viscosity[0])
    rho_0 = df.Constant(density[0])

    if EC_scheme in ["NL1", "NL2"]:
        nonlinear_EC = True
    else:
        nonlinear_EC = False

    # Navier-Stokes
    u_ = p_ = None
    u_1 = p_1 = None
    p0 = q0 = p0_ = p0_1 = None
    if enable_NS:
        u, p = trial_functions["NS"][:2]
        v, q = test_functions["NS"][:2]

        up_ = df.split(w_["NS"])
        up_1 = df.split(w_1["NS"])
        u_, p_ = up_[:2]
        u_1, p_1 = up_1[:2]
        if p_lagrange:
            p0 = trial_functions["NS"][-1]
            q0 = test_functions["NS"][-1]
            p0_ = up_[-1]
            p0_1 = up_1[-1]

    # Electrochemistry
    c_ = V_ = c_1 = V_1 = V0 = V0_ = V0_1 = b = U = U0 = None
    if enable_EC:
        num_solutes = len(trial_functions["EC"])-1
        if V_lagrange:
            num_solutes -= 1
        assert(num_solutes == len(solutes))

        cV_ = df.split(w_["EC"])
        cV_1 = df.split(w_1["EC"])
        c_, V_ = cV_[:num_solutes], cV_[num_solutes]
        c_1, V_1 = cV_1[:num_solutes], cV_1[num_solutes]
        if V_lagrange:
            V0_ = cV_[-1]
            V0_1 = cV_1[-1]

        if not nonlinear_EC:
            c = trial_functions["EC"][:num_solutes]
            V = trial_functions["EC"][num_solutes]
            if V_lagrange:
                V0 = trial_functions["EC"][-1]
        else:
            c = c_
            V = V_
            if V_lagrange:
                V0 = V0_

        b = test_functions["EC"][:num_solutes]
        U = test_functions["EC"][num_solutes]
        if V_lagrange:
            U0 = test_functions["EC"][-1]

    rho = rho_0
    rho_ = rho_0
    rho_1 = rho_0

    if enable_EC and density_per_concentration is not None:
        for drhodci, ci, ci_, ci_1 in zip(
                density_per_concentration, c, c_, c_1):
            if drhodci > 0.:
                rho += drhodci*ci
                rho_ += drhodci*ci_
                rho_1 += drhodci*ci_1

    mu = mu_0
    mu_ = mu_0
    mu_1 = mu_0

    if enable_EC and viscosity_per_concentration is not None:
        for dmudci, ci, ci_, ci_1 in zip(
                viscosity_per_concentration, c, c_, c_1):
            if dmudci != 0.:
                mu += dmudci*ci
                mu_ += dmudci*ci_
                mu_1 += dmudci*ci_1

    z = []  # Charge z[species]
    K = []  # Diffusivity K[species]
    beta = []

    if enable_EC:
        for solute in solutes:
            z.append(solute[1])
            K.append(solute[2])
            beta.append(solute[4])
    else:
        z = None
        K = None
        beta = None

    if enable_EC:
        rho_e = sum([c_e*z_e for c_e, z_e in zip(c, z)])  # Sum of trial func.
        rho_e_ = sum([c_e*z_e for c_e, z_e in zip(c_, z)])  # Sum of curr. sol.
    else:
        rho_e_ = None

    if enable_EC:
        g_c = []
        g_c_ = []
        g_c_1 = []
        grad_g_c = []
        grad_g_c_ = []
        c_reg = []
        for ci, ci_, ci_1, zi, betai in zip(c, c_, c_1, z, beta):
            g_ci = alpha_prime_approx(
                ci, ci_1, EC_scheme, c_cutoff) + betai + zi*V
            g_ci_ = alpha_prime_approx(
                ci_, ci_1, EC_scheme, c_cutoff) + betai + zi*V_
            g_ci_1 = alpha_c(ci_1) + betai + zi*V_1
            g_c.append(g_ci)
            g_c_.append(g_ci_)
            g_c_1.append(g_ci_1)
            grad_g_c.append(df.grad(g_ci))
            grad_g_c_.append(df.grad(g_ci_))
            c_reg.append(regulate(ci, ci_1, EC_scheme, c_cutoff))
    else:
        g_c = None
        g_c_ = None
        grad_g_c = None
        grad_g_c_ = None
        c_reg = None

    solvers = dict()
    if enable_EC:
        w_EC = w_["EC"]
        dirichlet_bcs_EC = dirichlet_bcs["EC"]
        solvers["EC"] = setup_EC(**vars())

    if enable_NS:
        w_NS = w_["NS"]
        dirichlet_bcs_NS = dirichlet_bcs["NS"]
        solvers["NS"] = setup_NS(**vars())
    return dict(solvers=solvers)