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