Skip to content
Merged
14,657 changes: 43 additions & 14,614 deletions examples/3D_Cylinder_Demo.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions spatialpy/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .datafunction import DataFunction
from .domain import Domain
from .geometry import (
CombinatoryGeometry,
Geometry,
GeometryAll,
GeometryExterior,
Expand Down
2 changes: 1 addition & 1 deletion spatialpy/core/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def compile_prep(self):
self.listOfTypeIDs = list(self.typeNdxMapping.values())
self._get_type_name_mapping()

def add_point(self, point, vol=0, mass=0, type_id=1, nu=0, fixed=False, rho=None, c=0):
def add_point(self, point, vol=1, mass=1, type_id=1, nu=0, fixed=False, rho=None, c=10):
"""
Add a single point particle to the domain space.

Expand Down
59 changes: 59 additions & 0 deletions spatialpy/core/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,67 @@

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import numpy

from spatialpy.core.spatialpyerror import GeometryError

class CombinatoryGeometry:
"""
Combinatory Geometry class uses one or more Geometry class for inclusion or exclusion of
multiple geometric shapes.

:param formula: Boolean logic formula to be evaluated. Example use: "(geo1 or geo2) and not geo3".
:type formula: str

:param geo_namespace: Namespace used when evaluating the formula. Example use:
{'geo1': Geometry1(), 'geo2': Geometry2(), 'geo3': Geometry3()} where 'geo1',
'geo2', and 'geo3' are found in the formula.
:type geo_namespace: dict
"""
def __init__(self, formula, geo_namespace):
self.formula = formula
self.geo_namespace = geo_namespace

self.validate()

def inside(self, point, on_boundary):
"""
:param point: X, Y, Z coodinates for the particle.
:type point: float[3]

:param on_boundary: Indicates whether a particle is on the edge of the domain.
:type on_boundary: bool

:returns: True if the particle satisfies boolean condition for all geometies, else False.
:rtype: bool

:raises GeometryError: If any geometries inside method does not return a bool.
"""
namespace = {}
for name, geometry in self.geo_namespace.items():
val = geometry.inside(point, on_boundary)
if not isinstance(val, (bool, numpy.bool_)):
errmsg = f"{name} is not a valid Geometry obj. Reason given: inside() method must return a bool"
raise GeometryError(errmsg)
namespace[name] = val
return eval(self.formula, {}, namespace)

def validate(self):
"""
Validate the combinatory geometry object.
"""
keys = list(self.geo_namespace.keys())
for name in keys:
if name not in self.formula:
raise GeometryError("geo_namespace entries must be in the formula.")
keys.extend(['and', 'or', 'not', '(', ')'])
formula = self.formula
for item in keys:
formula = formula.replace(item, "")
if formula.strip() != "":
errmsg = f"formula may only contain boolean operators or geometries in geo_namespace not {formula.split(' ')}"
raise GeometryError(errmsg)

class Geometry:
"""
Geometry class provides a method for tagging parts of the spatial domain as separate parts.
Expand Down