Source code for pySTDLM.Distributions

# 
# University of Illinois Open Source License
# Copyright 2008-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): Michael J. Hallock and Joseph R. Peterson
# 
#

import sys
import os
import random
import pyLM
from pyLM.LMLogger import *


## @class ParticleGenerator
[docs] class ParticleGenerator: """A particle generator that adds particles to a particular region of a simulation. Args: gen: A PDF set for x,y,z that on the domain [-1,1] and range [0,1) where x is the range of interest ptype: The name of the particle """ def __init__(self, gen, ptype): self.generator=gen if len(self.generator) != 3: LMLogger.error("Must pass a list of generators: [xgen,ygen,zgen]") raise ValueError("Axial generator list expected") self.particlename = ptype self.totalAdded = 0 self.addedLast = 0
[docs] def addParticlesToRegion(self,rdmesim, region, number, directions, spatial = None): """Add a number of particles to a region based on Monte-Carlo sampling of the generator Args: rdmesim: An RDME simulation object that has already been "discretized" region: A region name of the simulation to add particles to number: The number of the particle to add directions: A list of the form (x,y,z) where a 0 indicates a uniform distribution in that direction and a 1 indicates the particles are sampled from the generator in that direction spatial (OPTIONAL): A definition of a subsection of the domain that this generation should occur in as a list of lists [[xl,yl,zl],[xh,yh,zh]], otherwise the generator is scaled from (0,0,0) to domain extends (w,h,d) """ # bulletproofing if not isinstance(rdmesim, pyLM.RDME.RDMESimulation): LMLogger.error("addParticlesToRegion requires that an RDMESimulation be specified, given type: %s", rdmesim.__class__.__name__) raise TypeError("Expected RDMESimulation") if rdmesim.hasBeenDiscretized == False: LMLogger.error("Must discretize region before adding particles from a generator") raise Exception("Discretization required") if number < 1: LMLogger.warning('Must add at least one particle, given: %d', number) return if len(directions) != 3: LMLogger.error("Must specify a direction of form (x,y,z), given: %s", directions) raise ValueError("3-tuple expected") # Get the dimensions to normalize distribution to mins=3*[0.] maxs=[d for d in rdmesim.continuousDimensions] if spatial != None: if len(spatial) != 2: LMLogger.error("spatial argument must be list of list: [[x,y,z],[xh,yh,xh]]") raise ValueError("bounds expected") if len(spatial[0]) !=3 or len(spatial[1]) !=3: LMLogger.error("spatial must be list of lists: [[x,y,z],[xh,yh,xh]]") raise ValueError("bounds expected") mins=spatial[0] maxs=spatial[1] self.addedLast=0 # Get the particle number ptype=rdmesim.particleMap[self.particlename] stype = rdmesim.siteTypes[region] lat = rdmesim.lattice latspace=rdmesim.latticeSpacing dels = [maxs[i]-mins[i] for i in range(3)] # start adding particles while self.addedLast < number: # generate randoms xlocal=random.uniform(0.0,1.0) ylocal=random.uniform(0.0,1.0) zlocal=random.uniform(0.0,1.0) if directions[0] == 1: good=False while not good: rlocal = random.uniform(0,1.0) loc = self.generator[0](xlocal) LMLogger.info("x trying: %f with: %f"%(rlocal,loc)) if rlocal < loc: good=True else: xlocal=random.uniform(0.0,1.0) if directions[1] == 1: good=False while not good: rlocal = random.uniform(0,1.0) loc = self.generator[1](ylocal) LMLogger.info("y trying: %f with: %f"%(rlocal,loc)) if rlocal < loc: good=True else: ylocal=random.uniform(0.0,1.0) if directions[2] == 1: good=False while not good: rlocal = random.uniform(0,1.0) loc = self.generator[2](zlocal) LMLogger.info("z trying: %f with: %f"%(rlocal,loc)) if rlocal < loc: good=True else: zlocal=random.uniform(0.0,1.0) LMLogger.info("trying (%f,%f,%f)"%(xlocal, ylocal, zlocal)) # convert to ints xint = int(xlocal*dels[0]/latspace) yint = int(ylocal*dels[1]/latspace) zint = int(zlocal*dels[2]/latspace) LMLogger.info("loc (%d,%d,%d)"%(xint, yint, zint)) if lat.getSiteType(xint,yint,zint) == stype: # TODO: Add bulletproofing if a exception of type (InvalidSiteException,InvalidParticleException) is raised LMLogger.info("Added a particle of type %s to (%d,%d,%d)", self.particlename, xint, yint, zint) lat.addParticle(xint,yint,zint, ptype) self.addedLast += 1 # Count total number added self.totalAdded += self.addedLast rdmesim.customAddedParticleList.append((self.particlename,self.totalAdded)) return