Skip to content

Instantly share code, notes, and snippets.

@michaelsbradleyjr
Created December 23, 2011 20:51
Show Gist options
  • Save michaelsbradleyjr/1515326 to your computer and use it in GitHub Desktop.
Save michaelsbradleyjr/1515326 to your computer and use it in GitHub Desktop.
Monte Poly
# Particle definitions
# "Particle" serves as the base class, and we'll define specific particle types
# as subclasses
exports.Particle = class Particle
constructor: (@id) ->
@alreadyCalcCE = {}
name: 'unnamed'
charge: 0
dipole: 0
class P extends Particle
name: 'p'
class Pplus extends Particle
name: 'p+'
charge: 1
class N extends Particle
name: 'n'
charge: 1
class C extends Particle
name: 'c'
charge: -1
class U extends Particle
name: 'u'
dipole: 4.56
# O is really an empty site, or water
# Do we need to consider its dipole moment?
class O extends Particle
name: 'o'
# Keep a "list" of all the types as an attribute of the Particle constructor
# If another subclass is defined above, remember to add it to this list
Particle.types = [ P, Pplus, N, C, U, O ]
# Lattice definition
exports.Lattice = class Lattice
constructor: (@h, @w) ->
@nextId = nextId = (->
counter = 0
-> ++counter
)()
@population = []
for i in [0...@h]
@population.push []
for j in [0...@w]
@population[i].push new Particle.types[ Math.floor ( Math.random() * Particle.types.length ) ] nextId()
coulombEnergy: ->
sum = 0
counter = 0
for i in [0...@h]
for j in [0...@w]
itself = @population[i][j]
iCharge = itself.charge
iId = itself.id
if iCharge isnt 0
for k in [0...@h]
for l in [0...@w]
other = @population[k][l]
oCharge = other.charge
oId = other.id
if ((itself isnt other) and (oCharge isnt 0))
if not other.alreadyCalcCE[iId]?
counter += 1
itself.alreadyCalcCE[oId] = other
sum += ( iCharge * oCharge ) / ( Math.abs ( -10000 ) )
else
delete other.alreadyCalcCE[iId]
null
null
null
null
console.log 'this many calcs: ' + counter
sum
# helpers for Duff's Device (experimental CoffeeScript adaptation)
# See: http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
doWhile = (func, condition) ->
func()
func() while condition()
doWhile_8 = (func, condition) ->
func()
func()
func()
func()
func()
func()
func()
func()
while condition()
func()
func()
func()
func()
func()
func()
func()
func()
# for larger lattices, this "Duff's Device" implementation is faster and more
# memory efficient
coulombEnergy_duff: ->
values = @population
sum = 0
counter = 0
i = 0
inner_1 = ->
ival_1 = values[i++]
j = 0
inner_2 = ->
itself = ival_1[j++]
iCharge = itself.charge
iId = itself.id
if iCharge isnt 0
k = 0
inner_3 = ->
ival_2 = values[k++]
l = 0
inner_4 = ->
other = ival_2[l++]
oCharge = other.charge
oId = other.id
if ((itself isnt other) and (oCharge isnt 0))
if not other.alreadyCalcCE[iId]?
counter += 1
itself.alreadyCalcCE[oId] = other
sum += ( iCharge * oCharge ) / ( Math.abs ( -10000 ) )
else
delete other.alreadyCalcCE[iId]
undefined
cond_4_a = ->
--lovr_4 > 0
cond_4_b = ->
--iter_4 > 0
iter_4 = Math.floor (ival_2.length / 8)
lovr_4 = ival_2.length % 8
if lovr_4 > 0
doWhile inner_4, cond_4_a
doWhile_8 inner_4, cond_4_b
undefined
cond_3_a = ->
--lovr_3 > 0
cond_3_b = ->
--iter_3 > 0
iter_3 = Math.floor (values.length / 8)
lovr_3 = values.length % 8
if lovr_3 > 0
doWhile inner_3, cond_3_a
doWhile_8 inner_3, cond_3_b
undefined
cond_2_a = ->
--lovr_2 > 0
cond_2_b = ->
--iter_2 > 0
iter_2 = Math.floor (ival_1.length / 8)
lovr_2 = ival_1.length % 8
if lovr_2 > 0
doWhile inner_2, cond_2_a
doWhile_8 inner_2, cond_2_b
undefined
cond_1_a = ->
--lovr_1 > 0
cond_1_b = ->
--iter_1 > 0
iter_1 = Math.floor (values.length / 8)
lovr_1 = values.length % 8
if lovr_1 > 0
doWhile inner_1, cond_1_a
doWhile_8 inner_1, cond_1_b
console.log 'this many calcs: ' + counter
sum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment