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.DoubleArray;
41  import ffx.openmm.Force;
42  import ffx.openmm.IntArray;
43  import ffx.openmm.CustomCompoundBondForce;
44  import ffx.potential.bonded.Atom;
45  import ffx.potential.bonded.StretchTorsion;
46  
47  import java.util.logging.Level;
48  import java.util.logging.Logger;
49  
50  import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_KJPerKcal;
51  import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_NmPerAngstrom;
52  import static java.lang.String.format;
53  
54  /**
55   * OpenMM Stretch-Torsion Force.
56   */
57  public class StretchTorsionForce extends CustomCompoundBondForce {
58  
59    private static final Logger logger = Logger.getLogger(StretchTorsionForce.class.getName());
60  
61    /**
62     * Create an OpenMM Stretch-Torsion Force.
63     *
64     * @param openMMEnergy The OpenMM Energy instance that contains the Stretch-Torsions.
65     */
66    public StretchTorsionForce(OpenMMEnergy openMMEnergy) {
67      super(4, StretchTorsion.stretchTorsionForm());
68      StretchTorsion[] stretchTorsions = openMMEnergy.getStretchTorsions();
69      if (stretchTorsions == null || stretchTorsions.length < 1) {
70        return;
71      }
72  
73      addGlobalParameter("phi1", 0);
74      addGlobalParameter("phi2", Math.PI);
75      addGlobalParameter("phi3", 0);
76      for (int m = 1; m < 4; m++) {
77        for (int n = 1; n < 4; n++) {
78          addPerBondParameter(format("k%d%d", m, n));
79        }
80      }
81      for (int m = 1; m < 4; m++) {
82        addPerBondParameter(format("b%d", m));
83      }
84  
85      final double unitConv = OpenMM_KJPerKcal / OpenMM_NmPerAngstrom;
86  
87      for (StretchTorsion stretchTorsion : stretchTorsions) {
88        double[] constants = stretchTorsion.getConstants();
89        DoubleArray parameters = new DoubleArray(0);
90        for (int m = 0; m < 3; m++) {
91          for (int n = 0; n < 3; n++) {
92            int index = (3 * m) + n;
93            parameters.append(constants[index] * unitConv);
94          }
95        }
96        parameters.append(stretchTorsion.bondType1.distance * OpenMM_NmPerAngstrom);
97        parameters.append(stretchTorsion.bondType2.distance * OpenMM_NmPerAngstrom);
98        parameters.append(stretchTorsion.bondType3.distance * OpenMM_NmPerAngstrom);
99  
100       IntArray particles = new IntArray(0);
101       Atom[] atoms = stretchTorsion.getAtomArray(true);
102       for (int i = 0; i < 4; i++) {
103         particles.append(atoms[i].getXyzIndex() - 1);
104       }
105 
106       addBond(particles, parameters);
107       parameters.destroy();
108       particles.destroy();
109     }
110 
111     int forceGroup = openMMEnergy.getMolecularAssembly().getForceField().getInteger("STRETCH_TORSION_FORCE_GROUP", 0);
112     setForceGroup(forceGroup);
113     logger.log(Level.INFO, format("  Stretch-Torsions  \t%6d\t\t%1d", stretchTorsions.length, forceGroup));
114   }
115 
116   /**
117    * Convenience method to construct an OpenMM Stretch-Torsion Force.
118    *
119    * @param openMMEnergy The OpenMM Energy instance that contains the stretch-torsions.
120    * @return An OpenMM Stretch-Bend Force, or null if there are no stretch-torsion.
121    */
122   public static Force constructForce(OpenMMEnergy openMMEnergy) {
123     StretchTorsion[] stretchTorsions = openMMEnergy.getStretchTorsions();
124     if (stretchTorsions == null || stretchTorsions.length < 1) {
125       return null;
126     }
127     return new StretchTorsionForce(openMMEnergy);
128   }
129 }