1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.algorithms.optimize.manybody;
39
40 import static java.lang.String.format;
41
42 import edu.rit.mp.DoubleBuf;
43 import edu.rit.pj.Comm;
44 import edu.rit.pj.IntegerSchedule;
45 import edu.rit.pj.WorkerIntegerForLoop;
46 import edu.rit.pj.WorkerRegion;
47 import ffx.algorithms.optimize.RotamerOptimization;
48 import ffx.potential.bonded.Residue;
49 import ffx.potential.bonded.Rotamer;
50 import ffx.potential.utils.EnergyException;
51 import java.io.BufferedWriter;
52 import java.io.IOException;
53 import java.util.List;
54 import java.util.Map;
55 import java.util.Set;
56 import java.util.logging.Level;
57 import java.util.logging.Logger;
58
59
60 public class TwoBodyEnergyRegion extends WorkerRegion {
61
62 private static final Logger logger = Logger.getLogger(TwoBodyEnergyRegion.class.getName());
63 private final Residue[] residues;
64 private final RotamerOptimization rO;
65 private final DistanceMatrix dM;
66 private final EnergyExpansion eE;
67 private final EliminatedRotamers eR;
68
69
70
71
72 private final List<Residue> allResiduesList;
73
74 private final Map<Integer, Integer[]> twoBodyEnergyMap;
75
76 private final BufferedWriter energyWriter;
77
78 private final Comm world;
79
80 private final int numProc;
81
82 private final boolean prunePairClashes;
83
84
85
86
87 private final double superpositionThreshold;
88
89 private final boolean master;
90
91 private final int rank;
92
93 private final boolean verbose;
94
95 private final boolean writeEnergyRestart;
96
97
98
99
100 private final boolean printFiles;
101
102 private Set<Integer> keySet;
103
104 public TwoBodyEnergyRegion(RotamerOptimization rotamerOptimization, DistanceMatrix dM,
105 EnergyExpansion eE, EliminatedRotamers eR, Residue[] residues, List<Residue> allResiduesList,
106 BufferedWriter energyWriter, Comm world, int numProc, boolean prunePairClashes,
107 double superpositionThreshold, boolean master, int rank, boolean verbose,
108 boolean writeEnergyRestart, boolean printFiles) {
109 this.rO = rotamerOptimization;
110 this.dM = dM;
111 this.eE = eE;
112 this.eR = eR;
113 this.residues = residues;
114 this.allResiduesList = allResiduesList;
115 this.energyWriter = energyWriter;
116 this.world = world;
117 this.numProc = numProc;
118 this.prunePairClashes = prunePairClashes;
119 this.superpositionThreshold = superpositionThreshold;
120 this.master = master;
121 this.rank = rank;
122 this.verbose = verbose;
123 this.writeEnergyRestart = writeEnergyRestart;
124 this.printFiles = printFiles;
125
126 this.twoBodyEnergyMap = eE.getTwoBodyEnergyMap();
127 logger.info(format(" Number of 2-body energies to calculate: %d", twoBodyEnergyMap.size()));
128 }
129
130 @Override
131 public void finish() {
132
133 eR.prePrunePairs(residues);
134
135
136 if (prunePairClashes) {
137 eR.prunePairClashes(residues);
138 }
139
140
141 if (master && verbose) {
142 for (int i = 0; i < residues.length; i++) {
143 Residue resI = residues[i];
144 Rotamer[] rotI = resI.getRotamers();
145 for (int ri = 0; ri < rotI.length; ri++) {
146 if (eR.check(i, ri)) {
147 continue;
148 }
149 for (int j = i + 1; j < residues.length; j++) {
150 Residue resJ = residues[j];
151 Rotamer[] rotJ = resJ.getRotamers();
152 for (int rj = 0; rj < rotJ.length; rj++) {
153 if (eR.check(j, rj) || eR.check(i, ri, j, rj)) {
154 continue;
155 }
156 logger.info(
157 format(" Pair energy %8s %-2d, %8s %-2d: %s", residues[i].toString(rotI[ri]), ri,
158 residues[j].toString(rotJ[rj]), rj,
159 rO.formatEnergy(eE.get2Body(i, ri, j, rj))));
160 }
161 }
162 }
163 }
164 }
165 }
166
167 @Override
168 public void run() throws Exception {
169 if (!keySet.isEmpty()) {
170 execute(0, keySet.size() - 1, new TwoBodyEnergyLoop());
171 }
172 }
173
174 @Override
175 public void start() {
176 int numPair = twoBodyEnergyMap.size();
177 int remainder = numPair % numProc;
178
179
180 Integer[] padding = {-1, -1, -1, -1};
181
182 int padKey = numPair;
183 while (remainder != 0) {
184 twoBodyEnergyMap.put(padKey++, padding);
185 remainder = twoBodyEnergyMap.size() % numProc;
186 }
187
188 numPair = twoBodyEnergyMap.size();
189 if (numPair % numProc != 0) {
190 logger.severe(" Logic error padding pair energies.");
191 }
192
193
194 keySet = twoBodyEnergyMap.keySet();
195 }
196
197 private class TwoBodyEnergyLoop extends WorkerIntegerForLoop {
198
199 final DoubleBuf[] resultBuffer;
200 final DoubleBuf myBuffer;
201
202 TwoBodyEnergyLoop() {
203 resultBuffer = new DoubleBuf[numProc];
204 for (int i = 0; i < numProc; i++) {
205 resultBuffer[i] = DoubleBuf.buffer(new double[5]);
206 }
207 myBuffer = resultBuffer[rank];
208 }
209
210 @Override
211 public void run(int lb, int ub) {
212 for (int key = lb; key <= ub; key++) {
213 long time = -System.nanoTime();
214 Integer[] job = twoBodyEnergyMap.get(key);
215 int i = job[0];
216 int ri = job[1];
217 int j = job[2];
218 int rj = job[3];
219
220 myBuffer.put(0, i);
221 myBuffer.put(1, ri);
222 myBuffer.put(2, j);
223 myBuffer.put(3, rj);
224 myBuffer.put(4, 0.0);
225
226
227 if (i >= 0 && ri >= 0 && j >= 0 && rj >= 0) {
228 if (!eR.check(i, ri) || !eR.check(j, rj) || !eR.check(i, ri, j, rj)) {
229 Residue residueI = residues[i];
230 Residue residueJ = residues[j];
231 Rotamer[] rotI = residues[i].getRotamers();
232 Rotamer[] rotJ = residues[j].getRotamers();
233 int indexI = allResiduesList.indexOf(residueI);
234 int indexJ = allResiduesList.indexOf(residueJ);
235 double resDist = dM.getResidueDistance(indexI, ri, indexJ, rj);
236 String resDistString = "large";
237 if (resDist < Double.MAX_VALUE) {
238 resDistString = format("%5.3f", resDist);
239 }
240
241 double dist = dM.checkDistMatrix(indexI, ri, indexJ, rj);
242 String distString = " large";
243 if (dist < Double.MAX_VALUE) {
244 distString = format("%10.3f", dist);
245 }
246
247 double twoBodyEnergy;
248 if (dist < superpositionThreshold) {
249
250 twoBodyEnergy = Double.NaN;
251 logger.info(
252 format(" Pair %8s %-2d, %8s %-2d:\t NaN at %10.3f A (%s A by res) < %5.3f Ang",
253 residueI.toString(rotI[ri]), ri, residueJ.toString(rotJ[rj]), rj, dist,
254 resDist, superpositionThreshold));
255 } else if (dM.checkPairDistThreshold(indexI, ri, indexJ, rj)) {
256
257 twoBodyEnergy = 0.0;
258 time += System.nanoTime();
259 logger.info(
260 format(" Pair %8s %-2d, %8s %-2d: %s at %s A (%s A by res) in %6.4f (sec).",
261 residueI.toString(rotI[ri]), ri, residueJ.toString(rotJ[rj]), rj,
262 rO.formatEnergy(twoBodyEnergy), distString, resDistString, time * 1.0e-9));
263 } else {
264 try {
265 twoBodyEnergy = eE.compute2BodyEnergy(residues, i, ri, j, rj);
266 time += System.nanoTime();
267 logger.info(
268 format(" Pair %8s %-2d, %8s %-2d: %s at %s A (%s A by res) in %6.4f (sec).",
269 residueI.toString(rotI[ri]), ri, residueJ.toString(rotJ[rj]), rj,
270 rO.formatEnergy(twoBodyEnergy), distString, resDistString, time * 1.0e-9));
271 } catch (EnergyException ex) {
272 twoBodyEnergy = ex.getEnergy();
273 time += System.nanoTime();
274 logger.info(
275 format(" Pair %8s %-2d, %8s %-2d: %s at %s A (%s A by res) in %6.4f (sec).",
276 residueI.toString(rotI[ri]), ri, residueJ.toString(rotJ[rj]), rj,
277 rO.formatEnergy(twoBodyEnergy), distString, resDistString, time * 1.0e-9));
278 }
279 }
280 myBuffer.put(4, twoBodyEnergy);
281 }
282 }
283
284
285 if (numProc > 1) {
286 try {
287 world.allGather(myBuffer, resultBuffer);
288 } catch (Exception e) {
289 logger.log(Level.SEVERE, " Exception communicating pair energies.", e);
290 }
291 }
292
293
294 for (DoubleBuf doubleBuf : resultBuffer) {
295 int resI = (int) doubleBuf.get(0);
296 int rotI = (int) doubleBuf.get(1);
297 int resJ = (int) doubleBuf.get(2);
298 int rotJ = (int) doubleBuf.get(3);
299 double energy = doubleBuf.get(4);
300
301 if (resI >= 0 && rotI >= 0 && resJ >= 0 && rotJ >= 0) {
302 if (!Double.isFinite(energy)) {
303 logger.info(
304 " Rotamer pair eliminated: " + resI + ", " + rotI + ", " + resJ + ", " + rotJ);
305 eR.eliminateRotamerPair(residues, resI, rotI, resJ, rotJ, false);
306 }
307 eE.set2Body(resI, rotI, resJ, rotJ, energy);
308 if (rank == 0 && writeEnergyRestart && printFiles) {
309 try {
310 energyWriter.append(
311 format("Pair %d %d, %d %d: %16.8f", resI, rotI, resJ, rotJ, energy));
312 energyWriter.newLine();
313 energyWriter.flush();
314 } catch (IOException ex) {
315 logger.log(Level.SEVERE, " Exception writing energy restart file.", ex);
316 }
317 }
318 }
319 }
320 }
321 }
322
323 @Override
324 public IntegerSchedule schedule() {
325
326 return IntegerSchedule.fixed();
327 }
328 }
329 }