use of ffx.potential.nonbonded.NeighborList in project ffx by mjschnie.
the class RotamerOptimization method distanceMatrix.
/**
* Calculates a residue-residue distance matrix.
* <p>
* Residue-residue distance is defined as the shortest atom-atom distance in
* any possible rotamer-rotamer pair if the residues are neighbors (central
* atom-central atom distances are within a cutoff). Otherewise, distances
* are set to a default of Double.MAX_VALUE.
* </p>
* <p>
* The intent of using a neighbor list is to avoid tediously searching
* rotamer- rotamer pairs when two residues are so far apart we will never
* need the exact distance. We use the distance matrix for adding residues
* to the sliding window and determining whether to set 3-body energy to
* 0.0.
* </p>
* <p>
* If the central atoms are too distant from each other, we can safely
* assume no atoms will ever be close enough for addition to sliding window
* or to cause explicit calculation of 3-body energy.
* </p>
*/
private void distanceMatrix() {
distanceMatrix = new double[numResidues - 1][][][];
long numDistances = 0L;
for (int i = 0; i < (numResidues - 1); i++) {
Residue residuei = allResiduesArray[i];
int lengthRi;
try {
if (checkIfForced(residuei)) {
lengthRi = 1;
} else {
lengthRi = residuei.getRotamers(library).length;
}
} catch (IndexOutOfBoundsException ex) {
if (useForcedResidues) {
logger.warning(ex.toString());
} else {
logIfMaster(format(" Non-forced Residue i %s has null rotamers.", residuei.toFormattedString(false, true)), Level.WARNING);
}
continue;
}
distanceMatrix[i] = new double[lengthRi][][];
for (int ri = 0; ri < lengthRi; ri++) {
distanceMatrix[i][ri] = new double[numResidues][];
for (int j = (i + 1); j < numResidues; j++) {
Residue residuej = allResiduesArray[j];
int lengthRj;
try {
if (checkIfForced(residuej)) {
lengthRj = 1;
} else {
lengthRj = residuej.getRotamers(library).length;
}
} catch (IndexOutOfBoundsException ex) {
if (useForcedResidues) {
logger.warning(ex.toString());
} else {
logIfMaster(format(" Residue j %s has null rotamers.", residuej.toFormattedString(false, true)));
}
continue;
}
distanceMatrix[i][ri][j] = new double[lengthRj];
numDistances += lengthRj;
if (!lazyMatrix) {
fill(distanceMatrix[i][ri][j], Double.MAX_VALUE);
} else {
fill(distanceMatrix[i][ri][j], -1.0);
}
}
}
}
logger.info(format(" Number of pairwise distances: %d", numDistances));
if (!lazyMatrix) {
ResidueState[] orig = ResidueState.storeAllCoordinates(allResiduesList);
int nMultiRes = 0;
/**
* Build a list that contains one atom from each Residues: CA from
* amino acids, C1 from nucleic acids, or the first atom otherwise.
*/
Atom[] atoms = new Atom[numResidues];
for (int i = 0; i < numResidues; i++) {
Residue residuei = allResiduesArray[i];
atoms[i] = residuei.getReferenceAtom();
if (residuei instanceof MultiResidue) {
++nMultiRes;
}
}
/**
* Use of the pre-existing ParallelTeam causes a conflict when
* MultiResidues must re-init the force field. Temporary solution
* for sequence optimization: if > 1 residue optimized, run on only
* one thread.
*/
int nThreads = 1;
if (molecularAssembly.getPotentialEnergy().getParallelTeam() != null) {
nThreads = (nMultiRes > 1) ? 1 : molecularAssembly.getPotentialEnergy().getParallelTeam().getThreadCount();
} else {
// Suggested: nThreads = (nMultiRes > 1) ? 1 : ParallelTeam.getDefaultThreadCount();
nThreads = 16;
}
ParallelTeam parallelTeam = new ParallelTeam(nThreads);
Crystal crystal = molecularAssembly.getCrystal();
int nSymm = crystal.spaceGroup.getNumberOfSymOps();
logger.info("\n Computing Residue Distance Matrix");
double nlistCutoff = Math.max(Math.max(distance, twoBodyCutoffDist), threeBodyCutoffDist);
/**
* I think this originated from the fact that side-chain
* (and later nucleic acid) atoms could be fairly distant
* from the reference atom.
*/
double magicNumberBufferOfUnknownOrigin = 25.0;
nlistCutoff += magicNumberBufferOfUnknownOrigin;
NeighborList neighborList = new NeighborList(null, crystal, atoms, nlistCutoff, 0.0, parallelTeam);
// Expand coordinates
double[][] xyz = new double[nSymm][3 * numResidues];
double[] in = new double[3];
double[] out = new double[3];
for (int iSymOp = 0; iSymOp < nSymm; iSymOp++) {
SymOp symOp = crystal.spaceGroup.getSymOp(iSymOp);
for (int i = 0; i < numResidues; i++) {
int i3 = i * 3;
int iX = i3 + 0;
int iY = i3 + 1;
int iZ = i3 + 2;
Atom atom = atoms[i];
in[0] = atom.getX();
in[1] = atom.getY();
in[2] = atom.getZ();
crystal.applySymOp(in, out, symOp);
xyz[iSymOp][iX] = out[0];
xyz[iSymOp][iY] = out[1];
xyz[iSymOp][iZ] = out[2];
}
}
// Build the residue neighbor-list.
int[][][] lists = new int[nSymm][numResidues][];
boolean[] use = new boolean[numResidues];
fill(use, true);
boolean forceRebuild = true;
boolean printLists = false;
long neighborTime = -System.nanoTime();
neighborList.buildList(xyz, lists, use, forceRebuild, printLists);
neighborTime += System.nanoTime();
logger.info(format(" Built residue neighbor list: %8.3f sec", neighborTime * 1.0e-9));
DistanceRegion distanceRegion = new DistanceRegion(parallelTeam.getThreadCount(), numResidues, crystal, lists, neighborList.getPairwiseSchedule());
long parallelTime = -System.nanoTime();
try {
parallelTeam.execute(distanceRegion);
} catch (Exception e) {
String message = " Exception compting residue distance matrix.";
logger.log(Level.SEVERE, message, e);
}
parallelTime += System.nanoTime();
logger.info(format(" Pairwise distance matrix: %8.3f sec\n", parallelTime * 1.0e-9));
ResidueState.revertAllCoordinates(allResiduesList, orig);
try {
parallelTeam.shutdown();
} catch (Exception ex) {
logger.warning(format(" Exception shutting down parallel team for the distance matrix: %s", ex.toString()));
}
}
}
Aggregations