1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2023.
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.groovy;
39  
40  import static org.apache.commons.math3.util.FastMath.floor;
41  import static org.apache.commons.math3.util.FastMath.random;
42  import static org.junit.Assert.assertEquals;
43  
44  import ffx.potential.ForceFieldEnergy;
45  import ffx.potential.groovy.Energy;
46  import ffx.potential.groovy.test.Gradient;
47  import ffx.potential.groovy.test.LambdaGradient;
48  import ffx.potential.utils.PotentialTest;
49  import java.util.Arrays;
50  import java.util.Collection;
51  import org.junit.Test;
52  import org.junit.runner.RunWith;
53  import org.junit.runners.Parameterized;
54  import org.junit.runners.Parameterized.Parameters;
55  
56  /** Test OPLS-AA energy and gradient. */
57  @RunWith(Parameterized.class)
58  public class OPLSEnergyTest extends PotentialTest {
59  
60    private final String info;
61    private final String filename;
62    private final int nAtoms;
63    private final int nBonds;
64    private final int nAngles;
65    private final int nTorsions;
66    private final int nImproperTorsions;
67    private final int nVanDerWaals;
68    private final int nPermanent;
69    private final double bondEnergy;
70    private final double angleEnergy;
71    private final double torsionEnergy;
72    private final double improperTorsionEnergy;
73    private final double vanDerWaalsEnergy;
74    private final double permanentEnergy;
75    private final double tolerance = 1.0e-2;
76  
77    public OPLSEnergyTest(
78        String info,
79        String filename,
80        int nAtoms,
81        double bondEnergy,
82        int nBonds,
83        double angleEnergy,
84        int nAngles,
85        double torsionEnergy,
86        int nTorsions,
87        double improperTorsionEnergy,
88        int nImproperTorsions,
89        double vanDerWaalsEnergy,
90        int nVanDerWaals,
91        double permanentEnergy,
92        int nPermanent) {
93  
94      this.info = info;
95      this.filename = filename;
96      this.nAtoms = nAtoms;
97      this.bondEnergy = bondEnergy;
98      this.nBonds = nBonds;
99      this.angleEnergy = angleEnergy;
100     this.nAngles = nAngles;
101     this.torsionEnergy = torsionEnergy;
102     this.nTorsions = nTorsions;
103     this.improperTorsionEnergy = improperTorsionEnergy;
104     this.nImproperTorsions = nImproperTorsions;
105     this.vanDerWaalsEnergy = vanDerWaalsEnergy;
106     this.nVanDerWaals = nVanDerWaals;
107     this.permanentEnergy = permanentEnergy;
108     this.nPermanent = nPermanent;
109   }
110 
111   @Parameters
112   public static Collection<Object[]> data() {
113     return Arrays.asList(
114         new Object[][] {
115             {
116                 "OPLS Acetanilide Benchmark",
117                 "ffx/potential/structures/acetanilide-oplsaa.xyz",
118                 19,
119                 0.45009773,
120                 19,
121                 1.99659439,
122                 30,
123                 3.12713717,
124                 38,
125                 0.03415131,
126                 12,
127                 -10.22874283,
128                 7293,
129                 -24.11087720,
130                 2229
131             },
132             {
133                 "OPLS Ethylparaben Benchmark",
134                 "ffx/potential/structures/ethylparaben-oplsaa.xyz",
135                 44,
136                 1.23483793,
137                 44,
138                 1.17950432,
139                 70,
140                 0.58946840,
141                 88,
142                 0.01347012,
143                 22,
144                 -23.22505628,
145                 16759,
146                 -28.45972542,
147                 5029
148             },
149             {
150                 "OPLS Methylparaben Benchmark",
151                 "ffx/potential/structures/methylparaben-oplsaa.xyz",
152                 19,
153                 0.48582171,
154                 19,
155                 0.47331501,
156                 29,
157                 0.53855046,
158                 35,
159                 0.02598434,
160                 11,
161                 -8.71533364,
162                 7647,
163                 -16.384524645738537,
164                 2302
165             },
166             {
167                 "OPLS Paracetamol Benchmark",
168                 "ffx/potential/structures/paracetamol-oplsaa.xyz",
169                 20,
170                 0.63722563,
171                 20,
172                 2.63545869,
173                 31,
174                 3.01547224,
175                 40,
176                 0.06569712,
177                 10,
178                 -9.45895598,
179                 7831,
180                 -41.34298872,
181                 3334
182             },
183             {
184                 "OPLS Phenacetin Benchmark",
185                 "ffx/potential/structures/phenacetin-oplsaa.xyz",
186                 26,
187                 0.53495810,
188                 26,
189                 3.68523677,
190                 43,
191                 4.12682233,
192                 52,
193                 0.03932507,
194                 10,
195                 -14.31979877,
196                 10338,
197                 -31.561832525438113,
198                 3116
199             }
200         });
201   }
202 
203   @Test
204   public void testEnergy() {
205     logger.info(" Testing energy for " + info);
206 
207     // Set-up the input arguments for the Energy script.
208     String[] args = {"src/main/java/" + filename};
209     binding.setVariable("args", args);
210 
211     // Evaluate the script.
212     Energy energy = new Energy(binding).run();
213     potentialScript = energy;
214 
215     ForceFieldEnergy forceFieldEnergy = energy.forceFieldEnergy;
216 
217     // Bond Energy
218     assertEquals(info + " Bond Energy", bondEnergy, forceFieldEnergy.getBondEnergy(), tolerance);
219     assertEquals(info + " Bond Count", nBonds, forceFieldEnergy.getNumberofBonds());
220     // Angle Energy
221     assertEquals(info + " Angle Energy", angleEnergy, forceFieldEnergy.getAngleEnergy(), tolerance);
222     assertEquals(info + " Angle Count", nAngles, forceFieldEnergy.getNumberofAngles());
223     // Torsional Angle
224     assertEquals(
225         info + " Torsion Energy", torsionEnergy, forceFieldEnergy.getTorsionEnergy(), tolerance);
226     assertEquals(info + " Torsion Count", nTorsions, forceFieldEnergy.getNumberofTorsions());
227     // Improper Torsional Angle
228     assertEquals(
229         info + " Improper Torsion Energy",
230         improperTorsionEnergy,
231         forceFieldEnergy.getImproperTorsionEnergy(),
232         tolerance);
233     assertEquals(
234         info + " Improper Torsion Count",
235         nImproperTorsions,
236         forceFieldEnergy.getNumberofImproperTorsions());
237     // van Der Waals
238     assertEquals(
239         info + " van Der Waals Energy",
240         vanDerWaalsEnergy,
241         forceFieldEnergy.getVanDerWaalsEnergy(),
242         tolerance);
243     assertEquals(
244         info + " van Der Waals Count", nVanDerWaals, forceFieldEnergy.getVanDerWaalsInteractions());
245     // Permanent Multipoles
246     assertEquals(
247         info + " Permanent Multipole Energy",
248         permanentEnergy,
249         forceFieldEnergy.getPermanentMultipoleEnergy(),
250         tolerance);
251     assertEquals(
252         info + " Permanent Multipole Count",
253         nPermanent,
254         forceFieldEnergy.getPermanentInteractions());
255   }
256 
257   @Test
258   public void testGradient() {
259     logger.info(" Testing Cartesian gradient(s) for " + info);
260 
261     // Set-up the input arguments for the Gradient script.
262     // Choose a random atom to test.
263     int atomID = (int) floor(random() * nAtoms) + 1;
264     double stepSize = 1.0e-5;
265     String[] args = {"--ga", Integer.toString(atomID),
266         "--dx", Double.toString(stepSize),
267         "src/main/java/" + filename
268     };
269     binding.setVariable("args", args);
270 
271     // Construct and evaluate the script.
272     Gradient gradient = new Gradient(binding).run();
273     potentialScript = gradient;
274 
275     assertEquals(info + " gradient failures: ", 0, gradient.nFailures);
276   }
277 
278   @Test
279   public void testLambdaGradient() {
280     logger.info(" Testing lambda gradient(s) for " + info);
281 
282     // Set-up the input arguments for the LambdaGradient script.
283     // Choose a random atom to test dEdX gradient.
284     int atomID = (int) floor(random() * nAtoms) + 1;
285     double stepSize = 1.0e-5;
286     String[] args = {
287         "--ga", Integer.toString(atomID),
288         "--dx", Double.toString(stepSize),
289         "--tol", Double.toString(tolerance),
290         "--ac", "1" + "-" + nAtoms,
291         "-l", "0.5",
292         "src/main/java/" + filename
293     };
294     binding.setVariable("args", args);
295 
296     // Construct and evaluate the script.
297     LambdaGradient lambdaGradient = new LambdaGradient(binding).run();
298     potentialScript = lambdaGradient;
299 
300     assertEquals(info + " dEdL failures: ", 0, lambdaGradient.ndEdLFailures);
301     assertEquals(info + " d2EdL2 failures: ", 0, lambdaGradient.nd2EdL2Failures);
302     assertEquals(info + " dEdXdL failures: ", 0, lambdaGradient.ndEdXdLFailures);
303     assertEquals(info + " dEdX failures: ", 0, lambdaGradient.ndEdXFailures);
304   }
305 }