89a10d9d64c940a6837472bd9754068fc533e62b
[alexxy/gromacs.git] / src / gromacs / options / basicoptions.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2017,2018, 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 /*! \file
36  * \brief
37  * Declares option objects for basic option types.
38  *
39  * Together with options.h, this header forms the part of the public API
40  * that most classes will use to provide options.
41  *
42  * \author Teemu Murtola <teemu.murtola@gmail.com>
43  * \inpublicapi
44  * \ingroup module_options
45  */
46 #ifndef GMX_OPTIONS_BASICOPTIONS_H
47 #define GMX_OPTIONS_BASICOPTIONS_H
48
49 #include <string>
50 #include <vector>
51
52 #include "gromacs/options/abstractoption.h"
53 #include "gromacs/options/ivaluestore.h"
54 #include "gromacs/utility/arrayref.h"
55 #include "gromacs/utility/basedefinitions.h"
56 #include "gromacs/utility/gmxassert.h"
57
58 namespace gmx
59 {
60
61 class BooleanOptionInfo;
62 class BooleanOptionStorage;
63 class IntegerOptionInfo;
64 class IntegerOptionStorage;
65 class Int64OptionInfo;
66 class Int64OptionStorage;
67 class DoubleOptionInfo;
68 class DoubleOptionStorage;
69 class FloatOptionInfo;
70 class FloatOptionStorage;
71 class StringOptionInfo;
72 class StringOptionStorage;
73 class EnumOptionInfo;
74 class EnumOptionStorage;
75
76 //! \addtogroup module_options
77 //! \{
78
79 /*! \brief
80  * Specifies an option that provides boolean values.
81  *
82  * Example:
83  * \code
84    bool  bPBC;
85    using gmx::BooleanOption;
86    options.addOption(BooleanOption("pbc").store(&bPBC));
87  * \endcode
88  *
89  * Public methods in this class do not throw.
90  *
91  * \inpublicapi
92  */
93 class BooleanOption : public OptionTemplate<bool, BooleanOption>
94 {
95     public:
96         //! OptionInfo subclass corresponding to this option type.
97         typedef BooleanOptionInfo InfoType;
98
99         //! Initializes an option with the given name.
100         explicit BooleanOption(const char *name) : MyBase(name) {}
101
102     private:
103         //! Creates a BooleanOptionStorage object.
104         virtual AbstractOptionStorage *createStorage(
105             const OptionManagerContainer &managers) const;
106 };
107
108 /*! \brief
109  * Specifies an option that provides integer values.
110  *
111  * Examples:
112  * \code
113    using gmx::IntegerOption;
114    // Simple option
115    int  rcut = 0;
116    options.addOption(IntegerOption("rcut").store(&rcut));
117    // Vector-valued option
118    int  box[3] = {1, 1, 1};  // Default value
119    options.addOption(IntegerOption("box").store(box).vector());
120  * \endcode
121  *
122  * Public methods in this class do not throw.
123  *
124  * \inpublicapi
125  */
126 class IntegerOption : public OptionTemplate<int, IntegerOption>
127 {
128     public:
129         //! OptionInfo subclass corresponding to this option type.
130         typedef IntegerOptionInfo InfoType;
131
132         //! Initializes an option with the given name.
133         explicit IntegerOption(const char *name) : MyBase(name) {}
134
135         /*! \brief
136          * Sets the option to return a vector value.
137          *
138          * A vector value returns a fixed number of values, the default being
139          * three (can be changed with valueCount()).  However, it also accepts
140          * a single value, in which case the value is used to fill the whole
141          * vector.
142          */
143         MyClass &vector() { setVector(); return me(); }
144
145     private:
146         //! Creates an IntegerOptionStorage object.
147         virtual AbstractOptionStorage *createStorage(
148             const OptionManagerContainer &managers) const;
149
150         /*! \brief
151          * Needed to initialize IntegerOptionStorage from this class without
152          * otherwise unnecessary accessors.
153          */
154         friend class IntegerOptionStorage;
155 };
156
157 /*! \brief
158  * Specifies an option that provides 64-bit integer values.
159  *
160  * Public methods in this class do not throw.
161  *
162  * \see IntegerOption
163  *
164  * \inpublicapi
165  */
166 class Int64Option : public OptionTemplate<int64_t, Int64Option>
167 {
168     public:
169         //! OptionInfo subclass corresponding to this option type.
170         typedef Int64OptionInfo InfoType;
171
172         //! Initializes an option with the given name.
173         explicit Int64Option(const char *name) : MyBase(name) {}
174
175     private:
176         //! Creates an Int64OptionStorage object.
177         virtual AbstractOptionStorage *createStorage(
178             const OptionManagerContainer &managers) const;
179
180         /*! \brief
181          * Needed to initialize Int64OptionStorage from this class without
182          * otherwise unnecessary accessors.
183          */
184         friend class Int64OptionStorage;
185 };
186
187 /*! \brief
188  * Specifies an option that provides floating-point (double) values.
189  *
190  * Public methods in this class do not throw.
191  *
192  * \inpublicapi
193  */
194 class DoubleOption : public OptionTemplate<double, DoubleOption>
195 {
196     public:
197         //! OptionInfo subclass corresponding to this option type.
198         typedef DoubleOptionInfo InfoType;
199
200         //! Initializes an option with the given name.
201         explicit DoubleOption(const char *name) : MyBase(name), bTime_(false)
202         {
203         }
204
205         //! \copydoc IntegerOption::vector()
206         MyClass &vector() { setVector(); return me(); }
207         /*! \brief
208          * Marks this option as providing a time value whose unit can be changed.
209          *
210          * By itself, this option does nothing.  It marks the option as a time
211          * value such that TimeUnitManager::scaleTimeOptions() can process it.
212          * In typical cases, \Gromacs scales the time options just before
213          * Options::finish() has been called, so the option value is only
214          * available after all option values have been processed.
215          * All values in the program are in ps (including any default value);
216          * user-provided values are scaled according to the time unit set in
217          * TimeUnitManager.
218          */
219         MyClass &timeValue() { bTime_ = true; return me(); }
220
221     private:
222         //! Creates a DoubleOptionStorage object.
223         virtual AbstractOptionStorage *createStorage(
224             const OptionManagerContainer &managers) const;
225
226         bool bTime_;
227
228         /*! \brief
229          * Needed to initialize DoubleOptionStorage from this class without
230          * otherwise unnecessary accessors.
231          */
232         friend class DoubleOptionStorage;
233 };
234
235 /*! \brief
236  * Specifies an option that provides floating-point (float) values.
237  *
238  * Public methods in this class do not throw.
239  *
240  * \see DoubleOption
241  *
242  * \inpublicapi
243  */
244 class FloatOption : public OptionTemplate<float, FloatOption>
245 {
246     public:
247         //! OptionInfo subclass corresponding to this option type.
248         typedef FloatOptionInfo InfoType;
249
250         //! Initializes an option with the given name.
251         explicit FloatOption(const char *name) : MyBase(name), bTime_(false)
252         {
253         }
254
255         //! \copydoc IntegerOption::vector()
256         MyClass &vector() { setVector(); return me(); }
257         //! \copydoc DoubleOption::timeValue()
258         MyClass &timeValue() { bTime_ = true; return me(); }
259
260     private:
261         //! Creates a FloatOptionStorage object.
262         virtual AbstractOptionStorage *createStorage(
263             const OptionManagerContainer &managers) const;
264
265         bool bTime_;
266
267         /*! \brief
268          * Needed to initialize FloatOptionStorage from this class without
269          * otherwise unnecessary accessors.
270          */
271         friend class FloatOptionStorage;
272 };
273
274 /*! \brief
275  * Specifies an option that provides string values.
276  *
277  * Examples:
278  * \code
279    using gmx::StringOption;
280    // Simple option
281    std::string  str;
282    options.addOption(StringOption("str").store(&str));
283    // Option that only accepts predefined values
284    const char * const  allowed[] = { "atom", "residue", "molecule" };
285    std::string  str;
286    options.addOption(StringOption("type").enumValue(allowed).store(&str));
287  * \endcode
288  *
289  * Public methods in this class do not throw.
290  *
291  * \inpublicapi
292  */
293 class StringOption : public OptionTemplate<std::string, StringOption>
294 {
295     public:
296         //! OptionInfo subclass corresponding to this option type.
297         typedef StringOptionInfo InfoType;
298
299         //! Initializes an option with the given name.
300         explicit StringOption(const char *name)
301             : MyBase(name), enumValues_(nullptr), enumValuesCount_(0),
302               defaultEnumIndex_(-1)
303         {
304         }
305
306         /*! \brief
307          * Sets the option to only accept one of a fixed set of strings.
308          *
309          * \param[in] values  Array of strings to accept.
310          *
311          * Also accepts prefixes of the strings; if a prefix matches more than
312          * one of the possible strings, the shortest one is used (in a tie, the
313          * first one is).
314          *
315          * The strings are copied once the option is created.
316          */
317         template <size_t count>
318         MyClass &enumValue(const char *const (&values)[count])
319         {
320             GMX_ASSERT(enumValues_ == NULL,
321                        "Multiple sets of enumerated values specified");
322             enumValues_      = values;
323             enumValuesCount_ = count;
324             return me();
325         }
326         /*! \brief
327          * Sets the option to only accept one of a fixed set of strings.
328          *
329          * \param[in] values  Array of strings to accept, with a NULL pointer
330          *      following the last string.
331          *
332          * Works otherwise as the array version, but accepts a pointer to
333          * an array of undetermined length.  The end of the array is indicated
334          * by a NULL pointer in the array.
335          *
336          * \see enumValue()
337          */
338         MyClass &enumValueFromNullTerminatedArray(const char *const *values)
339         {
340             GMX_ASSERT(enumValues_ == NULL,
341                        "Multiple sets of enumerated values specified");
342             enumValues_      = values;
343             enumValuesCount_ = -1;
344             return me();
345         }
346         /*! \brief
347          * Sets the default value using an index into the enumeration table.
348          *
349          * Cannot be specified without enumValue().
350          */
351         MyClass &defaultEnumIndex(int index)
352         {
353             GMX_ASSERT(index >= 0, "Invalid enumeration index");
354             defaultEnumIndex_ = index;
355             return me();
356         }
357
358     private:
359         //! Creates a StringOptionStorage object.
360         virtual AbstractOptionStorage *createStorage(
361             const OptionManagerContainer &managers) const;
362
363         const char *const      *enumValues_;
364         int                     enumValuesCount_;
365         int                     defaultEnumIndex_;
366
367         /*! \brief
368          * Needed to initialize StringOptionStorage from this class without
369          * otherwise unnecessary accessors.
370          */
371         friend class StringOptionStorage;
372 };
373
374 //! \}
375
376 namespace internal
377 {
378
379 /*! \internal
380  * \brief
381  * Type-specific implementation for IOptionValueStore for an enum option.
382  *
383  * This class is instantiated for each enum type for which EnumOption is used,
384  * and takes care of managing `int`-to-`enum` conversions.  Having this part in
385  * the header allows the actual storage implementation to not be in the header,
386  * which would require exposing all the internals through this one header...
387  *
388  * \ingroup module_options
389  */
390 template <typename EnumType>
391 class EnumIndexStore : public IOptionValueStore<int>
392 {
393     public:
394         //! Initializes the storage for the given actual enum variables.
395         EnumIndexStore(EnumType *store, std::vector<EnumType> *storeVector)
396             : store_(store), storeVector_(storeVector)
397         {
398             if (storeVector_ != nullptr)
399             {
400                 for (EnumType value : *storeVector_)
401                 {
402                     intStore_.push_back(static_cast<int>(value));
403                 }
404             }
405             else if (store_ != nullptr)
406             {
407                 // TODO: Copy more than one value if that would make sense.
408                 intStore_.push_back(static_cast<int>(store_[0]));
409             }
410         }
411
412         virtual int valueCount() { return static_cast<int>(intStore_.size()); }
413         virtual ArrayRef<int> values() { return intStore_; }
414         virtual void clear()
415         {
416             intStore_.clear();
417             if (storeVector_ != nullptr)
418             {
419                 storeVector_->clear();
420             }
421         }
422         virtual void reserve(size_t count)
423         {
424             intStore_.reserve(intStore_.size() + count);
425             if (storeVector_ != nullptr)
426             {
427                 storeVector_->reserve(storeVector_->size() + count);
428             }
429         }
430         virtual void append(const int &value)
431         {
432             const size_t count = intStore_.size();
433             intStore_.push_back(value);
434             if (store_ != nullptr)
435             {
436                 store_[count] = static_cast<EnumType>(value);
437             }
438             if (storeVector_ != nullptr)
439             {
440                 storeVector_->push_back(static_cast<EnumType>(value));
441             }
442         }
443
444     private:
445         //! Stores the integer values for values().
446         std::vector<int>       intStore_;
447         EnumType              *store_;
448         std::vector<EnumType> *storeVector_;
449 };
450
451 //! \cond internal
452 /*! \internal
453  * \brief
454  * Helper to create EnumOptionStorage instances.
455  *
456  * This function works as a proxy between EnumOption::createStorage() and the
457  * EnumOptionStorage constructor, such that the latter does not need to be
458  * exposed in the header.
459  *
460  * \ingroup module_options
461  */
462 AbstractOptionStorage *
463 createEnumOptionStorage(const AbstractOption &option,
464                         const char *const *enumValues, int count,
465                         int defaultValue, int defaultValueIfSet,
466                         IOptionValueStore<int> *store);
467 //! \endcond
468
469 }   // namespace internal
470
471 //! \addtogroup module_options
472 //! \{
473
474 /*! \brief
475  * Specifies an option that accepts enumerated string values and writes the
476  * selected index into an `enum` variable.
477  *
478  * \tparam EnumType  Type of the variable that receives the values
479  *     (can also be `int`).
480  *
481  * Examples:
482  * \code
483    enum MyEnum { eAtom, eRes, eMol };
484    using gmx::EnumOption;
485    const char * const  allowed[] = { "atom", "residue", "molecule" };
486    MyEnum       value = eAtom; // default value
487    options.addOption(EnumOption<MyEnum>("type").enumValue(allowed).store(&value));
488  * \endcode
489  *
490  * storeCount() is not currently implemented for this option type, and
491  * providing multiple default values through an array passed to store() does
492  * not work consistently in all cases.
493  * In the current implementation, the values of the enum type should correspond
494  * to indices in the array passed to enumValue(), i.e., be consencutive
495  * starting from zero.  Only values corresponding to valid indices are accepted
496  * as parameters to, e.g., defaultValue().  However, other values can be used
497  * as the initial value of the variable (`value` in the above example), and
498  * those will be preserved if the option is not set.
499  *
500  * Public methods in this class do not throw.
501  *
502  * \inpublicapi
503  */
504 template <typename EnumType>
505 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType> >
506 {
507     public:
508         //! OptionInfo subclass corresponding to this option type.
509         typedef EnumOptionInfo InfoType;
510
511         // This needs to be duplicated from OptionTemplate because this class
512         // is a template.
513         //! Short-hand for the base class.
514         typedef OptionTemplate<EnumType, EnumOption<EnumType> > MyBase;
515
516         //! Initializes an option with the given name.
517         explicit EnumOption(const char *name)
518             : MyBase(name), enumValues_(nullptr), enumValuesCount_(0)
519         {
520         }
521
522         /*! \brief
523          * Sets the option to only accept one of a fixed set of strings.
524          *
525          * \param[in] values  Array of strings to accept.
526          *
527          * Also accepts prefixes of the strings; if a prefix matches more than
528          * one of the possible strings, the shortest one is used (in a tie, the
529          * first one is).
530          *
531          * The strings are copied once the option is created.
532          */
533         template <size_t count>
534         EnumOption &enumValue(const char *const (&values)[count])
535         {
536             GMX_ASSERT(enumValues_ == NULL,
537                        "Multiple sets of enumerated values specified");
538             enumValues_      = values;
539             enumValuesCount_ = count;
540             return MyBase::me();
541         }
542         /*! \brief
543          * Sets the option to only accept one of a fixed set of strings.
544          *
545          * \param[in] values  Array of strings to accept, with a NULL pointer
546          *      following the last string.
547          *
548          * Works otherwise as the array version, but accepts a pointer to
549          * an array of undetermined length.  The end of the array is indicated
550          * by a NULL pointer in the array.
551          *
552          * \see enumValue()
553          */
554         EnumOption &enumValueFromNullTerminatedArray(const char *const *values)
555         {
556             GMX_ASSERT(enumValues_ == NULL,
557                        "Multiple sets of enumerated values specified");
558             enumValues_      = values;
559             enumValuesCount_ = -1;
560             return MyBase::me();
561         }
562
563     private:
564         //! Helper function to convert default values for storate initialization.
565         static int convertToInt(const EnumType *defaultValue)
566         {
567             return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
568         }
569
570         //! Creates a EnumOptionStorage object.
571         virtual AbstractOptionStorage *createStorage(
572             const OptionManagerContainer & /*managers*/) const
573         {
574             // TODO: Implement storeCount() if necessary.
575             return internal::createEnumOptionStorage(
576                     *this, enumValues_, enumValuesCount_,
577                     convertToInt(MyBase::defaultValue()),
578                     convertToInt(MyBase::defaultValueIfSet()),
579                     new internal::EnumIndexStore<EnumType>(
580                             MyBase::store(), MyBase::storeVector()));
581         }
582
583         const char *const      *enumValues_;
584         int                     enumValuesCount_;
585
586         /*! \brief
587          * Needed to initialize EnumOptionStorage from this class without
588          * otherwise unnecessary accessors.
589          */
590         friend class EnumOptionStorage;
591 };
592
593 //! Shorthand for an enumerated option that stores into an `int` variable.
594 typedef EnumOption<int> EnumIntOption;
595
596 /*! \brief
597  * Wrapper class for accessing boolean option information.
598  *
599  * \inpublicapi
600  */
601 class BooleanOptionInfo : public OptionInfo
602 {
603     public:
604         //! Creates an option info object for the given option.
605         explicit BooleanOptionInfo(BooleanOptionStorage *option);
606
607         //! Returns the default value for this option.
608         bool defaultValue() const;
609
610     private:
611         const BooleanOptionStorage &option() const;
612 };
613
614 /*! \brief
615  * Wrapper class for accessing integer option information.
616  *
617  * \inpublicapi
618  */
619 class IntegerOptionInfo : public OptionInfo
620 {
621     public:
622         //! Creates an option info object for the given option.
623         explicit IntegerOptionInfo(IntegerOptionStorage *option);
624 };
625
626 /*! \brief
627  * Wrapper class for accessing 64-bit integer option information.
628  *
629  * \inpublicapi
630  */
631 class Int64OptionInfo : public OptionInfo
632 {
633     public:
634         //! Creates an option info object for the given option.
635         explicit Int64OptionInfo(Int64OptionStorage *option);
636 };
637
638 /*! \brief
639  * Wrapper class for accessing floating-point option information.
640  *
641  * \inpublicapi
642  */
643 class DoubleOptionInfo : public OptionInfo
644 {
645     public:
646         //! Creates an option info object for the given option.
647         explicit DoubleOptionInfo(DoubleOptionStorage *option);
648
649         //! Whether the option specifies a time value.
650         bool isTime() const;
651
652         /*! \brief
653          * Sets a scale factor for user-provided values.
654          *
655          * Any user-provided value is scaled by the provided factor.
656          * Programmatically set default values are not scaled.
657          * If called multiple times, later calls override the previously set
658          * value.  In other words, the scaling is not cumulative.
659          */
660         void setScaleFactor(double factor);
661
662     private:
663         DoubleOptionStorage &option();
664         const DoubleOptionStorage &option() const;
665 };
666
667 /*! \brief
668  * Wrapper class for accessing floating-point option information.
669  *
670  * \inpublicapi
671  */
672 class FloatOptionInfo : public OptionInfo
673 {
674     public:
675         //! Creates an option info object for the given option.
676         explicit FloatOptionInfo(FloatOptionStorage *option);
677
678         //! Whether the option specifies a time value.
679         bool isTime() const;
680
681         //! \copydoc DoubleOptionInfo::setScaleFactor()
682         void setScaleFactor(double factor);
683
684     private:
685         FloatOptionStorage &option();
686         const FloatOptionStorage &option() const;
687 };
688
689 /*! \brief
690  * Wrapper class for accessing string option information.
691  *
692  * \inpublicapi
693  */
694 class StringOptionInfo : public OptionInfo
695 {
696     public:
697         //! Creates an option info object for the given option.
698         explicit StringOptionInfo(StringOptionStorage *option);
699
700         /*! \brief
701          * Whether this option accepts an enumerated set of values.
702          *
703          * Returns true if StringOption::enumValues() was used when creating
704          * this option.
705          */
706         bool isEnumerated() const;
707         /*! \brief
708          * Returns the set of allowed values for this option.
709          *
710          * Returns an empty vector if isEnumerated() returns false.
711          */
712         const std::vector<std::string> &allowedValues() const;
713
714     private:
715         const StringOptionStorage &option() const;
716 };
717
718 /*! \brief
719  * Wrapper class for accessing enum option information.
720  *
721  * \inpublicapi
722  */
723 class EnumOptionInfo : public OptionInfo
724 {
725     public:
726         //! Creates an option info object for the given option.
727         explicit EnumOptionInfo(EnumOptionStorage *option);
728
729         /*! \brief
730          * Returns the set of allowed values for this option.
731          */
732         const std::vector<std::string> &allowedValues() const;
733
734     private:
735         const EnumOptionStorage &option() const;
736 };
737
738 /*! \typedef RealOption
739  * \brief
740  * Typedef for either DoubleOption or FloatOption, depending on precision.
741  *
742  * Generally, new would be better using DoubleOption, but this is provided for
743  * cases where the output value needs to be of type `real` for some reason.
744  */
745 /*! \typedef RealOptionInfo
746  * \brief
747  * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
748  *
749  * Generally, new would be better using DoubleOption, but this is provided for
750  * cases where the output value needs to be of type `real` for some reason.
751  */
752 #if GMX_DOUBLE
753 typedef DoubleOption     RealOption;
754 typedef DoubleOptionInfo RealOptionInfo;
755 #else
756 typedef FloatOption      RealOption;
757 typedef FloatOptionInfo  RealOptionInfo;
758 #endif
759
760 //! \}
761
762 } // namespace gmx
763
764 #endif