View Javadoc
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.algorithms.cli;
39  
40  import ffx.algorithms.dynamics.Barostat;
41  import ffx.crystal.CrystalPotential;
42  import ffx.potential.MolecularAssembly;
43  import picocli.CommandLine.ArgGroup;
44  import picocli.CommandLine.Option;
45  
46  import java.util.logging.Logger;
47  
48  import static java.lang.Double.parseDouble;
49  import static java.lang.Integer.parseInt;
50  import static java.lang.String.format;
51  
52  /**
53   * Represents command line options for scripts that use a barostat/NPT.
54   *
55   * @author Michael J. Schnieders
56   * @author Hernan V. Bernabe
57   * @since 1.0
58   */
59  public class BarostatOptions {
60  
61    /**
62     * Default maximum density constraint on the barostat that prevents reduction in unit cell
63     * (particularly at or near vapor states).
64     */
65    public static final String DEFAULT_MAX_DENSITY = "1.6";
66    /**
67     * Default "tin box" constraint on the barostat that prevents expansion of the unit cell
68     * (particularly at or near vapor states).
69     */
70    public static final String DEFAULT_MIN_DENSITY = "0.75";
71    /**
72     * Default width of proposed crystal angle moves (uniformly distributed) in degrees.
73     */
74    public static final String DEFAULT_MAX_ANGLE_MOVE = "0.5";
75    /**
76     * Default size of proposed unit cell volume moves (uniformly distributed) in Angstroms^3.
77     */
78    public static final String DEFAULT_MAX_VOLUME_MOVE = "1.0";
79    /**
80     * Default mean number of MD steps (Poisson distribution) between barostat move proposals.
81     */
82    public static final String DEFAULT_BAROSTAT_INTERVAL = "10";
83    /**
84     * Default number of Barostat moves between print statements.
85     */
86    public static final String DEFAULT_BAROSTAT_PRINT_INTERVAL = "1000";
87  
88    private static final Logger logger = Logger.getLogger(BarostatOptions.class.getName());
89  
90    /**
91     * The ArgGroup keeps the BarostatOptions together when printing help.
92     */
93    @ArgGroup(heading = "%n Monte Carlo Pressure Options%n", validate = false)
94    private final BarostatOptionGroup group = new BarostatOptionGroup();
95  
96    /**
97     * If pressure has been set > 0, creates a Barostat around a CrystalPotential, else returns the
98     * original, unmodified CrystalPotential.
99     *
100    * @param molecularAssembly Primary molecularAssembly of the CrystalPotential.
101    * @param crystalPotential  A CrystalPotential.
102    * @return Either a Barostat (NPT enabled) or the CrystalPotential.
103    */
104   public CrystalPotential checkNPT(MolecularAssembly molecularAssembly,
105                                    CrystalPotential crystalPotential) {
106     if (group.pressure > 0) {
107       return createBarostat(molecularAssembly, crystalPotential);
108     } else {
109       return crystalPotential;
110     }
111   }
112 
113   /**
114    * Creates a Barostat around a CrystalPotential.
115    *
116    * @param assembly         Primary assembly of the CrystalPotential.
117    * @param crystalPotential A CrystalPotential.
118    * @return An NPT potential.
119    * @throws IllegalArgumentException If this BarostatOptions has pressure <= 0.
120    */
121   public Barostat createBarostat(MolecularAssembly assembly, CrystalPotential crystalPotential)
122       throws IllegalArgumentException {
123     if (group.pressure > 0) {
124       Barostat barostat = new Barostat(assembly, crystalPotential);
125       barostat.setPressure(group.pressure);
126       barostat.setIsotropic(group.isotropic);
127       barostat.setMaxDensity(group.maxD);
128       barostat.setMinDensity(group.minD);
129       barostat.setBarostatPrintFrequency(group.barPrint);
130       double dens = barostat.density();
131       if (dens < group.minD) {
132         logger.info(format(
133             " Barostat: initial density %9.4g < minimum density %9.4g, resetting to minimum density",
134             dens, group.minD));
135         barostat.setDensity(group.minD);
136       } else if (dens > group.maxD) {
137         logger.info(format(
138             " Barostat: initial density %9.4g > maximum density %9.4g, resetting to maximum density",
139             dens, group.maxD));
140         barostat.setDensity(group.maxD);
141       }
142       barostat.setMaxAngleMove(group.maxAM);
143       barostat.setMaxVolumeMove(group.maxV);
144       barostat.setMeanBarostatInterval(group.barInt);
145       return barostat;
146     } else {
147       throw new IllegalArgumentException(" Pressure is <= 0; cannot create a Barostat!");
148     }
149   }
150 
151   /**
152    * -p or --npt Specify use of a Monte Carlo Barostat at the given pressure (default 0 = constant
153    * volume).
154    *
155    * @return Returns the pressure (atm).
156    */
157   public double getPressure() {
158     return group.pressure;
159   }
160 
161   public void setPressure(double pressure) {
162     group.pressure = pressure;
163   }
164 
165   /**
166    * Restrict the MC Barostat to isotropic moves. The lattice angles are * held fixed, and lattice
167    * lengths are scaled equally.
168    *
169    * @return Returns true if the Barostat is isotropic.
170    */
171   public boolean isIsotropic() {
172     return group.isotropic;
173   }
174 
175   public void setIsotropic(boolean isotropic) {
176     group.isotropic = isotropic;
177   }
178 
179   /**
180    * The maximum density accepted by the MC Barostat (g/cc).
181    *
182    * @return Returns the maximum density.
183    */
184   public double getMaxD() {
185     return group.maxD;
186   }
187 
188   public void setMaxD(double maxD) {
189     group.maxD = maxD;
190   }
191 
192   /**
193    * The minimum density accepted by the MC Barostat (g/cc).
194    *
195    * @return Returns the minimum density.
196    */
197   public double getMinD() {
198     return group.minD;
199   }
200 
201   public void setMinD(double minD) {
202     group.minD = minD;
203   }
204 
205   /**
206    * The volume of a proposed unit cell volume moves (uniformly distributed) in Angstroms^3.
207    *
208    * @return Returns the maximum volume move.
209    */
210   public double getMaxV() {
211     return group.maxV;
212   }
213 
214   /**
215    * The width of proposed crystal angle moves (uniformly distributed) in degrees.
216    *
217    * @return Returns the width of angle moves.
218    */
219   public double getMaxAM() {
220     return group.maxAM;
221   }
222 
223   public void setMaxAM(double maxAM) {
224     group.maxAM = maxAM;
225   }
226 
227   public void setMaxV(double maxV) {
228     group.maxV = maxV;
229   }
230 
231   /**
232    * The mean number of MD steps (Poisson distribution) between barostat move proposals.
233    *
234    * @return Returns the mean number of MD steps between barostat MC trials.
235    */
236   public int getBarInt() {
237     return group.barInt;
238   }
239 
240   public void setBarInt(int barInt) {
241     group.barInt = barInt;
242   }
243 
244   /**
245    * --bpi or --barostatPrintInterval Sets the number of Barostat MC cycles between print
246    * statements.
247    */
248   public int getPrintInt() {
249     return group.barPrint;
250   }
251 
252   public void setPrintInt(int printInterval) {
253     group.barPrint = printInterval;
254   }
255 
256   /**
257    * Collection of Barostat Options.
258    */
259   private static class BarostatOptionGroup {
260 
261     /**
262      * -p or --npt Specify use of a Monte Carlo Barostat at the given pressure (default 0 = constant
263      * volume).
264      */
265     @Option(names = {"-p", "--npt"}, paramLabel = "0", defaultValue = "0",
266         description = "Specify use of a MC Barostat at the given pressure; the default 0 disables NPT (atm).")
267     private double pressure = 0;
268     /**
269      * -iso or --isotropic Restrict the MC Barostat to isotropic moves. The lattice angles are held
270      * fixed, and lattice lengths are scaled equally.
271      */
272     @Option(names = {"--iso", "--isotropic"},
273         defaultValue = "false", description = "Restrict the MC Barostat to isotropic moves.")
274     private boolean isotropic = false;
275     /**
276      * --maxD or --maxDensity Specify the maximum density accepted by the MC Barostat (g/cc).
277      */
278     @Option(names = {"--maxD", " --maxDensity"},
279         paramLabel = DEFAULT_MAX_DENSITY, defaultValue = DEFAULT_MAX_DENSITY,
280         description = "Specify the maximum density accepted by the MC Barostat (g/cc).")
281     private double maxD = parseDouble(DEFAULT_MAX_DENSITY);
282     /**
283      * --minD or --minDensity Specify the minimum density accepted by the MC Barostat (g/cc).
284      */
285     @Option(names = {"--minD", " --minDensity"},
286         paramLabel = DEFAULT_MIN_DENSITY, defaultValue = DEFAULT_MIN_DENSITY,
287         description = "Specify the minimum density accepted by the MC Barostat (g/cc).")
288     private double minD = parseDouble(DEFAULT_MIN_DENSITY);
289     @Option(names = {"--maxAM", "--maxAngleMove"},
290         paramLabel = DEFAULT_MAX_ANGLE_MOVE, defaultValue = DEFAULT_MAX_ANGLE_MOVE,
291         description = "Sets the width of proposed crystal angle moves (uniformly distributed) in degrees.")
292     private double maxAM = parseDouble(DEFAULT_MAX_ANGLE_MOVE);
293     /**
294      * --maxV or --maxVolumeMove Sets the volume move size (uniformly distributed) in Angstroms^3.
295      */
296     @Option(names = {"--maxV", "--maxVolumeMove"},
297         paramLabel = DEFAULT_MAX_VOLUME_MOVE, defaultValue = DEFAULT_MAX_VOLUME_MOVE,
298         description = "Default width of proposed unit cell side length moves (uniformly distributed) in Angstroms.")
299     private double maxV = parseDouble(DEFAULT_MAX_VOLUME_MOVE);
300 
301     /**
302      * --barInt or --meanBarostatInterval Sets the mean number of MD steps (Poisson distribution)
303      * between barostat move proposals.
304      */
305     @Option(names = {"--barInt", "--meanBarostatInterval"},
306         paramLabel = DEFAULT_BAROSTAT_INTERVAL, defaultValue = DEFAULT_BAROSTAT_INTERVAL,
307         description = "Sets the mean number of MD steps between barostat move proposals.")
308     private int barInt = parseInt(DEFAULT_BAROSTAT_INTERVAL);
309     /**
310      * --bpi or --barostatPrintInterval Sets the number of Barostat MC cycles between print
311      * statements.
312      */
313     @Option(names = {"--bpi", "--barostatPrintInterval"},
314         paramLabel = DEFAULT_BAROSTAT_PRINT_INTERVAL, defaultValue = DEFAULT_BAROSTAT_PRINT_INTERVAL,
315         description = "Sets the number of Barostat MC cycles between print statements.")
316     private int barPrint = parseInt(DEFAULT_BAROSTAT_PRINT_INTERVAL);
317   }
318 }