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