PySALESetup

PySALESetup.creation

class PySALESetup.creation.PySALEDistributionBase

Bases: object

Base class for distributions.

In PySALESetup it is not uncommon to want to feed specific sizes, or rotations, or radii, to a setup routine. These distribution classes provide this capability. Everything random always comes from a distribution and if it’s not specified, it’s probably a uniform one.

details()
frequency(x: float, bounds: Tuple[float, float]) float

Get the frequency from the PDF over a specified interval.

Integrates over the probability density function of the chosen distribution over a specified interval to return an estimated frequency. Limits MUST be provided in the form of bounds, which allows for uneven limits and is always applied as + and - the given value of x.

Returns the probability DENSITY! this must be converted to a useful value outside of the function. :param x: :type x: float :param bounds: :type bounds: Tuple[float, float]

Returns:

frequency_density

Return type:

float

cdf(x: float)

Base method for calculating the CDF at a specified point.

Parameters:

x (float)

random_number()

Base method for getting a random number by the distribution.

class PySALESetup.creation.PySALEUniformDistribution(limits: Tuple[float, float])

Bases: PySALEDistributionBase

The uniform distribution.

All values are equally likely.

__init__(limits: Tuple[float, float])

Creates a uniform distribution given a pair of limits.

Parameters:

limits (Tuple[float, float])

cdf(x: float) float

CDF for a uniform probability density function.

Parameters:

x (float)

Returns:

probability

Return type:

float

random_number()

Generates a random number from the uniform distribution.

Returns:

number

Return type:

float

class PySALESetup.creation.PySALENormalDistribution(mu: float, sigma: float)

Bases: PySALEDistributionBase

Normal distribution.

__init__(mu: float, sigma: float)

Constructs a normal distribution given a mean and std.

Parameters:
  • mu (float) – mean

  • sigma (float) – standard deviation

cdf(x) float

CDF for a normal probability density function.

Parameters:

x (float)

Returns:

probability

Return type:

float

random_number() float

Generate a random number from the Normal distribution.

Returns:

random_number

Return type:

float

class PySALESetup.creation.PySALELogNormalDistribution(mu: float, sigma: float)

Bases: PySALEDistributionBase

Lognormal distribution.

__init__(mu: float, sigma: float)

Construct a Lognormal distribution from a mean and std.

Parameters:
  • mu (float) – mean

  • sigma (float) – standard deviation

cdf(x: float) float

CDF for the log-normal probability density function.

Parameters:

x (float)

Returns:

probability

Return type:

float

frequency(x: float, bounds: Tuple[float, float]) float

Frequency of the Lognormal PDF over a given range.

Parameters:
  • x (float)

  • bounds (Tuple[float, float])

Returns:

frequency

Return type:

float

random_number() float

Generate a random number from the Lognormal distribution.

Returns:

random_number

Return type:

float

class PySALESetup.creation.PySALEWeibull2Distribution(lambda_: float, k: float)

Bases: PySALEDistributionBase

Weibull 2-parameter distribution.

This distribution is typically used for Particle Size Distributions generated by grinding, milling, and crushing operations.

__init__(lambda_: float, k: float)

Construct a Weibull 2-parameter distribution.

Parameters:
  • lambda (float) – The ‘scale’ of the distribution

  • k (float) – The ‘shape’ of the distribution.

cdf(x: float) float

CDF for a Weibull 2-parameter distribution

Parameters:

x (float)

Returns:

probability

Return type:

float

random_number() float

Generate a random number from the Weibull2 distribution.

Returns:

random_number

Return type:

float

class PySALESetup.creation.PySALECustomDistribution(cdf_function: Callable, random_number_function: Callable)

Bases: PySALEDistributionBase

A user-defined distribution.

__init__(cdf_function: Callable, random_number_function: Callable)

Construct a user-defined distribution from two functions.

Parameters:
  • cdf_function (Callable)

  • random_number_function (Callable)

cdf(x: float)

Overwritten by the constructor

random_number()

Overwritten by the constructor

details()
class PySALESetup.creation.PySALEDomain(domain_object: PySALEObject)

Bases: object

Domain class providing insertion methods and statistics.

Create an instance from an existing PySALEObject and then use the class to insert objects in more complex ways than available on the standard object class. In particular optimise_materials is available as a way to distribute materials in a host object such that as few objects of the same material are in contact as possible.

Examples

>>> from PySALESetup import PySALEObject, PySALEDomain
>>> main = PySALEObject([(0, 0), (0, 30), (30, 30), (30, 0)])
>>> main.set_material(0)
>>> domain = PySALEDomain(main)
>>> circle = PySALEObject.generate_ellipse([0., 0.], 1, 1, 0.)
>>> domain.fill_to_threshold_area(circle, 40)
>>> domain.optimise_materials()
>>> fig, ax = main.plot()
>>> ax.set_aspect(1)
>>> fig.savefig('PySALEDomain_example.png')
__init__(domain_object: PySALEObject)
Parameters:

domain_object

fill_with_random_grains_to_threshold(grain_object: PySALEObject, threshold_fill_percent: float, rotation_distribution: PySALEDistributionBase = None, size_distribution: PySALEDistributionBase = None, max_retries: int = 10) float

Fill host object to threshold fill percent.

Parameters:
  • grain_object (PySALEObject) – The filler object

  • threshold_fill_percent (float)

  • rotation_distribution (PySALEDistributionBase) – The distribution for the rotation angles.

  • size_distribution (PySALEDistributionBase) – The distribution for the grain sizes.

  • max_retries (int) – If a grain fails to be placed how many retries with new grains before giving up? Does not reset between grains.

Returns:

Inserted area

Return type:

float

static randomly_rotate_object(duplicated_grain_object: PySALEObject, rotation_distribution: PySALEDistributionBase = None) PySALEObject

Rotate the supplied object by a random amount.

Parameters:
Returns:

rotated_object

Return type:

PySALEObject

static randomly_resize_object(grain_object: PySALEObject, size_distribution: PySALEDistributionBase = None, area: bool = False) PySALEObject

Resize the supplied object by a random amount.

The supplied distribution should return either areas or radii. Areas and radii are taken to be “equivalent” radii. I.e. the radius of the equivalent circle to the polygon with the same area.

Parameters:
  • grain_object (PySALEObject)

  • size_distribution (PySALEDistributionBase)

  • area (bool) – True if the distribution is returning an area, False if its an equivalent radius.

Returns:

rotated_object

Return type:

PySALEObject

insert_randomly(grain_object: PySALEObject, max_attempts: int = 100) bool

Insert object into the host at random locations until it fits

“fits” means - “is not intersecting with any other objects.”

Parameters:
  • grain_object (PySALEObject)

  • max_attempts (int) – The number of attempts the algorithm will make before giving up

Returns:

success

Return type:

bool

optimise_materials(allowed_materials: List[int] = (1, 2, 3, 4, 5, 6, 7, 8, 9)) None

Redistribute material numbers to not be in contact.

This function has the greatest success and is based on that used in JP Borg’s work with CTH.

Function to assign material numbers to each particle This function tries to optimise the assignments such that as few particles of the same material are in contact as possible. It works by creating a list of the Mth closest polygons, where “M” is the number of different materials being used.

Then they are sorted into the order closest -> furthest.

If the list contains all the same elements, as the allowed materials then there are necessarily no repeats and all material numbers are used up. So, => use the number of the particle furthest away.

If there is at least one repeat, then at least one material number has not been used. Select the first remaining material number that is unused and assign that.

Continue until all the particles are assigned.

Parameters:

allowed_materials (List[int]) – defaults to all materials except for void.

Return type:

None

PySALESetup.functions

PySALESetup.functions.get_figure_from_ax(ax: Axes | None = None) Tuple[Axes, Figure]

Get the matplotlib figure from an Axes or create some if None.

Parameters:

ax (plt.Axes)

Returns:

(ax, fig)

Return type:

Tuple[plt.Axes, plt.figure]

PySALESetup.mesh

class PySALESetup.mesh.CellCoords(i: int, j: int)

Bases: object

Cell coordinates in absolute indices

i: int
j: int
class PySALESetup.mesh.Region(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

NORTH = 1
SOUTH = 2
EAST = 3
WEST = 4
class PySALESetup.mesh.ExtensionZoneFactor(multiplier: float | int, max_cell_size: float)

Bases: object

Immutable dataclass recording how the extension zone scales.

multiplier: float | int
max_cell_size: float
class PySALESetup.mesh.ExtensionZone(depth: int, region: Region, cell_size: float, factor: ExtensionZoneFactor = None)

Bases: object

iSALE Extension zone object.

Extension zones can be bolted onto the main mesh (aka the high resolution zone). These can only have one material, a fixed velocity and a specific depth. Up to four can be added at a time and the order they appear in the PySALEMesh object is the order they will be applied.

        North
          |
          |
West----MESH----East
          |
          |
        South
property length: float

Physical length of the zone.

Returns:

length

Return type:

float

calculate_zone_length() float

Calculate physical length of the zone.

Return type:

float

class PySALESetup.mesh.Cell(point: Point, i: int, j: int, material: int = None, velocity: Velocity = Velocity(x=0.0, y=0.0))

Bases: object

PySALEMesh cell dataclass object.

Contains cell information including the physical centroid of a cell as a shapely.geometry.Point object; the indices of the cell in the mesh as integers; the material in the cell as an integer; the velocity of the cell as a pss Velocity object.

point: Point
i: int
j: int
material: int = None
velocity: Velocity = Velocity(x=0.0, y=0.0)
class PySALESetup.mesh.PySALEMesh(x_cells: int, y_cells: int, cell_size: float = 2e-06, extension_zones: List[ExtensionZone] = None, cylindrical_symmetry: bool = False, collision_index: int = None, origin: Tuple[float, float] = (0.0, 0.0))

Bases: object

Mesh object of discrete cells which polygons can be projected on.

Examples

Once creating a polygon (or polygons) to represent your simulation it must then be projected onto/applied to this mesh object in order to save the resulting mesh to an iSALE input file.

Here we create a void polygon that is 10 m x 15 m and populate it to 40% area fraction with circles of radius 1 m. Then we optimise the material distribution and apply the polygon to a mesh object. Then we can save the file.

>>> from PySALESetup import PySALEObject, PySALEDomain, PySALEMesh
>>> main = PySALEObject([(0, 0), (0, 15), (10, 15), (10, 0)])
>>> main.set_material(0)
>>> domain = PySALEDomain(main)
>>> circle = PySALEObject.generate_ellipse([0., 0.], 1, 1, 0.)
>>> domain.fill_with_random_grains_to_threshold(circle, 40)
>>> domain.optimise_materials()
>>> mesh = PySALEMesh(100, 150, cell_size=.1)
>>> mesh.project_polygons_onto_mesh([main])
>>> mesh.save()
__init__(x_cells: int, y_cells: int, cell_size: float = 2e-06, extension_zones: List[ExtensionZone] = None, cylindrical_symmetry: bool = False, collision_index: int = None, origin: Tuple[float, float] = (0.0, 0.0))

Discrete rectangular mesh construction.

Parameters:
  • x_cells (int)

  • y_cells (int)

  • cell_size (float)

  • extension_zones (Optional[List[ExtensionZone]])

  • cylindrical_symmetry (bool)

  • collision_index (int)

  • origin (Tuple[float, float] - The origin for the) – coordinate system. AKA coordinate of the bottom-left point of mesh.

spawn_copy(scale_factor: float = 1.0)
property origin: Tuple[float, float]

The origin coordinate of the mesh.

All dimensions are relative to this coordinate. Defaults to (0, 0). This coordinate is in the coordinate system of the mesh before the origin is applied. This has the 0, 0 at the bottom-left corner of the high-resolution zone.

Returns:

origin

Return type:

Tuple[int, int]

classmethod from_dimensions(dimensions: Tuple[float, float], cell_size: float, extensions: List[ExtensionZone] | None = None, origin: Tuple[float, float] = (0.0, 0.0)) PySALEMesh

Given high-res zone dimensions and cell size, return PySALEMesh.

Parameters:
  • dimensions (Tuple[float, float] X - Y Dimensions of the high-res) – region in metres

  • cell_size (float Dimension of a high-res cell in the mesh)

  • extensions (List[ExtensionZone] List of all the extension zones) – that should be applied

  • origin (Tuple[float, float] The coordinate to be considered the) – origin. This coordinate is in the same coordinate system as the default, where the origin is the bottom left of the high-res zone.

Return type:

PySALEMesh instance.

property x_physical

The physical x-length of the mesh.

Returns:

length

Return type:

float

property y_physical

The physical y-length of the mesh.

Returns:

length

Return type:

float

property objresh: int

iSALE input parameter; half the height of the mesh.

Despite being the “horizontal” object resolution this refers to the height of the mesh. This is because there IS an OBJRESV but you only need to use it if your object does not cover the full width of the mesh. If no OBJRESV is present, its value defaults to OBJRESH. When using PySALESetup-created input files we never want anything less than the full width of the mesh so it is simpler to leave it out and use OBJRESH instead. In PySALESetup you can easily create objects of any size or shape you want!

Notes

If the number of cells is not divisible by 2, this property will guarantee that the returned value is rounded up, rather than down.

E.g. a mesh width of 100 would return a value of 50. A mesh width of 99 would also return a value of 50. 98 would return a value of 49, and so on.

Returns:

objresh

Return type:

int

property vertical_offset: int

Half the vertical depth of the mesh, rounded down, in cells.

Returns:

offset

Return type:

int

property max_cell_size: float

Return the maximum allowed cell size according to extensions.

No extensions returns a max cell size identical to the mesh cell size.

Returns:

max_cell_size

Return type:

float

property collision_site: int

The vertical collision location in the mesh, in cells.

Defaults to 0, and normally returns the smallest y-coordinate of the mesh with below zero y-velocity.

This does not make sense for horizontal velocity or many-velocity scenarios, and in those a manual site should be found, but it is required by iSALE to be specified in some circumstances.

Returns:

collision_site

Return type:

int

property x_range: ndarray

Array of the cell x-positions in the mesh.

Returns:

x_range

Return type:

float

property y_range: ndarray

Array of the cell y-positions in the mesh.

Returns:

x_range

Return type:

float

get_geometric_centre() Tuple[float, float]

Return the geometric centre of the mesh in physical coords.

Returns:

centre

Return type:

Tuple[float, float]

property material_meshes: Dict[int, ndarray]

Dictionary of numpy arrays representing material fill, indexed by material number.

Returns:

meshes

Return type:

Dict[int, np.ndarray]

property velocities: Dict[str, ndarray]

Velocity arrays in the mesh in a dict indexed by axis.

Returns:

velocities

Return type:

Dict[str, np.ndarray]

property cells: List[Cell]

List of all Cell objects in the mesh.

The mesh is represented by a collection of Cell objects, each of which represents a single cell in the mesh. These Cell objects are namedtuples containing all the information needed about that cell, including its indices, geometric centre, velocity, and material.

Returns:

cells

Return type:

List[Cell]

property cells_by_point

Cells as a dict indexed by their absolute position in the mesh Point.

Return type:

dict[CellCoords, Cell]

project_polygons_onto_mesh(polygons: List[PySALEObject]) None

Project a polygon (and all its children) onto the mesh.

Method calls itself recursively on all children of the polygon. The children at the bottom of the hierachy get priority. Once a cell is populated with material, new material will NOT overwrite it.

Parameters:

polygons (List[PySALEObject])

Return type:

None

Examples

Here we create a solid circle that is 5 m x 5 m and populate it to 40% area fraction with circles of radius 0.5 m. Then we optimise the material distribution and apply the polygon to a mesh object. Then we plot the result.

>>> from PySALESetup import PySALEObject, PySALEDomain, PySALEMesh
>>> import matplotlib.pyplot as plt
>>> main = PySALEObject.generate_ellipse([5., 5.], 5., 5., 0.)
>>> main.set_material(1)
>>> domain = PySALEDomain(main)
>>> circle = PySALEObject.generate_ellipse([0., 0.], .5, .5, 0.)
>>> domain.fill_with_random_grains_to_threshold(circle, 40)
>>> domain.optimise_materials([2, 3, 4, 5])
>>> mesh = PySALEMesh(100, 100, cell_size=.1)
>>> mesh.project_polygons_onto_mesh([main])
>>> mesh.plot_materials()
>>> plt.show()
plot_cells(ax: Axes = None)

Plot the cell centres of the mesh.

Parameters:

ax (plt.Axes)

Returns:

fig, ax

Return type:

Tuple[plt.Axes, plt.figure]

plot_materials(ax: Axes = None, cmap: str = 'rainbow') Tuple[Figure, Axes]

Plot the materials in the mesh using matplotlib.

If no axes are provided, axes and a figure are made. Otherwise, the given axes are used and returned along with the associated figure object.

Parameters:
  • ax (plt.Axes)

  • cmap (str)

Returns:

fig, ax

Return type:

Tuple[plt.Axes, plt.figure]

Examples

Here we construct a simple 2D meteorite impacting flat ground. Once our objects have been created and applied, we use plot_materials to view the mesh, although we need to use plt.show() to visualise the object you could just as easily save the figure instead.

>>> from PySALESetup import PySALEObject
>>> from PySALESetup import PySALEMesh
>>> import matplotlib.pyplot as plt
>>> impactor = PySALEObject.generate_ellipse([5., 8.], 2., 2., 0.)
>>> impactor.set_material(1)
>>> impactor.set_velocity(0. -1000.)
>>> target = PySALEObject([(0, 0), (0, 6), (10, 6), (10, 0)])
>>> target.set_material(3)
>>> mesh = PySALEMesh(100, 100, cell_size=.1)
>>> mesh.project_polygons_onto_mesh([impactor, target])
>>> mesh.plot_materials()
>>> plt.show()
plot_velocities(ax1: Axes | None = None, ax2: Axes | None = None, cmap: str = 'coolwarm') Tuple[Figure, Figure, Axes, Axes]

Plot the velocities of cells.

If axes are provided they are used. If any are not provided, they are created. Either way the axes and figures are returned.

Parameters:
  • ax1 (Optional[plt.Axes])

  • ax2 (Optional[plt.Axes])

  • cmap (str)

Returns:

fig1, fig2, ax1, ax2 – plt.Axes, plt.Axes]

Return type:

Tuple[plt.Figure, plt.Figure,

Examples

>>> from PySALESetup import PySALEObject
>>> from PySALESetup.mesh import PySALEMesh
>>> import matplotlib.pyplot as plt
>>> impactor = PySALEObject.generate_ellipse([5., 8.], 2., 2., 0.)
>>> impactor.set_material(1)
>>> impactor.set_velocity(0. -1000.)
>>> target = PySALEObject([(0, 0), (0, 6), (10, 6), (10, 0)])
>>> target.set_material(3)
>>> mesh = PySALEMesh(100, 100, cell_size=.1)
>>> mesh.project_polygons_onto_mesh([impactor, target])
>>> mesh.plot_materials()
>>> plt.show()
property material_numbers: List[int]

List of non-zero materials in the mesh.

Returns:

numbers

Return type:

List[int]

save(file_name: Path = PosixPath('meso_m.iSALE'), compress: bool = False) None

Save the current mesh to a meso_m.iSALE file.

This compiles the integer indices of each cell, as well as the material in them. It saves all this to the file specified by the user, which defaults to meso_m.iSALE in the user’s current directory.

Parameters:
  • file_name (Path)

  • compress (bool) – Compress the resulting text file using gunzip. Users are expected to add their own .gz file extension. If one is not present a UserWarning is raised.

Return type:

None

property extension_zones: List[ExtensionZone]

The extension zones applied to the mesh.

Returns:

zones

Return type:

List[ExtensionZone]

property extension_factor: ExtensionZoneFactor

The ExtensionZoneFactor associated with this mesh.

There can only be one extension factor associated with a mesh. When this property is called it also checks that the given extension zones don’t have clashing properties.

Returns:

factor

Return type:

ExtensionZoneFactor

PySALESetup.objects

class PySALESetup.objects.Velocity(x: float | int, y: float | int)

Bases: object

Immutable velocity dataclass

x: float | int
y: float | int
class PySALESetup.objects.PySALEObject(*args, **kwargs)

Bases: ABC

Base object for all objects in PySALESetup

Based on shapely.geometry.Polygon.

Examples

This object forms the basis of everything we do in PySALESetup. First here’s an example of a rectangular object 10 m x 15 m.

>>> from PySALESetup import PySALEObject
>>> import matplotlib.pyplot as plt
>>> main = PySALEObject([(0, 0), (0, 15), (10, 15), (10, 0)])
>>> main.plot()
>>> plt.show()

This example creates a triangular object.

>>> from PySALESetup import PySALEObject
>>> import matplotlib.pyplot as plt
>>> main = PySALEObject([(0, 0), (5, 5), (10, 0)])
>>> main.plot()
>>> plt.show()

This example creates an elliptical object with centroid (5, 5) major axis 1, minor axis 0.5 and rotated by 10 degrees.

>>> from PySALESetup import PySALEObject
>>> import matplotlib.pyplot as plt
>>> main = PySALEObject.generate_ellipse([5., 5.], 1., .5, 10.)
>>> main.plot()
>>> plt.show()
__init__(*args, **kwargs)

Construct a Polygon PySALEObject instance.

Parameters:
  • args – See shapely.geometry.Polygon args

  • kwargs – See shapely.geometry.Polygon kwargs

copy() PySALEObject

deepcopy of the object in question.

Return type:

PySALEObject

property polygon: Polygon

shapely.geometry.polygon.Polygon object describing this object.

Return type:

shapely.geometry.polygon.Polygon

copy_properties_to_new_polygon(polygon: PySALEObject) PySALEObject

Copy properties to a another polygon.

Properties copied are:
  • children

  • velocity

  • material colors

  • material number

Parameters:

polygon (PySALEObject)

Returns:

target

Return type:

PySALEObject

classmethod generate_ellipse(xy: Iterable[float] | Point, major: float, minor: float, rotation: float, material: int = 1) PySALEObject

Create an “ellipse” version of the PySALEObject.

ellipse PySALEObjects are actually just polygons with many points (65) and not true ellipses, however, given that these are to be applied to a discrete mesh, exact ellipses are not necessary.

Parameters:
  • xy (List[float]) – centroid of the ellipse

  • major (float) – major radius/axis of the ellipse

  • minor (float) – minor radius/axis of the ellipse

  • rotation (float) – rotation of the ellipse in degrees from the horizontal

  • material (int) – material number to be assigned to. Defaults to 1.

Returns:

ellipse

Return type:

PySALEObject

classmethod create_from_file(file_name: Path) PySALEObject

Create a polygon object from coordinates in a csv file.

It is assumed the text file is of the following format.

> 0., 0. > 0., 1. > 1., 1. > 1., 0.

With no headers or footers.

This function is designed to be used with the grain library.

Parameters:

file_name (Path)

Returns:

new

Return type:

PySALEObject

property children: List[PySALEObject]

PySALEObjects contained (and spawned from) the PySALEObject.

Returns:

children

Return type:

List[PySALEObject]

property velocity: Velocity

Named tuple Velocity assigned to the object.

Use PySALEObject.set_velocity() to change this.

Returns:

velocity_object

Return type:

Velocity

property is_void: bool

Return a bool indicating if the polygon is a void.

Returns:

void_status

Return type:

bool

property material: int

Returns the material assigned to the polygon.

If no material has yet been assigned, it is assigned to material number 1.

Returns:

material_number

Return type:

int

property material_colors: Dict[int, str]

Returns the colors assigned to each material number.

Returns:

material_colors

Return type:

Dict[int, str]

set_velocity(x: float, y: float, include_children: bool = True) None

Set the velocity of the object.

Parameters:
  • x (float)

  • y (float)

  • include_children (bool) – Set velocity of all children as well? defaults to True.

Return type:

None

set_as_void() None

Set the material to void.

Additionally, sets the velocities to 0.0.

Return type:

None

set_material(material: int) None

Set the material number of the object.

material must be between 0 and 9 inclusive. 0 represents void.

Parameters:

material (int)

Return type:

None

calculate_equivalent_radius()

Calculate the radius of the circle with the same area.

Returns:

Radius of the equivalent circle

Return type:

float

property has_children: bool

Returns True if object has children.

Returns:

has_children

Return type:

bool

add_child(child: PySALEObject) None

Add existing object as a child to this object.

Parameters:

child (PySALEObject)

Return type:

None

spawn_polygon_in_shape(*args, **kwargs) PySALEObject

Create a child polygon for the object.

Child must be contained within the host, otherwise an AssertionError is raised.

Parameters:
  • args

  • kwargs

Returns:

polygon

Return type:

PySALEObject

spawn_ellipse_in_shape(xy: List[float], major: float, minor: float, rotation: float, material: int = 1) PySALEObject

Create a child ellipse for the object.

Parameters:
  • xy (List[float]) – coordinates of the centroid

  • major (float) – major axis

  • minor (float) – minor axis

  • rotation (float) – angle to the horizontal, anticlockwise, in degrees

  • material (int) – material for the spawned object to have. Defaults to 1.

Returns:

polygon

Return type:

PySALEObject

scale_object(factor: float, area: bool = False) PySALEObject

Create new scaled object from current object.

Parameters:
  • factor (float)

  • area (bool) – Does the factor refer to area or equivalent radius?

Returns:

The new scaled object

Return type:

PySALEObject

plot(ax: Axes | None = None, include_children: bool = True, cmap: str = 'rainbow') Tuple[Figure, Axes]

Plot the object on matplotlib axes.

If no axes, the method will create some.

Parameters:
  • ax (Optional[plt.Axes])

  • include_children (bool) – Recursively plot all children as well

  • cmap (str) – The colormap used when plotting

Returns:

fig, ax – If axes were provided these are the same that were given.

Return type:

plt.Figure, plt.Axes

set_material_colormap(colormap: str, void: str = 'gray', unassigned: str = 'brown') None

Set the colors to be used when plotting.

Parameters:
  • colormap (str)

  • void (str)

  • unassigned (str)

Return type:

None

property krumbein_phi: float

Return the Krumbein Phi of the object.

A dimensionless, logarithmic, grain size metric commonly used in particle size distributions.

>>> krumbein_phi = -log2(D/D0)

Where D is the diameter of the sphere (circle in our case) that has the same volume (area) as the grain in question, and D0 is a reference length equal to 1 mm (so that the equation remains dimensionally consistent.

See [Investigating the effect of mesostructure on the shock response of granular materials through numerical modelling - James G. Derrick 2018 Section 6.1](https://doi.org/10.25560/66097)

Returns:

krumbein_phi

Return type:

float

property elongation: float

Ratio of length of the bounding box to its width.

Return type:

float

property area_ratio

Ratio of the area of the bounding box to the polygon area.

Return type:

float

translate(newx: float, newy: float)

Translate from one centroid to another.

Returns a copy of the translated polygon. Does NOT change the polygon itself.

Parameters:
  • newx (float)

  • newy (float)

Returns:

translated_copy

Return type:

PySALEObject

rotate(angle: float, origin: str | Tuple[float, float] | Point = 'center')

Rotate by angle degrees and about the point origin.

Returns a copy of the rotated polygon. Does NOT change the polygon itself.

Parameters:
  • angle (float) – rotation amount in degrees anticlockwise from the horizontal

  • origin (Union[str, Point, Tuple[float, float]]) – can either be the string ‘center’, where the self origin is used, or it can be a shapely.geometry.Point object.

Returns:

rotated_copy

Return type:

PySALEObject

resize(xfactor: float = 1.0, yfactor: float = 1.0)

Resize by xfactor and yfactor in the x and y directions.

Returns a copy of the resized polygon. Does NOT change the polygon itself.

Parameters:
  • xfactor (float)

  • yfactor (float)

Returns:

resize_copy

Return type:

PySALEObject

PySALESetup.input_files

class PySALESetup.input_files.TimeStep(initial: float, max: float, end: float, save: float)

Bases: object

Immutable time step dataclass.

initial: float
max: float
end: float
save: float
class PySALESetup.input_files.InputFile(type_: str)

Bases: object

Base input file class.

__init__(type_: str)

Input file type must be supplied to the constructor.

Parameters:

type (str)

property template_path: Path

Path to the template

Returns:

path

Return type:

pathlib.Path

property template: Template

The template string for the input file.

Returns:

template

Return type:

str

class PySALESetup.input_files.AsteroidInput(model_name: str, timestep: TimeStep, mesh: PySALEMesh)

Bases: InputFile

asteroid.inp file creator class.

Allows a user to build an asteroid.inp file and uses a simple template to write one to a new file of the user’s choice.

__init__(model_name: str, timestep: TimeStep, mesh: PySALEMesh)

Construct the AsteroidInput class.

Only model_name, timestep and mesh, need to be provided. However, multiple other properties are also set. These are:

  • surface_temperature = 300.

  • east_bc = ‘FREESLIP’

  • west_bc = ‘FREESLIP’

  • south_bc = ‘OUTFLOW’

  • north_bc = ‘OUTFLOW’

But they can all be changed after initialisation.

Parameters:
write_to(path: Path = PosixPath('/home/runner/work/PySALESetup/PySALESetup/examples/asteroid.inp')) None

Write the asteroid.inp file to given path.

Defaults to asteroid.inp in the current working directory.

Parameters:

path (pathlib.Path)

class PySALESetup.input_files.AdditionalInput(mesh: PySALEMesh, material_names: Dict[int, str], host_object_number: int = 1)

Bases: InputFile

additional.inp file creator class.

Allows a user to build an additional.inp file and uses a simple template to write one to a new file of the user’s choice.

__init__(mesh: PySALEMesh, material_names: Dict[int, str], host_object_number: int = 1)

Initialise the AdditionalInput class.

Parameters:
  • mesh (PySALEMesh)

  • material_names (Dict[int, str])

  • host_object_number (int)

write_to(path: Path = PosixPath('/home/runner/work/PySALESetup/PySALESetup/examples/asteroid.inp')) None

Write the asteroid.inp file to given path.

Defaults to additional.inp in the current working directory.

Parameters:

path (pathlib.Path)

PySALESetup.grain_library

class PySALESetup.grain_library.GrainLibrary

Bases: object

Loads and deploys grains generated from file.

load_from_directory(directory: Path) None

Given a directory, loads all grain files it can find.

Parameters:

directory (pathlib.Path)

load_builtin_library() None

Load all grains in the builtin library

random_grain()

Return a random grain from the list.

Returns:

grain

Return type:

PySALEObject