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-2024.
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.potential.openmm;
39  
40  import ffx.openmm.Integrator;
41  import ffx.openmm.LangevinIntegrator;
42  import ffx.openmm.VerletIntegrator;
43  import ffx.potential.parameters.ForceField;
44  import org.apache.commons.configuration2.CompositeConfiguration;
45  
46  import java.util.logging.Logger;
47  
48  import static ffx.potential.ForceFieldEnergy.DEFAULT_CONSTRAINT_TOLERANCE;
49  import static java.lang.String.format;
50  
51  /**
52   * Create and manage an OpenMM Integrator.
53   *
54   * <p>An Integrator defines a method for simulating a System by integrating the equations of
55   * motion.
56   *
57   * <p>Each Integrator object is bound to a particular Context which it integrates. This connection
58   * is specified by passing the Integrator as an argument to the constructor of the Context.
59   */
60  public class OpenMMIntegrator {
61  
62    private static final Logger logger = Logger.getLogger(OpenMMIntegrator.class.getName());
63  
64    /**
65     * Constraint tolerance as a fraction of the constrained bond length.
66     */
67    private final static double constraintTolerance = DEFAULT_CONSTRAINT_TOLERANCE;
68  
69    /**
70     * Prevent instantiation.
71     */
72    private OpenMMIntegrator() {
73  
74    }
75  
76    /**
77     * Create a integrator.
78     *
79     * @param name Name of the integrator to use.
80     * @param timeStep         Time step (psec).
81     * @param temperature      Target temperature (kelvin).
82     * @param openMMSystem     OpenMM System.
83     * @return Integrator reference.
84     */
85    public static Integrator createIntegrator(String name, double timeStep, double temperature, OpenMMSystem openMMSystem) {
86      switch (name) {
87        default -> {
88          return createVerletIntegrator(timeStep);
89        }
90        case "LANGEVIN" -> {
91          return createLangevinIntegrator(timeStep, temperature, openMMSystem.getForceField());
92        }
93        case "MTS" -> {
94          return createCustomMTSIntegrator(timeStep, openMMSystem);
95        }
96        case "LANGEVIN-MTS" -> {
97          return createCustomMTSLangevinIntegrator(timeStep, temperature, openMMSystem);
98        }
99      }
100   }
101 
102   /**
103    * Create a Langevin integrator.
104    *
105    * @param dt          Time step (psec).
106    * @param temperature Temperature (K).
107    * @param forceField  Force field.
108    */
109   public static LangevinIntegrator createLangevinIntegrator(double dt, double temperature, ForceField forceField) {
110     CompositeConfiguration properties = forceField.getProperties();
111     int seed = 0;
112     if (properties.containsKey("integrator-seed")) {
113       seed = properties.getInt("integrator-seed", 0);
114     }
115     double frictionCoeff = forceField.getDouble("FRICTION_COEFF", 91.0);
116     LangevinIntegrator langevinIntegrator = new LangevinIntegrator(dt, temperature, frictionCoeff);
117     langevinIntegrator.setRandomNumberSeed(seed);
118     langevinIntegrator.setConstraintTolerance(constraintTolerance);
119     logger.info("  Langevin Integrator");
120     logger.info(format("  Target Temperature:   %6.2f (K)", temperature));
121     logger.info(format("  Friction Coefficient: %6.2f (1/psec)", frictionCoeff));
122     logger.info(format("  Time step:            %6.2f (fsec)", dt * 1000));
123     return langevinIntegrator;
124   }
125 
126   /**
127    * Create a Custom MTS Integrator.
128    *
129    * @param dt The outer time step (psec).
130    */
131   public static CustomMTSIntegrator createCustomMTSIntegrator(double dt, OpenMMSystem openMMSystem) {
132     return new CustomMTSIntegrator(dt, constraintTolerance, openMMSystem.hasAmoebaCavitationForce());
133   }
134 
135 
136   /**
137    * Create a Custom MTS Langevin integrator.
138    *
139    * @param dt           The outer time step (psec).
140    * @param temperature  The target temperature (K).
141    * @param openMMSystem OpenMM System.
142    */
143   public static CustomMTSLangevinIntegrator createCustomMTSLangevinIntegrator(double dt, double temperature, OpenMMSystem openMMSystem) {
144 
145     ForceField forceField = openMMSystem.getForceField();
146     double frictionCoeff = forceField.getDouble("FRICTION_COEFF", 91.0);
147     CustomMTSLangevinIntegrator customMTSLangevinIntegrator =
148         new CustomMTSLangevinIntegrator(dt, temperature, frictionCoeff, openMMSystem.hasAmoebaCavitationForce());
149     return customMTSLangevinIntegrator;
150   }
151 
152   /**
153    * Create a Verlet integrator.
154    *
155    * @param dt Time step (psec).
156    */
157   public static VerletIntegrator createVerletIntegrator(double dt) {
158     VerletIntegrator verletIntegrator = new VerletIntegrator(dt);
159     verletIntegrator.setConstraintTolerance(constraintTolerance);
160     logger.info("  Verlet Integrator");
161     logger.info(format("  Time step:            %6.2f (fsec)", dt * 1000));
162     return verletIntegrator;
163   }
164 
165 }