Skip to content

Commit e678d23

Browse files
#492 get direct voltage model working
1 parent 3c5cbc0 commit e678d23

File tree

16 files changed

+165
-79
lines changed

16 files changed

+165
-79
lines changed

examples/scripts/DFN.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
pybamm.set_logging_level("INFO")
99

1010
# load model
11-
model = pybamm.lithium_ion.DFN()
11+
model = pybamm.lithium_ion.DFN({"operating mode": "voltage"})
1212

1313
# create geometry
1414
geometry = model.default_geometry
1515

1616
# load parameter values and process model and geometry
1717
param = model.default_parameter_values
18+
param["Voltage function"] = 4.1
1819
param.process_model(model)
1920
param.process_geometry(geometry)
2021

pybamm/models/full_battery_models/base_battery_model.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -534,13 +534,13 @@ def set_external_circuit_submodel(self):
534534
self.param
535535
)
536536
elif self.options["operating mode"] == "voltage":
537-
self.submodels["external circuit"] = pybamm.external_circuit.VoltageControl(
538-
self.param
539-
)
537+
self.submodels[
538+
"external circuit"
539+
] = pybamm.external_circuit.VoltageFunctionControl(self.param)
540540
elif self.options["operating mode"] == "power":
541-
self.submodels["external circuit"] = pybamm.external_circuit.PowerControl(
542-
self.param
543-
)
541+
self.submodels[
542+
"external circuit"
543+
] = pybamm.external_circuit.PowerFunctionControl(self.param)
544544
elif callable(self.options["operating mode"]):
545545
self.submodels[
546546
"external circuit"

pybamm/models/full_battery_models/lead_acid/full.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ def set_interfacial_submodel(self):
6969
def set_solid_submodel(self):
7070
if self.options["surface form"] is False:
7171
submod_n = pybamm.electrode.ohm.Full(self.param, "Negative", self.reactions)
72-
submod_p = pybamm.electrode.ohm.Full(self.param, "Positive", self.reactions)
72+
submod_p = pybamm.electrode.ohm.Full(
73+
self.param, "Positive", self.reactions, self.options["operating mode"]
74+
)
7375
else:
7476
submod_n = pybamm.electrode.ohm.SurfaceForm(self.param, "Negative")
7577
submod_p = pybamm.electrode.ohm.SurfaceForm(self.param, "Positive")
@@ -124,3 +126,12 @@ def set_side_reaction_submodels(self):
124126
self.submodels[
125127
"negative oxygen interface"
126128
] = pybamm.interface.lead_acid_oxygen.NoReaction(self.param, "Negative")
129+
130+
def set_external_circuit_submodel(self):
131+
""" See :meth:`BaseBatteryModel.set_external_circuit_submodel` """
132+
if self.options["operating mode"] == "voltage":
133+
self.submodels["external circuit"] = pybamm.external_circuit.VoltageControl(
134+
self.param
135+
)
136+
else:
137+
super().set_external_circuit_submodel()

pybamm/models/full_battery_models/lithium_ion/base_lithium_ion_model.py

-14
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,6 @@ def __init__(self, options=None, name="Unnamed lithium-ion model"):
1919

2020
def set_standard_output_variables(self):
2121
super().set_standard_output_variables()
22-
# Current
23-
i_cell = pybamm.standard_parameters_lithium_ion.current_with_time
24-
i_cell_dim = (
25-
pybamm.standard_parameters_lithium_ion.dimensional_current_density_with_time
26-
)
27-
I = pybamm.standard_parameters_lithium_ion.dimensional_current_with_time
28-
self.variables.update(
29-
{
30-
"Total current density": i_cell,
31-
"Total current density [A.m-2]": i_cell_dim,
32-
"Current [A]": I,
33-
}
34-
)
3522

3623
# Time
3724
time_scale = pybamm.standard_parameters_lithium_ion.tau_discharge
@@ -40,7 +27,6 @@ def set_standard_output_variables(self):
4027
"Time [s]": pybamm.t * time_scale,
4128
"Time [min]": pybamm.t * time_scale / 60,
4229
"Time [h]": pybamm.t * time_scale / 3600,
43-
"Discharge capacity [A.h]": I * pybamm.t * time_scale / 3600,
4430
}
4531
)
4632

pybamm/models/full_battery_models/lithium_ion/dfn.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def set_solid_submodel(self):
8888
self.param, "Negative", self.reactions
8989
)
9090
self.submodels["positive electrode"] = pybamm.electrode.ohm.Full(
91-
self.param, "Positive", self.reactions
91+
self.param, "Positive", self.reactions, self.options["operating mode"]
9292
)
9393

9494
def set_electrolyte_submodel(self):
@@ -102,6 +102,15 @@ def set_electrolyte_submodel(self):
102102
self.param, self.reactions
103103
)
104104

105+
def set_external_circuit_submodel(self):
106+
""" See :meth:`BaseBatteryModel.set_external_circuit_submodel` """
107+
if self.options["operating mode"] == "voltage":
108+
self.submodels["external circuit"] = pybamm.external_circuit.VoltageControl(
109+
self.param
110+
)
111+
else:
112+
super().set_external_circuit_submodel()
113+
105114
@property
106115
def default_geometry(self):
107116
dimensionality = self.options["dimensionality"]

pybamm/models/submodels/electrode/base_electrode.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,6 @@ def _get_standard_current_collector_potential_variables(self, phi_s_cn, phi_s_cp
134134
# Voltage is local current collector potential difference at the tabs, in 1D
135135
# this will be equal to the local current collector potential difference
136136
phi_s_cp_dim = U_ref + phi_s_cp * pot_scale
137-
V = pybamm.boundary_value(phi_s_cp, "positive tab")
138-
V_dim = pybamm.boundary_value(phi_s_cp_dim, "positive tab")
139137

140138
variables = {
141139
"Negative current collector potential": phi_s_cn,
@@ -144,8 +142,6 @@ def _get_standard_current_collector_potential_variables(self, phi_s_cn, phi_s_cp
144142
"Positive current collector potential [V]": phi_s_cp_dim,
145143
"Local voltage": V_cc,
146144
"Local voltage [V]": U_ref + V_cc * pot_scale,
147-
"Terminal voltage": V,
148-
"Terminal voltage [V]": V_dim,
149145
}
150146

151147
return variables
@@ -191,5 +187,6 @@ def _get_standard_whole_cell_variables(self, variables):
191187
phi_s_cn, phi_s_cp
192188
)
193189
)
190+
194191
return variables
195192

pybamm/models/submodels/electrode/ohm/full_ohm.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ class Full(BaseModel):
1919
**Extends:** :class:`pybamm.electrode.ohm.BaseModel`
2020
"""
2121

22-
def __init__(self, param, domain, reactions):
22+
def __init__(self, param, domain, reactions, operating_mode="current"):
2323
super().__init__(param, domain, reactions)
24+
self.operating_mode = operating_mode
2425

2526
def get_fundamental_variables(self):
2627

@@ -71,19 +72,23 @@ def set_boundary_conditions(self, variables):
7172
phi_s = variables[self.domain + " electrode potential"]
7273
phi_s_cn = variables["Negative current collector potential"]
7374
tor = variables[self.domain + " electrode tortuosity"]
74-
i_boundary_cc = variables["Current collector current density"]
7575

7676
if self.domain == "Negative":
7777
lbc = (phi_s_cn, "Dirichlet")
7878
rbc = (pybamm.Scalar(0), "Neumann")
7979

8080
elif self.domain == "Positive":
8181
lbc = (pybamm.Scalar(0), "Neumann")
82-
sigma_eff = self.param.sigma_p * tor
83-
rbc = (
84-
i_boundary_cc / pybamm.boundary_value(-sigma_eff, "right"),
85-
"Neumann",
86-
)
82+
if self.operating_mode == "voltage":
83+
V = variables["Terminal voltage"]
84+
rbc = (V, "Dirichlet")
85+
else:
86+
sigma_eff = self.param.sigma_p * tor
87+
i_boundary_cc = variables["Current collector current density"]
88+
rbc = (
89+
i_boundary_cc / pybamm.boundary_value(-sigma_eff, "right"),
90+
"Neumann",
91+
)
8792

8893
self.boundary_conditions[phi_s] = {"left": lbc, "right": rbc}
8994

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from .base_external_circuit import BaseModel
22
from .current_control_external_circuit import CurrentControl
3-
from .function_control_external_circuit import FunctionControl
3+
from .function_control_external_circuit import (
4+
FunctionControl,
5+
VoltageFunctionControl,
6+
PowerFunctionControl,
7+
)
48
from .voltage_control_external_circuit import VoltageControl
5-
from .power_control_external_circuit import PowerControl
69

pybamm/models/submodels/external_circuit/current_control_external_circuit.py

+12
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,15 @@ def get_fundamental_variables(self):
2525
}
2626

2727
return variables
28+
29+
def get_coupled_variables(self, variables):
30+
# Update terminal voltage
31+
phi_s_cp_dim = variables["Positive current collector potential [V]"]
32+
phi_s_cp = variables["Positive current collector potential"]
33+
34+
V = pybamm.boundary_value(phi_s_cp, "positive tab")
35+
V_dim = pybamm.boundary_value(phi_s_cp_dim, "positive tab")
36+
variables["Terminal voltage"] = V
37+
variables["Terminal voltage [V]"] = V_dim
38+
39+
return variables

pybamm/models/submodels/external_circuit/function_control_external_circuit.py

+44
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ def get_fundamental_variables(self):
3535

3636
return variables
3737

38+
def get_coupled_variables(self, variables):
39+
# Update terminal voltage
40+
phi_s_cp_dim = variables["Positive current collector potential [V]"]
41+
phi_s_cp = variables["Positive current collector potential"]
42+
43+
V = pybamm.boundary_value(phi_s_cp, "positive tab")
44+
V_dim = pybamm.boundary_value(phi_s_cp_dim, "positive tab")
45+
variables["Terminal voltage"] = V
46+
variables["Terminal voltage [V]"] = V_dim
47+
3848
def set_initial_conditions(self, variables):
3949
# Initial condition as a guess for consistent initial conditions
4050
i_cell = variables["Total current density"]
@@ -46,3 +56,37 @@ def set_algebraic(self, variables):
4656
# or a combination (e.g. I*V for power control)
4757
i_cell = variables["Total current density"]
4858
self.algebraic[i_cell] = self.external_circuit_class(variables)
59+
60+
61+
class VoltageFunctionControl(FunctionControl):
62+
"""
63+
External circuit with voltage control, implemented as an extra algebraic equation.
64+
"""
65+
66+
def __init__(self, param):
67+
super().__init__(param, ConstantVoltage())
68+
69+
70+
class ConstantVoltage:
71+
num_switches = 0
72+
73+
def __call__(self, variables):
74+
V = variables["Terminal voltage [V]"]
75+
return V - pybamm.FunctionParameter("Voltage function", pybamm.t)
76+
77+
78+
class PowerFunctionControl(FunctionControl):
79+
"""External circuit with power control. """
80+
81+
def __init__(self, param):
82+
super().__init__(param, ConstantPower())
83+
84+
85+
class ConstantPower:
86+
num_switches = 0
87+
88+
def __call__(self, variables):
89+
I = variables["Current [A]"]
90+
V = variables["Terminal voltage [V]"]
91+
return I * V - pybamm.FunctionParameter("Power function", pybamm.t)
92+

pybamm/models/submodels/external_circuit/power_control_external_circuit.py

-22
This file was deleted.

pybamm/models/submodels/external_circuit/voltage_control_external_circuit.py

+36-9
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,47 @@
22
# External circuit with voltage control
33
#
44
import pybamm
5-
from .function_control_external_circuit import FunctionControl
5+
from .base_external_circuit import BaseModel
66

77

8-
class VoltageControl(FunctionControl):
9-
"""External circuit with voltage control. """
8+
class VoltageControl(BaseModel):
9+
"""
10+
External circuit with voltage control, implemented directly.
11+
"""
1012

1113
def __init__(self, param):
12-
super().__init__(param, ConstantVoltage())
14+
super().__init__(param)
1315

16+
def get_fundamental_variables(self):
17+
# Voltage is given as a function of time
18+
V_dim = pybamm.FunctionParameter("Voltage function", pybamm.t)
1419

15-
class ConstantVoltage:
16-
num_switches = 0
20+
param = self.param
21+
V = (V_dim - (param.U_p_ref - param.U_n_ref)) / param.potential_scale
1722

18-
def __call__(self, variables):
19-
V = variables["Terminal voltage [V]"]
20-
return V - pybamm.FunctionParameter("Voltage function", pybamm.t)
23+
variables = {"Terminal voltage [V]": V_dim, "Terminal voltage": V}
2124

25+
return variables
26+
27+
def get_coupled_variables(self, variables):
28+
# Update currrent
29+
phi_s_p = variables["Positive electrode potential"]
30+
tor = variables["Positive electrode tortuosity"]
31+
32+
param = self.param
33+
i_boundary_cc = (
34+
-param.sigma_p
35+
* pybamm.BoundaryValue(tor, "right")
36+
* pybamm.BoundaryGradient(phi_s_p, "right")
37+
)
38+
i_cell = pybamm.BoundaryValue(i_boundary_cc, "right")
39+
I = i_cell * abs(param.I_typ)
40+
i_cell_dim = I / (param.n_electrodes_parallel * param.A_cc)
41+
42+
variables = {
43+
"Total current density": i_cell,
44+
"Total current density [A.m-2]": i_cell_dim,
45+
"Current [A]": I,
46+
}
47+
48+
return variables

0 commit comments

Comments
 (0)