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.drude;
39
40 import ffx.openmm.NoseHooverIntegrator;
41
42 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_computeDrudeKineticEnergy;
43 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_computeDrudeTemperature;
44 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_computeSystemTemperature;
45 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_computeTotalKineticEnergy;
46 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_create;
47 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_destroy;
48 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_getMaxDrudeDistance;
49 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeNoseHooverIntegrator_setMaxDrudeDistance;
50
51 /**
52 * This Integrator simulates systems that include Drude particles. It applies two different Nose-Hoover
53 * chain thermostats to the different parts of the system. The first is applied to ordinary particles (ones
54 * that are not part of a Drude particle pair), as well as to the center of mass of each Drude particle pair.
55 * A second thermostat, typically with a much lower temperature, is applied to the relative internal
56 * displacement of each pair.
57 * <p>
58 * This integrator can optionally set an upper limit on how far any Drude particle is ever allowed to
59 * get from its parent particle. This can sometimes help to improve stability. The limit is enforced
60 * with a hard wall constraint. By default the limit is set to 0.02 nm.
61 * <p>
62 * This Integrator requires the System to include a DrudeForce, which it uses to identify the Drude
63 * particles.
64 */
65 public class DrudeNoseHooverIntegrator extends NoseHooverIntegrator {
66
67 /**
68 * Create a DrudeNoseHooverIntegrator.
69 *
70 * @param stepSize the step size with which to integrator the system (in picoseconds)
71 * @param temperature the target temperature for the system (in Kelvin).
72 * @param drudeTemperature the target temperature for the Drude particles, relative to their parent atom (in Kelvin).
73 * @param frequency the frequency of the system's interaction with the heat bath (in inverse picoseconds).
74 * @param drudeFrequency the frequency of the drude particles' interaction with the heat bath (in inverse picoseconds).
75 * @param chainLength the number of beads in the Nose-Hoover chain.
76 * @param drudeChainLength the number of beads in the Nose-Hoover chain for Drude particles.
77 * @param numMTS the number of step in the multiple time step chain propagation algorithm.
78 */
79 public DrudeNoseHooverIntegrator(double stepSize, double temperature, double drudeTemperature,
80 double frequency, double drudeFrequency, int chainLength,
81 int drudeChainLength, int numMTS) {
82 super(OpenMM_DrudeNoseHooverIntegrator_create(stepSize, temperature, drudeTemperature,
83 frequency, drudeFrequency, chainLength, drudeChainLength, numMTS));
84 }
85
86 /**
87 * Compute the kinetic energy of the Drude particles.
88 * <p>
89 * This method calculates the total kinetic energy associated with the Drude particles
90 * in the system. This can be used to monitor the energy distribution between nuclear
91 * and electronic degrees of freedom during the simulation.
92 *
93 * @return The Drude kinetic energy in kJ/mol.
94 */
95 public double computeDrudeKineticEnergy() {
96 return OpenMM_DrudeNoseHooverIntegrator_computeDrudeKineticEnergy(pointer);
97 }
98
99 /**
100 * Compute the instantaneous temperature of the Drude particles.
101 * <p>
102 * This method calculates the current kinetic temperature of the Drude particles
103 * based on their velocities. This provides a measure of the thermal state
104 * of the electronic degrees of freedom in the system.
105 *
106 * @return The instantaneous Drude temperature in Kelvin.
107 */
108 public double computeDrudeTemperature() {
109 return OpenMM_DrudeNoseHooverIntegrator_computeDrudeTemperature(pointer);
110 }
111
112 /**
113 * Compute the instantaneous temperature of the real atoms.
114 * <p>
115 * This method calculates the current kinetic temperature of the real atoms
116 * based on their velocities. This provides a measure of the thermal state
117 * of the nuclear degrees of freedom in the system.
118 *
119 * @return The instantaneous system temperature in Kelvin.
120 */
121 public double computeSystemTemperature() {
122 return OpenMM_DrudeNoseHooverIntegrator_computeSystemTemperature(pointer);
123 }
124
125 /**
126 * Compute the total kinetic energy of the system.
127 * <p>
128 * This method calculates the total kinetic energy of all particles in the system,
129 * including both real atoms and Drude particles. This is useful for monitoring
130 * energy conservation and the overall thermal state of the system.
131 *
132 * @return The total kinetic energy in kJ/mol.
133 */
134 public double computeTotalKineticEnergy() {
135 return OpenMM_DrudeNoseHooverIntegrator_computeTotalKineticEnergy(pointer);
136 }
137
138 /**
139 * Destroy the integrator.
140 * <p>
141 * This method releases the memory associated with the DrudeNoseHooverIntegrator object.
142 * After calling this method, the integrator should not be used.
143 */
144 @Override
145 public void destroy() {
146 if (pointer != null) {
147 OpenMM_DrudeNoseHooverIntegrator_destroy(pointer);
148 pointer = null;
149 }
150 }
151
152 /**
153 * Get the maximum allowed distance between Drude particles and their parent atoms.
154 * <p>
155 * This method returns the constraint distance that limits how far Drude particles
156 * can move from their parent atoms. This constraint prevents the polarization
157 * from becoming unphysically large and maintains numerical stability.
158 *
159 * @return The maximum Drude distance in nanometers.
160 */
161 public double getMaxDrudeDistance() {
162 return OpenMM_DrudeNoseHooverIntegrator_getMaxDrudeDistance(pointer);
163 }
164
165 /**
166 * Set the maximum allowed distance between Drude particles and their parent atoms.
167 * <p>
168 * This method sets the constraint distance that limits how far Drude particles
169 * can move from their parent atoms. This constraint is essential for maintaining
170 * numerical stability and preventing unphysical polarization. A typical value
171 * is around 0.02 nm.
172 *
173 * @param distance The maximum Drude distance in nanometers.
174 */
175 public void setMaxDrudeDistance(double distance) {
176 OpenMM_DrudeNoseHooverIntegrator_setMaxDrudeDistance(pointer, distance);
177 }
178 }