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 }