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.PointerByReference;
41
42 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
43 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_create;
44 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_destroy;
45 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_getParticles;
46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_getReferencePositions;
47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_setParticles;
48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_setReferencePositions;
49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_updateParametersInContext;
50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_RMSDForce_usesPeriodicBoundaryConditions;
51
52 /**
53 * This is a force whose energy equals the root mean squared deviation (RMSD)
54 * between the current coordinates and a reference structure. It is intended for
55 * use with CustomCVForce. You will not normally want a force that exactly equals
56 * the RMSD, but there are many situations where it is useful to have a restraining
57 * or biasing force that depends on the RMSD in some way.
58 * <p>
59 * The force is computed by first aligning the particle positions to the reference
60 * structure, then computing the RMSD between the aligned positions and the reference.
61 * The computation can optionally be done based on only a subset of the particles
62 * in the system.
63 */
64 public class RMSDForce extends Force {
65
66 /**
67 * Create an RMSDForce.
68 *
69 * @param referencePositions the reference positions to compute the deviation
70 * from. The length of this vector must equal the
71 * number of particles in the system, even if not
72 * all particles are used in computing the RMSD.
73 * @param particles the indices of the particles to use when computing
74 * the RMSD. If this is empty (the default), all
75 * particles in the system will be used.
76 */
77 public RMSDForce(PointerByReference particles, PointerByReference referencePositions) {
78 super(OpenMM_RMSDForce_create(particles, referencePositions));
79 }
80
81 /**
82 * Destroy the force.
83 */
84 @Override
85 public void destroy() {
86 if (pointer != null) {
87 OpenMM_RMSDForce_destroy(pointer);
88 pointer = null;
89 }
90 }
91
92 /**
93 * Get the indices of the particles to use when computing the RMSD. If this
94 * is empty, all particles in the system will be used.
95 *
96 * @return the indices of the particles to use when computing the RMSD.
97 */
98 public PointerByReference getParticles() {
99 return OpenMM_RMSDForce_getParticles(pointer);
100 }
101
102 /**
103 * Get the reference positions to compute the deviation from.
104 *
105 * @return the reference positions to compute the deviation from.
106 */
107 public PointerByReference getReferencePositions() {
108 return OpenMM_RMSDForce_getReferencePositions(pointer);
109 }
110
111 /**
112 * Set the indices of the particles to use when computing the RMSD. If this
113 * is empty, all particles in the system will be used.
114 *
115 * @param particles the indices of the particles to use when computing the RMSD.
116 */
117 public void setParticles(PointerByReference particles) {
118 OpenMM_RMSDForce_setParticles(pointer, particles);
119 }
120
121 /**
122 * Set the reference positions to compute the deviation from.
123 *
124 * @param referencePositions the reference positions to compute the deviation from.
125 */
126 public void setReferencePositions(PointerByReference referencePositions) {
127 OpenMM_RMSDForce_setReferencePositions(pointer, referencePositions);
128 }
129
130 /**
131 * Update the reference positions and particle indices in a Context to match those stored
132 * in this Force object. This method provides an efficient method to update certain parameters
133 * in an existing Context without needing to reinitialize it. Simply call setReferencePositions()
134 * and setParticles() to modify this object's parameters, then call updateParametersInContext()
135 * to copy them over to the Context.
136 *
137 * @param context the Context in which to update the parameters.
138 */
139 public void updateParametersInContext(Context context) {
140 if (context.hasContextPointer()) {
141 OpenMM_RMSDForce_updateParametersInContext(pointer, context.getPointer());
142 }
143 }
144
145 /**
146 * Returns whether or not this force makes use of periodic boundary
147 * conditions.
148 *
149 * @return true if force uses PBC and false otherwise.
150 */
151 @Override
152 public boolean usesPeriodicBoundaryConditions() {
153 int pbc = OpenMM_RMSDForce_usesPeriodicBoundaryConditions(pointer);
154 return pbc == OpenMM_True;
155 }
156 }