Source code for jLM.Solvers

# 
# University of Illinois Open Source License
# Copyright 2016-2018 Luthey-Schulten Group,
# All rights reserved.
# 
# Developed by: Luthey-Schulten Group
#                           University of Illinois at Urbana-Champaign
#                           http://www.scs.uiuc.edu/~schulten
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the Software), to deal with 
# the Software without restriction, including without limitation the rights to 
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
# of the Software, and to permit persons to whom the Software is furnished to 
# do so, subject to the following conditions:
# 
# - Redistributions of source code must retain the above copyright notice, 
# this list of conditions and the following disclaimers.
# 
# - Redistributions in binary form must reproduce the above copyright notice, 
# this list of conditions and the following disclaimers in the documentation 
# and/or other materials provided with the distribution.
# 
# - Neither the names of the Luthey-Schulten Group, University of Illinois at
# Urbana-Champaign, nor the names of its contributors may be used to endorse or
# promote products derived from this Software without specific prior written
# permission.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
# THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
# OTHER DEALINGS WITH THE SOFTWARE.
# 
# Author(s): Tyler M. Earnest
# 

"""Generic RDME solvers"""
import numpy as np

from . import RDME
from . import Lattice
from . import Types as T

[docs] def makeSolver(rdmeSolver, customSolver): """Create custom solver Note: The user defined class should define a `hookSimulation(self, t, lattice)` method where `t` is the current simulation time and `lattice` is the current state of the :py:class:`lm.CudaByteLattice`. Warning: If `__init__` is overridden, `super().__init__` must be called first. Args: rdmeSolver (:py:class:`lm.RDMESolver`): Base solver class customSolver (class): User defined solver class Returns: class: Composed class """ name = customSolver.__name__ + "_" + rdmeSolver.__name__ return type(name, (customSolver, rdmeSolver), {})
[docs] class ConstBoundaryConc: """Solver with fixed concentration boundary conditions The simulation hook runs a cythonized function which destructively sets the specified boundaries to a prescribed concentration. """ def __init__(self, lmFile, exact=False): super(ConstBoundaryConc,self).__init__() self.exact=exact if isinstance(lmFile, (RDME.Sim, RDME.File)): self.rdme = lmFile else: self.rdme = RDME.File(lmFile) self.dists = [] self.distTable = None self.bMask = np.zeros_like(self.rdme.siteLattice) self.bLattice = np.zeros_like(self.rdme.siteLattice)
[docs] def setBoundary(self, species, concs, boundary): r"""Specify boundary conditions Specify a boundary condition using a species (or list of species), a concentration (or list of concentrations; in mol/L), and a specification of the boundary in terms of a binary lattice. Subsequent calls will add new boundary conditions. When the boundary region given by a subsequent call overlaps with a previously described region, the later call will override the earlier conditions. Args: species (:py:class:`~jLM.Types.Species`): Species at boundary concs (float): Concentrations boundary (:py:class:`~numpy.ndarray`): Binary lattice describing the boundary """ if isinstance(species, str): species = [self.rdme.speciesList[species]] concs = [concs] elif isinstance(species, T.Species): concs = [concs] species = [species] elif isinstance(species[0], str): species = [self.rdme.speciesList[x] for x in species] elif isinstance(species[0], T.Species): pass else: raise TypeError() dist = np.zeros(256) for sp, conc in zip(species, concs): particle_number = self.rdme.siteNAV*conc dist[sp.idx] = particle_number dist[0] = self.rdme.pps - np.sum(dist) dist /= self.rdme.pps if dist[0] < 0: raise RuntimeError("Requested concentration exceeds site capacity") self.bMask[boundary>0] = 1 self.bLattice[boundary>0] = len(self.dists) self.dists.append(dist)
[docs] def hookSimulation(self, t, lattice): """Replaces all particles on boundary according to B.C.s""" if self.distTable is None: self.distTable = np.vstack(self.dists) particles = lattice.getParticleLatticeView() Lattice.populateLattice(particles, self.bLattice, self.distTable, mask=self.bMask, exact=self.exact) return 1