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.potential.terms;
39
40 import ffx.crystal.Crystal;
41 import ffx.numerics.switching.ConstantSwitch;
42 import ffx.numerics.switching.UnivariateFunctionFactory;
43 import ffx.numerics.switching.UnivariateSwitchingFunction;
44 import ffx.potential.bonded.Atom;
45 import ffx.potential.bonded.BondedTerm;
46 import ffx.potential.bonded.RestrainDistance;
47 import ffx.potential.parameters.BondType;
48 import org.apache.commons.configuration2.CompositeConfiguration;
49
50 import javax.annotation.Nullable;
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.List;
55 import java.util.logging.Logger;
56
57 import static java.lang.String.format;
58
59
60
61
62
63
64
65 public class RestrainDistancePotentialEnergy extends EnergyTerm {
66
67 private static final Logger logger = Logger.getLogger(RestrainDistancePotentialEnergy.class.getName());
68
69
70
71
72 @Override
73 public void log() {
74 if (getNumberOfRestrainDistances() <= 0) {
75 return;
76 }
77 logger.info("\n Restrain Distance Interactions:");
78 for (RestrainDistance restrainDistance : getRestrainDistances()) {
79 logger.info(" Restrain Distance \t" + restrainDistance.toString());
80 }
81 }
82
83
84
85
86 private final List<RestrainDistance> restrainDistances = new ArrayList<>();
87
88
89
90
91
92
93 public RestrainDistancePotentialEnergy(String name) {
94 super(name);
95 }
96
97
98
99
100
101
102
103 public RestrainDistancePotentialEnergy(String name, int forceGroup) {
104 super(name, forceGroup);
105 }
106
107
108
109
110
111
112
113
114 public RestrainDistancePotentialEnergy(String name, int forceGroup, List<RestrainDistance> restrainDistances) {
115 super(name, forceGroup);
116 if (restrainDistances != null) {
117 Collections.sort(restrainDistances);
118 this.restrainDistances.addAll(restrainDistances);
119 logger.info(String.format(" Restrain Distances: %10d", getNumberOfRestrainDistances()));
120 }
121 }
122
123
124
125
126 @Override
127 public int getNumberOfTerms() {
128 return getNumberOfRestrainDistances();
129 }
130
131
132
133
134 @Override
135 public BondedTerm[] getBondedTermsArray() {
136 return getRestrainDistanceArray();
137 }
138
139
140
141
142
143
144
145 public RestrainDistancePotentialEnergy(String name, Collection<RestrainDistance> restrainDistances) {
146 super(name);
147 if (restrainDistances != null) {
148 this.restrainDistances.addAll(restrainDistances);
149 }
150 }
151
152
153
154
155
156
157
158 public boolean addRestrainDistance(RestrainDistance restrainDistance) {
159 if (restrainDistance == null) {
160 return false;
161 }
162 return restrainDistances.add(restrainDistance);
163 }
164
165
166
167
168
169
170
171 public boolean addRestrainDistances(RestrainDistance[] restrainDistances) {
172 if (restrainDistances == null) {
173 return false;
174 }
175 Collections.addAll(this.restrainDistances, restrainDistances);
176 return true;
177 }
178
179
180
181
182
183
184
185 public boolean addRestrainDistances(List<RestrainDistance> restrainDistances) {
186 if (restrainDistances == null) {
187 return false;
188 }
189 this.restrainDistances.addAll(restrainDistances);
190 return true;
191 }
192
193
194
195
196
197
198
199 public boolean removeRestrainDistance(RestrainDistance restrainDistance) {
200 if (restrainDistance == null) {
201 return false;
202 }
203 return restrainDistances.remove(restrainDistance);
204 }
205
206
207
208
209
210
211
212
213 public RestrainDistance getRestrainDistance(int index) {
214 return restrainDistances.get(index);
215 }
216
217
218
219
220
221
222 public List<RestrainDistance> getRestrainDistances() {
223 return Collections.unmodifiableList(restrainDistances);
224 }
225
226
227
228
229
230
231 public RestrainDistance[] getRestrainDistanceArray() {
232 return restrainDistances.toArray(new RestrainDistance[0]);
233 }
234
235
236
237
238
239
240 public int getNumberOfRestrainDistances() {
241 return restrainDistances.size();
242 }
243
244
245
246
247
248
249
250
251 public List<RestrainDistance> getRestrainDistances(@Nullable BondType.BondFunction bondFunction) {
252
253 if (bondFunction == null) {
254 return restrainDistances;
255 }
256
257 List<RestrainDistance> list = new ArrayList<>();
258 for (RestrainDistance restrainDistance : restrainDistances) {
259 if (restrainDistance.getBondType().bondFunction == bondFunction) {
260 list.add(restrainDistance);
261 }
262 }
263 if (!list.isEmpty()) {
264 return list;
265 }
266 return null;
267 }
268
269 @Override
270 public String toPDBString() {
271 if (getNumberOfRestrainDistances() <= 0) {
272 return "";
273 }
274 return String.format("REMARK 3 %s %g (%d)\n", "RESTRAIN DISTANCE : ", getEnergy(), getNumberOfRestrainDistances());
275 }
276
277 @Override
278 public String toString() {
279 return String.format(" %s %20.8f %12d %12.3f\n", "Restrain Distance ",
280 getEnergy(), getNumberOfRestrainDistances(), getTime());
281 }
282
283
284
285
286
287
288 public static RestrainDistance[] configureRestrainDistances(
289 CompositeConfiguration properties,
290 Atom[] atoms, Crystal crystal, boolean lambdaTerm) {
291 List<RestrainDistance> restrainDistanceList = new ArrayList<>();
292 String[] bondRestraints = properties.getStringArray("restrain-distance");
293 for (String bondRest : bondRestraints) {
294 try {
295 String[] toks = bondRest.split("\\s+");
296 if (toks.length < 2) {
297 throw new IllegalArgumentException(
298 format(" restrain-distance value %s could not be parsed!", bondRest));
299 }
300
301
302 int at1 = Integer.parseInt(toks[0]) - 1;
303 int at2 = Integer.parseInt(toks[1]) - 1;
304
305 double forceConst = 100.0;
306 double flatBottomRadius = 0;
307 Atom a1 = atoms[at1];
308 Atom a2 = atoms[at2];
309
310 if (toks.length > 2) {
311 forceConst = Double.parseDouble(toks[2]);
312 }
313 double dist;
314 switch (toks.length) {
315 case 2:
316 case 3:
317 double[] xyz1 = new double[3];
318 xyz1 = a1.getXYZ(xyz1);
319 double[] xyz2 = new double[3];
320 xyz2 = a2.getXYZ(xyz2);
321
322 dist = crystal.minDistOverSymOps(xyz1, xyz2);
323 break;
324 case 4:
325 dist = Double.parseDouble(toks[3]);
326 break;
327 case 5:
328 default:
329 double minDist = Double.parseDouble(toks[3]);
330 double maxDist = Double.parseDouble(toks[4]);
331 dist = 0.5 * (minDist + maxDist);
332 flatBottomRadius = 0.5 * Math.abs(maxDist - minDist);
333 break;
334 }
335
336 UnivariateSwitchingFunction switchF;
337 double lamStart = RestrainDistance.DEFAULT_RB_LAM_START;
338 double lamEnd = RestrainDistance.DEFAULT_RB_LAM_END;
339 if (toks.length > 5) {
340 int offset = 5;
341 if (toks[5].matches("^[01](?:\\.[0-9]*)?")) {
342 offset = 6;
343 lamStart = Double.parseDouble(toks[5]);
344 if (toks[6].matches("^[01](?:\\.[0-9]*)?")) {
345 offset = 7;
346 lamEnd = Double.parseDouble(toks[6]);
347 }
348 }
349 switchF = UnivariateFunctionFactory.parseUSF(toks, offset);
350 } else {
351 switchF = new ConstantSwitch();
352 }
353
354 RestrainDistance restrainDistance = createRestrainDistance(a1, a2, dist,
355 forceConst, flatBottomRadius, lamStart, lamEnd, switchF, lambdaTerm, crystal);
356 restrainDistanceList.add(restrainDistance);
357 } catch (Exception ex) {
358 logger.info(format(" Exception in parsing restrain-distance: %s", ex));
359 }
360 }
361 if (!restrainDistanceList.isEmpty()) {
362 return restrainDistanceList.toArray(new RestrainDistance[0]);
363 } else {
364 return null;
365 }
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 private static RestrainDistance createRestrainDistance(Atom a1, Atom a2, double distance, double forceConstant,
383 double flatBottom, double lamStart, double lamEnd,
384 UnivariateSwitchingFunction switchingFunction,
385 boolean lambdaTerm, Crystal crystal) {
386 boolean rbLambda = !(switchingFunction instanceof ConstantSwitch) && lambdaTerm;
387 RestrainDistance restrainDistance = new RestrainDistance(a1, a2, crystal, rbLambda, lamStart, lamEnd, switchingFunction);
388 int[] classes = {a1.getAtomType().atomClass, a2.getAtomType().atomClass};
389 if (flatBottom != 0) {
390 BondType bondType = new BondType(classes, forceConstant, distance,
391 BondType.BondFunction.FLAT_BOTTOM_HARMONIC, flatBottom);
392 restrainDistance.setBondType(bondType);
393 } else {
394 BondType bondType = new BondType(classes, forceConstant, distance,
395 BondType.BondFunction.HARMONIC);
396 restrainDistance.setBondType(bondType);
397 }
398 return restrainDistance;
399 }
400 }