Refactor md_enums
[alexxy/gromacs.git] / src / gromacs / tools / report_methods.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 #include "gmxpre.h"
36
37 #include "report_methods.h"
38
39 #include "gromacs/commandline/cmdlineoptionsmodule.h"
40 #include "gromacs/fileio/confio.h"
41 #include "gromacs/fileio/filetypes.h"
42 #include "gromacs/fileio/tpxio.h"
43 #include "gromacs/mdtypes/inputrec.h"
44 #include "gromacs/mdtypes/state.h"
45 #include "gromacs/options/basicoptions.h"
46 #include "gromacs/options/filenameoption.h"
47 #include "gromacs/options/ioptionscontainer.h"
48 #include "gromacs/selection/selectionoptionbehavior.h"
49 #include "gromacs/topology/mtop_util.h"
50 #include "gromacs/utility/fatalerror.h"
51 #include "gromacs/utility/fileredirector.h"
52 #include "gromacs/utility/filestream.h"
53 #include "gromacs/utility/stringutil.h"
54
55 namespace gmx
56 {
57
58 void writeHeader(TextWriter* writer, const std::string& text, const std::string& section, bool writeFormattedText)
59 {
60     std::string formattedText;
61     if (writeFormattedText)
62     {
63         formattedText = "\\" + section + "{" + text + "}\n";
64     }
65     else
66     {
67         formattedText = section + ": " + text + "\n";
68     }
69     writer->writeString(formattedText);
70 }
71
72 void writeSystemInformation(TextWriter* writer, const gmx_mtop_t& top, bool writeFormattedText)
73 {
74     int                       nmol, nvsite = 0;
75     gmx_mtop_atomloop_block_t aloop;
76     const t_atom*             atom;
77
78     writeHeader(writer, "Simulation system", "subsection", writeFormattedText);
79     aloop = gmx_mtop_atomloop_block_init(&top);
80     while (gmx_mtop_atomloop_block_next(aloop, &atom, &nmol))
81     {
82         if (atom->ptype == eptVSite)
83         {
84             nvsite += nmol;
85         }
86     }
87     {
88         writer->writeLine(formatString("A system of %d molecules (%d atoms) was simulated.",
89                                        gmx_mtop_num_molecules(top),
90                                        top.natoms - nvsite));
91     }
92     if (nvsite)
93     {
94         writer->writeLine(formatString("Virtual sites were used in some of the molecules."));
95     }
96     writer->ensureEmptyLine();
97 }
98
99 void writeParameterInformation(TextWriter* writer, const t_inputrec& ir, bool writeFormattedText)
100 {
101     writeHeader(writer, "Simulation settings", "subsection", writeFormattedText);
102     writer->writeLine(formatString("A total of %g ns were simulated with a time step of %g fs.",
103                                    ir.nsteps * ir.delta_t * 0.001,
104                                    1000 * ir.delta_t));
105     writer->writeLine(formatString("Neighbor searching was performed every %d steps.", ir.nstlist));
106     writer->writeLine(formatString("The %s algorithm was used for electrostatic interactions.",
107                                    enumValueToString(ir.coulombtype)));
108     writer->writeLine(formatString("with a cut-off of %g nm.", ir.rcoulomb));
109     if (ir.coulombtype == CoulombInteractionType::Pme)
110     {
111         writer->writeLine(
112                 formatString("A reciprocal grid of %d x %d x %d cells was used with %dth order "
113                              "B-spline interpolation.",
114                              ir.nkx,
115                              ir.nky,
116                              ir.nkz,
117                              ir.pme_order));
118     }
119     writer->writeLine(formatString(
120             "A single cut-off of %g nm was used for Van der Waals interactions.", ir.rlist));
121     if (ir.etc != TemperatureCoupling::No)
122     {
123         writer->writeLine(formatString("Temperature coupling was done with the %s algorithm.",
124                                        enumValueToString(ir.etc)));
125     }
126     if (ir.epc != PressureCoupling::No)
127     {
128         writer->writeLine(formatString("Pressure coupling was done with the %s algorithm.",
129                                        enumValueToString(ir.epc)));
130     }
131     writer->ensureEmptyLine();
132 }
133
134 void writeInformation(TextOutputFile*   outputStream,
135                       const t_inputrec& ir,
136                       const gmx_mtop_t& top,
137                       bool              writeFormattedText,
138                       bool              notStdout)
139 {
140     TextWriter writer(outputStream);
141     writer.ensureEmptyLine();
142     writeHeader(&writer, "Methods", "section", writeFormattedText);
143     writeSystemInformation(&writer, top, writeFormattedText);
144     writeParameterInformation(&writer, ir, writeFormattedText);
145     writer.ensureEmptyLine();
146
147     if (notStdout)
148     {
149         writer.close();
150     }
151 }
152
153 namespace
154 {
155
156 class ReportMethods : public ICommandLineOptionsModule
157 {
158 public:
159     ReportMethods() : writeLatex_(false), writePlainText_(false) {}
160
161     // From ICommandLineOptionsModule
162     void init(CommandLineModuleSettings* /*settings*/) override {}
163     void initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings) override;
164     void optionsFinished() override;
165     int  run() override;
166
167 private:
168     //! File name for the output LaTeX file or empty.
169     std::string outputFileLatex_;
170     //! File name for the unformatted output file or empty.
171     std::string outputFileUnformatted_;
172     //! File name of the run input file with full topology.
173     std::string inputTopology_;
174     //! Boolean reporting if writing to the LaTeX output file is requested.
175     bool writeLatex_;
176     //! Boolean reporting if writing to unformatted output is requested.
177     bool writePlainText_;
178 };
179
180 void ReportMethods::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings)
181 {
182     const char* const desc[] = { "[THISMODULE] reports basic system information for the run input",
183                                  "file specfied with [TT]-s[tt] either to the",
184                                  "terminal, to a LaTeX formatted output file if run with",
185                                  "the [TT]-m[tt] option or to an unformatted file with",
186                                  "the [TT]-o[tt] option.",
187                                  "The functionality has been moved here from its previous",
188                                  "place in [gmx-check]." };
189
190     settings->setHelpText(desc);
191
192     options->addOption(FileNameOption("s")
193                                .filetype(eftTopology)
194                                .inputFile()
195                                .required()
196                                .store(&inputTopology_)
197                                .defaultBasename("topol")
198                                .description("Run input file for report"));
199
200     // TODO: Replace use of legacyType.
201     options->addOption(FileNameOption("m")
202                                .legacyType(efTEX)
203                                .outputFile()
204                                .store(&outputFileLatex_)
205                                .storeIsSet(&writeLatex_)
206                                .defaultBasename("report")
207                                .description("LaTeX formatted report output"));
208     options->addOption(FileNameOption("o")
209                                .legacyType(efOUT)
210                                .outputFile()
211                                .store(&outputFileUnformatted_)
212                                .storeIsSet(&writePlainText_)
213                                .defaultBasename("report")
214                                .description("Unformatted report output to file"));
215 }
216
217 void ReportMethods::optionsFinished() {}
218
219 int ReportMethods::run()
220 {
221     t_state    state;
222     t_inputrec ir;
223     gmx_mtop_t top;
224     read_tpx_state(inputTopology_.c_str(), &ir, &state, &top);
225     if (writeLatex_)
226     {
227         TextOutputFile file(outputFileLatex_);
228         writeInformation(&file, ir, top, true, true);
229     }
230     if (writePlainText_)
231     {
232         TextOutputFile file(outputFileUnformatted_);
233         writeInformation(&file, ir, top, false, true);
234     }
235     TextOutputFile& stdoutFile = TextOutputFile::standardOutput();
236     writeInformation(&stdoutFile, ir, top, false, false);
237
238     return 0;
239 }
240
241 } // namespace
242
243 const char ReportMethodsInfo::name[] = "report-methods";
244 const char ReportMethodsInfo::shortDescription[] =
245         "Write short summary about the simulation setup to a text file "
246         "and/or to the standard output.";
247 ICommandLineOptionsModulePointer ReportMethodsInfo::create()
248 {
249     return ICommandLineOptionsModulePointer(std::make_unique<ReportMethods>());
250 }
251
252 } // namespace gmx