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.Pointer;
41
42 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
43 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_addGlobalParameter;
44 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_create;
45 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_destroy;
46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_getEnergyFunction;
47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_getGlobalParameterDefaultValue;
48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_getGlobalParameterName;
49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_getNumGlobalParameters;
50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_setEnergyFunction;
51 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_setGlobalParameterDefaultValue;
52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_setGlobalParameterName;
53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomVolumeForce_usesPeriodicBoundaryConditions;
54
55 /**
56 * This class computes an energy that depends only on the volume of the periodic box, or more generally
57 * on the box shape as specified by the elements of the box vectors. Because the energy does not
58 * depend on particle positions, it does not apply any forces to particles. It is primarily useful
59 * for constant pressure simulations, where the volume-dependent energy can influence the behavior
60 * of the barostat. Energy terms of this sort are often used for pressure matching in coarse grained
61 * force fields.
62 *
63 * <p>To use this class, create a CustomVolumeForce object, passing an algebraic expression to the constructor
64 * that defines the energy. The expression may depend on the following variables.
65 *
66 * <ul>
67 * <li>v: The volume of the periodic box in nm^3.</li>
68 * <li>ax: The x component of the first box vector in nm. (The y and z components are always zero.)</li>
69 * <li>bx, by: The x and y components of the second box vector in nm. (The z component is always zero.)</li>
70 * <li>cx, cy, cz: The x, y and z components of the third box vector in nm.</li>
71 * <li>Global parameters that you define by calling addGlobalParameter().</li>
72 * </ul>
73 *
74 * <p>The initial value of a global parameter is specified in the call to addGlobalParameter(). Their values
75 * can be modified during a simulation by calling Context::setParameter().
76 *
77 * <p>Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following
78 * functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, atan2, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions
79 * are defined in radians, and log is the natural logarithm. step(x) = 0 if x < 0, 1 otherwise. delta(x) = 1 if x = 0, 0 otherwise.
80 * select(x,y,z) = z if x = 0, y otherwise.
81 */
82 public class CustomVolumeForce extends Force {
83
84 /**
85 * Create a CustomVolumeForce.
86 *
87 * @param energy an algebraic expression giving the energy as a function of the box shape
88 */
89 public CustomVolumeForce(String energy) {
90 super(OpenMM_CustomVolumeForce_create(energy));
91 }
92
93 /**
94 * Add a new global parameter that the interaction may depend on. The default value provided to
95 * this method is the initial value of the parameter in newly created Contexts. You can change
96 * the value at any time by calling setParameter() on the Context.
97 *
98 * @param name the name of the parameter
99 * @param defaultValue the default value of the parameter
100 * @return the index of the parameter that was added
101 */
102 public int addGlobalParameter(String name, double defaultValue) {
103 return OpenMM_CustomVolumeForce_addGlobalParameter(pointer, name, defaultValue);
104 }
105
106 /**
107 * Add a new global parameter that the energy may depend on.
108 *
109 * @param name The name of the parameter.
110 * @param defaultValue The default value of the parameter.
111 * @return The index of the parameter that was added.
112 */
113 public int addGlobalParameter(Pointer name, double defaultValue) {
114 return OpenMM_CustomVolumeForce_addGlobalParameter(pointer, name, defaultValue);
115 }
116
117 /**
118 * Destroy the force.
119 */
120 @Override
121 public void destroy() {
122 if (pointer != null) {
123 OpenMM_CustomVolumeForce_destroy(pointer);
124 pointer = null;
125 }
126 }
127
128 /**
129 * Get the algebraic expression that defines the energy.
130 *
131 * @return the energy expression
132 */
133 public String getEnergyFunction() {
134 Pointer p = OpenMM_CustomVolumeForce_getEnergyFunction(pointer);
135 if (p == null) {
136 return null;
137 }
138 return p.getString(0);
139 }
140
141 /**
142 * Get the default value of a global parameter.
143 *
144 * @param index the index of the parameter for which to get the default value
145 * @return the parameter default value
146 */
147 public double getGlobalParameterDefaultValue(int index) {
148 return OpenMM_CustomVolumeForce_getGlobalParameterDefaultValue(pointer, index);
149 }
150
151 /**
152 * Get the name of a global parameter.
153 *
154 * @param index the index of the parameter for which to get the name
155 * @return the parameter name
156 */
157 public String getGlobalParameterName(int index) {
158 Pointer p = OpenMM_CustomVolumeForce_getGlobalParameterName(pointer, index);
159 if (p == null) {
160 return null;
161 }
162 return p.getString(0);
163 }
164
165 /**
166 * Get the number of global parameters that the energy depends on.
167 *
168 * @return The number of parameters.
169 */
170 public int getNumGlobalParameters() {
171 return OpenMM_CustomVolumeForce_getNumGlobalParameters(pointer);
172 }
173
174 /**
175 * Set the algebraic expression that defines the energy.
176 *
177 * @param energy the energy expression
178 */
179 public void setEnergyFunction(String energy) {
180 OpenMM_CustomVolumeForce_setEnergyFunction(pointer, energy);
181 }
182
183 /**
184 * Set the algebraic expression that defines the energy.
185 *
186 * @param energy the energy expression
187 */
188 public void setEnergyFunction(Pointer energy) {
189 OpenMM_CustomVolumeForce_setEnergyFunction(pointer, energy);
190 }
191
192 /**
193 * Set the default value of a global parameter.
194 *
195 * @param index the index of the parameter for which to set the default value
196 * @param defaultValue the default value of the parameter
197 */
198 public void setGlobalParameterDefaultValue(int index, double defaultValue) {
199 OpenMM_CustomVolumeForce_setGlobalParameterDefaultValue(pointer, index, defaultValue);
200 }
201
202 /**
203 * Set the name of a global parameter.
204 *
205 * @param index the index of the parameter for which to set the name
206 * @param name the name of the parameter
207 */
208 public void setGlobalParameterName(int index, String name) {
209 OpenMM_CustomVolumeForce_setGlobalParameterName(pointer, index, name);
210 }
211
212 /**
213 * Set the name of a global parameter.
214 *
215 * @param index the index of the parameter for which to set the name
216 * @param name the name of the parameter
217 */
218 public void setGlobalParameterName(int index, Pointer name) {
219 OpenMM_CustomVolumeForce_setGlobalParameterName(pointer, index, name);
220 }
221
222 /**
223 * Returns whether or not this force makes use of periodic boundary conditions. Because this
224 * class is only applicable to periodic systems, this always returns true.
225 *
226 * @return true if the force uses periodic boundary conditions
227 */
228 @Override
229 public boolean usesPeriodicBoundaryConditions() {
230 int pbc = OpenMM_CustomVolumeForce_usesPeriodicBoundaryConditions(pointer);
231 return pbc == OpenMM_True;
232 }
233 }