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.potential.terms;
39  
40  import ffx.potential.bonded.BondedTerm;
41  import ffx.potential.bonded.TorsionTorsion;
42  
43  import java.util.ArrayList;
44  import java.util.Collection;
45  import java.util.Collections;
46  import java.util.List;
47  import java.util.logging.Logger;
48  
49  /**
50   * Torsion-Torsion potential energy term using {@link ffx.potential.bonded.TorsionTorsion} instances.
51   *
52   * @author Michael J. Schnieders
53   * @since 1.0
54   */
55  public class TorsionTorsionPotentialEnergy extends EnergyTerm {
56  
57    private static final Logger logger = Logger.getLogger(TorsionTorsionPotentialEnergy.class.getName());
58  
59  
60    /**
61     * Internal list of TorsionTorsion instances.
62     */
63    private final List<TorsionTorsion> torsionTorsions = new ArrayList<>();
64  
65    /**
66     * Create a TorsionTorsionPotentialEnergy with the provided name.
67     *
68     * @param name Name for this term.
69     */
70    public TorsionTorsionPotentialEnergy(String name) {
71      super(name);
72    }
73  
74    /**
75     * Create a TorsionTorsionPotentialEnergy with the provided name and force group.
76     *
77     * @param name       Name for this term.
78     * @param forceGroup Integer force group identifier.
79     */
80    public TorsionTorsionPotentialEnergy(String name, int forceGroup) {
81      super(name, forceGroup);
82    }
83  
84    /**
85     * Create a TorsionTorsionPotentialEnergy initialized with a list of terms and force group.
86     *
87     * @param name            Name for this term.
88     * @param forceGroup      Force group identifier.
89     * @param torsionTorsions List of TorsionTorsion instances to add (null-safe).
90     */
91    public TorsionTorsionPotentialEnergy(String name, int forceGroup, List<TorsionTorsion> torsionTorsions) {
92      super(name, forceGroup);
93      if (torsionTorsions != null) {
94        Collections.sort(torsionTorsions);
95        this.torsionTorsions.addAll(torsionTorsions);
96        logger.info(String.format("  Torsion-Torsions:                  %10d", getNumberOfTorsionTorsions()));
97      }
98    }
99  
100   /**
101    * {@inheritDoc}
102    */
103   @Override
104   public int getNumberOfTerms() {
105     return getNumberOfTorsionTorsions();
106   }
107 
108   /**
109    * {@inheritDoc}
110    */
111   @Override
112   public BondedTerm[] getBondedTermsArray() {
113     return getTorsionTorsionArray();
114   }
115 
116   /**
117    * Create a TorsionTorsionPotentialEnergy initialized with a collection of terms.
118    *
119    * @param name            Name for this term (may be null).
120    * @param torsionTorsions Collection of TorsionTorsion instances to add (null-safe).
121    */
122   public TorsionTorsionPotentialEnergy(String name, Collection<TorsionTorsion> torsionTorsions) {
123     super(name);
124     if (torsionTorsions != null) {
125       this.torsionTorsions.addAll(torsionTorsions);
126     }
127   }
128 
129   /**
130    * Add a TorsionTorsion to this term.
131    *
132    * @param torsionTorsion TorsionTorsion to add (ignored if null).
133    * @return true if it was added.
134    */
135   public boolean addTorsionTorsion(TorsionTorsion torsionTorsion) {
136     if (torsionTorsion == null) {
137       return false;
138     }
139     return torsionTorsions.add(torsionTorsion);
140   }
141 
142   /**
143    * Add an array of TorsionTorsions to this term.
144    *
145    * @param torsionTorsions Array of TorsionTorsion instances to add.
146    * @return true if they were added.
147    */
148   public boolean addTorsionTorsions(TorsionTorsion[] torsionTorsions) {
149     if (torsionTorsions == null) {
150       return false;
151     }
152     Collections.addAll(this.torsionTorsions, torsionTorsions);
153     return true;
154   }
155 
156   /**
157    * Add a list of TorsionTorsions to this term.
158    *
159    * @param torsionTorsions List of TorsionTorsion instances to add.
160    * @return true if they were added.
161    */
162   public boolean addTorsionTorsions(List<TorsionTorsion> torsionTorsions) {
163     if (torsionTorsions == null) {
164       return false;
165     }
166     this.torsionTorsions.addAll(torsionTorsions);
167     return true;
168   }
169 
170   /**
171    * Remove a TorsionTorsion from this term.
172    *
173    * @param torsionTorsion TorsionTorsion to remove (ignored if null).
174    * @return true if it was present and removed.
175    */
176   public boolean removeTorsionTorsion(TorsionTorsion torsionTorsion) {
177     if (torsionTorsion == null) {
178       return false;
179     }
180     return torsionTorsions.remove(torsionTorsion);
181   }
182 
183   /**
184    * Get the TorsionTorsion at a given index.
185    *
186    * @param index Index in the internal list.
187    * @return TorsionTorsion at the specified index.
188    * @throws IndexOutOfBoundsException if index is invalid.
189    */
190   public TorsionTorsion getTorsionTorsion(int index) {
191     return torsionTorsions.get(index);
192   }
193 
194   /**
195    * Get an unmodifiable view of the TorsionTorsions in this term.
196    *
197    * @return Unmodifiable List of TorsionTorsions.
198    */
199   public List<TorsionTorsion> getTorsionTorsions() {
200     return Collections.unmodifiableList(torsionTorsions);
201   }
202 
203   /**
204    * Get an array of TorsionTorsions in this term.
205    *
206    * @return Array of TorsionTorsions.
207    */
208   public TorsionTorsion[] getTorsionTorsionArray() {
209     return torsionTorsions.toArray(new TorsionTorsion[0]);
210   }
211 
212   /**
213    * Get the number of TorsionTorsions in this term.
214    *
215    * @return The number of TorsionTorsions.
216    */
217   public int getNumberOfTorsionTorsions() {
218     return torsionTorsions.size();
219   }
220 
221   /**
222    * Set the lambda value for all TorsionTorsions in this term.
223    *
224    * @param lambda The new lambda value to set.
225    */
226   public void setLambda(double lambda) {
227     for (TorsionTorsion torsionTorsion : torsionTorsions) {
228       torsionTorsion.setLambda(lambda);
229     }
230   }
231 
232   /**
233    * Get the energy contribution from all Torsion-Torsions in this term.
234    * @return Total energy from all Torsion-Torsions.
235    */
236   public double getdEdL() {
237     double dEdL = 0.0;
238     for (TorsionTorsion torsionTorsion : torsionTorsions) {
239       dEdL += torsionTorsion.getdEdL();
240     }
241     return dEdL;
242   }
243 
244   /**
245    * Get the energy contribution from all Torsion-Torsions in this term.
246    * @return Total energy from all Torsion-Torsions.
247    */
248   public double getd2EdL2() {
249     double d2EdLambda2 = 0.0;
250     for (TorsionTorsion torsionTorsion : torsionTorsions) {
251       d2EdLambda2 += torsionTorsion.getd2EdL2();
252     }
253     return d2EdLambda2;
254   }
255 
256   /**
257    * Log the details of Torsion-Torsion interactions.
258    */
259   @Override
260   public void log() {
261     if (getNumberOfTorsionTorsions() <= 0) {
262       return;
263     }
264     logger.info("\n Torsion-Torsion Interactions:");
265     for (TorsionTorsion torsionTorsion : getTorsionTorsions()) {
266       logger.info(" Torsion-Torsion \t" + torsionTorsion.toString());
267     }
268   }
269 
270   @Override
271   public String toPDBString() {
272     if (getNumberOfTorsionTorsions() <= 0) {
273       return "";
274     }
275     return String.format("REMARK   3   %s %g (%d)\n", "TORSION-TORSION            : ", getEnergy(), getNumberOfTorsionTorsions());
276   }
277 
278   @Override
279   public String toString() {
280     return String.format("  %s %20.8f %12d %12.3f\n", "Torsion-Torsion   ",
281         getEnergy(), getNumberOfTorsionTorsions(), getTime());
282   }
283 }