2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010-2018, The GROMACS development team.
5 * Copyright (c) 2019,2020, 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/enumerationhelpers.h"
58 #include "gromacs/utility/gmxassert.h"
60 #include "ivaluestore.h"
65 class BooleanOptionInfo;
66 class BooleanOptionStorage;
67 class IntegerOptionInfo;
68 class IntegerOptionStorage;
69 class Int64OptionInfo;
70 class Int64OptionStorage;
71 class DoubleOptionInfo;
72 class DoubleOptionStorage;
73 class FloatOptionInfo;
74 class FloatOptionStorage;
75 class StringOptionInfo;
76 class StringOptionStorage;
78 class EnumOptionStorage;
80 //! \addtogroup module_options
84 * Specifies an option that provides boolean values.
89 using gmx::BooleanOption;
90 options.addOption(BooleanOption("pbc").store(&bPBC));
93 * Public methods in this class do not throw.
97 class BooleanOption : public OptionTemplate<bool, BooleanOption>
100 //! OptionInfo subclass corresponding to this option type.
101 typedef BooleanOptionInfo InfoType;
103 //! Initializes an option with the given name.
104 explicit BooleanOption(const char* name) : MyBase(name) {}
107 //! Creates a BooleanOptionStorage object.
108 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
112 * Specifies an option that provides integer values.
116 using gmx::IntegerOption;
119 options.addOption(IntegerOption("rcut").store(&rcut));
120 // Vector-valued option
121 int box[3] = {1, 1, 1}; // Default value
122 options.addOption(IntegerOption("box").store(box).vector());
125 * Public methods in this class do not throw.
129 class IntegerOption : public OptionTemplate<int, IntegerOption>
132 //! OptionInfo subclass corresponding to this option type.
133 typedef IntegerOptionInfo InfoType;
135 //! Initializes an option with the given name.
136 explicit IntegerOption(const char* name) : MyBase(name) {}
139 * Sets the option to return a vector value.
141 * A vector value returns a fixed number of values, the default being
142 * three (can be changed with valueCount()). However, it also accepts
143 * a single value, in which case the value is used to fill the whole
153 //! Creates an IntegerOptionStorage object.
154 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
157 * Needed to initialize IntegerOptionStorage from this class without
158 * otherwise unnecessary accessors.
160 friend class IntegerOptionStorage;
164 * Specifies an option that provides 64-bit integer values.
166 * Public methods in this class do not throw.
172 class Int64Option : public OptionTemplate<int64_t, Int64Option>
175 //! OptionInfo subclass corresponding to this option type.
176 typedef Int64OptionInfo InfoType;
178 //! Initializes an option with the given name.
179 explicit Int64Option(const char* name) : MyBase(name) {}
182 //! Creates an Int64OptionStorage object.
183 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
186 * Needed to initialize Int64OptionStorage from this class without
187 * otherwise unnecessary accessors.
189 friend class Int64OptionStorage;
193 * Specifies an option that provides floating-point (double) values.
195 * Public methods in this class do not throw.
199 class DoubleOption : public OptionTemplate<double, DoubleOption>
202 //! OptionInfo subclass corresponding to this option type.
203 typedef DoubleOptionInfo InfoType;
205 //! Initializes an option with the given name.
206 explicit DoubleOption(const char* name) : MyBase(name), bTime_(false) {}
208 //! \copydoc IntegerOption::vector()
215 * Marks this option as providing a time value whose unit can be changed.
217 * By itself, this option does nothing. It marks the option as a time
218 * value such that TimeUnitManager::scaleTimeOptions() can process it.
219 * In typical cases, \Gromacs scales the time options just before
220 * Options::finish() has been called, so the option value is only
221 * available after all option values have been processed.
222 * All values in the program are in ps (including any default value);
223 * user-provided values are scaled according to the time unit set in
233 //! Creates a DoubleOptionStorage object.
234 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
239 * Needed to initialize DoubleOptionStorage from this class without
240 * otherwise unnecessary accessors.
242 friend class DoubleOptionStorage;
246 * Specifies an option that provides floating-point (float) values.
248 * Public methods in this class do not throw.
254 class FloatOption : public OptionTemplate<float, FloatOption>
257 //! OptionInfo subclass corresponding to this option type.
258 typedef FloatOptionInfo InfoType;
260 //! Initializes an option with the given name.
261 explicit FloatOption(const char* name) : MyBase(name), bTime_(false) {}
263 //! \copydoc IntegerOption::vector()
269 //! \copydoc DoubleOption::timeValue()
277 //! Creates a FloatOptionStorage object.
278 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
283 * Needed to initialize FloatOptionStorage from this class without
284 * otherwise unnecessary accessors.
286 friend class FloatOptionStorage;
290 * Specifies an option that provides string values.
294 using gmx::StringOption;
297 options.addOption(StringOption("str").store(&str));
298 // Option that only accepts predefined values
299 const char * const allowed[] = { "atom", "residue", "molecule" };
301 options.addOption(StringOption("type").enumValue(allowed).store(&str));
304 * Public methods in this class do not throw.
308 class StringOption : public OptionTemplate<std::string, StringOption>
311 //! OptionInfo subclass corresponding to this option type.
312 typedef StringOptionInfo InfoType;
314 //! Initializes an option with the given name.
315 explicit StringOption(const char* name) :
317 enumValues_(nullptr),
319 defaultEnumIndex_(-1)
324 * Sets the option to only accept one of a fixed set of strings.
326 * \param[in] values Array of strings to accept.
328 * Also accepts prefixes of the strings; if a prefix matches more than
329 * one of the possible strings, the shortest one is used (in a tie, the
332 * The strings are copied once the option is created.
334 template<size_t count>
335 MyClass& enumValue(const char* const (&values)[count])
337 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
338 enumValues_ = values;
339 enumValuesCount_ = count;
343 * Sets the option to only accept one of a fixed set of strings.
345 * \param[in] values Array of strings to accept, with a NULL pointer
346 * following the last string.
348 * Works otherwise as the array version, but accepts a pointer to
349 * an array of undetermined length. The end of the array is indicated
350 * by a NULL pointer in the array.
354 MyClass& enumValueFromNullTerminatedArray(const char* const* values)
356 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
357 enumValues_ = values;
358 enumValuesCount_ = -1;
362 * Sets the default value using an index into the enumeration table.
364 * Cannot be specified without enumValue().
366 MyClass& defaultEnumIndex(int index)
368 GMX_ASSERT(index >= 0, "Invalid enumeration index");
369 defaultEnumIndex_ = index;
374 //! Creates a StringOptionStorage object.
375 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
377 const char* const* enumValues_;
378 int enumValuesCount_;
379 int defaultEnumIndex_;
382 * Needed to initialize StringOptionStorage from this class without
383 * otherwise unnecessary accessors.
385 friend class StringOptionStorage;
395 * Type-specific implementation for IOptionValueStore for an enum option.
397 * This class is instantiated for each enum type for which EnumOption is used,
398 * and takes care of managing `int`-to-`enum` conversions. Having this part in
399 * the header allows the actual storage implementation to not be in the header,
400 * which would require exposing all the internals through this one header...
402 * \ingroup module_options
404 template<typename EnumType>
405 class EnumIndexStore : public IOptionValueStore<int>
408 //! Initializes the storage for the given actual enum variables.
409 EnumIndexStore(EnumType* store, std::vector<EnumType>* storeVector) :
411 storeVector_(storeVector)
413 if (storeVector_ != nullptr)
415 for (EnumType value : *storeVector_)
417 intStore_.push_back(static_cast<int>(value));
420 else if (store_ != nullptr)
422 // TODO: Copy more than one value if that would make sense.
423 intStore_.push_back(static_cast<int>(store_[0]));
427 int valueCount() override { return ssize(intStore_); }
428 ArrayRef<int> values() override { return intStore_; }
429 void clear() override
432 if (storeVector_ != nullptr)
434 storeVector_->clear();
437 void reserve(size_t count) override
439 intStore_.reserve(intStore_.size() + count);
440 if (storeVector_ != nullptr)
442 storeVector_->reserve(storeVector_->size() + count);
445 void append(const int& value) override
447 const size_t count = intStore_.size();
448 intStore_.push_back(value);
449 if (store_ != nullptr)
451 store_[count] = static_cast<EnumType>(value);
453 if (storeVector_ != nullptr)
455 storeVector_->push_back(static_cast<EnumType>(value));
460 //! Stores the integer values for values().
461 std::vector<int> intStore_;
463 std::vector<EnumType>* storeVector_;
469 * Helper to create EnumOptionStorage instances.
471 * This function works as a proxy between EnumOption::createStorage() and the
472 * EnumOptionStorage constructor, such that the latter does not need to be
473 * exposed in the header.
475 * \ingroup module_options
477 AbstractOptionStorage* createEnumOptionStorage(const AbstractOption& option,
478 const char* const* enumValues,
481 int defaultValueIfSet,
482 std::unique_ptr<IOptionValueStore<int>> store);
485 } // namespace internal
487 //! \addtogroup module_options
491 * Specifies an option that accepts an EnumerationArray of string values and writes the
492 * selected index into an `enum` variable.
494 * \tparam EnumType DataType of the variable that receives the values
498 enum class MyEnum { Atom, Res, Mol, Count } : int;
499 EnumerationArray<MyEnum, const char *> myEnumNames = { "atom", "residue", "molecule" };
500 MyEnum value = MyEnum::Atom; // default value
501 options.addOption(EnumOption<MyEnum>("type").enumValue(myEnumNames).store(&value));
504 * storeCount() is not currently implemented for this option type, and
505 * providing multiple default values through an array passed to store() does
506 * not work consistently in all cases.
507 * In the current implementation, the values of the enum type should correspond
508 * to indices in the array passed to enumValue(), i.e., be consecutive
509 * starting from zero. Only values corresponding to valid indices are accepted
510 * as parameters to, e.g., defaultValue(). However, other values can be used
511 * as the initial value of the variable (`value` in the above example), and
512 * those will be preserved if the option is not set.
514 * Public methods in this class do not throw.
518 template<typename EnumType>
519 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType>>
522 //! OptionInfo subclass corresponding to this option type.
523 typedef EnumOptionInfo InfoType;
525 // This needs to be duplicated from OptionTemplate because this class
527 //! Short-hand for the base class.
528 typedef OptionTemplate<EnumType, EnumOption<EnumType>> MyBase;
530 //! Initializes an option with the given name.
531 explicit EnumOption(const char* name) : MyBase(name), enumValues_(nullptr), enumValuesCount_(0)
536 * 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 EnumOption& enumValue(const EnumerationArray<EnumType, const char*>& values)
549 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
550 enumValues_ = values.data();
551 enumValuesCount_ = values.size();
556 //! Helper function to convert default values for storage initialization.
557 static int convertToInt(const EnumType* defaultValue)
559 return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
562 //! Creates a EnumOptionStorage object.
563 AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override
565 // TODO: Implement storeCount() if necessary.
566 return internal::createEnumOptionStorage(*this, enumValues_, enumValuesCount_,
567 convertToInt(MyBase::defaultValue()),
568 convertToInt(MyBase::defaultValueIfSet()),
569 std::make_unique<internal::EnumIndexStore<EnumType>>(
570 MyBase::store(), MyBase::storeVector()));
573 const char* const* enumValues_;
574 int enumValuesCount_;
577 * Needed to initialize EnumOptionStorage from this class without
578 * otherwise unnecessary accessors.
580 friend class EnumOptionStorage;
584 * Specifies an option that accepts enumerated string values and writes the
585 * selected index into an `enum` variable.
587 * \tparam EnumType Type of the variable that receives the values
588 * (can also be `int`).
592 enum MyEnum { eAtom, eRes, eMol };
593 using gmx::LegacyEnumOption;
594 const char * const allowed[] = { "atom", "residue", "molecule" };
595 MyEnum value = eAtom; // default value
596 options.addOption(LegacyEnumOption<MyEnum>("type").enumValue(allowed).store(&value));
599 * Works exactly as EnumOption.
601 * This is legacy support for pargsToOptions and can be removed when it
602 * is removed. No new uses of it should be made.
604 * Public methods in this class do not throw.
608 template<typename EnumType>
609 class LegacyEnumOption : public OptionTemplate<EnumType, LegacyEnumOption<EnumType>>
612 //! OptionInfo subclass corresponding to this option type.
613 typedef EnumOptionInfo InfoType;
615 // This needs to be duplicated from OptionTemplate because this class
617 //! Short-hand for the base class.
618 typedef OptionTemplate<EnumType, LegacyEnumOption<EnumType>> MyBase;
620 //! Initializes an option with the given name.
621 explicit LegacyEnumOption(const char* name) :
623 enumValues_(nullptr),
629 * Sets the option to only accept one of a fixed set of strings.
631 * \param[in] values Array of strings to accept.
633 * Also accepts prefixes of the strings; if a prefix matches more than
634 * one of the possible strings, the shortest one is used (in a tie, the
637 * The strings are copied once the option is created.
639 template<size_t count>
640 LegacyEnumOption& enumValue(const char* const (&values)[count])
642 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
643 enumValues_ = values;
644 enumValuesCount_ = count;
648 * Sets the option to only accept one of a fixed set of strings.
650 * \param[in] values Array of strings to accept, with a NULL pointer
651 * following the last string.
653 * Works otherwise as the array version, but accepts a pointer to
654 * an array of undetermined length. The end of the array is indicated
655 * by a NULL pointer in the array.
659 LegacyEnumOption& enumValueFromNullTerminatedArray(const char* const* values)
661 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
662 enumValues_ = values;
663 enumValuesCount_ = -1;
668 //! Helper function to convert default values for storage initialization.
669 static int convertToInt(const EnumType* defaultValue)
671 return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
674 //! Creates a EnumOptionStorage object.
675 AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override
677 // TODO: Implement storeCount() if necessary.
678 return internal::createEnumOptionStorage(*this, enumValues_, enumValuesCount_,
679 convertToInt(MyBase::defaultValue()),
680 convertToInt(MyBase::defaultValueIfSet()),
681 std::make_unique<internal::EnumIndexStore<EnumType>>(
682 MyBase::store(), MyBase::storeVector()));
685 const char* const* enumValues_;
686 int enumValuesCount_;
689 * Needed to initialize EnumOptionStorage from this class without
690 * otherwise unnecessary accessors.
692 friend class EnumOptionStorage;
696 * Wrapper class for accessing boolean option information.
700 class BooleanOptionInfo : public OptionInfo
703 //! Creates an option info object for the given option.
704 explicit BooleanOptionInfo(BooleanOptionStorage* option);
706 //! Returns the default value for this option.
707 bool defaultValue() const;
710 const BooleanOptionStorage& option() const;
714 * Wrapper class for accessing integer option information.
718 class IntegerOptionInfo : public OptionInfo
721 //! Creates an option info object for the given option.
722 explicit IntegerOptionInfo(IntegerOptionStorage* option);
726 * Wrapper class for accessing 64-bit integer option information.
730 class Int64OptionInfo : public OptionInfo
733 //! Creates an option info object for the given option.
734 explicit Int64OptionInfo(Int64OptionStorage* option);
738 * Wrapper class for accessing floating-point option information.
742 class DoubleOptionInfo : public OptionInfo
745 //! Creates an option info object for the given option.
746 explicit DoubleOptionInfo(DoubleOptionStorage* option);
748 //! Whether the option specifies a time value.
752 * Sets a scale factor for user-provided values.
754 * Any user-provided value is scaled by the provided factor.
755 * Programmatically set default values are not scaled.
756 * If called multiple times, later calls override the previously set
757 * value. In other words, the scaling is not cumulative.
759 void setScaleFactor(double factor);
762 DoubleOptionStorage& option();
763 const DoubleOptionStorage& option() const;
767 * Wrapper class for accessing floating-point option information.
771 class FloatOptionInfo : public OptionInfo
774 //! Creates an option info object for the given option.
775 explicit FloatOptionInfo(FloatOptionStorage* option);
777 //! Whether the option specifies a time value.
780 //! \copydoc DoubleOptionInfo::setScaleFactor()
781 void setScaleFactor(double factor);
784 FloatOptionStorage& option();
785 const FloatOptionStorage& option() const;
789 * Wrapper class for accessing string option information.
793 class StringOptionInfo : public OptionInfo
796 //! Creates an option info object for the given option.
797 explicit StringOptionInfo(StringOptionStorage* option);
800 * Whether this option accepts an enumerated set of values.
802 * Returns true if StringOption::enumValues() was used when creating
805 bool isEnumerated() const;
807 * Returns the set of allowed values for this option.
809 * Returns an empty vector if isEnumerated() returns false.
811 const std::vector<std::string>& allowedValues() const;
814 const StringOptionStorage& option() const;
818 * Wrapper class for accessing enum option information.
822 class EnumOptionInfo : public OptionInfo
825 //! Creates an option info object for the given option.
826 explicit EnumOptionInfo(EnumOptionStorage* option);
829 * Returns the set of allowed values for this option.
831 const std::vector<std::string>& allowedValues() const;
834 const EnumOptionStorage& option() const;
837 /*! \typedef RealOption
839 * Typedef for either DoubleOption or FloatOption, depending on precision.
841 * Generally, new would be better using DoubleOption, but this is provided for
842 * cases where the output value needs to be of type `real` for some reason.
844 /*! \typedef RealOptionInfo
846 * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
848 * Generally, new would be better using DoubleOption, but this is provided for
849 * cases where the output value needs to be of type `real` for some reason.
852 typedef DoubleOption RealOption;
853 typedef DoubleOptionInfo RealOptionInfo;
855 typedef FloatOption RealOption;
856 typedef FloatOptionInfo RealOptionInfo;