2 * This file is part of the GROMACS molecular simulation package.
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.
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.
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.
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.
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.
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.
37 * Declares option objects for basic option types.
39 * Together with options.h, this header forms the part of the public API
40 * that most classes will use to provide options.
42 * \author Teemu Murtola <teemu.murtola@gmail.com>
44 * \ingroup module_options
46 #ifndef GMX_OPTIONS_BASICOPTIONS_H
47 #define GMX_OPTIONS_BASICOPTIONS_H
52 #include "gromacs/compat/make_unique.h"
53 #include "gromacs/options/abstractoption.h"
54 #include "gromacs/options/ivaluestore.h"
55 #include "gromacs/utility/arrayref.h"
56 #include "gromacs/utility/basedefinitions.h"
57 #include "gromacs/utility/gmxassert.h"
62 class BooleanOptionInfo;
63 class BooleanOptionStorage;
64 class IntegerOptionInfo;
65 class IntegerOptionStorage;
66 class Int64OptionInfo;
67 class Int64OptionStorage;
68 class DoubleOptionInfo;
69 class DoubleOptionStorage;
70 class FloatOptionInfo;
71 class FloatOptionStorage;
72 class StringOptionInfo;
73 class StringOptionStorage;
75 class EnumOptionStorage;
77 //! \addtogroup module_options
81 * Specifies an option that provides boolean values.
86 using gmx::BooleanOption;
87 options.addOption(BooleanOption("pbc").store(&bPBC));
90 * Public methods in this class do not throw.
94 class BooleanOption : public OptionTemplate<bool, BooleanOption>
97 //! OptionInfo subclass corresponding to this option type.
98 typedef BooleanOptionInfo InfoType;
100 //! Initializes an option with the given name.
101 explicit BooleanOption(const char *name) : MyBase(name) {}
104 //! Creates a BooleanOptionStorage object.
105 AbstractOptionStorage *createStorage(
106 const OptionManagerContainer &managers) const override;
110 * Specifies an option that provides integer values.
114 using gmx::IntegerOption;
117 options.addOption(IntegerOption("rcut").store(&rcut));
118 // Vector-valued option
119 int box[3] = {1, 1, 1}; // Default value
120 options.addOption(IntegerOption("box").store(box).vector());
123 * Public methods in this class do not throw.
127 class IntegerOption : public OptionTemplate<int, IntegerOption>
130 //! OptionInfo subclass corresponding to this option type.
131 typedef IntegerOptionInfo InfoType;
133 //! Initializes an option with the given name.
134 explicit IntegerOption(const char *name) : MyBase(name) {}
137 * Sets the option to return a vector value.
139 * A vector value returns a fixed number of values, the default being
140 * three (can be changed with valueCount()). However, it also accepts
141 * a single value, in which case the value is used to fill the whole
144 MyClass &vector() { setVector(); return me(); }
147 //! Creates an IntegerOptionStorage object.
148 AbstractOptionStorage *createStorage(
149 const OptionManagerContainer &managers) const override;
152 * Needed to initialize IntegerOptionStorage from this class without
153 * otherwise unnecessary accessors.
155 friend class IntegerOptionStorage;
159 * Specifies an option that provides 64-bit integer values.
161 * Public methods in this class do not throw.
167 class Int64Option : public OptionTemplate<int64_t, Int64Option>
170 //! OptionInfo subclass corresponding to this option type.
171 typedef Int64OptionInfo InfoType;
173 //! Initializes an option with the given name.
174 explicit Int64Option(const char *name) : MyBase(name) {}
177 //! Creates an Int64OptionStorage object.
178 AbstractOptionStorage *createStorage(
179 const OptionManagerContainer &managers) const override;
182 * Needed to initialize Int64OptionStorage from this class without
183 * otherwise unnecessary accessors.
185 friend class Int64OptionStorage;
189 * Specifies an option that provides floating-point (double) values.
191 * Public methods in this class do not throw.
195 class DoubleOption : public OptionTemplate<double, DoubleOption>
198 //! OptionInfo subclass corresponding to this option type.
199 typedef DoubleOptionInfo InfoType;
201 //! Initializes an option with the given name.
202 explicit DoubleOption(const char *name) : MyBase(name), bTime_(false)
206 //! \copydoc IntegerOption::vector()
207 MyClass &vector() { setVector(); return me(); }
209 * Marks this option as providing a time value whose unit can be changed.
211 * By itself, this option does nothing. It marks the option as a time
212 * value such that TimeUnitManager::scaleTimeOptions() can process it.
213 * In typical cases, \Gromacs scales the time options just before
214 * Options::finish() has been called, so the option value is only
215 * available after all option values have been processed.
216 * All values in the program are in ps (including any default value);
217 * user-provided values are scaled according to the time unit set in
220 MyClass &timeValue() { bTime_ = true; return me(); }
223 //! Creates a DoubleOptionStorage object.
224 AbstractOptionStorage *createStorage(
225 const OptionManagerContainer &managers) const override;
230 * Needed to initialize DoubleOptionStorage from this class without
231 * otherwise unnecessary accessors.
233 friend class DoubleOptionStorage;
237 * Specifies an option that provides floating-point (float) values.
239 * Public methods in this class do not throw.
245 class FloatOption : public OptionTemplate<float, FloatOption>
248 //! OptionInfo subclass corresponding to this option type.
249 typedef FloatOptionInfo InfoType;
251 //! Initializes an option with the given name.
252 explicit FloatOption(const char *name) : MyBase(name), bTime_(false)
256 //! \copydoc IntegerOption::vector()
257 MyClass &vector() { setVector(); return me(); }
258 //! \copydoc DoubleOption::timeValue()
259 MyClass &timeValue() { bTime_ = true; return me(); }
262 //! Creates a FloatOptionStorage object.
263 AbstractOptionStorage *createStorage(
264 const OptionManagerContainer &managers) const override;
269 * Needed to initialize FloatOptionStorage from this class without
270 * otherwise unnecessary accessors.
272 friend class FloatOptionStorage;
276 * Specifies an option that provides string values.
280 using gmx::StringOption;
283 options.addOption(StringOption("str").store(&str));
284 // Option that only accepts predefined values
285 const char * const allowed[] = { "atom", "residue", "molecule" };
287 options.addOption(StringOption("type").enumValue(allowed).store(&str));
290 * Public methods in this class do not throw.
294 class StringOption : public OptionTemplate<std::string, StringOption>
297 //! OptionInfo subclass corresponding to this option type.
298 typedef StringOptionInfo InfoType;
300 //! Initializes an option with the given name.
301 explicit StringOption(const char *name)
302 : MyBase(name), enumValues_(nullptr), enumValuesCount_(0),
303 defaultEnumIndex_(-1)
308 * Sets the option to only accept one of a fixed set of strings.
310 * \param[in] values Array of strings to accept.
312 * Also accepts prefixes of the strings; if a prefix matches more than
313 * one of the possible strings, the shortest one is used (in a tie, the
316 * The strings are copied once the option is created.
318 template <size_t count>
319 MyClass &enumValue(const char *const (&values)[count])
321 GMX_ASSERT(enumValues_ == nullptr,
322 "Multiple sets of enumerated values specified");
323 enumValues_ = values;
324 enumValuesCount_ = count;
328 * Sets the option to only accept one of a fixed set of strings.
330 * \param[in] values Array of strings to accept, with a NULL pointer
331 * following the last string.
333 * Works otherwise as the array version, but accepts a pointer to
334 * an array of undetermined length. The end of the array is indicated
335 * by a NULL pointer in the array.
339 MyClass &enumValueFromNullTerminatedArray(const char *const *values)
341 GMX_ASSERT(enumValues_ == nullptr,
342 "Multiple sets of enumerated values specified");
343 enumValues_ = values;
344 enumValuesCount_ = -1;
348 * Sets the default value using an index into the enumeration table.
350 * Cannot be specified without enumValue().
352 MyClass &defaultEnumIndex(int index)
354 GMX_ASSERT(index >= 0, "Invalid enumeration index");
355 defaultEnumIndex_ = index;
360 //! Creates a StringOptionStorage object.
361 AbstractOptionStorage *createStorage(
362 const OptionManagerContainer &managers) const override;
364 const char *const *enumValues_;
365 int enumValuesCount_;
366 int defaultEnumIndex_;
369 * Needed to initialize StringOptionStorage from this class without
370 * otherwise unnecessary accessors.
372 friend class StringOptionStorage;
382 * Type-specific implementation for IOptionValueStore for an enum option.
384 * This class is instantiated for each enum type for which EnumOption is used,
385 * and takes care of managing `int`-to-`enum` conversions. Having this part in
386 * the header allows the actual storage implementation to not be in the header,
387 * which would require exposing all the internals through this one header...
389 * \ingroup module_options
391 template <typename EnumType>
392 class EnumIndexStore : public IOptionValueStore<int>
395 //! Initializes the storage for the given actual enum variables.
396 EnumIndexStore(EnumType *store, std::vector<EnumType> *storeVector)
397 : store_(store), storeVector_(storeVector)
399 if (storeVector_ != nullptr)
401 for (EnumType value : *storeVector_)
403 intStore_.push_back(static_cast<int>(value));
406 else if (store_ != nullptr)
408 // TODO: Copy more than one value if that would make sense.
409 intStore_.push_back(static_cast<int>(store_[0]));
413 int valueCount() override { return static_cast<int>(intStore_.size()); }
414 ArrayRef<int> values() override { return intStore_; }
415 void clear() override
418 if (storeVector_ != nullptr)
420 storeVector_->clear();
423 void reserve(size_t count) override
425 intStore_.reserve(intStore_.size() + count);
426 if (storeVector_ != nullptr)
428 storeVector_->reserve(storeVector_->size() + count);
431 void append(const int &value) override
433 const size_t count = intStore_.size();
434 intStore_.push_back(value);
435 if (store_ != nullptr)
437 store_[count] = static_cast<EnumType>(value);
439 if (storeVector_ != nullptr)
441 storeVector_->push_back(static_cast<EnumType>(value));
446 //! Stores the integer values for values().
447 std::vector<int> intStore_;
449 std::vector<EnumType> *storeVector_;
455 * Helper to create EnumOptionStorage instances.
457 * This function works as a proxy between EnumOption::createStorage() and the
458 * EnumOptionStorage constructor, such that the latter does not need to be
459 * exposed in the header.
461 * \ingroup module_options
463 AbstractOptionStorage *
464 createEnumOptionStorage(const AbstractOption &option,
465 const char *const *enumValues, int count,
466 int defaultValue, int defaultValueIfSet,
467 std::unique_ptr<IOptionValueStore<int> > store);
470 } // namespace internal
472 //! \addtogroup module_options
476 * Specifies an option that accepts enumerated string values and writes the
477 * selected index into an `enum` variable.
479 * \tparam EnumType Type of the variable that receives the values
480 * (can also be `int`).
484 enum MyEnum { eAtom, eRes, eMol };
485 using gmx::EnumOption;
486 const char * const allowed[] = { "atom", "residue", "molecule" };
487 MyEnum value = eAtom; // default value
488 options.addOption(EnumOption<MyEnum>("type").enumValue(allowed).store(&value));
491 * storeCount() is not currently implemented for this option type, and
492 * providing multiple default values through an array passed to store() does
493 * not work consistently in all cases.
494 * In the current implementation, the values of the enum type should correspond
495 * to indices in the array passed to enumValue(), i.e., be consencutive
496 * starting from zero. Only values corresponding to valid indices are accepted
497 * as parameters to, e.g., defaultValue(). However, other values can be used
498 * as the initial value of the variable (`value` in the above example), and
499 * those will be preserved if the option is not set.
501 * Public methods in this class do not throw.
505 template <typename EnumType>
506 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType> >
509 //! OptionInfo subclass corresponding to this option type.
510 typedef EnumOptionInfo InfoType;
512 // This needs to be duplicated from OptionTemplate because this class
514 //! Short-hand for the base class.
515 typedef OptionTemplate<EnumType, EnumOption<EnumType> > MyBase;
517 //! Initializes an option with the given name.
518 explicit EnumOption(const char *name)
519 : MyBase(name), enumValues_(nullptr), enumValuesCount_(0)
524 * Sets the option to only accept one of a fixed set of strings.
526 * \param[in] values Array of strings to accept.
528 * Also accepts prefixes of the strings; if a prefix matches more than
529 * one of the possible strings, the shortest one is used (in a tie, the
532 * The strings are copied once the option is created.
534 template <size_t count>
535 EnumOption &enumValue(const char *const (&values)[count])
537 GMX_ASSERT(enumValues_ == nullptr,
538 "Multiple sets of enumerated values specified");
539 enumValues_ = values;
540 enumValuesCount_ = count;
544 * Sets the option to only accept one of a fixed set of strings.
546 * \param[in] values Array of strings to accept, with a NULL pointer
547 * following the last string.
549 * Works otherwise as the array version, but accepts a pointer to
550 * an array of undetermined length. The end of the array is indicated
551 * by a NULL pointer in the array.
555 EnumOption &enumValueFromNullTerminatedArray(const char *const *values)
557 GMX_ASSERT(enumValues_ == nullptr,
558 "Multiple sets of enumerated values specified");
559 enumValues_ = values;
560 enumValuesCount_ = -1;
565 //! Helper function to convert default values for storate initialization.
566 static int convertToInt(const EnumType *defaultValue)
568 return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
571 //! Creates a EnumOptionStorage object.
572 AbstractOptionStorage *createStorage(
573 const OptionManagerContainer & /*managers*/) const override
575 // TODO: Implement storeCount() if necessary.
576 return internal::createEnumOptionStorage(
577 *this, enumValues_, enumValuesCount_,
578 convertToInt(MyBase::defaultValue()),
579 convertToInt(MyBase::defaultValueIfSet()),
580 compat::make_unique<internal::EnumIndexStore<EnumType> >(
581 MyBase::store(), MyBase::storeVector()));
584 const char *const *enumValues_;
585 int enumValuesCount_;
588 * Needed to initialize EnumOptionStorage from this class without
589 * otherwise unnecessary accessors.
591 friend class EnumOptionStorage;
594 //! Shorthand for an enumerated option that stores into an `int` variable.
595 typedef EnumOption<int> EnumIntOption;
598 * Wrapper class for accessing boolean option information.
602 class BooleanOptionInfo : public OptionInfo
605 //! Creates an option info object for the given option.
606 explicit BooleanOptionInfo(BooleanOptionStorage *option);
608 //! Returns the default value for this option.
609 bool defaultValue() const;
612 const BooleanOptionStorage &option() const;
616 * Wrapper class for accessing integer option information.
620 class IntegerOptionInfo : public OptionInfo
623 //! Creates an option info object for the given option.
624 explicit IntegerOptionInfo(IntegerOptionStorage *option);
628 * Wrapper class for accessing 64-bit integer option information.
632 class Int64OptionInfo : public OptionInfo
635 //! Creates an option info object for the given option.
636 explicit Int64OptionInfo(Int64OptionStorage *option);
640 * Wrapper class for accessing floating-point option information.
644 class DoubleOptionInfo : public OptionInfo
647 //! Creates an option info object for the given option.
648 explicit DoubleOptionInfo(DoubleOptionStorage *option);
650 //! Whether the option specifies a time value.
654 * Sets a scale factor for user-provided values.
656 * Any user-provided value is scaled by the provided factor.
657 * Programmatically set default values are not scaled.
658 * If called multiple times, later calls override the previously set
659 * value. In other words, the scaling is not cumulative.
661 void setScaleFactor(double factor);
664 DoubleOptionStorage &option();
665 const DoubleOptionStorage &option() const;
669 * Wrapper class for accessing floating-point option information.
673 class FloatOptionInfo : public OptionInfo
676 //! Creates an option info object for the given option.
677 explicit FloatOptionInfo(FloatOptionStorage *option);
679 //! Whether the option specifies a time value.
682 //! \copydoc DoubleOptionInfo::setScaleFactor()
683 void setScaleFactor(double factor);
686 FloatOptionStorage &option();
687 const FloatOptionStorage &option() const;
691 * Wrapper class for accessing string option information.
695 class StringOptionInfo : public OptionInfo
698 //! Creates an option info object for the given option.
699 explicit StringOptionInfo(StringOptionStorage *option);
702 * Whether this option accepts an enumerated set of values.
704 * Returns true if StringOption::enumValues() was used when creating
707 bool isEnumerated() const;
709 * Returns the set of allowed values for this option.
711 * Returns an empty vector if isEnumerated() returns false.
713 const std::vector<std::string> &allowedValues() const;
716 const StringOptionStorage &option() const;
720 * Wrapper class for accessing enum option information.
724 class EnumOptionInfo : public OptionInfo
727 //! Creates an option info object for the given option.
728 explicit EnumOptionInfo(EnumOptionStorage *option);
731 * Returns the set of allowed values for this option.
733 const std::vector<std::string> &allowedValues() const;
736 const EnumOptionStorage &option() const;
739 /*! \typedef RealOption
741 * Typedef for either DoubleOption or FloatOption, depending on precision.
743 * Generally, new would be better using DoubleOption, but this is provided for
744 * cases where the output value needs to be of type `real` for some reason.
746 /*! \typedef RealOptionInfo
748 * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
750 * Generally, new would be better using DoubleOption, but this is provided for
751 * cases where the output value needs to be of type `real` for some reason.
754 typedef DoubleOption RealOption;
755 typedef DoubleOptionInfo RealOptionInfo;
757 typedef FloatOption RealOption;
758 typedef FloatOptionInfo RealOptionInfo;