import numpy as np
from scipy.sparse.linalg import LinearOperator as LinOp
"""
Module that contains the implementation of the linear operator of the reaction term of the pheromone propagation model.
"""
[docs]
class Reaction(LinOp):
r"""
Class containing the reaction term linear operator :math:`R:c\mapsto \tau_{loss}c~\forall (x,y)\in\Omega~\forall t\in]0;T]`.
The implementation of this linear operator is a subclass of the :py:class:`~scipy.sparse.linalg.LinearOperator` class.
Attributes
----------
reaction_coeff : ~numpy.ndarray
The loss coefficient :math:`\tau_{loss}(x,y)`.
msh : ~pheromone_dispersion.geom.MeshRect2D
The geometry of the domain.
shape : tuple of int
Shape of the matrix of the linear operator.
The shape is (:attr:`msh.y.size` * :attr:`msh.x.size`, :attr:`msh.y.size` * :attr:`msh.x.size`)
dtype : ~numpy.dtype
Data type of the elements of the matrix of the linear operator.
The type is `float64`
"""
[docs]
def __init__(self, reaction_coeff, msh):
r"""
Constructor method
Parameters
----------
reaction_coeff : ~numpy.ndarray
The loss coefficient :math:`\tau_{loss}(x,y)` at the center of each cells.
msh: ~pheromone_dispersion.geom.MeshRect2D
The geometry of the domain.
Raises
------
ValueError
if shape of the array of loss coefficient does not fit with the shape of the arrays of the coordinates of the cells' center.
"""
if reaction_coeff.shape != (msh.y.size, msh.x.size):
raise ValueError("The shape of the deposition coefficient at the center of the cells does not match with the shape of the msh.")
self.msh = msh
self.reaction_coeff = reaction_coeff
self.shape = (self.msh.y.size * self.msh.x.size, self.msh.y.size * self.msh.x.size)
self.dtype = np.dtype(float)
[docs]
def update_reaction_coeff(self, reaction_coeff):
r"""
Update the attribute :attr:`reaction_coeff` with the value provided as input.
Parameters
----------
reaction_coeff : ~numpy.ndarray
The new value of loss coefficient :math:`\tau_{loss}(x,y)`.
"""
self.reaction_coeff = reaction_coeff
[docs]
def _matvec(self, x_out):
r"""
Compute the image (matrix-vector product) of :math:`R:c\mapsto \tau_{loss}c`
for a given concentration map :math:`c` at the current time.
Parameters
----------
x_out : ~numpy.ndarray
The map of concentration of pheromones :math:`c(x,y)` at a given time :math:`t` raveled into a vector.
Returns
-------
~numpy.ndarray
Array containing the image :math:`\tau_{loss}c`.
Notes
-----
The input :math:`c` has to be raveled into a (:attr:`msh.y.size` * :attr:`msh.x.size`,)-shape array
to match the format of the :py:class:`~scipy.sparse.linalg.LinearOperator` class.
The same way, the ouput can be reshape into a (:attr:`msh.y.size`, :attr:`msh.x.size`)-shape array
to get the map :math:`Rc(x,y)` at the current time :math:`t`
"""
# reshape the vector (of (msh.x.size*msh.y.size, )) containg the concentration into a matrix (of shape (msh.y.size, msh.x.size))
x = x_out.reshape((self.msh.y.size, self.msh.x.size))
reaction = self.reaction_coeff * x
return reaction.reshape((self.msh.y.size * self.msh.x.size,))
def _matmat(self, x_out):
# Compute the image (matrix-matrix product)
# using a naive method based on the _matvec method
output = np.zeros((self.shape[0], x_out.shape[1]))
for i_col, col in enumerate(x_out.T):
output[:, i_col] = self.matvec(col)
return output
# return np.hstack([self.matvec(col.reshape(-1, 1)) for col in x_out.T])