private bool processRank(Particle p, Rank rank, ref Dictionary<Particle, Rank> ranks) { _moveAttempts[p] = true; bool particleMoved = false; // Try to move the Particle in its preferred direction Direction dir = rank.MaxDirection; int offset = Math.Sign(rank.Pulls[dir]); bool canMove = canMoveInDirection(p, rank, dir, offset, ref ranks); if (canMove) { moveParticle(p, dir, offset); particleMoved = true; } // If unsuccessful, try to move in the other direction else { dir = (rank.MaxDirection == Direction.Vertical) ? Direction.Horizontal : Direction.Vertical; offset = Math.Sign(rank.Pulls[dir]); canMove = canMoveInDirection(p, rank, dir, offset, ref ranks); if (canMove) { moveParticle(p, dir, offset); particleMoved = true; } } // Either way, this Particle has been processed, so remove it from the Dictionary ranks.Remove(p); _moveAttempts[p] = false; return particleMoved; }
// HELPER FUNCTIONS private void initialize() { // Add a random number of random particles for (int p = 0; p < ParticleCount; ++p) { int atomicNum = _rand.Next(0, ElementCount); int x, y; do { x = _rand.Next(0, Size); y = _rand.Next(0, Size); } while (_lattice[x, y] != null); Particle particle = new Particle(atomicNum, x, y, Temperature); _lattice[x, y] = particle; _moveAttempts.Add(particle, false); } }
private bool canMoveInDirection(Particle p, Rank rank, Direction dir, int offset, ref Dictionary<Particle, Rank> ranks) { int x = p.Position.X; int y = p.Position.Y; // If the neighboring position is off the lattice then retun false bool vertMax = (dir == Direction.Vertical); if ( ( vertMax && (y + offset < 0 || Size <= y + offset)) || (!vertMax && (x + offset < 0 || Size <= x + offset)) ) { return false; } // Otherwise, if the position is open, return true Particle neighbor = (vertMax ? _lattice[x, y + offset] : _lattice[x + offset, y]); if (neighbor == null) return true; // Recursive case: the position is occupied, so return whether or not the neighbor can move if (!ranks.ContainsKey(neighbor)) return false; if (_moveAttempts[p]) return true; bool neighborCanMove = processRank(neighbor, ranks[neighbor], ref ranks); return neighborCanMove; }
private Rank getParticleRank(Particle particle) { int x = particle.Position.X; int y = particle.Position.Y; // Get the pulls in all directions double sumLeft = 0d; for (int px = 0; px < x; ++px) { Particle other = _lattice[px, y]; double electronegativity = (other?.Electronegativity ?? 1d); sumLeft += electronegativity / Math.Abs(px - x); } double sumRight = 0d; for (int px = x + 1; px < Size; ++px) { Particle other = _lattice[px, y]; double electronegativity = (other?.Electronegativity ?? 1d); sumRight += electronegativity / Math.Abs(px - x); } double sumUp = 0d; for (int py = 0; py < y; ++py) { Particle other = _lattice[x, py]; double electronegativity = (other?.Electronegativity ?? 1d); sumUp += electronegativity / Math.Abs(py - y); } double sumDown = 0d; for (int py = y + 1; py < Size; ++py) { Particle other = _lattice[x, py]; double electronegativity = (other?.Electronegativity ?? 1d); sumDown += electronegativity / Math.Abs(py - y); } // Store the effective pull in each direction Dictionary<Direction, double> pulls = new Dictionary<Direction, double>() { { Direction.Vertical, sumDown - sumUp }, { Direction.Horizontal, sumRight - sumLeft }, }; // Get the max Direction double max = 0d; Direction maxDir = Direction.Vertical; double absVert = Math.Abs(pulls[Direction.Vertical]); if (absVert > max) { max = absVert; maxDir = Direction.Vertical; } double absHorz = Math.Abs(pulls[Direction.Horizontal]); if (absHorz > max) { max = absHorz; maxDir = Direction.Horizontal; } // Return the rank for this Particle Rank r = new Rank() { Pulls = pulls, MaxDirection = maxDir, }; return r; }
public void moveParticle(Particle p, Direction dir, int offset) { int x = p.Position.X; int y = p.Position.Y; if (_lattice[x, y].Equals(p)) _lattice[x, y] = null; bool vertMax = (dir == Direction.Vertical); if (vertMax) { _lattice[x, y + offset] = p; p.Position = new Point(x, y + offset); } else { _lattice[x + offset, y] = p; p.Position = new Point(x + offset, y); } }