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.commands.test;
39  
40  import edu.rit.pj.Comm;
41  import ffx.algorithms.cli.AlgorithmsCommand;
42  import ffx.utilities.FFXCommand;
43  import ffx.utilities.FFXBinding;
44  import picocli.CommandLine.Command;
45  import picocli.CommandLine.Option;
46  import picocli.CommandLine.Unmatched;
47  
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  import static java.lang.String.format;
52  
53  /**
54   * The ManyBodyPhScan script runs a pH scan with ManyBody optimization by executing another
55   * FFXScript multiple times across a pH range. It uses MPI for parallel execution.
56   * <br>
57   * Usage:
58   * <br>
59   * ffxc test.ManyBodyPhScan [options] &lt;script-name&gt; [script-args...]
60   */
61  @Command(description = " Run a pH Scan with ManyBody.", name = "test.ManyBodyPHScan")
62  public class ManyBodyPhScan extends AlgorithmsCommand {
63  
64    /**
65     * --spH --startpH Lower end of the pH range to be evaluated.
66     */
67    @Option(names = {"--spH", "--startpH"}, paramLabel = "0.0", defaultValue = "0.0",
68        description = "Lower end of the pH range to be evaluated.")
69    private double start;
70  
71    /**
72     * --epH --endpH Upper end of the pH range to be evaluated.
73     */
74    @Option(names = {"--epH", "--endpH"}, paramLabel = "14.0", defaultValue = "14.0",
75        description = "Upper end of the pH range to be evaluated.")
76    private double end;
77  
78    /**
79     * --ns --nSteps Number of steps for the given pH range.
80     */
81    @Option(names = {"--ns", "--nSteps"}, paramLabel = "2.0", defaultValue = "2.0",
82        description = "Number of steps for a given pH range.")
83    private double nSteps;
84  
85    /**
86     * The final argument(s) should be one or more filenames.
87     */
88    @Unmatched
89    private List<String> unmatched;
90  
91    /**
92     * ManyBodyPhScan Constructor.
93     */
94    public ManyBodyPhScan() {
95      super();
96    }
97  
98    /**
99     * ManyBodyPhScan Constructor.
100    * @param binding The Binding to use.
101    */
102   public ManyBodyPhScan(FFXBinding binding) {
103     super(binding);
104   }
105 
106   /**
107    * ManyBodyPhScan constructor that sets the command line arguments.
108    * @param args Command line arguments.
109    */
110   public ManyBodyPhScan(String[] args) {
111     super(args);
112   }
113 
114   /**
115    * {@inheritDoc}
116    */
117   @Override
118   public ManyBodyPhScan run() {
119 
120     if (!init()) {
121       return this;
122     }
123 
124     // Set a flag to avoid double use of MPI in downstream commands.
125     System.setProperty("pj.use.mpi", "false");
126 
127     Class<? extends FFXCommand> script = FFXCommand.getCommand(unmatched.get(0));
128     Comm world = Comm.world();
129     int numProc = world.size();
130     int rank = world.rank();
131 
132     if (numProc > 1) {
133       logger.info(format(" Number of processes:  %d", numProc));
134       logger.info(format(" Rank of this process: %d", rank));
135     }
136 
137     // Remove ManyBodyPHScan command.
138     unmatched.remove(0);
139 
140     double stepSize = (end - start) / (nSteps - 1);
141 
142     int pHIndex = unmatched.indexOf("0.0");
143     for (int i = 0; i < nSteps; i++) {
144       double pHValue = start + (stepSize * i);
145       List<String> commandArgs = new ArrayList<>();
146       for (String arg : unmatched) {
147         unmatched.set(pHIndex, String.valueOf(pHValue));
148         commandArgs.add(arg);
149       }
150 
151       // Create a Binding for command line arguments.
152       FFXBinding binding = new FFXBinding();
153       binding.setVariable("args", commandArgs);
154 
155       try {
156         FFXCommand command = script.getDeclaredConstructor().newInstance();
157         command.setBinding(binding);
158         command.run();
159       } catch (Exception e) {
160         logger.info(format(" Exception for pH value: %s", pHValue));
161       }
162     }
163     // Clear the pj.use.mpi flag.
164     System.clearProperty("pj.use.mpi");
165 
166     return this;
167 
168   }
169 }