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.CustomIntegrator; 41 42 import java.util.logging.Logger; 43 44 import static java.lang.String.format; 45 import static java.util.Arrays.copyOfRange; 46 47 /** 48 * OpenMM Custom MTS Integrator. 49 */ 50 public class CustomMTSIntegrator extends CustomIntegrator { 51 52 private static final Logger logger = Logger.getLogger(CustomMTSIntegrator.class.getName()); 53 54 public CustomMTSIntegrator(double dt, double constraintTolerance, boolean hasAmoebaCavitationForce) { 55 super(dt); 56 setConstraintTolerance(constraintTolerance); 57 58 int n = 4; 59 // Force group 1 contains slowly varying forces. 60 // Force group 0 contains the fast varying forces. 61 int[] forceGroups = {1, 0}; 62 // There will be 1 force evaluation per outer step, and 4 per inner step. 63 int[] subSteps = {1, 4}; 64 if (hasAmoebaCavitationForce) { 65 n = 8; 66 // Force group 2 contains the cavitation force. 67 // Force group 1 contains slowly varying forces. 68 // Force group 0 contains the fast varying forces. 69 forceGroups = new int[]{2, 1, 0}; 70 // There will be 1 force evaluation per outer step. 71 // There will be 2 force evaluations per middle step. 72 // There will be 8 force evaluations per inner step. 73 subSteps = new int[]{1, 2, 8}; 74 } 75 76 addPerDofVariable("x1", 0.0); 77 addUpdateContextState(); 78 createMTSSubStep(1, forceGroups, subSteps); 79 addConstrainVelocities(); 80 logger.info(" Custom MTS Integrator"); 81 logger.info(format(" Time step: %6.2f (fsec)", dt * 1000)); 82 logger.info(format(" Inner Time step: %6.2f (fsec)", dt / n * 1000)); 83 } 84 85 /** 86 * Create substeps for the MTS CustomIntegrator. 87 * 88 * @param parentSubsteps The number of substeps for the previous force group. 89 * @param forceGroups The force groups to be evaluated. 90 * @param subSteps The number of substeps for each force group. 91 */ 92 public void createMTSSubStep(int parentSubsteps, int[] forceGroups, int[] subSteps) { 93 int forceGroup = forceGroups[0]; 94 int steps = subSteps[0]; 95 int stepsPerParentStep = steps / parentSubsteps; 96 if (stepsPerParentStep < 1 || steps % parentSubsteps != 0) { 97 throw new IllegalArgumentException( 98 "The number for substeps for each group must be a multiple of the number for the previous group"); 99 } 100 if (forceGroup < 0 || forceGroup > 31) { 101 throw new IllegalArgumentException("Force group must be between 0 and 31"); 102 } 103 for (int i = 0; i < stepsPerParentStep; i++) { 104 addComputePerDof("v", "v+0.5*(dt/" + steps + ")*f" + forceGroup + "/m"); 105 if (forceGroups.length == 1) { 106 addComputePerDof("x", "x+(dt/" + steps + ")*v"); 107 addComputePerDof("x1", "x"); 108 addConstrainPositions(); 109 addComputePerDof("v", "v+(x-x1)/(dt/" + steps + ")"); 110 addConstrainVelocities(); 111 } else { 112 createMTSSubStep(steps, copyOfRange(forceGroups, 1, forceGroups.length), 113 copyOfRange(subSteps, 1, subSteps.length)); 114 } 115 addComputePerDof("v", "v+0.5*(dt/" + steps + ")*f" + forceGroup + "/m"); 116 } 117 } 118 }