void setupSolvent() {
		/*
		 * The surface fragment idea:
		 * 
		 * isosurface solvent|sasurface both work on the SELECTED atoms, thus allowing for a subset of the molecule to
		 * be involved. But in that case we don't want to be creating a surface that goes right through another atom.
		 * Rather, what we want (probably) is just the portion of the OVERALL surface that involves these atoms.
		 * 
		 * The addition of Mesh.voxelValue[] means that we can specify any voxel we want to NOT be excluded (NaN). Here
		 * we first exclude any voxel that would have been INSIDE a nearby atom. This will take care of any portion of
		 * the vanderwaals surface that would be there. Then we exclude any special-case voxel that is between two
		 * nearby atoms.
		 * 
		 * Bob Hanson 13 Jul 2006
		 * 
		 */
		bsSolventSelected = new BitSet();
		if (thePlane != null)
			setPlaneParameters(thePlane);
		solvent_quickPlane = true;// viewer.getTestFlag1();
		Atom[] atoms = frame.atoms;
		Point3f xyzMin = new Point3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
		Point3f xyzMax = new Point3f(-Float.MAX_VALUE, -Float.MAX_VALUE, -Float.MAX_VALUE);
		solvent_modelIndex = -1;
		int iAtom = 0;
		int nAtoms = viewer.getAtomCount();
		iUseBitSets = true;
		if (bsIgnore == null) {
			bsIgnore = new BitSet();
		}
		for (int i = 0; i < nAtoms; i++) {
			if (bsSelected.get(i) && (!bsIgnore.get(i))) {
				if (solvent_quickPlane && thePlane != null
						&& Math.abs(distancePointToPlane(atoms[i], thePlane)) > 2 * solventWorkingRadius(atoms[i])) {
					continue;
				}
				bsSolventSelected.set(i);
			}
		}
		atomSet = new BitSet();
		int firstSet = -1;
		int lastSet = 0;
		for (int i = 0; i < nAtoms; i++)
			if (bsSolventSelected.get(i)) {
				if (solvent_modelIndex < 0)
					solvent_modelIndex = atoms[i].modelIndex;
				if (solvent_modelIndex != atoms[i].modelIndex) {
					bsIgnore.set(i);
					continue;
				}
				++iAtom;
				atomSet.set(i);
				if (firstSet == -1)
					firstSet = i;
				lastSet = i;
			}
		int nH = 0;
		int[] atomNo = null;
		if (iAtom > 0) {
			Point3f[] hAtoms = null;
			if (addHydrogens) {
				hAtoms = viewer.getAdditionalHydrogens(atomSet);
				nH = hAtoms.length;
			}
			solvent_atomRadius = new float[iAtom + nH];
			solvent_ptAtom = new Point3f[iAtom + nH];
			atomNo = new int[iAtom + nH];

			float r = solventWorkingRadius(null);
			for (int i = 0; i < nH; i++) {
				atomNo[i] = 1;
				solvent_atomRadius[i] = r;
				solvent_ptAtom[i] = hAtoms != null ? hAtoms[i] : null;
			}
			iAtom = nH;
			for (int i = firstSet; i <= lastSet; i++) {
				if (!atomSet.get(i))
					continue;
				atomNo[iAtom] = atoms[i].getElementNumber();
				solvent_ptAtom[iAtom] = atoms[i];
				solvent_atomRadius[iAtom++] = solventWorkingRadius(atoms[i]);
			}
		}
		solvent_nAtoms = solvent_firstNearbyAtom = iAtom;
		Logger.info(iAtom + " atoms will be used in the solvent-accessible surface calculation");

		for (int i = 0; i < solvent_nAtoms; i++) {
			Point3f pt = solvent_ptAtom[i];
			float rA = solvent_atomRadius[i];
			if (pt.x - rA < xyzMin.x)
				xyzMin.x = pt.x - rA;
			if (pt.x + rA > xyzMax.x)
				xyzMax.x = pt.x + rA;
			if (pt.y - rA < xyzMin.y)
				xyzMin.y = pt.y - rA;
			if (pt.y + rA > xyzMax.y)
				xyzMax.y = pt.y + rA;
			if (pt.z - rA < xyzMin.z)
				xyzMin.z = pt.z - rA;
			if (pt.z + rA > xyzMax.z)
				xyzMax.z = pt.z + rA;
		}
		Logger.info("surface range " + xyzMin + " to " + xyzMax);
		jvxlFileHeader = new StringBuffer();
		jvxlFileHeader.append("solvent-" + (dataType == SURFACE_SASURFACE ? "accesible" : "excluded")
				+ " surface\nrange " + xyzMin + " to " + xyzMax + "\n");

		// fragment idea

		Point3f pt = new Point3f();

		BitSet bsNearby = new BitSet();
		int nNearby = 0;
		firstSet = -1;
		lastSet = 0;
		for (int i = 0; i < nAtoms; i++) {
			if (atomSet.get(i) || bsIgnore.get(i))
				continue;
			float rA = solventWorkingRadius(atoms[i]);
			if (solvent_quickPlane && thePlane != null && Math.abs(distancePointToPlane(atoms[i], thePlane)) > 2 * rA)
				continue;
			pt = atoms[i];
			if (pt.x + rA > xyzMin.x && pt.x - rA < xyzMax.x && pt.y + rA > xyzMin.y && pt.y - rA < xyzMax.y
					&& pt.z + rA > xyzMin.z && pt.z - rA < xyzMax.z) {
				if (firstSet == -1)
					firstSet = i;
				lastSet = i;
				bsNearby.set(i);
				nNearby++;
			}
		}

		if (nNearby != 0) {
			solvent_nAtoms += nNearby;
			solvent_atomRadius = ArrayUtil.setLength(solvent_atomRadius, solvent_nAtoms);
			solvent_ptAtom = (Point3f[]) ArrayUtil.setLength(solvent_ptAtom, solvent_nAtoms);

			iAtom = solvent_firstNearbyAtom;
			for (int i = firstSet; i <= lastSet; i++) {
				if (!bsNearby.get(i))
					continue;
				solvent_ptAtom[iAtom] = atoms[i];
				solvent_atomRadius[iAtom++] = solventWorkingRadius(atoms[i]);
			}
		}

		int maxGrid;
		maxGrid = solvent_gridMax;
		setVoxelRange(0, xyzMin.x, xyzMax.x, solvent_ptsPerAngstrom, maxGrid);
		setVoxelRange(1, xyzMin.y, xyzMax.y, solvent_ptsPerAngstrom, maxGrid);
		setVoxelRange(2, xyzMin.z, xyzMax.z, solvent_ptsPerAngstrom, maxGrid);
		precalculateVoxelData = newSolventMethod;
		int nAtomsWritten = Math.min(solvent_firstNearbyAtom, 100);
		jvxlFileHeader.append(jvxlGetVolumeHeader(nAtomsWritten));

		pt = new Point3f();
		for (int i = 0; i < nAtomsWritten; i++) {
			pt.set(solvent_ptAtom[i]);
			pt.scale(1 / ANGSTROMS_PER_BOHR);
			if (atomNo != null)
				jvxlFileHeader.append(atomNo[i] + " " + atomNo[i] + ".0 " + pt.x + " " + pt.y + " " + pt.z + "\n");
		}
		atomCount = -Integer.MAX_VALUE;
		negativeAtomCount = false;
	}