Skip to content

Commit

Permalink
#871 spatial vars
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinsulzer committed Mar 12, 2020
1 parent a50bdee commit 5fedf67
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 93 deletions.
1 change: 0 additions & 1 deletion examples/scripts/compare_lithium_ion_3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
solutions[i] = solution

# plot
# TO DO: plotting 3D variables
output_variables = ["Terminal voltage [V]"]
plot = pybamm.QuickPlot(solutions, output_variables)
plot.dynamic_plot()
4 changes: 4 additions & 0 deletions pybamm/processed_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ def initialise_2Dspace_scikit_fem(self):
self.z_sol = z_sol
self.first_dimension = "y"
self.second_dimension = "z"
self.first_dim_pts = y_sol
self.second_dim_pts = z_sol

# set up interpolation
self._interpolation_function = interp.interp2d(
Expand Down Expand Up @@ -313,6 +315,8 @@ def initialise_3D_scikit_fem(self):
self.z_sol = z_sol
self.first_dimension = "y"
self.second_dimension = "z"
self.first_dim_pts = y_sol
self.second_dim_pts = z_sol

# set up interpolation
self._interpolation_function = interp.RegularGridInterpolator(
Expand Down
75 changes: 47 additions & 28 deletions pybamm/quick_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,33 @@ def __init__(
raise ValueError("spatial unit '{}' not recognized".format(spatial_unit))

variables = models[0].variables
self.spatial_scales = {"x": 1, "y": 1, "z": 1, "r_n": 1, "r_p": 1}
# empty spatial scales, will raise error later if can't find a particular one
self.spatial_scales = {}
if "x [m]" and "x" in variables:
self.spatial_scales["x"] = (variables["x [m]"] / variables["x"]).evaluate()[
x_scale = (variables["x [m]"] / variables["x"]).evaluate()[
-1
] * spatial_factor
self.spatial_scales.update(
{
"negative electrode": x_scale,
"separator": x_scale,
"positive electrode": x_scale,
}
)
if "y [m]" and "y" in variables:
self.spatial_scales["y"] = (variables["y [m]"] / variables["y"]).evaluate()[
-1
] * spatial_factor
self.spatial_scales["current collector y"] = (
variables["y [m]"] / variables["y"]
).evaluate()[-1] * spatial_factor
if "z [m]" and "z" in variables:
self.spatial_scales["z"] = (variables["z [m]"] / variables["z"]).evaluate()[
-1
] * spatial_factor
self.spatial_scales["current collector z"] = (
variables["z [m]"] / variables["z"]
).evaluate()[-1] * spatial_factor
if "r_n [m]" and "r_n" in variables:
self.spatial_scales["r_n"] = (
self.spatial_scales["negative particle"] = (
variables["r_n [m]"] / variables["r_n"]
).evaluate()[-1] * spatial_factor
if "r_p [m]" and "r_p" in variables:
self.spatial_scales["r_p"] = (
self.spatial_scales["positive particle"] = (
variables["r_p [m]"] / variables["r_p"]
).evaluate()[-1] * spatial_factor

Expand All @@ -169,7 +177,7 @@ def __init__(
# Set timescale
if time_unit is None:
# defaults depend on how long the simulation is
if self.max_t >= 3600:
if max_t >= 3600:
time_scaling_factor = 3600 # time in hours
self.time_unit = "h"
else:
Expand Down Expand Up @@ -212,9 +220,6 @@ def __init__(
"Electrolyte potential [V]",
"Terminal voltage [V]",
]
# else plot all variables in first model
else:
output_variables = models[0].variables

self.set_output_variables(output_variables, solutions)
self.reset_axis()
Expand Down Expand Up @@ -285,7 +290,9 @@ def set_output_variables(self, output_variables, solutions):
spatial_scale,
) = self.get_spatial_var(key, first_variable, "first")
self.spatial_variable_dict[key] = {spatial_var_name: spatial_var_value}
self.first_dimensional_spatial_variable[key] = spatial_var_value * spatial_scale
self.first_dimensional_spatial_variable[key] = (
spatial_var_value * spatial_scale
)
self.first_spatial_scale[key] = spatial_scale

elif first_variable.dimensions == 2:
Expand All @@ -312,8 +319,12 @@ def set_output_variables(self, output_variables, solutions):
first_spatial_var_name: first_spatial_var_value,
second_spatial_var_name: second_spatial_var_value,
}
self.first_dimensional_spatial_variable[key] = first_spatial_var_value * first_spatial_scale
self.second_dimensional_spatial_variable[key] = second_spatial_var_value * second_spatial_scale
self.first_dimensional_spatial_variable[key] = (
first_spatial_var_value * first_spatial_scale
)
self.second_dimensional_spatial_variable[key] = (
second_spatial_var_value * second_spatial_scale
)

# Store variables and subplot position
self.variables[key] = variables
Expand All @@ -323,25 +334,33 @@ def get_spatial_var(self, key, variable, dimension):
"Return the appropriate spatial variable(s)"

# Extract name and dimensionless value
# Special case for current collector, which is 2D but in a weird way (both
# first and second variables are in the same domain, not auxiliary domain)
if dimension == "first":
spatial_var_name = variable.first_dimension
spatial_var_value = variable.first_dim_pts
domain = variable.domain[0]
elif dimension == "second":
spatial_var_name = variable.second_dimension
spatial_var_value = variable.second_dim_pts
if variable.domain[0] == "current collector":
domain = "current collector"
else:
domain = variable.auxiliary_domains["secondary"][0]

if domain == "current collector":
domain += " {}".format(spatial_var_name)

# Get scale
if spatial_var_name == "r":
if "negative" in key[0].lower():
spatial_scale = self.spatial_scales["r_n"]
elif "positive" in key[0].lower():
spatial_scale = self.spatial_scales["r_p"]
else:
raise NotImplementedError(
"Cannot determine the spatial scale for '{}'".format(key[0])
)
else:
spatial_scale = self.spatial_scales[spatial_var_name]
try:
spatial_scale = self.spatial_scales[domain]
except KeyError:
raise KeyError(
(
"Can't find spatial scale for '{}', make sure both '{} [m]' "
+ "and '{}' are defined in the model variables"
).format(domain, *[spatial_var_name] * 2)
)

return spatial_var_name, spatial_var_value, spatial_scale

Expand Down
37 changes: 35 additions & 2 deletions tests/integration/test_quick_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_plot_lithium_ion(self):
# check dynamic plot loads
quick_plot.dynamic_plot(testing=True)

quick_plot.update(0.01)
quick_plot.slider_update(0.01)

# Test with different output variables
output_vars = [
Expand Down Expand Up @@ -71,7 +71,7 @@ def test_plot_lithium_ion(self):
# check dynamic plot loads
quick_plot.dynamic_plot(testing=True)

quick_plot.update(0.01)
quick_plot.slider_update(0.01)

def test_plot_lead_acid(self):
loqs = pybamm.lead_acid.LOQS()
Expand All @@ -87,6 +87,39 @@ def test_plot_lead_acid(self):

pybamm.QuickPlot(solution_loqs)

def test_plot_2plus1D_spm(self):
spm = pybamm.lithium_ion.SPM(
{"current collector": "potential pair", "dimensionality": 2}
)
geometry = spm.default_geometry
param = spm.default_parameter_values
param.process_model(spm)
param.process_geometry(geometry)
var = pybamm.standard_spatial_vars
var_pts = {
var.x_n: 5,
var.x_s: 5,
var.x_p: 5,
var.r_n: 5,
var.r_p: 5,
var.y: 5,
var.z: 5,
}
mesh = pybamm.Mesh(geometry, spm.default_submesh_types, var_pts)
disc_spm = pybamm.Discretisation(mesh, spm.default_spatial_methods)
disc_spm.process_model(spm)
t_eval = np.linspace(0, 3600, 100)
solution_spm = spm.default_solver.solve(spm, t_eval)

pybamm.QuickPlot(
solution_spm,
[
"Negative current collector potential [V]",
"Positive current collector potential [V]",
"Terminal voltage [V]",
],
)


if __name__ == "__main__":
print("Add -v for more debug output")
Expand Down
Loading

0 comments on commit 5fedf67

Please sign in to comment.