diff --git a/src/pybamm/__init__.py b/src/pybamm/__init__.py index c26dfed0fa..8d94afdff1 100644 --- a/src/pybamm/__init__.py +++ b/src/pybamm/__init__.py @@ -107,7 +107,6 @@ from .geometry.geometry import Geometry from .geometry.battery_geometry import battery_geometry -from .expression_tree.independent_variable import KNOWN_COORD_SYS from .geometry import standard_spatial_vars # Parameter classes and methods diff --git a/src/pybamm/expression_tree/independent_variable.py b/src/pybamm/expression_tree/independent_variable.py index 015b6ae49d..6b4bc61274 100644 --- a/src/pybamm/expression_tree/independent_variable.py +++ b/src/pybamm/expression_tree/independent_variable.py @@ -8,8 +8,6 @@ import pybamm from pybamm.type_definitions import DomainType, AuxiliaryDomainType, DomainsType -KNOWN_COORD_SYS = ["cartesian", "cylindrical polar", "spherical polar"] - class IndependentVariable(pybamm.Symbol): """ @@ -141,9 +139,7 @@ def __init__( domain: DomainType = None, auxiliary_domains: AuxiliaryDomainType = None, domains: DomainsType = None, - coord_sys=None, ) -> None: - self.coord_sys = coord_sys super().__init__( name, domain=domain, auxiliary_domains=auxiliary_domains, domains=domains ) @@ -176,7 +172,7 @@ def create_copy( perform_simplifications=True, ): """See :meth:`pybamm.Symbol.new_copy()`.""" - return self.__class__(self.name, domains=self.domains, coord_sys=self.coord_sys) + return self.__class__(self.name, domains=self.domains) class SpatialVariableEdge(SpatialVariable): @@ -206,9 +202,8 @@ def __init__( domain: DomainType = None, auxiliary_domains: AuxiliaryDomainType = None, domains: DomainsType = None, - coord_sys=None, ) -> None: - super().__init__(name, domain, auxiliary_domains, domains, coord_sys) + super().__init__(name, domain, auxiliary_domains, domains) def _evaluates_on_edges(self, dimension): return True diff --git a/src/pybamm/geometry/battery_geometry.py b/src/pybamm/geometry/battery_geometry.py index 3e1986507a..483c786f0e 100644 --- a/src/pybamm/geometry/battery_geometry.py +++ b/src/pybamm/geometry/battery_geometry.py @@ -39,86 +39,74 @@ def battery_geometry( # Set up electrode/separator/electrode geometry geometry = { - "negative electrode": {"x_n": {"min": 0, "max": L_n}}, - "separator": {"x_s": {"min": L_n, "max": L_n_L_s}}, - "positive electrode": {"x_p": {"min": L_n_L_s, "max": geo.L_x}}, + "negative electrode": {"x_n": {"min": 0, "max": L_n}, "coord_sys": "cartesian"}, + "separator": {"x_s": {"min": L_n, "max": L_n_L_s}, "coord_sys": "cartesian"}, + "positive electrode": { + "x_p": {"min": L_n_L_s, "max": geo.L_x}, + "coord_sys": "cartesian", + }, } # Add particle domains if include_particles is True: for domain in ["negative", "positive"]: + domain_options = getattr(options, domain) if options.electrode_types[domain] == "porous": + particle_coord_sys = domain_options["particle shape"] + " polar" geo_domain = geo.domain_params[domain] d = domain[0] geometry.update( { f"{domain} particle": { - f"r_{d}": {"min": 0, "max": geo_domain.prim.R_typ} + f"r_{d}": {"min": 0, "max": geo_domain.prim.R_typ}, + "coord_sys": particle_coord_sys, }, } ) - phases = int(getattr(options, domain)["particle phases"]) + phases = int(domain_options["particle phases"]) if phases >= 2: geometry.update( { f"{domain} primary particle": { - f"r_{d}_prim": {"min": 0, "max": geo_domain.prim.R_typ} + f"r_{d}_prim": {"min": 0, "max": geo_domain.prim.R_typ}, + "coord_sys": particle_coord_sys, }, f"{domain} secondary particle": { - f"r_{d}_sec": {"min": 0, "max": geo_domain.sec.R_typ} + f"r_{d}_sec": {"min": 0, "max": geo_domain.sec.R_typ}, + "coord_sys": particle_coord_sys, }, } ) - # Add particle size domains - if ( - options is not None - and options.negative["particle size"] == "distribution" - and options.electrode_types["negative"] == "porous" - ): - R_min_n = geo.n.prim.R_min - R_max_n = geo.n.prim.R_max - geometry.update( - { - "negative particle size": {"R_n": {"min": R_min_n, "max": R_max_n}}, - } - ) - phases = int(options.negative["particle phases"]) - if phases >= 2: - geometry.update( - { - "negative primary particle size": { - "R_n_prim": {"min": R_min_n, "max": R_max_n} - }, - "negative secondary particle size": { - "R_n_sec": {"min": R_min_n, "max": R_max_n} - }, - } - ) - if ( - options is not None - and options.positive["particle size"] == "distribution" - and options.electrode_types["positive"] == "porous" - ): - R_min_p = geo.p.prim.R_min - R_max_p = geo.p.prim.R_max - geometry.update( - { - "positive particle size": {"R_p": {"min": R_min_p, "max": R_max_p}}, - } - ) - phases = int(options.positive["particle phases"]) - if phases >= 2: - geometry.update( - { - "positive primary particle size": { - "R_p_prim": {"min": R_min_p, "max": R_max_p} - }, - "positive secondary particle size": { - "R_p_sec": {"min": R_min_p, "max": R_max_p} - }, - } - ) + if domain_options["particle size"] == "distribution": + if phases == 1: + geometry.update( + { + f"{domain} particle size": { + f"R_{d}": { + "min": geo_domain.prim.R_min, + "max": geo_domain.prim.R_max, + } + }, + } + ) + elif phases == 2: + geometry.update( + { + f"{domain} primary particle size": { + f"R_{d}_prim": { + "min": geo_domain.prim.R_min, + "max": geo_domain.prim.R_max, + } + }, + f"{domain} secondary particle size": { + f"R_{d}_sec": { + "min": geo_domain.sec.R_min, + "max": geo_domain.sec.R_max, + } + }, + } + ) # Add current collector domains current_collector_dimension = options["dimensionality"] @@ -128,6 +116,7 @@ def battery_geometry( elif current_collector_dimension == 1: geometry["current collector"] = { "z": {"min": 0, "max": geo.L_z}, + "coord_sys": "cartesian", "tabs": { "negative": {"z_centre": geo.n.centre_z_tab}, "positive": {"z_centre": geo.p.centre_z_tab}, @@ -137,6 +126,7 @@ def battery_geometry( geometry["current collector"] = { "y": {"min": 0, "max": geo.L_y}, "z": {"min": 0, "max": geo.L_z}, + "coord_sys": "cartesian", "tabs": { "negative": { "y_centre": geo.n.centre_y_tab, @@ -156,6 +146,7 @@ def battery_geometry( elif current_collector_dimension == 1: geometry["current collector"] = { "r_macro": {"min": geo.r_inner, "max": 1}, + "coord_sys": "cylindrical polar", } else: raise pybamm.GeometryError( diff --git a/src/pybamm/geometry/standard_spatial_vars.py b/src/pybamm/geometry/standard_spatial_vars.py index b6638694f7..69913f11da 100644 --- a/src/pybamm/geometry/standard_spatial_vars.py +++ b/src/pybamm/geometry/standard_spatial_vars.py @@ -7,32 +7,26 @@ "x_n", domain=["negative electrode"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) x_s = pybamm.SpatialVariable( "x_s", domain=["separator"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) x_p = pybamm.SpatialVariable( "x_p", domain=["positive electrode"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) x = pybamm.SpatialVariable( "x", domain=whole_cell, auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) -y = pybamm.SpatialVariable("y", domain="current collector", coord_sys="cartesian") -z = pybamm.SpatialVariable("z", domain="current collector", coord_sys="cartesian") -r_macro = pybamm.SpatialVariable( - "r_macro", domain="current collector", coord_sys="cylindrical polar" -) +y = pybamm.SpatialVariable("y", domain="current collector") +z = pybamm.SpatialVariable("z", domain="current collector") +r_macro = pybamm.SpatialVariable("r_macro", domain="current collector") r_n = pybamm.SpatialVariable( "r_n", @@ -41,7 +35,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) r_p = pybamm.SpatialVariable( "r_p", @@ -50,7 +43,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) r_n_prim = pybamm.SpatialVariable( "r_n_prim", @@ -59,7 +51,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) r_p_prim = pybamm.SpatialVariable( "r_p_prim", @@ -68,7 +59,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) r_n_sec = pybamm.SpatialVariable( "r_n_sec", @@ -77,7 +67,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) r_p_sec = pybamm.SpatialVariable( "r_p_sec", @@ -86,7 +75,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) R_n = pybamm.SpatialVariable( @@ -96,7 +84,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) R_p = pybamm.SpatialVariable( @@ -106,7 +93,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) R_n_prim = pybamm.SpatialVariable( @@ -116,7 +102,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) R_p_prim = pybamm.SpatialVariable( "R_p_prim", @@ -125,7 +110,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) R_n_sec = pybamm.SpatialVariable( @@ -135,7 +119,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) R_p_sec = pybamm.SpatialVariable( "R_p_sec", @@ -144,7 +127,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) # Domains at cell edges @@ -152,36 +134,26 @@ "x_n", domain=["negative electrode"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) x_s_edge = pybamm.SpatialVariableEdge( "x_s", domain=["separator"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) x_p_edge = pybamm.SpatialVariableEdge( "x_p", domain=["positive electrode"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) x_edge = pybamm.SpatialVariableEdge( "x", domain=whole_cell, auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) -y_edge = pybamm.SpatialVariableEdge( - "y", domain="current collector", coord_sys="cartesian" -) -z_edge = pybamm.SpatialVariableEdge( - "z", domain="current collector", coord_sys="cartesian" -) -r_macro_edge = pybamm.SpatialVariableEdge( - "r_macro", domain="current collector", coord_sys="cylindrical polar" -) +y_edge = pybamm.SpatialVariableEdge("y", domain="current collector") +z_edge = pybamm.SpatialVariableEdge("z", domain="current collector") +r_macro_edge = pybamm.SpatialVariableEdge("r_macro", domain="current collector") r_n_edge = pybamm.SpatialVariableEdge( @@ -191,7 +163,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) r_p_edge = pybamm.SpatialVariableEdge( "r_p", @@ -200,7 +171,6 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) R_n_edge = pybamm.SpatialVariableEdge( @@ -210,7 +180,6 @@ "secondary": "negative electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) R_p_edge = pybamm.SpatialVariableEdge( "R_p", @@ -219,5 +188,4 @@ "secondary": "positive electrode", "tertiary": "current collector", }, - coord_sys="cartesian", ) diff --git a/src/pybamm/meshes/meshes.py b/src/pybamm/meshes/meshes.py index 2f0977d9a6..ab6559a71c 100644 --- a/src/pybamm/meshes/meshes.py +++ b/src/pybamm/meshes/meshes.py @@ -62,8 +62,8 @@ def __init__(self, geometry, submesh_types, var_pts): "Geometry should no longer be given keys 'primary' or " "'secondary'. See pybamm.battery_geometry() for example" ) - # skip over tabs key - if var != "tabs": + # skip over tabs and coord_sys keys + if var not in ["tabs", "coord_sys"]: if isinstance(var, str): var = getattr(pybamm.standard_spatial_vars, var) # Raise error if the number of points for a particular @@ -80,6 +80,13 @@ def __init__(self, geometry, submesh_types, var_pts): submesh_pts[domain][var.name] = var_name_pts[var.name] self.submesh_pts = submesh_pts + coord_sys = {} + for domain in geometry: + if "coord_sys" in geometry[domain].keys(): + coord_sys[domain] = geometry[domain].pop("coord_sys") + else: + coord_sys[domain] = "cartesian" + # evaluate any expressions in geometry for domain in geometry: for spatial_variable, spatial_limits in geometry[domain].items(): @@ -114,7 +121,9 @@ def __init__(self, geometry, submesh_types, var_pts): # Create submeshes self.base_domains = [] for domain in geometry: - self[domain] = submesh_types[domain](geometry[domain], submesh_pts[domain]) + self[domain] = submesh_types[domain]( + geometry[domain], submesh_pts[domain], coord_sys[domain] + ) self.base_domains.append(domain) # add ghost meshes @@ -297,8 +306,8 @@ def __init__(self, submesh_type, submesh_params=None): self.submesh_type = submesh_type self.submesh_params = submesh_params or {} - def __call__(self, lims, npts): - return self.submesh_type(lims, npts, **self.submesh_params) + def __call__(self, lims, npts, coord_sys): + return self.submesh_type(lims, npts, coord_sys, **self.submesh_params) def __repr__(self): return f"Generator for {self.submesh_type.__name__}" diff --git a/src/pybamm/meshes/one_dimensional_submeshes.py b/src/pybamm/meshes/one_dimensional_submeshes.py index 0e95b2ac59..338ead80f1 100644 --- a/src/pybamm/meshes/one_dimensional_submeshes.py +++ b/src/pybamm/meshes/one_dimensional_submeshes.py @@ -61,12 +61,12 @@ def read_lims(self, lims): # Read and remove tabs. If "tabs" is not a key in "lims", then tabs is set to # "None" and nothing is removed from lims tabs = lims.pop("tabs", None) - + lims_without_coord_sys = {l: v for l, v in lims.items() if l != "coord_sys"} # check that only one variable passed in - if len(lims) != 1: + if len(lims_without_coord_sys) != 1: raise pybamm.GeometryError("lims should only contain a single variable") - ((spatial_var, spatial_lims),) = lims.items() + ((spatial_var, spatial_lims),) = lims_without_coord_sys.items() if isinstance(spatial_var, str): spatial_var = getattr(pybamm.standard_spatial_vars, spatial_var) @@ -121,17 +121,17 @@ class Uniform1DSubMesh(SubMesh1D): A dictionary that contains the number of points to be used on each spatial variable. Note: the number of nodes (located at the cell centres) is npts, and the number of edges is npts+1. + coord_sys : str + The coordinate system of the submesh """ - def __init__(self, lims, npts): + def __init__(self, lims, npts, coord_sys): spatial_var, spatial_lims, tabs = self.read_lims(lims) npts = npts[spatial_var.name] edges = np.linspace(spatial_lims["min"], spatial_lims["max"], npts + 1) - coord_sys = spatial_var.coord_sys - - super().__init__(edges, coord_sys=coord_sys, tabs=tabs) + super().__init__(edges, coord_sys, tabs=tabs) @classmethod def _from_json(cls, snippet: dict): diff --git a/src/pybamm/meshes/zero_dimensional_submesh.py b/src/pybamm/meshes/zero_dimensional_submesh.py index 70ec3d7b69..f8da0a842d 100644 --- a/src/pybamm/meshes/zero_dimensional_submesh.py +++ b/src/pybamm/meshes/zero_dimensional_submesh.py @@ -20,9 +20,12 @@ class SubMesh0D(SubMesh): npts : dict, optional Number of points to be used. Included for compatibility with other meshes, but ignored by this mesh class + coord_sys : str, optional + The coordinate system of the submesh. Included for compatibility with other + meshes, but ignored by this mesh class """ - def __init__(self, position, npts=None): + def __init__(self, position, npts=1, coord_sys=None): # Remove tabs position.pop("tabs", None) diff --git a/src/pybamm/parameters/lithium_ion_parameters.py b/src/pybamm/parameters/lithium_ion_parameters.py index 6485047bfc..01373433cd 100644 --- a/src/pybamm/parameters/lithium_ion_parameters.py +++ b/src/pybamm/parameters/lithium_ion_parameters.py @@ -233,7 +233,6 @@ def _set_parameters(self): f"x_{domain[0]}", domain=[f"{domain} electrode"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) # Macroscale geometry @@ -401,7 +400,6 @@ def _set_parameters(self): f"x_{domain[0]}", domain=[f"{domain} electrode"], auxiliary_domains={"secondary": "current collector"}, - coord_sys="cartesian", ) r = pybamm.SpatialVariable( f"r_{domain[0]}", @@ -410,7 +408,6 @@ def _set_parameters(self): "secondary": f"{domain} electrode", "tertiary": "current collector", }, - coord_sys="spherical polar", ) # Microscale geometry diff --git a/src/pybamm/parameters/parameter_values.py b/src/pybamm/parameters/parameter_values.py index ba8c6c324e..7f93af3af4 100644 --- a/src/pybamm/parameters/parameter_values.py +++ b/src/pybamm/parameters/parameter_values.py @@ -623,6 +623,8 @@ def process_and_check(sym): geometry[domain]["tabs"][tab][position_size] = ( process_and_check(sym) ) + elif spatial_variable == "coord_sys": + continue else: for lim, sym in spatial_limits.items(): geometry[domain][spatial_variable][lim] = process_and_check(sym) diff --git a/src/pybamm/solvers/processed_variable.py b/src/pybamm/solvers/processed_variable.py index 30fbcedc70..3677c32325 100644 --- a/src/pybamm/solvers/processed_variable.py +++ b/src/pybamm/solvers/processed_variable.py @@ -197,7 +197,7 @@ def _process_spatial_variable_names(self, spatial_variable): raw_names = [] for var in spatial_variable: # Ignore tabs in domain names - if var == "tabs": + if var in ["tabs", "coord_sys"]: continue if isinstance(var, str): raw_names.append(var) diff --git a/tests/unit/test_meshes/test_meshes.py b/tests/unit/test_meshes/test_meshes.py index b51f902fd0..bb3c3927ca 100644 --- a/tests/unit/test_meshes/test_meshes.py +++ b/tests/unit/test_meshes/test_meshes.py @@ -332,7 +332,11 @@ def test_mesh_coord_sys(self, submesh_types): for submesh in mesh.values(): if not isinstance(submesh, pybamm.SubMesh0D): - assert submesh.coord_sys in pybamm.KNOWN_COORD_SYS + assert submesh.coord_sys in [ + "cartesian", + "cylindrical polar", + "spherical polar", + ] def test_unimplemented_meshes(self): var_pts = {"x_n": 10, "y": 10}