View Javadoc
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 }