lgca.lgca_1d.NoVE_LGCA_1D

class lgca.lgca_1d.NoVE_LGCA_1D(nodes=None, dims=None, restchannels=1, density=0.1, bc='periodic', seed=None, capacity=None, propagation=True, **kwargs)

Bases: LGCA_1D, NoVE_LGCA_base

1D version of an LGCA without volume exclusion.

apply_abc()

Apply absorbing boundary conditions.

Update self.nodes, using the shadow border nodes and respecting the geometry.

apply_inflowbc()

Apply inflow boundary conditions.

Update self.nodes, using the shadow border nodes and respecting the geometry.

apply_pbc()

Apply periodic boundary conditions.

Update self.nodes, using the shadow border nodes and respecting the geometry.

apply_rbc()

Apply reflecting boundary conditions.

Update self.nodes, using the shadow border nodes and respecting the geometry.

c = array([[ 1., -1.]])
calc_entropy(base=None)

Calculate entropy of the lattice. :type base: :param base: base of the logarithm, defaults to 2 :return: entropy according to information theory as scalar

calc_flux(nodes)

Calculate the flux vector for all lattice sites in nodes.

The elements of the flux vectors are computed as the dot product between the LGCA’s neighborhood vectors and the velocity channel configuration in nodes.

Parameters:

nodes (numpy.ndarray) – Lattice configuration to compute the flux for. Must have more than or the same number of dimensions as self.nodes and nodes.shape[-1] >= self.velocitychannels. Is typically self.nodes.

Returns:

Array of flux vectors at each lattice site. Dimensions: nodes.shape[:-1] + (len(self.c),).

calc_mean_alignment()

Calculate the mean alignment measure. The mean alignment is a measure for local alignment of particle orientation in the lattice. It is calculated as the agreement in direction between the flux of a lattice site and the flux of the director field summed up and normalized over all lattice sites. .. note:: This is buggy! :return: Local alignment parameter: ranging from -1 (antiparallel alignment) through 0 (no alignment) to 1 (parallel alignment)

calc_normalized_entropy(base=None)

Calculate entropy of the lattice normalized to maximal possible entropy. :type base: :param base: base of the logarithm, defaults to 2 :return: normalized entropy as scalar

calc_permutations()

Initialize lazy computation structures for permutations. Only compute permutations when actually needed.

calc_polar_alignment_parameter()

Calculate the polar alignment parameter. The polar alignment parameter is a measure for global agreement of particle orientation in the lattice. It is calculated as the magnitude of the sum of the velocities of all particles normalized by the number of particles. :return: Polar alignment parameter of the lattice from 0 (no alignment) to 1 (complete alignment)

channel_weight(qty)

Calculate weights for the velocity channels in interactions depending on a field qty.

The weight for the right rsp. left velocity channel is given by the value of qty of the right rsp. left neighboring node.

Parameters:

qty (numpy.ndarray) – Scalar field with the same shape as self.cell_density.

Returns:

Weights for the velocity channels of shape self.dims + (self.velocitychannels,).

get_flux_permutations(n_particles)

Get flux permutations for n_particles.

get_permutations(n_particles)

Get permutations for n_particles.

Parameters:

n_particles (int) – Number of occupied channels.

Returns:

Array of permutations for n_particles.

gradient(qty)

Compute the gradient of qty along all axes.

Parameters:

qty (numpy.ndarray) – Quantity to take the gradient of. Needs to have the same number of dimensions as self.nodes. If qty.shape == self.nodes.shape[:-1] the result can be indexed with the LGCA coordinates (see example).

Returns:

Computed gradient. Dimensions: qty.shape + (len(self.c),). If self and qty are 2D arrays, gradient(qty)[...,0] is the gradient in x direction and gradient(qty)[...,1] the gradient in y direction.

Notes

The gradient is calculated using numpy.gradient() with stepwidth h=0.5 (s.t. no normalization takes place). It is computed as the central finite difference with equidistant support points and supports one-sided differences at the boundaries.

In most cases this yields the simple difference between the two closest array elements in the given direction. For example, the gradient at position 1 of np.array([1, 2, 4]) would be (4 - 1)/(2 * 0.5) = 3.

Examples

If the input quantity has the same x (and y) dimensions as the LGCA’s nodes, the gradient at each node position can be accessed the same way as the node itself.

>>> from lgca import get_lgca
>>> import numpy as np
>>> # define a square LGCA to illustrate dimensions
>>> lgca = get_lgca(geometry='square', dims=(2,3))
>>> lgca.nodes.shape  # (xdim, ydim, number of channels)
(4, 5, 4)
>>> my_qty = np.array([[0,0,0,0,0],
>>>                    [1,1,1,1,1],
>>>                    [2,2,2,3,2],
>>>                    [3,3,3,3,3]])
>>> my_qty.shape  # (xdim, ydim)
(4, 5)
>>> grad = lgca.gradient(my_qty)
>>> grad.shape  # (xdim, ydim, number of dimensions)
(4, 5, 2)
>>> # address like internal LGCA fields: first dimension is x (printed vertically),
>>> # second dimension is y (printed horizontally), this can be a bit confusing
>>> for coord in lgca.coord_pairs:
>>>     if np.any(grad[coord]>2):
>>>         print("Gradient at index", coord, "is ", grad[coord])
>>>         print("Configuration at index ", coord, " is ", lgca.nodes[coord],
>>>               ", with cell density ", lgca.cell_density[coord])
Gradient at index (1, 3) is  [3. 0.]
Configuration at index  (1, 3)  is  [False False False  True] , with cell density  1

The first element of the gradient holds the gradient in x direction, the second element the gradient in y direction. Note that (1, 3) is the index corresponding to a logical non-border coordinate (0, 2) if the interaction radius is 1. This is relevant for defining a custom field qty: Only the field values at non-border indices will be “felt” by the particles in the LGCA if the interaction is defined accordingly, but border nodes can be used to specify the field’s boundary conditions.

The gradient in x direction is 3 = (3 - 0)/1. In y direction it is 0 = (1 - 1)/1.

init_coords()

Initialize LGCA coordinates.

These are used to index the lattice nodes logically and programmatically (see below). Initializes self.nonborder and self.xcoords.

See also

set_dims

Set LGCA dimensions.

init_nodes

Initialize LGCA lattice configuration.

set_r_int

Change the interaction radius.

Notes

self.xcoords holds the logical coordinates of non-border nodes starting with 0. Non-border nodes belong to the lattice in the mathematical definition of the LGCA, while border nodes (=shadow nodes) are only included in order to implement boundary conditions.

>>> lgca = get_lgca(geometry='lin', dims=3)
>>> lgca.xcoords
array([0., 1., 2.])

self.nonborder holds the programmatical coordinates of non-border nodes, i.e. the indices of the self.nodes array where non-border nodes are stored. This is why it is a tuple: Because it is used to index a numpy array. All non-border lattice nodes can be called as self.nodes[self.nonborder].

>>> lgca = get_lgca(geometry='lin', dims=3)  # default: periodic boundary conditions
>>> lgca.r_int
1
>>> lgca.nodes.sum(-1)  # show contents of the lattice
array([0, 0, 1, 0, 0])
>>> lgca.nodes[lgca.nonborder].sum(-1)
array([0, 1, 0])

Summing along the last axis means summing over all channels of a node since we are interested in the geometry. The first and the last element in the output of lgca.nodes.sum(-1) are the contents of the border (=shadow) nodes, which reflects the interaction radius of 1. The innermost three elements are the contents of the non-border nodes. Accordingly we find their indices to be:

>>> lgca.nonborder
(array([1, 2, 3]),)

In one dimension the y component of the tuple is empty. Changing the interaction radius updates the shape of self.nodes by including more border (=shadow) nodes. This also changes the coordinates. With an interaction radius of 3, there is 3 border nodes on each side enveloping the non-border nodes whose contents remain the same. Therefore the first non-border node has the index 3.

>>> lgca.set_r_int(3)  # change the interaction radius
>>> lgca.r_int
3
>>> lgca.nodes.sum(-1)  # show contents of the lattice
array([0, 1, 0, 0, 1, 0, 0, 1, 0])
>>> lgca.nonborder
(array([3, 4, 5]),)
init_nodes(density, nodes=None)

Initialize nodes for the instance. :type density: :param density: desired particle density in the lattice: number of particles/(dimensions*number of channels) :type nodes: :param nodes: existing lattice to use, optionally containing particles (ndarray)

nb_sum(qty, addCenter=False)

Calculate sum of values in neighboring lattice sites of each lattice site.

Parameters:
  • qty – ndarray in which neighboring values have to be added first dimension indexes lattice sites

  • addCenter – toggle adding central value

Returns:

sum as ndarray

plot_density(density_t=None, figindex=None, figsize=None, cmap='hot_r', relative_max=None, cbar=True, absolute_max=None, offset_t=0, offset_x=0, cbarlabel=None, **kwargs)

Create a plot showing the number of particles per lattice site. :type density_t: :param density_t: particle number per lattice site (ndarray of dimension (timesteps + 1,) + self.dims) :type figindex: :param figindex: number of the figure to create/activate :type figsize: :param figsize: desired figure size :type cmap: :param cmap: matplotlib color map for encoding the number of particles :return: plot as a matplotlib.image

plot_flux(nodes_t=None, cbar=True, colorbarwidth=0.03, **kwargs)

Plot flux in each node over time. X axis: 1D lattice, y axis: time.

A flux vector to the left is indicated by a blue color of the node, a flux vector to the right by red. If the velocities of all particles cancel out, the node is colored in black. Empty nodes are white. A color bar illustrates the mapping from colors to flux direction.

Parameters:
  • nodes_t (numpy.ndarray, optional) – Node configurations for a lattice over time, used to calculate the flux and plot it. If set to None and a simulation has been performed before with record=True, the result of the simulation is plotted. Dimensions: (timesteps + 1,) + self.dims + (self.K,).

  • cbar (bool, default=True) – Draw a color bar indicating the flux coding.

  • colorbarwidth (float) – Width of the additional axis for the color bar, passed to mpl_toolkits.axes_grid1.axes_divider.AxesDivider.append_axes().

  • **kwargs – Arguments to be passed on to setup_figure().

Returns:

Density plot over time.

See also

setup_figure

Manage basic layout.

print_interactions()

Print the list of pre-implemented interactions for this LGCA type.

print_nodes()

Print the full lattice configuration as integers.

propagation()

Perform the transport step of the LGCA: Move particles through the lattice according to their velocity.

Updates self.nodes such that resting particles (the contents of self.nodes[:, 2:]) stay in their position and particles in velocity channels (the contents of self.nodes[:, :2]) are relocated according to the direction of the channel they reside in. Boundary conditions are enforced later by apply_boundaries().

See also

base.LGCA_base.nodes

State of the lattice showing the structure of the lgca.nodes array.

Notes

>>> lgca = get_lgca(geometry='lin', density=0.1, dims=5, restchannels=1)
>>> lgca.cell_density[lgca.nonborder]
array([0, 0, 0, 3, 0])
>>> lgca.nodes[lgca.nonborder]
array([[False, False, False],
       [False, False, False],
       [False, False, False],
       [ True,  True, True],
       [False, False, False]])

Before propagation, three particles occupy the fourth node. One resides in the velocity channel to the right, one in the velocity channel to the left and one in the resting channel.

>>> lgca.propagation()
>>> lgca.update_dynamic_fields()  # to update lgca.cell_density
>>> lgca.cell_density[lgca.nonborder]
array([0, 0, 1, 1, 1])
>>> lgca.nodes[lgca.nonborder]
array([[False, False, False],
       [False, False, False],
       [False,  True, False],
       [False, False, True],
       [ True, False, False]])

The particle with velocity 1 has moved to the right velocity channel in the fifth node. The particle in the velocity channel to the left has moved to the respective channel in the third node. The resting particle stayed in its channel in the fourth node.

random_reset(density)

Populate the lattice from a Poisson distribution with mean density per node.

set_bc(bc)

Set the boundary conditions.

Selects a method which is called every timestep to enforce boundary conditions. The methods to select from are implemented in the derived classes. The chosen one is assigned to self.apply_boundaries().

Parameters:

bc ({'absorbing', 'reflecting', 'periodic', 'inflow'}) – Boundary conditions. Not all bc are supported in all geometries (yet).

set_dims(dims=None, nodes=None, restchannels=None, capacity=None)

Set the dimensions of the instance according to given values. Sets self.l, self.K, self.dims and self.restchannels :type dims: :param dims: desired lattice size (int or array-like) :type nodes: :param nodes: existing lattice to use (ndarray) :type restchannels: :param restchannels: desired number of resting channels, will be capped to 1 if >1 because of no volume exclusion

set_interaction(**kwargs)

Set the interaction rule and respective needed parameters.

Set self.interaction and possibly add entries in self.interaction_params. Do not use this to specify a custom interaction. In order to do this (as of now), self.interaction and self.interaction_params must be manipulated directly from an external script.

Parameters:
  • kwargs['interaction'] (str, default='random_walk') – Name of the predefined interaction in lgca.interactions.

  • **kwargs – Interaction parameters.

set_r_int(r)

Change the interaction radius. Update shadow border nodes accordingly.

This has effects on self.nodes, the coordinates and the computed fields.

Parameters:

r (int) – New interaction radius.

setup_figure(tmax, figindex=None, figsize=(8, 8), tight_layout=True)

Create a matplotlib figure and manage basic layout.

Used by the class’ plotting functions.

Parameters:
  • figindex (int or str, optional) – An identifier for the figure (passed to matplotlib.pyplot.figure()). If it is a string, the figure label and the window title is set to this value.

  • figsize (tuple of int or tuple of float with 2 elements, default=(8,8)) – Desired figure size in inches (x, y).

  • tight_layout (bool, default=True) – If matplotlib.figure.Figure.tight_layout() is called for padding between and around subplots.

  • tmax (int or float) – Maximum simulation time to plot in order to scale the y axis.

Returns:

  • fig (matplotlib.figure.Figure) – New customized figure.

  • ax (matplotlib.axes.Axes) – Drawing axis associated with fig.

See also

plot_density

Plot particle density over time.

plot_flux

Plot flux over time.

timeevo(timesteps=100, record=False, recordN=False, recorddens=True, showprogress=True, recordorderparams=False, recordpertype=False)

Perform a simulation of the LGCA for timesteps timesteps.

Different quantities can be recorded during the simulation, e.g. the total number of particles at each timestep. They are stored in LGCA attributes.

Parameters:
  • timesteps (int, default=100) – How long the simulation should be performed.

  • record (bool, default=False) – Record the full lattice configuration for each timestep in self.nodes_t.

  • recorddens (bool, default=True) – Record the number of particles at each lattice site for each timestep in self.dens_t.

  • recordN (bool, default=False) – Record the total number of particles in the lattice for each timestep in self.n_t.

  • recordpertype (bool, default=False) – Record the number of particles in velocity channels/resting channels at each lattice site for each timestep in self.velcells_t and self.restcells_t, respectively.

  • showprogress (bool, default=True) – Show a simple progress bar with a percentage of performed timesteps in the standard output.

timestep()

Update the state of the LGCA from time k to k+1. Includes the interaction and propagation steps.

total_population()

Calculate the amount of particles in the lattice.

Returns:

Total population size.

update_dynamic_fields()

Update “fields” from the current LGCA state that store important variables to compute other dynamic steps.

Computes self.cell_density, number of particles at each lattice node.