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