Skip to content

Commit

Permalink
#617 mesh generators for 2D
Browse files Browse the repository at this point in the history
  • Loading branch information
rtimms committed Oct 11, 2019
1 parent 7d86a33 commit 4ddfe35
Show file tree
Hide file tree
Showing 17 changed files with 315 additions and 206 deletions.
9 changes: 3 additions & 6 deletions docs/source/meshes/one_dimensional_submeshes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@
.. autoclass:: pybamm.SubMesh1D
:members:

.. autoclass:: pybamm.Uniform1DSubMesh
.. autoclass:: pybamm.MeshGenerator1D
:members:

.. autoclass:: pybamm.Exponential1DSubMesh
.. autoclass:: pybamm.Uniform1DSubMesh
:members:

.. autoclass:: pybamm.Exponential1DSubMeshGenerator
.. autoclass:: pybamm.Exponential1DSubMesh
:members:

.. autoclass:: pybamm.Chebyshev1DSubMesh
:members:

.. autoclass:: pybamm.UserSupplied1DSubMesh
:members:

.. autoclass:: pybamm.UserSupplied1DSubMeshGenerator
:members:
8 changes: 4 additions & 4 deletions docs/source/meshes/two_dimensional_submeshes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
.. autoclass:: pybamm.ScikitSubMesh2D
:members:

.. autoclass:: pybamm.MeshGenerator2D
:members:

.. autoclass:: pybamm.ScikitUniform2DSubMesh
:members:

.. autoclass:: pybamm.ScikitTopExponential2DSubMesh
.. autoclass:: pybamm.ScikitExponential2DSubMesh
:members:

.. autoclass:: pybamm.ScikitChebyshev2DSubMesh
:members:

.. autoclass:: pybamm.UserSupplied2DSubMesh
:members:

.. autoclass:: pybamm.UserSupplied2DSubMeshGenerator
:members:
3 changes: 3 additions & 0 deletions docs/source/meshes/zero_dimensional_submeshes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@

.. autoclass:: pybamm.SubMesh0D
:members:

.. autoclass:: pybamm.MeshGenerator0D
:members:
6 changes: 3 additions & 3 deletions examples/scripts/SPM_compare_particle_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
# set mesh
submesh_types = models[0].default_submesh_types
particle_meshes = [
pybamm.Uniform1DSubMesh,
pybamm.Chebyshev1DSubMesh,
pybamm.Exponential1DSubMeshGenerator(side="right"),
pybamm.MeshGenerator1D(),
pybamm.MeshGenerator1D("Chebyshev"),
pybamm.MeshGenerator1D("Exponential", {"side": "right"}),
]
meshes = [None] * len(models)
# discretise models
Expand Down
9 changes: 4 additions & 5 deletions pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,23 +224,22 @@ def version(formatted=False):
#
from .discretisations.discretisation import Discretisation
from .meshes.meshes import Mesh, MeshGenerator
from .meshes.zero_dimensional_submesh import SubMesh0D
from .meshes.zero_dimensional_submesh import SubMesh0D, MeshGenerator0D
from .meshes.one_dimensional_submeshes import (
SubMesh1D,
MeshGenerator1D,
Uniform1DSubMesh,
Exponential1DSubMesh,
Exponential1DSubMeshGenerator,
Chebyshev1DSubMesh,
UserSupplied1DSubMesh,
UserSupplied1DSubMeshGenerator,
)
from .meshes.scikit_fem_submeshes import (
ScikitSubMesh2D,
MeshGenerator2D,
ScikitUniform2DSubMesh,
ScikitTopExponential2DSubMesh,
ScikitExponential2DSubMesh,
ScikitChebyshev2DSubMesh,
UserSupplied2DSubMesh,
UserSupplied2DSubMeshGenerator,
)

#
Expand Down
19 changes: 11 additions & 8 deletions pybamm/meshes/meshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ def __init__(self, geometry, submesh_types, var_pts):
submesh_pts = {}
for domain in geometry:
# Zero dimensional submesh case (only one point)
if submesh_types[domain] == pybamm.SubMesh0D:
if submesh_types[domain] == pybamm.SubMesh0D or isinstance(
submesh_types[domain], pybamm.MeshGenerator0D
):
submesh_pts[domain] = 1
# other cases
else:
Expand Down Expand Up @@ -95,9 +97,9 @@ def __init__(self, geometry, submesh_types, var_pts):

# Create submeshes
for domain in geometry:
if (
domain == "current collector"
and submesh_types[domain] != pybamm.SubMesh0D
if domain == "current collector" and not (
submesh_types[domain] == pybamm.SubMesh0D
or isinstance(submesh_types[domain], pybamm.MeshGenerator0D)
):
self[domain] = [
submesh_types[domain](
Expand Down Expand Up @@ -205,14 +207,15 @@ class MeshGenerator:
Parameters
----------
submesh_type: str
The type of submeshes to use.
submesh_type: str, optional
The type of submeshes to use. Default is "Uniform".
submesh_params: dict, optional
Contains any parameters required by the submesh.
"""

def __init__(self, submesh_type, submesh_params=None):
pass
def __init__(self, submesh_type="Uniform", submesh_params={}):
self.submesh_type = submesh_type
self.submesh_params = submesh_params

def __call__(self):
"""
Expand Down
100 changes: 29 additions & 71 deletions pybamm/meshes/one_dimensional_submeshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ class MeshGenerator1D(MeshGenerator):
Parameters
----------
submesh_type: str
submesh_type: str, optional
The type of submeshes to use. Can be "Uniform", "Exponential", "Chebyshev"
or "User".
or "User". Default is "Uniform".
submesh_params: dict, optional
Contains any parameters required by the submesh.
**Extends**: :class:`pybamm.MeshGenerator`
"""

def __init__(self, submesh_type, submesh_params=None):
def __init__(self, submesh_type="Uniform", submesh_params={}):
self.submesh_type = submesh_type
self.submesh_params = submesh_params

Expand All @@ -69,17 +71,7 @@ def __call__(self, lims, npts, tabs=None):
return Uniform1DSubMesh(lims, npts, tabs)

elif self.submesh_type == "Exponential":
try:
side = self.submesh_params["side"]
except KeyError:
raise pybamm.GeometryError("Exponenital mesh requires parameter 'side'")
if self.submesh_params["stretch"]:
stretch = self.submesh_params["stretch"]
elif side == "symmetric":
stretch = 1.15
elif side in ["left", "right"]:
stretch = 2.3
return Exponential1DSubMesh(lims, npts, tabs, side, stretch)
return Exponential1DSubMesh(lims, npts, tabs, **self.submesh_params)

elif self.submesh_type == "Chebyshev":
return Chebyshev1DSubMesh(lims, npts, tabs)
Expand All @@ -91,6 +83,11 @@ def __call__(self, lims, npts, tabs=None):
raise pybamm.GeometryError("User mesh requires parameter 'edges'")
return UserSupplied1DSubMesh(lims, npts, tabs, edges)

else:
raise pybamm.GeometryError(
"Submesh {} not recognised.".format(self.submesh_type)
)


class Uniform1DSubMesh(SubMesh1D):
"""
Expand Down Expand Up @@ -130,8 +127,7 @@ class Exponential1DSubMesh(SubMesh1D):
"""
A class to generate a submesh on a 1D domain in which the points are clustered
close to one or both of boundaries using an exponential formula on the interval
[a,b]. Note: this mesh should be created using
:class:`Exponential1DSubMeshGenerator`.
[a,b].
If side is "left", the gridpoints are given by
Expand Down Expand Up @@ -167,17 +163,20 @@ class Exponential1DSubMesh(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.
side : str
Whether the points are clustered near to the left or right boundary,
or both boundaries. Can be "left", "right" or "symmetric"
tabs : dict
A dictionary that contains information about the size and location of
the tabs
stretch : float
The factor (alpha) which appears in the exponential.
side : str, optional
Whether the points are clustered near to the left or right boundary,
or both boundaries. Can be "left", "right" or "symmetric". Default is
"symmetric"
stretch : float, optional
The factor (alpha) which appears in the exponential. If side is "symmetric"
then the default stretch is 1.15. If side is "left" or "right" then the
default stretch is 2.3.
"""

def __init__(self, lims, npts, tabs, side, stretch):
def __init__(self, lims, npts, tabs, side="symmetric", stretch=None):

# check that only one variable passed in
if len(lims) != 1:
Expand All @@ -190,6 +189,14 @@ def __init__(self, lims, npts, tabs, side, stretch):
npts = npts[spatial_var.id]
coord_sys = spatial_var.coord_sys

# Set stretch if not provided
if not stretch:
if side == "symmetric":
stretch = 1.15
elif side in ["left", "right"]:
stretch = 2.3

# Create edges accoriding to "side"
if side == "left":
ii = np.array(range(0, npts + 1))
edges = (b - a) * (np.exp(stretch * ii / npts) - 1) / (
Expand Down Expand Up @@ -225,36 +232,6 @@ def __init__(self, lims, npts, tabs, side, stretch):
super().__init__(edges, coord_sys=coord_sys, tabs=tabs)


class Exponential1DSubMeshGenerator(MeshGenerator):
"""
A class to generate a submesh on a 1D domain in which the points are clustered
close to one or both boundaries using an exponential formula on the interval [a,b].
Parameters
----------
side : str, optional
Whether the points are clustered near to the left or right boundary,
or both boundaries. Can be "left", "right" or "symmetric". Defualt is
"symmetric".
stretch : float, optional
The factor (alpha) which appears in the exponential, defualt is 1.15 is
side is "symmetric" and 2.3 is side is "left" or "right".
"""

def __init__(self, side="symmetric", stretch=None):
self.side = side
if stretch:
self.stretch = stretch
elif side == "symmetric":
self.stretch = 1.15
elif side in ["left", "right"]:
self.stretch = 2.3

def __call__(self, lims, npts, tabs=None):
return Exponential1DSubMesh(lims, npts, tabs, self.side, self.stretch)


class Chebyshev1DSubMesh(SubMesh1D):
"""
A class to generate a submesh on a 1D domain using Chebyshev nodes on the
Expand Down Expand Up @@ -310,7 +287,6 @@ def __init__(self, lims, npts, tabs=None):
class UserSupplied1DSubMesh(SubMesh1D):
"""
A class to generate a submesh on a 1D domain from a user supplied array of
Note: this mesh should be created using :class:`UserSupplied1DSubMeshGenerator`.
edges.
Parameters
Expand Down Expand Up @@ -366,21 +342,3 @@ def __init__(self, lims, npts, tabs, edges):
coord_sys = spatial_var.coord_sys

super().__init__(edges, coord_sys=coord_sys, tabs=tabs)


class UserSupplied1DSubMeshGenerator(MeshGenerator):
"""
A class to generate a submesh on a 1D domain using a user supplied vector of
edges.
Parameters
----------
edges : array_like
The array of points which correspond to the edges of the mesh.
"""

def __init__(self, edges):
self.edges = edges

def __call__(self, lims, npts, tabs=None):
return UserSupplied1DSubMesh(lims, npts, tabs, self.edges)
Loading

0 comments on commit 4ddfe35

Please sign in to comment.