Skip to content

Commit

Permalink
#617 unify mesh generators
Browse files Browse the repository at this point in the history
  • Loading branch information
rtimms committed Oct 15, 2019
1 parent 65f78d8 commit 5e9b746
Show file tree
Hide file tree
Showing 22 changed files with 334 additions and 366 deletions.
3 changes: 3 additions & 0 deletions docs/source/meshes/meshes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ Meshes
.. autoclass:: pybamm.Mesh
:members:

.. autoclass:: pybamm.SubMesh
:members:

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

.. autoclass:: pybamm.MeshGenerator1D
:members:

.. autoclass:: pybamm.Uniform1DSubMesh
:members:

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

.. autoclass:: pybamm.MeshGenerator2D
:members:

.. autoclass:: pybamm.ScikitUniform2DSubMesh
:members:

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

.. autoclass:: pybamm.SubMesh0D
:members:

.. autoclass:: pybamm.MeshGenerator0D
:members:
22 changes: 11 additions & 11 deletions examples/notebooks/models/SPM.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@
"source": [
"The next step is to mesh the input geometry. We can do this using the [`pybamm.Mesh`](https://pybamm.readthedocs.io/en/latest/source/meshes/meshes.html) class. This class takes in the geometry of the problem, and also two dictionaries containing the type of mesh to use within each domain of the geometry (i.e. within the positive or negative electrode domains), and the number of mesh points. \n",
"\n",
"The default mesh types and the default number of points to use in each variable for the SPH model are:"
"The default mesh types and the default number of points to use in each variable for the SPM model are:"
]
},
{
Expand All @@ -227,12 +227,12 @@
"name": "stdout",
"output_type": "stream",
"text": [
"negative electrode is of type MeshGenerator1D : Uniform\n",
"separator is of type MeshGenerator1D : Uniform\n",
"positive electrode is of type MeshGenerator1D : Uniform\n",
"negative particle is of type MeshGenerator1D : Uniform\n",
"positive particle is of type MeshGenerator1D : Uniform\n",
"current collector is of type MeshGenerator0D : Position\n",
"negative electrode is of type Generator for Uniform1DSubMesh\n",
"separator is of type Generator for Uniform1DSubMesh\n",
"positive electrode is of type Generator for Uniform1DSubMesh\n",
"negative particle is of type Generator for Uniform1DSubMesh\n",
"positive particle is of type Generator for Uniform1DSubMesh\n",
"current collector is of type Generator for SubMesh0D\n",
"x_n has 20 mesh points\n",
"x_s has 20 mesh points\n",
"x_p has 20 mesh points\n",
Expand All @@ -245,7 +245,7 @@
],
"source": [
"for k, t in model.default_submesh_types.items():\n",
" print(k,'is of type',t.__class__.__name__,':',t.submesh_type )\n",
" print(k,'is of type',t.__repr__())\n",
"for var, npts in model.default_var_pts.items():\n",
" print(var,'has',npts,'mesh points')"
]
Expand Down Expand Up @@ -309,7 +309,7 @@
{
"data": {
"text/plain": [
"<pybamm.models.full_battery_models.lithium_ion.spm.SPM at 0x7fc1812341d0>"
"<pybamm.models.full_battery_models.lithium_ion.spm.SPM at 0x7f75886cf198>"
]
},
"execution_count": 11,
Expand Down Expand Up @@ -760,7 +760,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "19149e76db2642209815a3c6150b8dc7",
"model_id": "99e13279bde044ea9cea75d2f873e7c6",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -808,7 +808,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "509fb382c8984dc883a10d85dcb2dfbc",
"model_id": "5198757616254d11a031a8deee5a51f7",
"version_major": 2,
"version_minor": 0
},
Expand Down
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.MeshGenerator1D(),
pybamm.MeshGenerator1D("Chebyshev"),
pybamm.MeshGenerator1D("Exponential", {"side": "right"}),
pybamm.MeshGenerator(pybamm.Uniform1DSubMesh),
pybamm.MeshGenerator(pybamm.Chebyshev1DSubMesh),
pybamm.MeshGenerator(pybamm.Exponential1DSubMesh, submesh_params={"side": "right"}),
]
meshes = [None] * len(models)
# discretise models
Expand Down
6 changes: 2 additions & 4 deletions pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,19 +223,17 @@ def version(formatted=False):
# Mesh and Discretisation classes
#
from .discretisations.discretisation import Discretisation
from .meshes.meshes import Mesh, MeshGenerator
from .meshes.zero_dimensional_submesh import SubMesh0D, MeshGenerator0D
from .meshes.meshes import Mesh, SubMesh, MeshGenerator
from .meshes.zero_dimensional_submesh import SubMesh0D
from .meshes.one_dimensional_submeshes import (
SubMesh1D,
MeshGenerator1D,
Uniform1DSubMesh,
Exponential1DSubMesh,
Chebyshev1DSubMesh,
UserSupplied1DSubMesh,
)
from .meshes.scikit_fem_submeshes import (
ScikitSubMesh2D,
MeshGenerator2D,
ScikitUniform2DSubMesh,
ScikitExponential2DSubMesh,
ScikitChebyshev2DSubMesh,
Expand Down
61 changes: 38 additions & 23 deletions pybamm/meshes/meshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ def __init__(self, geometry, submesh_types, var_pts):
# create submesh_pts from var_pts
submesh_pts = {}
for domain in geometry:
# create mesh generator if just class is passed (will throw an error
# later if the mesh needed parameters)
if not isinstance(
submesh_types[domain], pybamm.MeshGenerator
) and issubclass(submesh_types[domain], pybamm.SubMesh):
submesh_types[domain] = pybamm.MeshGenerator(submesh_types[domain])
# Zero dimensional submesh case (only one point)
if submesh_types[domain] == pybamm.SubMesh0D or isinstance(
submesh_types[domain], pybamm.MeshGenerator0D
):
if issubclass(submesh_types[domain].submesh_type, pybamm.SubMesh0D):
submesh_pts[domain] = 1
# other cases
else:
Expand Down Expand Up @@ -97,24 +101,23 @@ def __init__(self, geometry, submesh_types, var_pts):

# Create submeshes
for domain in geometry:
if domain == "current collector" and not (
submesh_types[domain] == pybamm.SubMesh0D
or isinstance(submesh_types[domain], pybamm.MeshGenerator0D)
):
# repeat mesh if domain has secondary dimension
if "secondary" in geometry[domain].keys():
repeats = 1
for var in geometry[domain]["secondary"].keys():
repeats *= submesh_pts[domain][var.id] # note (specific to FV)
else:
repeats = 1
# create submesh, passing tab information if provided
if "tabs" in geometry[domain].keys():
self[domain] = [
submesh_types[domain](
geometry[domain]["primary"],
submesh_pts[domain],
geometry[domain]["tabs"],
)
]
] * repeats
else:
if "secondary" in geometry[domain].keys():
repeats = 1
for var in geometry[domain]["secondary"].keys():
repeats *= submesh_pts[domain][var.id] # note (specific to FV)
else:
repeats = 1
self[domain] = [
submesh_types[domain](
geometry[domain]["primary"], submesh_pts[domain]
Expand Down Expand Up @@ -200,26 +203,38 @@ def add_ghost_meshes(self):
)


class SubMesh:
"""
Base submesh class.
Contains the position of the nodes, the number of mesh points, and
(optionally) information about the tab locations.
"""

def __init__(self):
pass


class MeshGenerator:
"""
Base class for mesh generator objects that are used to generate submeshes.
Parameters
----------
submesh_type: str, optional
The type of submeshes to use. Default is "Uniform".
submesh_type: :class:`pybamm.SubMesh`
The type of submesh to use (e.g. Uniform1DSubMesh).
submesh_params: dict, optional
Contains any parameters required by the submesh.
"""

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

def __call__(self):
"""
Each Mesh Generator should implemented a call method which returns
an instance of a submesh.
"""
raise NotImplementedError
def __call__(self, lims, npts, tabs=None):
return self.submesh_type(lims, npts, tabs, **self.submesh_params)

def __repr__(self):
return "Generator for {}".format(
self.submesh_type.__name__
)
74 changes: 27 additions & 47 deletions pybamm/meshes/one_dimensional_submeshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,28 @@
# One-dimensional submeshes
#
import pybamm
from .meshes import MeshGenerator
from .meshes import SubMesh

import numpy as np


class SubMesh1D:
class SubMesh1D(SubMesh):
"""
1D submesh class.
Contains the position of the nodes, the number of mesh points, and
(optionally) information about the tab locations.
Parameters
----------
edges : array_like
An array containing the points corresponding to the edges of the submesh
coord_sys : string
The coordinate system of the submesh
tabs : dict, optional
A dictionary that contains information about the size and location of
the tabs
**Extends:"": :class:`pybamm.SubMesh`
"""

def __init__(self, edges, coord_sys, tabs=None):
Expand Down Expand Up @@ -45,50 +57,6 @@ def near(x, point, tol=3e-16):
)


class MeshGenerator1D(MeshGenerator):
"""
A class to generate a submesh on a 1D domain.
Parameters
----------
submesh_type: str, optional
The type of submeshes to use. Can be "Uniform", "Exponential", "Chebyshev"
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="Uniform", submesh_params=None):
self.submesh_type = submesh_type
self.submesh_params = submesh_params or {}

def __call__(self, lims, npts, tabs=None):

if self.submesh_type == "Uniform":
return Uniform1DSubMesh(lims, npts, tabs)

elif self.submesh_type == "Exponential":
return Exponential1DSubMesh(lims, npts, tabs, **self.submesh_params)

elif self.submesh_type == "Chebyshev":
return Chebyshev1DSubMesh(lims, npts, tabs)

elif self.submesh_type == "User":
try:
edges = self.submesh_params["edges"]
except KeyError:
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):
"""
A class to generate a uniform submesh on a 1D domain
Expand All @@ -104,6 +72,8 @@ class Uniform1DSubMesh(SubMesh1D):
tabs : dict, optional
A dictionary that contains information about the size and location of
the tabs
**Extends:"": :class:`pybamm.SubMesh1D`
"""

def __init__(self, lims, npts, tabs=None):
Expand Down Expand Up @@ -174,6 +144,8 @@ class Exponential1DSubMesh(SubMesh1D):
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.
**Extends:"": :class:`pybamm.SubMesh1D`
"""

def __init__(self, lims, npts, tabs, side="symmetric", stretch=None):
Expand Down Expand Up @@ -257,6 +229,8 @@ class Chebyshev1DSubMesh(SubMesh1D):
tabs : dict, optional
A dictionary that contains information about the size and location of
the tabs
**Extends:"": :class:`pybamm.SubMesh1D`
"""

def __init__(self, lims, npts, tabs=None):
Expand Down Expand Up @@ -302,9 +276,15 @@ class UserSupplied1DSubMesh(SubMesh1D):
the tabs
edges : array_like
The array of points which correspond to the edges of the mesh.
**Extends:"": :class:`pybamm.SubMesh1D`
"""

def __init__(self, lims, npts, tabs, edges):
def __init__(self, lims, npts, tabs, edges=None):

# raise error if no edges passed
if edges is None:
raise pybamm.GeometryError("User mesh requires parameter 'edges'")

# check that only one variable passed in
if len(lims) != 1:
Expand Down
Loading

0 comments on commit 5e9b746

Please sign in to comment.