General remarks
All physical quantities are assumed to be consistently represented through their values expressed in basic SI units (m, kg, s, A, K, mol, cd), supported by the LessUnitful.jl package built on top of Unitful.jl.
Electrolyte data
LiquidElectrolytes.AbstractElectrolyteData
— Typeabstract type AbstractElectrolyteData
Abstract super type for electrolytes.
LiquidElectrolytes.ElectrolyteData
— Typemutable struct ElectrolyteData <: AbstractElectrolyteData
Data for electrolyte. It is defined using Base.@kwdef
Leading to keyword constructors like
ElectrolyteData(nc=3,z=[-1,2,1])
Fields (for default values, see below):
nc::Int64
: Number of ionic species.na::Int64
: Number of surface speciesiϕ::Int64
: Potential index in species list.ip::Int64
: Pressure index in species listD::Vector{Float64}
: Mobility coefficientz::Vector{Int64}
: Charge numbers of ionsM0::Float64
: Molar weight of solventM::Vector{Float64}
: Molar weights of ionsv0::Float64
: Molar volume of solventv::Vector{Float64}
: Molar volumes of ionsκ::Vector{Float64}
: Solvation numbers of ionsc_bulk::Vector{Float64}
: Bulk ion concentrationsϕ_bulk::Float64
: Bulk voltagep_bulk::Float64
: Bulk pressureΓ_bulk::Int64
: Bulk boundary numberϕ_we::Float64
: Working electrode voltageΓ_we::Int64
: Working electrode boundary numberT::Float64
: TemperatureRT::Float64
: Molar gas constant scaled with temperatureF::Float64
: Faraday constantε::Float64
: Dielectric permittivity of solventε_0::Float64
: Dielectric permittivity of vacuumpscale::Float64
: Pressure scaling factoreneutral::Bool
: Local electroneutrality switchscheme::Symbol
: Flux caculation scheme This allows to choose between
solvepressure::Bool
: Solve for pressure.This is
true
by default. Setting this tofalse
can serve two purposes:- Take the pressure from the solution of a flow equation
- Ignore the pressure contribution to the excess chemical potential
weights::Vector{Float64}
: Species weights for norms in solver control.
edgevelocity::Union{Float64, Vector{Float64}}
: Edge velocity projection.
model::Symbol
: Electrolyte model
The default values for electrolyte data are those of an symmetric 0.1M aqueous binary electrolyte at 298.5K with solvation number κ=10, ion molar volumes and masses similar to those of water molecules and diffusion coefficients 2.0e-9 $m^2/s$. All values given in SI base units:
using LiquidElectrolytes
ElectrolyteData()
nc = 2
na = 0
iϕ = 3
ip = 4
D = [2.0e-9, 2.0e-9]
z = [1, -1]
M0 = 0.018015
M = [0.018015, 0.018015]
v0 = 1.8051e-5
v = [1.8051e-5, 1.8051e-5]
κ = [10.0, 10.0]
c_bulk = [100.0, 100.0]
ϕ_bulk = 0.0
p_bulk = 0.0
Γ_bulk = 2
ϕ_we = 0.0
Γ_we = 1
T = 298.15
RT = 2479.0
F = 96485.0
ε = 78.49
ε_0 = 8.8542e-12
pscale = 1.0e9
eneutral = false
scheme = μex
solvepressure = true
weights = [1.8051e-5, 1.8051e-5, 1.0, 0.0]
edgevelocity = 0.0
model = DGL
LiquidElectrolytes.dlcap0
— Methoddlcap0(electrolyte)
Double layer capacitance at zero voltage for symmetric binary electrolyte.
Example
using LessUnitful
ely = ElectrolyteData(c_bulk=fill(0.01ufac"mol/dm^3",2))
round(dlcap0(ely),sigdigits=5) |> u"μF/cm^2"
# output
22.847 μF cm^-2
LiquidElectrolytes.debyelength
— Methoddebyelength(electrolyte)
Debye length.
using LessUnitful
ely = ElectrolyteData(c_bulk=fill(0.01ufac"mol/dm^3",2))
round(debyelength(ely),sigdigits=5) |> u"nm"
# output
4.3018 nm
LiquidElectrolytes.chargedensity
— Functionchargedensity(c,electrolyte)
Calculate charge density from vector of concentrations (in one grid point).
chargedensity(sol,electrolyte)
Calculate charge density vector from solution (on whole grid)
chargedensity(tsol,electrolyte)
Calculate charge densities from from time/voltage dependent solution solution (on whole grid)
LiquidElectrolytes.chemical_potential
— Function chemical_potential(c, barc, p, barv, electrolyte)
Calculate chemical potential of species with concentration c
\[ μ = \bar v(p-p_{ref}) + RT\log \frac{c}{\bar c}\]
LiquidElectrolytes.chemical_potentials!
— Functionchemical_potentials!(μ,u,electrolyte)
Calculate chemical potentials from concentrations.
Input:
μ
: memory for result (will be filled)u
: local solution vector (concentrations, potential, pressure)
Returns μ0, μ
: chemical potential of solvent and chemical potentials of ions.
using LessUnitful
ely = ElectrolyteData(c_bulk = fill(0.01ufac"mol/dm^3", 2))
μ0, μ = chemical_potentials!([0.0, 0.0], vcat(ely.c_bulk, [0, 0]), ely)
round(μ0, sigdigits = 5), round.(μ, sigdigits = 5)
# output
(-0.89834, [-21359.0, -21359.0])
This function has been corrected in version 0.3. Before it used the molar volume $v$ instead of the effective molar volume $\bar v = v + κv_0$ to calculate the ion chemical potentials. Examples with κ=0 are not affected.
LiquidElectrolytes.rrate
— Functionrrate(R0,β,A)
Reaction rate expression
rrate(R0,β,A)=R0*(exp(-β*A) - exp((1-β)*A))
LiquidElectrolytes.iselectroneutral
— Functioniselectroneutral(cx::Vector,celldata)
Check for electroneutrality of concentration vector
iselectroneutral(tsol::TransientSolution,celldata)
Check for electroneutrality of transient solution
LiquidElectrolytes.isincompressible
— Functionisincompressible(cx::Vector,celldata)
Check for incompressibility of concentration vector
isincompressible(tsol::TransientSolution,celldata)
Check for incompressibility of transient solution
LiquidElectrolytes.c0_barc
— Functionc0_barc(u,electrolyte)
Calculate solvent concentration $c_0$ and summary concentration $\bar c$ from vector of concentrations c
using the incompressibility constraint (assuming $κ_0=0$):
\[ \sum_{i=0}^N c_i (v_i + κ_iv_0) =1\]
This gives
\[ c_0v_0=1-\sum_{i=1}^N c_i (v_i+ κ_iv_0)\]
\[c_0= 1/v_0 - \sum_{i=1}^N c_i(\frac{v_i}{v_0}+κ_i)\]
Then we can calculate
\[ \bar c= \sum_{i=0}^N c_i\]
Poisson-Nernst-Planck system
LiquidElectrolytes.PNPSystem
— FunctionPNPSystem(grid;
celldata=ElectrolyteData(),
bcondition=(f, u, n, e)-> nothing,
reaction=(f, u, n, e)-> nothing,
kwargs...)
Create VoronoiFVM system for generalized Poisson-Nernst-Planck. Input:
grid
: discretization gridcelldata
: composite struct containing electrolyte databcondition
: boundary conditionreaction
: reactions of the bulk specieskwargs
: Keyword arguments of VoronoiFVM.System
LiquidElectrolytes.pnpunknowns
— Functionpnpunknowns(sys)
Return vector of unknowns initialized with bulk data.
LiquidElectrolytes.electrolytedata
— Functionelectrolytedata(sys)
Extract electrolyte data from system.
LiquidElectrolytes.solventconcentration
— Function solventconcentration(U::Array, electrolyte)
Calculate vector of solvent concentrations from solution array.
LiquidElectrolytes.chemical_potentials
— Functionchemical_potentials(solution, electrolyte)
Calculate chemical potentials from solution. Returns μ0, μ
, where μ0
is the vector of solvent chemical potentials, and μ
is the nc×nnodes
matrix of solute chemical potentials.
LiquidElectrolytes.electrochemical_potentials
— Functionelectrochemical_potentials(solution, electrolyte)
Calculate electrochemical potentials from solution. and return nc×nnodes
matrix of solute electrochemical potentials measured in Volts.
Poisson-Boltzmann system
LiquidElectrolytes.PBSystem
— FunctionPBSystem(grid;
celldata=ElectrolyteData(),
bcondition=(f, u, n, e)-> nothing,
kwargs...)
Create VoronoiFVM system generalized Poisson-Boltzmann. Input:
grid
: discretization gridcelldata
: composite struct containing electrolyte databcondition
: boundary conditionkwargs
: Keyword arguments of VoronoiFVM.System
Poisson-Nernst-Planck-Stokes system
LiquidElectrolytes.PNPStokesSolver
— Typestruct PNPStokesSolver{Tflow, Tpnp}
Stokes solver struct.
flowsolver::Any
pnpsolver::Any
Utilities
LiquidElectrolytes.RLog
— TypeRLog(eps)
Functor struct for regularized logarithm. Smooth linear continuation for x<eps
. This means we can calculate a "logarithm" of a small negative number. Objects of this type are meant to replace the logarithm function.
LiquidElectrolytes.RExp
— TypeRExp(trunc)
Functor struct for regularized exponential. Linear continuation for x>trunc
, returns 1/rexp(-x) for x<-trunc
. Objects of this type are meant to replace the exponential function.