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_NoseHooverIntegrator_addSubsystemThermostat;
43 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_addThermostat;
44 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_computeHeatBathEnergy;
45 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_create;
46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_create_2;
47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_destroy;
48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getCollisionFrequency;
49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getMaximumPairDistance;
50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getNumThermostats;
51 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getRelativeCollisionFrequency;
52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getRelativeTemperature;
53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getTemperature;
54 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_getThermostat;
55 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_hasSubsystemThermostats;
56 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_setCollisionFrequency;
57 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_setMaximumPairDistance;
58 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_setRelativeCollisionFrequency;
59 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_setRelativeTemperature;
60 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_setTemperature;
61 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NoseHooverIntegrator_step;
62
63 /**
64 * This is an Integrator which simulates a System using one or more Nose Hoover chain
65 * thermostats, using the "middle" leapfrog propagation algorithm described in
66 * J. Phys. Chem. A 2019, 123, 6056-6079.
67 */
68 public class NoseHooverIntegrator extends Integrator {
69
70 /**
71 * Create a NoseHooverIntegrator with a single thermostat.
72 *
73 * @param pointer A pointer to the native OpenMM NoseHooverIntegrator object.
74 */
75 public NoseHooverIntegrator(PointerByReference pointer) {
76 super(pointer);
77 }
78
79 /**
80 * Create a NoseHooverIntegrator with a single thermostat.
81 *
82 * @param stepSize The step size with which to integrate the system (in ps).
83 */
84 public NoseHooverIntegrator(double stepSize) {
85 super(OpenMM_NoseHooverIntegrator_create(stepSize));
86 }
87
88 /**
89 * Create a NoseHooverIntegrator with detailed thermostat parameters.
90 *
91 * @param stepSize The step size with which to integrate the system (in ps).
92 * @param temperature The temperature of the heat bath (in Kelvin).
93 * @param collisionFrequency The collision frequency (in 1/ps).
94 * @param numMTS The number of multiple time step levels.
95 * @param numYoshidaSuzuki The number of Yoshida-Suzuki steps.
96 * @param numNoseHoover The number of Nosé-Hoover chain thermostats.
97 */
98 public NoseHooverIntegrator(double stepSize, double temperature, double collisionFrequency,
99 int numMTS, int numYoshidaSuzuki, int numNoseHoover) {
100 super(OpenMM_NoseHooverIntegrator_create_2(stepSize, temperature, collisionFrequency,
101 numMTS, numYoshidaSuzuki, numNoseHoover));
102 }
103
104 /**
105 * Add a subsystem thermostat to the integrator.
106 *
107 * @param particles The particles to be controlled by this thermostat.
108 * @param chainWeights The weights for the thermostat chain.
109 * @param temperature The temperature for this thermostat (in Kelvin).
110 * @param collisionFrequency The collision frequency for this thermostat (in 1/ps).
111 * @param relativeTemperature The relative temperature scaling factor.
112 * @param relativeCollisionFrequency The relative collision frequency scaling factor.
113 * @param numMTS The number of multiple time step levels.
114 * @param numYoshidaSuzuki The number of Yoshida-Suzuki steps.
115 * @param numNoseHoover The number of Nosé-Hoover chain thermostats.
116 * @return The index of the thermostat that was added.
117 */
118 public int addSubsystemThermostat(PointerByReference particles, PointerByReference chainWeights,
119 double temperature, double collisionFrequency,
120 double relativeTemperature, double relativeCollisionFrequency,
121 int numMTS, int numYoshidaSuzuki, int numNoseHoover) {
122 return OpenMM_NoseHooverIntegrator_addSubsystemThermostat(pointer, particles, chainWeights,
123 temperature, collisionFrequency,
124 relativeTemperature, relativeCollisionFrequency,
125 numMTS, numYoshidaSuzuki, numNoseHoover);
126 }
127
128 /**
129 * Add a thermostat to the integrator.
130 *
131 * @param temperature The temperature for this thermostat (in Kelvin).
132 * @param collisionFrequency The collision frequency for this thermostat (in 1/ps).
133 * @param numMTS The number of multiple time step levels.
134 * @param numYoshidaSuzuki The number of Yoshida-Suzuki steps.
135 * @param numNoseHoover The number of Nosé-Hoover chain thermostats.
136 * @return The index of the thermostat that was added.
137 */
138 public int addThermostat(double temperature, double collisionFrequency,
139 int numMTS, int numYoshidaSuzuki, int numNoseHoover) {
140 return OpenMM_NoseHooverIntegrator_addThermostat(pointer, temperature, collisionFrequency,
141 numMTS, numYoshidaSuzuki, numNoseHoover);
142 }
143
144 /**
145 * Compute the total energy of all heat baths.
146 *
147 * @return The total heat bath energy.
148 */
149 public double computeHeatBathEnergy() {
150 return OpenMM_NoseHooverIntegrator_computeHeatBathEnergy(pointer);
151 }
152
153 /**
154 * Destroy the integrator.
155 */
156 @Override
157 public void destroy() {
158 if (pointer != null) {
159 OpenMM_NoseHooverIntegrator_destroy(pointer);
160 pointer = null;
161 }
162 }
163
164 /**
165 * Get the collision frequency for a thermostat.
166 *
167 * @param thermostat The index of the thermostat.
168 * @return The collision frequency (in 1/ps).
169 */
170 public double getCollisionFrequency(int thermostat) {
171 return OpenMM_NoseHooverIntegrator_getCollisionFrequency(pointer, thermostat);
172 }
173
174 /**
175 * Get the maximum pair distance for neighbor list updates.
176 *
177 * @return The maximum pair distance (in nm).
178 */
179 public double getMaximumPairDistance() {
180 return OpenMM_NoseHooverIntegrator_getMaximumPairDistance(pointer);
181 }
182
183 /**
184 * Get the number of thermostats.
185 *
186 * @return The number of thermostats.
187 */
188 public int getNumThermostats() {
189 return OpenMM_NoseHooverIntegrator_getNumThermostats(pointer);
190 }
191
192 /**
193 * Get the relative collision frequency for a thermostat.
194 *
195 * @param thermostat The index of the thermostat.
196 * @return The relative collision frequency scaling factor.
197 */
198 public double getRelativeCollisionFrequency(int thermostat) {
199 return OpenMM_NoseHooverIntegrator_getRelativeCollisionFrequency(pointer, thermostat);
200 }
201
202 /**
203 * Get the relative temperature for a thermostat.
204 *
205 * @param thermostat The index of the thermostat.
206 * @return The relative temperature scaling factor.
207 */
208 public double getRelativeTemperature(int thermostat) {
209 return OpenMM_NoseHooverIntegrator_getRelativeTemperature(pointer, thermostat);
210 }
211
212 /**
213 * Get the temperature for a thermostat.
214 *
215 * @param thermostat The index of the thermostat.
216 * @return The temperature (in Kelvin).
217 */
218 public double getTemperature(int thermostat) {
219 return OpenMM_NoseHooverIntegrator_getTemperature(pointer, thermostat);
220 }
221
222 /**
223 * Get a reference to a thermostat.
224 *
225 * @param thermostat The index of the thermostat.
226 * @return A reference to the thermostat object.
227 */
228 public PointerByReference getThermostat(int thermostat) {
229 return OpenMM_NoseHooverIntegrator_getThermostat(pointer, thermostat);
230 }
231
232 /**
233 * Check if the integrator has subsystem thermostats.
234 *
235 * @return 1 if subsystem thermostats are present, 0 otherwise.
236 */
237 public int hasSubsystemThermostats() {
238 return OpenMM_NoseHooverIntegrator_hasSubsystemThermostats(pointer);
239 }
240
241 /**
242 * Set the collision frequency for a thermostat.
243 *
244 * @param collisionFrequency The collision frequency (in 1/ps).
245 * @param thermostat The index of the thermostat.
246 */
247 public void setCollisionFrequency(double collisionFrequency, int thermostat) {
248 OpenMM_NoseHooverIntegrator_setCollisionFrequency(pointer, collisionFrequency, thermostat);
249 }
250
251 /**
252 * Set the maximum pair distance for neighbor list updates.
253 *
254 * @param distance The maximum pair distance (in nm).
255 */
256 public void setMaximumPairDistance(double distance) {
257 OpenMM_NoseHooverIntegrator_setMaximumPairDistance(pointer, distance);
258 }
259
260 /**
261 * Set the relative collision frequency for a thermostat.
262 *
263 * @param relativeCollisionFrequency The relative collision frequency scaling factor.
264 * @param thermostat The index of the thermostat.
265 */
266 public void setRelativeCollisionFrequency(double relativeCollisionFrequency, int thermostat) {
267 OpenMM_NoseHooverIntegrator_setRelativeCollisionFrequency(pointer, relativeCollisionFrequency, thermostat);
268 }
269
270 /**
271 * Set the relative temperature for a thermostat.
272 *
273 * @param relativeTemperature The relative temperature scaling factor.
274 * @param thermostat The index of the thermostat.
275 */
276 public void setRelativeTemperature(double relativeTemperature, int thermostat) {
277 OpenMM_NoseHooverIntegrator_setRelativeTemperature(pointer, relativeTemperature, thermostat);
278 }
279
280 /**
281 * Set the temperature for a thermostat.
282 *
283 * @param temperature The temperature (in Kelvin).
284 * @param thermostat The index of the thermostat.
285 */
286 public void setTemperature(double temperature, int thermostat) {
287 OpenMM_NoseHooverIntegrator_setTemperature(pointer, temperature, thermostat);
288 }
289
290 /**
291 * Advance a simulation through time by taking a series of time steps.
292 *
293 * @param steps The number of time steps to take.
294 */
295 public void step(int steps) {
296 OpenMM_NoseHooverIntegrator_step(pointer, steps);
297 }
298 }