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.StretchBend;
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  import static java.lang.String.format;
50  import static org.apache.commons.math3.util.FastMath.PI;
51  
52  /**
53   * Stretch-Bend potential energy term using {@link ffx.potential.bonded.StretchBend} instances.
54   *
55   * @author Michael J. Schnieders
56   * @since 1.0
57   */
58  public class StretchBendPotentialEnergy extends EnergyTerm {
59  
60    private static final Logger logger = Logger.getLogger(StretchBendPotentialEnergy.class.getName());
61  
62  
63    /**
64     * Internal list of StretchBend instances.
65     */
66    private final List<StretchBend> stretchBends = new ArrayList<>();
67  
68    /**
69     * Create a StretchBendPotentialEnergy with the provided name.
70     *
71     * @param name Name for this term.
72     */
73    public StretchBendPotentialEnergy(String name) {
74      super(name);
75    }
76  
77    /**
78     * Create a StretchBendPotentialEnergy with the provided name and force group.
79     *
80     * @param name       Name for this term.
81     * @param forceGroup Integer force group identifier.
82     */
83    public StretchBendPotentialEnergy(String name, int forceGroup) {
84      super(name, forceGroup);
85    }
86  
87    /**
88     * Create a StretchBendPotentialEnergy initialized with a list of stretch-bends and force group.
89     *
90     * @param name         Name for this term.
91     * @param forceGroup   Force group identifier.
92     * @param stretchBends List of StretchBend instances to add (null-safe).
93     */
94    public StretchBendPotentialEnergy(String name, int forceGroup, List<StretchBend> stretchBends) {
95      super(name, forceGroup);
96      if (stretchBends != null) {
97        Collections.sort(stretchBends);
98        this.stretchBends.addAll(stretchBends);
99        logger.info(format("  Stretch-Bends:                     %10d", getNumberOfStretchBends()));
100     }
101   }
102 
103   /**
104    * Get the number of terms in this potential energy term.
105    *
106    * @return The number of terms, which is the same as the number of stretch-bends.
107    */
108   @Override
109   public int getNumberOfTerms() {
110     return getNumberOfStretchBends();
111   }
112 
113   /**
114    * Get an array of BondedTerms in this term.
115    *
116    * @return Array of BondedTerms, which are actually StretchBends in this case.
117    */
118   @Override
119   public BondedTerm[] getBondedTermsArray() {
120     return getStretchBendArray();
121   }
122 
123   /**
124    * Create a StretchBendPotentialEnergy initialized with a collection of stretch-bends.
125    *
126    * @param name         Name for this term (may be null).
127    * @param stretchBends Collection of StretchBend instances to add (null-safe).
128    */
129   public StretchBendPotentialEnergy(String name, Collection<StretchBend> stretchBends) {
130     super(name);
131     if (stretchBends != null) {
132       this.stretchBends.addAll(stretchBends);
133     }
134   }
135 
136   /**
137    * Add a StretchBend to this term.
138    *
139    * @param stretchBend StretchBend to add (ignored if null).
140    * @return true if the stretch-bend was added.
141    */
142   public boolean addStretchBend(StretchBend stretchBend) {
143     if (stretchBend == null) {
144       return false;
145     }
146     return stretchBends.add(stretchBend);
147   }
148 
149   /**
150    * Add an array of StretchBends to this term.
151    *
152    * @param stretchBends Array of StretchBend instances to add.
153    * @return true if the stretch-bends were added.
154    */
155   public boolean addStretchBends(StretchBend[] stretchBends) {
156     if (stretchBends == null) {
157       return false;
158     }
159     Collections.addAll(this.stretchBends, stretchBends);
160     return true;
161   }
162 
163   /**
164    * Add a list of StretchBends to this term.
165    *
166    * @param stretchBends List of StretchBend instances to add.
167    * @return true if the stretch-bends were added.
168    */
169   public boolean addStretchBends(List<StretchBend> stretchBends) {
170     if (stretchBends == null) {
171       return false;
172     }
173     this.stretchBends.addAll(stretchBends);
174     return true;
175   }
176 
177   /**
178    * Remove a StretchBend from this term.
179    *
180    * @param stretchBend StretchBend to remove (ignored if null).
181    * @return true if the stretch-bend was present and removed.
182    */
183   public boolean removeStretchBend(StretchBend stretchBend) {
184     if (stretchBend == null) {
185       return false;
186     }
187     return stretchBends.remove(stretchBend);
188   }
189 
190   /**
191    * Get the StretchBend at a given index.
192    *
193    * @param index Index in the internal list.
194    * @return StretchBend at the specified index.
195    * @throws IndexOutOfBoundsException if index is invalid.
196    */
197   public StretchBend getStretchBend(int index) {
198     return stretchBends.get(index);
199   }
200 
201   /**
202    * Get an unmodifiable view of the StretchBends in this term.
203    *
204    * @return Unmodifiable List of StretchBends.
205    */
206   public List<StretchBend> getStretchBends() {
207     return Collections.unmodifiableList(stretchBends);
208   }
209 
210   /**
211    * Get an array of StretchBends in this term.
212    *
213    * @return Array of StretchBends.
214    */
215   public StretchBend[] getStretchBendArray() {
216     return stretchBends.toArray(new StretchBend[0]);
217   }
218 
219   /**
220    * Get the number of StretchBends in this term.
221    *
222    * @return The number of StretchBends.
223    */
224   public int getNumberOfStretchBends() {
225     return stretchBends.size();
226   }
227 
228   /**
229    * Get a formatted string representing the energy expression for Stretch-Bend interactions.
230    * @return String representing the Stretch-Bend energy expression.
231    */
232   public static String getStretchBendEnergyString() {
233     return format("(k1*(distance(p1,p2)-r12) + k2*(distance(p2,p3)-r23))*(%.15g*(angle(p1,p2,p3)-theta0))", 180.0 / PI);
234   }
235 
236   /**
237    * Log the details of Stretch-Bend interactions.
238    */
239   @Override
240   public void log() {
241     if (getNumberOfStretchBends() <= 0) {
242       return;
243     }
244     logger.info("\n Stretch-Bend Interactions:");
245     for (StretchBend stretchBend : getStretchBends()) {
246       logger.info(" Stretch-Bend \t" + stretchBend.toString());
247     }
248   }
249 
250   @Override
251   public String toPDBString() {
252     if (getNumberOfStretchBends() <= 0) {
253       return "";
254     }
255     return format("REMARK   3   %s %g (%d)\n", "STRETCH-BEND               : ", getEnergy(), getNumberOfStretchBends());
256   }
257 
258   @Override
259   public String toString() {
260     return format("  %s %20.8f %12d %12.3f\n", "Stretch-Bend      ",
261         getEnergy(), getNumberOfStretchBends(), getTime());
262   }
263 
264 }