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 edu.rit.pj.reduction.SharedDouble;
41 import ffx.potential.bonded.BondedTerm;
42
43 import java.util.logging.Logger;
44
45 import static org.apache.commons.math3.util.FastMath.sqrt;
46
47 /**
48 * Base class for potential energy terms used by ForceFieldEnergy.
49 * <p>
50 * This abstract class holds minimal, common metadata shared by energy terms:
51 * a human-readable name and an integer force-group identifier. Specific energy
52 * terms (bonded, nonbonded, restraints, etc.) should extend this class.
53 */
54 public abstract class EnergyTerm {
55
56 private static final Logger logger = Logger.getLogger(EnergyTerm.class.getName());
57
58 /**
59 * Optional name for this energy term (for reporting/logging).
60 */
61 protected String name;
62
63 /**
64 * Integer force group this term belongs to. Defaults to 0.
65 */
66 protected int forceGroup = 0;
67
68 /**
69 * Total potential energy for this term.
70 */
71 protected SharedDouble energy = new SharedDouble();
72
73 /**
74 * Shared double for RMSD calculations.
75 */
76 private final SharedDouble sharedRMSD = new SharedDouble();
77
78 /**
79 * The time taken to compute the energy for this term in nanoseconds.
80 */
81 private long computeTime = 0L;
82
83 /**
84 * Create an unnamed EnergyTerm with default force group 0.
85 */
86 protected EnergyTerm() {
87 }
88
89 /**
90 * Create a named EnergyTerm with default force group 0.
91 *
92 * @param name Name for this energy term.
93 */
94 protected EnergyTerm(String name) {
95 this.name = name;
96 }
97
98 /**
99 * Create a named EnergyTerm with a specified force group.
100 *
101 * @param name Name for this energy term.
102 * @param forceGroup Integer force group identifier.
103 */
104 protected EnergyTerm(String name, int forceGroup) {
105 this.name = name;
106 this.forceGroup = forceGroup;
107 }
108
109 /**
110 * Get the number of BondedTerms in this term.
111 *
112 * @return The number of BondedTerms.
113 */
114 abstract public int getNumberOfTerms();
115
116 /**
117 * Get an array of BondedTerms in this term.
118 *
119 * @return Array of BondedTerms.
120 */
121 abstract public BondedTerm[] getBondedTermsArray();
122
123 /**
124 * Log the details of this energy term.
125 */
126 abstract public void log();
127
128 /**
129 * Get a string representation of this energy term.
130 *
131 * @return A string representation of the energy term.
132 */
133 abstract public String toString();
134
135 /**
136 * Get a PDB-style REMARK representation of this energy term.
137 * @return A PDB REMARK string for this energy term.
138 */
139 abstract public String toPDBString();
140
141 /**
142 * Get the current force group identifier.
143 *
144 * @return force group as an int
145 */
146 public int getForceGroup() {
147 return forceGroup;
148 }
149
150 /**
151 * Set the force group identifier.
152 *
153 * @param forceGroup integer force group
154 */
155 public void setForceGroup(int forceGroup) {
156 this.forceGroup = forceGroup;
157 }
158
159 /**
160 * Get the name of this energy term.
161 *
162 * @return name (may be null)
163 */
164 public String getName() {
165 return name;
166 }
167
168 /**
169 * Set the name of this energy term.
170 *
171 * @param name A human-readable name
172 */
173 public void setName(String name) {
174 this.name = name;
175 }
176
177 /**
178 * Get the total potential energy of this term.
179 *
180 * @return Energy value as a double.
181 */
182 public double getEnergy() {
183 return energy.get();
184 }
185
186 /**
187 * Set the total potential energy of this term.
188 *
189 * @param e Energy value to set.
190 */
191 protected void setEnergy(double e) {
192 energy.set(e);
193 }
194
195 /**
196 * Add energy to the total energy for this term and return the new total.
197 *
198 * @param e Energy value to add to the total.
199 * @return The new total energy after adding the provided energy.
200 */
201 protected double addAndGetEnergy(double e) {
202 return energy.addAndGet(e);
203 }
204
205 /**
206 * Set the RMSD accumulator value for this term.
207 *
208 * @param rmsd RMSD value to set for this term.
209 */
210 protected void setRMSD(double rmsd) {
211 sharedRMSD.set(rmsd);
212 }
213
214 /**
215 * Get the RMSD for this term.
216 */
217 public double getRMSD() {
218 return sqrt(sharedRMSD.get() / getNumberOfTerms());
219 }
220
221 /**
222 * Add RMSD to the shared RMSD and return the new total.
223 *
224 * @param rmsd RMSD value to add to the shared RMSD.
225 * @return The new total RMSD after adding the provided value.
226 */
227 protected double addAndGetRMSD(double rmsd) {
228 return sharedRMSD.addAndGet(rmsd);
229 }
230
231 /**
232 * Set the starting time for the energy computation.
233 */
234 protected void startTime() {
235 computeTime = -System.nanoTime();
236 }
237
238 /**
239 * Stop the timer for the energy computation.
240 */
241 public void stopTime() {
242 computeTime += System.nanoTime();
243 }
244
245 /**
246 * Get the time taken to compute the energy for this term in seconds.
247 *
248 * @return The time in seconds.
249 */
250 public double getTime() {
251 return computeTime * 1.0e-9;
252 }
253
254
255 }