1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.openmm;
39
40 import com.sun.jna.ptr.IntByReference;
41 import com.sun.jna.ptr.PointerByReference;
42
43 import java.nio.IntBuffer;
44
45 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_addMap;
47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_addTorsion;
48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_create;
49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_destroy;
50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_getMapParameters;
51 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_getNumMaps;
52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_getNumTorsions;
53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_getTorsionParameters;
54 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_setMapParameters;
55 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_setTorsionParameters;
56 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_setUsesPeriodicBoundaryConditions;
57 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_updateParametersInContext;
58 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CMAPTorsionForce_usesPeriodicBoundaryConditions;
59
60 /**
61 * This class implements an interaction between pairs of dihedral angles. The interaction energy is
62 * defined by an "energy correction map" (CMAP), which is simply a set of tabulated energy values
63 * on a regular grid of (phi, psi) angles. Natural cubic spline interpolation is used to compute
64 * forces and energies at arbitrary values of the two angles.
65 * <p>
66 * To use this class, first create one or more energy correction maps by calling addMap(). For each
67 * one, you provide an array of energies at uniformly spaced values of the two angles. Next,
68 * add interactions by calling addTorsion(). For each one, you specify the sequence of particles used
69 * to calculate each of the two dihedral angles, and the index of the map used to calculate their
70 * interaction energy.
71 */
72 public class CMAPTorsionForce extends Force {
73
74 /**
75 * Create a CMAPTorsionForce.
76 */
77 public CMAPTorsionForce() {
78 super(OpenMM_CMAPTorsionForce_create());
79 }
80
81 /**
82 * Create a new map that can be used for torsion pairs.
83 *
84 * @param size the size of the map along each dimension
85 * @param energy the energy values for the map. This must be of length size*size.
86 * The element energy[i+size*j] contains the energy when the first
87 * torsion angle equals i*2*PI/size and the second torsion angle
88 * equals j*2*PI/size.
89 * @return the index of the map that was added
90 */
91 public int addMap(int size, PointerByReference energy) {
92 return OpenMM_CMAPTorsionForce_addMap(pointer, size, energy);
93 }
94
95 /**
96 * Add a CMAP torsion term to the force field.
97 *
98 * @param map the index of the map to use for this term
99 * @param a1 the index of the first particle forming the first torsion
100 * @param a2 the index of the second particle forming the first torsion
101 * @param a3 the index of the third particle forming the first torsion
102 * @param a4 the index of the fourth particle forming the first torsion
103 * @param b1 the index of the first particle forming the second torsion
104 * @param b2 the index of the second particle forming the second torsion
105 * @param b3 the index of the third particle forming the second torsion
106 * @param b4 the index of the fourth particle forming the second torsion
107 * @return the index of the torsion that was added
108 */
109 public int addTorsion(int map, int a1, int a2, int a3, int a4, int b1, int b2, int b3, int b4) {
110 return OpenMM_CMAPTorsionForce_addTorsion(pointer, map, a1, a2, a3, a4, b1, b2, b3, b4);
111 }
112
113 /**
114 * Destroy the force.
115 */
116 @Override
117 public void destroy() {
118 if (pointer != null) {
119 OpenMM_CMAPTorsionForce_destroy(pointer);
120 pointer = null;
121 }
122 }
123
124 /**
125 * Get the energy values of a map.
126 *
127 * @param index the index of the map for which to get energy values
128 * @param size the size of the map along each dimension
129 * @param energy the energy values for the map. This must be of length size*size.
130 * The element energy[i+size*j] contains the energy when the first
131 * torsion angle equals i*2*PI/size and the second torsion angle
132 * equals j*2*PI/size.
133 */
134 public void getMapParameters(int index, IntByReference size, PointerByReference energy) {
135 OpenMM_CMAPTorsionForce_getMapParameters(pointer, index, size, energy);
136 }
137
138 /**
139 * Get the energy values of a map.
140 *
141 * @param index the index of the map for which to get energy values
142 * @param size the size of the map along each dimension
143 * @param energy the energy values for the map. This must be of length size*size.
144 * The element energy[i+size*j] contains the energy when the first
145 * torsion angle equals i*2*PI/size and the second torsion angle
146 * equals j*2*PI/size.
147 */
148 public void getMapParameters(int index, IntBuffer size, PointerByReference energy) {
149 OpenMM_CMAPTorsionForce_getMapParameters(pointer, index, size, energy);
150 }
151
152 /**
153 * Get the number of maps that have been defined.
154 */
155 public int getNumMaps() {
156 return OpenMM_CMAPTorsionForce_getNumMaps(pointer);
157 }
158
159 /**
160 * Get the number of CMAP torsion terms in the potential function
161 */
162 public int getNumTorsions() {
163 return OpenMM_CMAPTorsionForce_getNumTorsions(pointer);
164 }
165
166 /**
167 * Get the force field parameters for a CMAP torsion term.
168 *
169 * @param index the index of the torsion for which to get parameters
170 * @param map the index of the map to use for this term
171 * @param a1 the index of the first particle forming the first torsion
172 * @param a2 the index of the second particle forming the first torsion
173 * @param a3 the index of the third particle forming the first torsion
174 * @param a4 the index of the fourth particle forming the first torsion
175 * @param b1 the index of the first particle forming the second torsion
176 * @param b2 the index of the second particle forming the second torsion
177 * @param b3 the index of the third particle forming the second torsion
178 * @param b4 the index of the fourth particle forming the second torsion
179 */
180 public void getTorsionParameters(int index, IntByReference map, IntByReference a1, IntByReference a2,
181 IntByReference a3, IntByReference a4, IntByReference b1,
182 IntByReference b2, IntByReference b3, IntByReference b4) {
183 OpenMM_CMAPTorsionForce_getTorsionParameters(pointer, index, map, a1, a2, a3, a4, b1, b2, b3, b4);
184 }
185
186 /**
187 * Get the force field parameters for a CMAP torsion term.
188 *
189 * @param index the index of the torsion for which to get parameters
190 * @param map the index of the map to use for this term
191 * @param a1 the index of the first particle forming the first torsion
192 * @param a2 the index of the second particle forming the first torsion
193 * @param a3 the index of the third particle forming the first torsion
194 * @param a4 the index of the fourth particle forming the first torsion
195 * @param b1 the index of the first particle forming the second torsion
196 * @param b2 the index of the second particle forming the second torsion
197 * @param b3 the index of the third particle forming the second torsion
198 * @param b4 the index of the fourth particle forming the second torsion
199 */
200 public void getTorsionParameters(int index, IntBuffer map, IntBuffer a1, IntBuffer a2,
201 IntBuffer a3, IntBuffer a4, IntBuffer b1,
202 IntBuffer b2, IntBuffer b3, IntBuffer b4) {
203 OpenMM_CMAPTorsionForce_getTorsionParameters(pointer, index, map, a1, a2, a3, a4, b1, b2, b3, b4);
204 }
205
206 /**
207 * Set the energy values of a map.
208 *
209 * @param index the index of the map for which to set energy values
210 * @param size the size of the map along each dimension
211 * @param energy the energy values for the map. This must be of length size*size.
212 * The element energy[i+size*j] contains the energy when the first
213 * torsion angle equals i*2*PI/size and the second torsion angle
214 * equals j*2*PI/size.
215 */
216 public void setMapParameters(int index, int size, PointerByReference energy) {
217 OpenMM_CMAPTorsionForce_setMapParameters(pointer, index, size, energy);
218 }
219
220 /**
221 * Set the force field parameters for a CMAP torsion term.
222 *
223 * @param index the index of the torsion for which to set parameters
224 * @param map the index of the map to use for this term
225 * @param a1 the index of the first particle forming the first torsion
226 * @param a2 the index of the second particle forming the first torsion
227 * @param a3 the index of the third particle forming the first torsion
228 * @param a4 the index of the fourth particle forming the first torsion
229 * @param b1 the index of the first particle forming the second torsion
230 * @param b2 the index of the second particle forming the second torsion
231 * @param b3 the index of the third particle forming the second torsion
232 * @param b4 the index of the fourth particle forming the second torsion
233 */
234 public void setTorsionParameters(int index, int map, int a1, int a2, int a3, int a4,
235 int b1, int b2, int b3, int b4) {
236 OpenMM_CMAPTorsionForce_setTorsionParameters(pointer, index, map, a1, a2, a3, a4, b1, b2, b3, b4);
237 }
238
239 /**
240 * Set whether this force should apply periodic boundary conditions when calculating displacements.
241 * Usually this is not appropriate for bonded forces, but there are situations when it can be useful.
242 */
243 public void setUsesPeriodicBoundaryConditions(boolean periodic) {
244 OpenMM_CMAPTorsionForce_setUsesPeriodicBoundaryConditions(pointer, periodic ? 1 : 0);
245 }
246
247 /**
248 * Update the map and torsion parameters in a Context to match those stored in this Force object. This method provides
249 * an efficient method to update certain parameters in an existing Context without needing to reinitialize it.
250 * Simply call setMapParameters() and setTorsionParameters() to modify this object's parameters, then call updateParametersInContext()
251 * to copy them over to the Context.
252 * <p>
253 * The only information that can be updated with this method is the energy values for a map, and the map index
254 * for a torsion. The size of a map and the set of particles involved in a torsion cannot be changed. Also,
255 * new bonds and torsions cannot be added.
256 */
257 public void updateParametersInContext(Context context) {
258 if (context.hasContextPointer()) {
259 OpenMM_CMAPTorsionForce_updateParametersInContext(pointer, context.getPointer());
260 }
261 }
262
263 /**
264 * Returns whether or not this force makes use of periodic boundary
265 * conditions.
266 *
267 * @return true if force uses PBC and false otherwise
268 */
269 @Override
270 public boolean usesPeriodicBoundaryConditions() {
271 int pbc = OpenMM_CMAPTorsionForce_usesPeriodicBoundaryConditions(pointer);
272 return pbc == OpenMM_True;
273 }
274 }