2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010-2018, The GROMACS development team.
5 * Copyright (c) 2019, by the GROMACS development team, led by
6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 * and including many others, as listed in the AUTHORS file in the
8 * top-level source directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
38 * Declares option objects for basic option types.
40 * Together with options.h, this header forms the part of the public API
41 * that most classes will use to provide options.
43 * \author Teemu Murtola <teemu.murtola@gmail.com>
45 * \ingroup module_options
47 #ifndef GMX_OPTIONS_BASICOPTIONS_H
48 #define GMX_OPTIONS_BASICOPTIONS_H
54 #include "gromacs/options/abstractoption.h"
55 #include "gromacs/utility/arrayref.h"
56 #include "gromacs/utility/basedefinitions.h"
57 #include "gromacs/utility/gmxassert.h"
59 #include "ivaluestore.h"
64 class BooleanOptionInfo
;
65 class BooleanOptionStorage
;
66 class IntegerOptionInfo
;
67 class IntegerOptionStorage
;
68 class Int64OptionInfo
;
69 class Int64OptionStorage
;
70 class DoubleOptionInfo
;
71 class DoubleOptionStorage
;
72 class FloatOptionInfo
;
73 class FloatOptionStorage
;
74 class StringOptionInfo
;
75 class StringOptionStorage
;
77 class EnumOptionStorage
;
79 //! \addtogroup module_options
83 * Specifies an option that provides boolean values.
88 using gmx::BooleanOption;
89 options.addOption(BooleanOption("pbc").store(&bPBC));
92 * Public methods in this class do not throw.
96 class BooleanOption
: public OptionTemplate
<bool, BooleanOption
>
99 //! OptionInfo subclass corresponding to this option type.
100 typedef BooleanOptionInfo InfoType
;
102 //! Initializes an option with the given name.
103 explicit BooleanOption(const char* name
) : MyBase(name
) {}
106 //! Creates a BooleanOptionStorage object.
107 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& managers
) const override
;
111 * Specifies an option that provides integer values.
115 using gmx::IntegerOption;
118 options.addOption(IntegerOption("rcut").store(&rcut));
119 // Vector-valued option
120 int box[3] = {1, 1, 1}; // Default value
121 options.addOption(IntegerOption("box").store(box).vector());
124 * Public methods in this class do not throw.
128 class IntegerOption
: public OptionTemplate
<int, IntegerOption
>
131 //! OptionInfo subclass corresponding to this option type.
132 typedef IntegerOptionInfo InfoType
;
134 //! Initializes an option with the given name.
135 explicit IntegerOption(const char* name
) : MyBase(name
) {}
138 * Sets the option to return a vector value.
140 * A vector value returns a fixed number of values, the default being
141 * three (can be changed with valueCount()). However, it also accepts
142 * a single value, in which case the value is used to fill the whole
152 //! Creates an IntegerOptionStorage object.
153 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& managers
) const override
;
156 * Needed to initialize IntegerOptionStorage from this class without
157 * otherwise unnecessary accessors.
159 friend class IntegerOptionStorage
;
163 * Specifies an option that provides 64-bit integer values.
165 * Public methods in this class do not throw.
171 class Int64Option
: public OptionTemplate
<int64_t, Int64Option
>
174 //! OptionInfo subclass corresponding to this option type.
175 typedef Int64OptionInfo InfoType
;
177 //! Initializes an option with the given name.
178 explicit Int64Option(const char* name
) : MyBase(name
) {}
181 //! Creates an Int64OptionStorage object.
182 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& managers
) const override
;
185 * Needed to initialize Int64OptionStorage from this class without
186 * otherwise unnecessary accessors.
188 friend class Int64OptionStorage
;
192 * Specifies an option that provides floating-point (double) values.
194 * Public methods in this class do not throw.
198 class DoubleOption
: public OptionTemplate
<double, DoubleOption
>
201 //! OptionInfo subclass corresponding to this option type.
202 typedef DoubleOptionInfo InfoType
;
204 //! Initializes an option with the given name.
205 explicit DoubleOption(const char* name
) : MyBase(name
), bTime_(false) {}
207 //! \copydoc IntegerOption::vector()
214 * Marks this option as providing a time value whose unit can be changed.
216 * By itself, this option does nothing. It marks the option as a time
217 * value such that TimeUnitManager::scaleTimeOptions() can process it.
218 * In typical cases, \Gromacs scales the time options just before
219 * Options::finish() has been called, so the option value is only
220 * available after all option values have been processed.
221 * All values in the program are in ps (including any default value);
222 * user-provided values are scaled according to the time unit set in
232 //! Creates a DoubleOptionStorage object.
233 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& managers
) const override
;
238 * Needed to initialize DoubleOptionStorage from this class without
239 * otherwise unnecessary accessors.
241 friend class DoubleOptionStorage
;
245 * Specifies an option that provides floating-point (float) values.
247 * Public methods in this class do not throw.
253 class FloatOption
: public OptionTemplate
<float, FloatOption
>
256 //! OptionInfo subclass corresponding to this option type.
257 typedef FloatOptionInfo InfoType
;
259 //! Initializes an option with the given name.
260 explicit FloatOption(const char* name
) : MyBase(name
), bTime_(false) {}
262 //! \copydoc IntegerOption::vector()
268 //! \copydoc DoubleOption::timeValue()
276 //! Creates a FloatOptionStorage object.
277 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& managers
) const override
;
282 * Needed to initialize FloatOptionStorage from this class without
283 * otherwise unnecessary accessors.
285 friend class FloatOptionStorage
;
289 * Specifies an option that provides string values.
293 using gmx::StringOption;
296 options.addOption(StringOption("str").store(&str));
297 // Option that only accepts predefined values
298 const char * const allowed[] = { "atom", "residue", "molecule" };
300 options.addOption(StringOption("type").enumValue(allowed).store(&str));
303 * Public methods in this class do not throw.
307 class StringOption
: public OptionTemplate
<std::string
, StringOption
>
310 //! OptionInfo subclass corresponding to this option type.
311 typedef StringOptionInfo InfoType
;
313 //! Initializes an option with the given name.
314 explicit StringOption(const char* name
) :
316 enumValues_(nullptr),
318 defaultEnumIndex_(-1)
323 * Sets the option to only accept one of a fixed set of strings.
325 * \param[in] values Array of strings to accept.
327 * Also accepts prefixes of the strings; if a prefix matches more than
328 * one of the possible strings, the shortest one is used (in a tie, the
331 * The strings are copied once the option is created.
333 template<size_t count
>
334 MyClass
& enumValue(const char* const (&values
)[count
])
336 GMX_ASSERT(enumValues_
== nullptr, "Multiple sets of enumerated values specified");
337 enumValues_
= values
;
338 enumValuesCount_
= count
;
342 * Sets the option to only accept one of a fixed set of strings.
344 * \param[in] values Array of strings to accept, with a NULL pointer
345 * following the last string.
347 * Works otherwise as the array version, but accepts a pointer to
348 * an array of undetermined length. The end of the array is indicated
349 * by a NULL pointer in the array.
353 MyClass
& enumValueFromNullTerminatedArray(const char* const* values
)
355 GMX_ASSERT(enumValues_
== nullptr, "Multiple sets of enumerated values specified");
356 enumValues_
= values
;
357 enumValuesCount_
= -1;
361 * Sets the default value using an index into the enumeration table.
363 * Cannot be specified without enumValue().
365 MyClass
& defaultEnumIndex(int index
)
367 GMX_ASSERT(index
>= 0, "Invalid enumeration index");
368 defaultEnumIndex_
= index
;
373 //! Creates a StringOptionStorage object.
374 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& managers
) const override
;
376 const char* const* enumValues_
;
377 int enumValuesCount_
;
378 int defaultEnumIndex_
;
381 * Needed to initialize StringOptionStorage from this class without
382 * otherwise unnecessary accessors.
384 friend class StringOptionStorage
;
394 * Type-specific implementation for IOptionValueStore for an enum option.
396 * This class is instantiated for each enum type for which EnumOption is used,
397 * and takes care of managing `int`-to-`enum` conversions. Having this part in
398 * the header allows the actual storage implementation to not be in the header,
399 * which would require exposing all the internals through this one header...
401 * \ingroup module_options
403 template<typename EnumType
>
404 class EnumIndexStore
: public IOptionValueStore
<int>
407 //! Initializes the storage for the given actual enum variables.
408 EnumIndexStore(EnumType
* store
, std::vector
<EnumType
>* storeVector
) :
410 storeVector_(storeVector
)
412 if (storeVector_
!= nullptr)
414 for (EnumType value
: *storeVector_
)
416 intStore_
.push_back(static_cast<int>(value
));
419 else if (store_
!= nullptr)
421 // TODO: Copy more than one value if that would make sense.
422 intStore_
.push_back(static_cast<int>(store_
[0]));
426 int valueCount() override
{ return ssize(intStore_
); }
427 ArrayRef
<int> values() override
{ return intStore_
; }
428 void clear() override
431 if (storeVector_
!= nullptr)
433 storeVector_
->clear();
436 void reserve(size_t count
) override
438 intStore_
.reserve(intStore_
.size() + count
);
439 if (storeVector_
!= nullptr)
441 storeVector_
->reserve(storeVector_
->size() + count
);
444 void append(const int& value
) override
446 const size_t count
= intStore_
.size();
447 intStore_
.push_back(value
);
448 if (store_
!= nullptr)
450 store_
[count
] = static_cast<EnumType
>(value
);
452 if (storeVector_
!= nullptr)
454 storeVector_
->push_back(static_cast<EnumType
>(value
));
459 //! Stores the integer values for values().
460 std::vector
<int> intStore_
;
462 std::vector
<EnumType
>* storeVector_
;
468 * Helper to create EnumOptionStorage instances.
470 * This function works as a proxy between EnumOption::createStorage() and the
471 * EnumOptionStorage constructor, such that the latter does not need to be
472 * exposed in the header.
474 * \ingroup module_options
476 AbstractOptionStorage
* createEnumOptionStorage(const AbstractOption
& option
,
477 const char* const* enumValues
,
480 int defaultValueIfSet
,
481 std::unique_ptr
<IOptionValueStore
<int>> store
);
484 } // namespace internal
486 //! \addtogroup module_options
490 * Specifies an option that accepts enumerated string values and writes the
491 * selected index into an `enum` variable.
493 * \tparam EnumType Type of the variable that receives the values
494 * (can also be `int`).
498 enum MyEnum { eAtom, eRes, eMol };
499 using gmx::EnumOption;
500 const char * const allowed[] = { "atom", "residue", "molecule" };
501 MyEnum value = eAtom; // default value
502 options.addOption(EnumOption<MyEnum>("type").enumValue(allowed).store(&value));
505 * storeCount() is not currently implemented for this option type, and
506 * providing multiple default values through an array passed to store() does
507 * not work consistently in all cases.
508 * In the current implementation, the values of the enum type should correspond
509 * to indices in the array passed to enumValue(), i.e., be consencutive
510 * starting from zero. Only values corresponding to valid indices are accepted
511 * as parameters to, e.g., defaultValue(). However, other values can be used
512 * as the initial value of the variable (`value` in the above example), and
513 * those will be preserved if the option is not set.
515 * Public methods in this class do not throw.
519 template<typename EnumType
>
520 class EnumOption
: public OptionTemplate
<EnumType
, EnumOption
<EnumType
>>
523 //! OptionInfo subclass corresponding to this option type.
524 typedef EnumOptionInfo InfoType
;
526 // This needs to be duplicated from OptionTemplate because this class
528 //! Short-hand for the base class.
529 typedef OptionTemplate
<EnumType
, EnumOption
<EnumType
>> MyBase
;
531 //! Initializes an option with the given name.
532 explicit EnumOption(const char* name
) : MyBase(name
), enumValues_(nullptr), enumValuesCount_(0)
537 * Sets the option to only accept one of a fixed set of strings.
539 * \param[in] values Array of strings to accept.
541 * Also accepts prefixes of the strings; if a prefix matches more than
542 * one of the possible strings, the shortest one is used (in a tie, the
545 * The strings are copied once the option is created.
547 template<size_t count
>
548 EnumOption
& enumValue(const char* const (&values
)[count
])
550 GMX_ASSERT(enumValues_
== nullptr, "Multiple sets of enumerated values specified");
551 enumValues_
= values
;
552 enumValuesCount_
= count
;
556 * Sets the option to only accept one of a fixed set of strings.
558 * \param[in] values Array of strings to accept, with a NULL pointer
559 * following the last string.
561 * Works otherwise as the array version, but accepts a pointer to
562 * an array of undetermined length. The end of the array is indicated
563 * by a NULL pointer in the array.
567 EnumOption
& enumValueFromNullTerminatedArray(const char* const* values
)
569 GMX_ASSERT(enumValues_
== nullptr, "Multiple sets of enumerated values specified");
570 enumValues_
= values
;
571 enumValuesCount_
= -1;
576 //! Helper function to convert default values for storate initialization.
577 static int convertToInt(const EnumType
* defaultValue
)
579 return defaultValue
!= nullptr ? static_cast<int>(*defaultValue
) : -1;
582 //! Creates a EnumOptionStorage object.
583 AbstractOptionStorage
* createStorage(const OptionManagerContainer
& /*managers*/) const override
585 // TODO: Implement storeCount() if necessary.
586 return internal::createEnumOptionStorage(*this, enumValues_
, enumValuesCount_
,
587 convertToInt(MyBase::defaultValue()),
588 convertToInt(MyBase::defaultValueIfSet()),
589 std::make_unique
<internal::EnumIndexStore
<EnumType
>>(
590 MyBase::store(), MyBase::storeVector()));
593 const char* const* enumValues_
;
594 int enumValuesCount_
;
597 * Needed to initialize EnumOptionStorage from this class without
598 * otherwise unnecessary accessors.
600 friend class EnumOptionStorage
;
603 //! Shorthand for an enumerated option that stores into an `int` variable.
604 typedef EnumOption
<int> EnumIntOption
;
607 * Wrapper class for accessing boolean option information.
611 class BooleanOptionInfo
: public OptionInfo
614 //! Creates an option info object for the given option.
615 explicit BooleanOptionInfo(BooleanOptionStorage
* option
);
617 //! Returns the default value for this option.
618 bool defaultValue() const;
621 const BooleanOptionStorage
& option() const;
625 * Wrapper class for accessing integer option information.
629 class IntegerOptionInfo
: public OptionInfo
632 //! Creates an option info object for the given option.
633 explicit IntegerOptionInfo(IntegerOptionStorage
* option
);
637 * Wrapper class for accessing 64-bit integer option information.
641 class Int64OptionInfo
: public OptionInfo
644 //! Creates an option info object for the given option.
645 explicit Int64OptionInfo(Int64OptionStorage
* option
);
649 * Wrapper class for accessing floating-point option information.
653 class DoubleOptionInfo
: public OptionInfo
656 //! Creates an option info object for the given option.
657 explicit DoubleOptionInfo(DoubleOptionStorage
* option
);
659 //! Whether the option specifies a time value.
663 * Sets a scale factor for user-provided values.
665 * Any user-provided value is scaled by the provided factor.
666 * Programmatically set default values are not scaled.
667 * If called multiple times, later calls override the previously set
668 * value. In other words, the scaling is not cumulative.
670 void setScaleFactor(double factor
);
673 DoubleOptionStorage
& option();
674 const DoubleOptionStorage
& option() const;
678 * Wrapper class for accessing floating-point option information.
682 class FloatOptionInfo
: public OptionInfo
685 //! Creates an option info object for the given option.
686 explicit FloatOptionInfo(FloatOptionStorage
* option
);
688 //! Whether the option specifies a time value.
691 //! \copydoc DoubleOptionInfo::setScaleFactor()
692 void setScaleFactor(double factor
);
695 FloatOptionStorage
& option();
696 const FloatOptionStorage
& option() const;
700 * Wrapper class for accessing string option information.
704 class StringOptionInfo
: public OptionInfo
707 //! Creates an option info object for the given option.
708 explicit StringOptionInfo(StringOptionStorage
* option
);
711 * Whether this option accepts an enumerated set of values.
713 * Returns true if StringOption::enumValues() was used when creating
716 bool isEnumerated() const;
718 * Returns the set of allowed values for this option.
720 * Returns an empty vector if isEnumerated() returns false.
722 const std::vector
<std::string
>& allowedValues() const;
725 const StringOptionStorage
& option() const;
729 * Wrapper class for accessing enum option information.
733 class EnumOptionInfo
: public OptionInfo
736 //! Creates an option info object for the given option.
737 explicit EnumOptionInfo(EnumOptionStorage
* option
);
740 * Returns the set of allowed values for this option.
742 const std::vector
<std::string
>& allowedValues() const;
745 const EnumOptionStorage
& option() const;
748 /*! \typedef RealOption
750 * Typedef for either DoubleOption or FloatOption, depending on precision.
752 * Generally, new would be better using DoubleOption, but this is provided for
753 * cases where the output value needs to be of type `real` for some reason.
755 /*! \typedef RealOptionInfo
757 * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
759 * Generally, new would be better using DoubleOption, but this is provided for
760 * cases where the output value needs to be of type `real` for some reason.
763 typedef DoubleOption RealOption
;
764 typedef DoubleOptionInfo RealOptionInfo
;
766 typedef FloatOption RealOption
;
767 typedef FloatOptionInfo RealOptionInfo
;