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