public void alignParticles(int id, int m, int n, double xoffset, double yoffset, double xspacing, double yspacing, boolean randomize) {
		Element e = getElement(id);
		if (e == null)
			throw new IllegalArgumentException("atom id incorrect");
		double sigma = e.getSigma();
		if (xspacing < sigma || yspacing < sigma)
			throw new IllegalArgumentException("spacings may be too small");
		if (xoffset < 0 || yoffset < 0)
			throw new IllegalArgumentException("negative offset");
		if (m <= 0 || n <= 0)
			throw new IllegalArgumentException("m and n must be positive");
		int k = 0;
		double w = boundary.getWidth();
		double h = boundary.getHeight();
		double x = boundary.getX();
		double y = boundary.getY();
		double rx, ry;
		terminate: for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				rx = xoffset + i * xspacing;
				ry = yoffset + j * yspacing;
				if (rx - sigma * 0.5 >= x && rx + sigma * 0.5 < x + w && ry - sigma * 0.5 >= y && ry + sigma * 0.5 < y + h) {
					atom[k].rx = rx;
					atom[k].ry = ry;
					if (randomize) {
						atom[k].rx += (0.5 - Math.random()) * xspacing;
						atom[k].ry += (0.5 - Math.random()) * yspacing;
					}
					atom[k].setElement(e);
					atom[k].setCharge(0);
					atom[k].setCustom(0);
					atom[k].setRestraint(null);
					atom[k].setFriction(0);
					atom[k].setRadical(true);
					atom[k].setUserField(null);
					k++;
					if (k >= atom.length)
						break terminate;
				}
			}
		}
		setNumberOfParticles(k);
		if (randomize) {
			putInBounds();
			Thread t = new Thread("Energy Minimizer in alignParticles()") {
				public void run() {
					for (int i = 0; i < 100; i++) {
						steepestDescent(1.0);
					}
				}
			};
			t.setPriority(Thread.NORM_PRIORITY);
			t.start();
		}
	}