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/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"
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;
74 class EnumOptionStorage;
76 //! \addtogroup module_options
80 * Specifies an option that provides boolean values.
85 using gmx::BooleanOption;
86 options.addOption(BooleanOption("pbc").store(&bPBC));
89 * Public methods in this class do not throw.
93 class BooleanOption : public OptionTemplate<bool, BooleanOption>
96 //! OptionInfo subclass corresponding to this option type.
97 typedef BooleanOptionInfo InfoType;
99 //! Initializes an option with the given name.
100 explicit BooleanOption(const char *name) : MyBase(name) {}
103 //! Creates a BooleanOptionStorage object.
104 virtual AbstractOptionStorage *createStorage(
105 const OptionManagerContainer &managers) const;
109 * Specifies an option that provides integer values.
113 using gmx::IntegerOption;
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());
122 * Public methods in this class do not throw.
126 class IntegerOption : public OptionTemplate<int, IntegerOption>
129 //! OptionInfo subclass corresponding to this option type.
130 typedef IntegerOptionInfo InfoType;
132 //! Initializes an option with the given name.
133 explicit IntegerOption(const char *name) : MyBase(name) {}
136 * Sets the option to return a vector value.
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
143 MyClass &vector() { setVector(); return me(); }
146 //! Creates an IntegerOptionStorage object.
147 virtual AbstractOptionStorage *createStorage(
148 const OptionManagerContainer &managers) const;
151 * Needed to initialize IntegerOptionStorage from this class without
152 * otherwise unnecessary accessors.
154 friend class IntegerOptionStorage;
158 * Specifies an option that provides 64-bit integer values.
160 * Public methods in this class do not throw.
166 class Int64Option : public OptionTemplate<int64_t, Int64Option>
169 //! OptionInfo subclass corresponding to this option type.
170 typedef Int64OptionInfo InfoType;
172 //! Initializes an option with the given name.
173 explicit Int64Option(const char *name) : MyBase(name) {}
176 //! Creates an Int64OptionStorage object.
177 virtual AbstractOptionStorage *createStorage(
178 const OptionManagerContainer &managers) const;
181 * Needed to initialize Int64OptionStorage from this class without
182 * otherwise unnecessary accessors.
184 friend class Int64OptionStorage;
188 * Specifies an option that provides floating-point (double) values.
190 * Public methods in this class do not throw.
194 class DoubleOption : public OptionTemplate<double, DoubleOption>
197 //! OptionInfo subclass corresponding to this option type.
198 typedef DoubleOptionInfo InfoType;
200 //! Initializes an option with the given name.
201 explicit DoubleOption(const char *name) : MyBase(name), bTime_(false)
205 //! \copydoc IntegerOption::vector()
206 MyClass &vector() { setVector(); return me(); }
208 * Marks this option as providing a time value whose unit can be changed.
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
219 MyClass &timeValue() { bTime_ = true; return me(); }
222 //! Creates a DoubleOptionStorage object.
223 virtual AbstractOptionStorage *createStorage(
224 const OptionManagerContainer &managers) const;
229 * Needed to initialize DoubleOptionStorage from this class without
230 * otherwise unnecessary accessors.
232 friend class DoubleOptionStorage;
236 * Specifies an option that provides floating-point (float) values.
238 * Public methods in this class do not throw.
244 class FloatOption : public OptionTemplate<float, FloatOption>
247 //! OptionInfo subclass corresponding to this option type.
248 typedef FloatOptionInfo InfoType;
250 //! Initializes an option with the given name.
251 explicit FloatOption(const char *name) : MyBase(name), bTime_(false)
255 //! \copydoc IntegerOption::vector()
256 MyClass &vector() { setVector(); return me(); }
257 //! \copydoc DoubleOption::timeValue()
258 MyClass &timeValue() { bTime_ = true; return me(); }
261 //! Creates a FloatOptionStorage object.
262 virtual AbstractOptionStorage *createStorage(
263 const OptionManagerContainer &managers) const;
268 * Needed to initialize FloatOptionStorage from this class without
269 * otherwise unnecessary accessors.
271 friend class FloatOptionStorage;
275 * Specifies an option that provides string values.
279 using gmx::StringOption;
282 options.addOption(StringOption("str").store(&str));
283 // Option that only accepts predefined values
284 const char * const allowed[] = { "atom", "residue", "molecule" };
286 options.addOption(StringOption("type").enumValue(allowed).store(&str));
289 * Public methods in this class do not throw.
293 class StringOption : public OptionTemplate<std::string, StringOption>
296 //! OptionInfo subclass corresponding to this option type.
297 typedef StringOptionInfo InfoType;
299 //! Initializes an option with the given name.
300 explicit StringOption(const char *name)
301 : MyBase(name), enumValues_(nullptr), enumValuesCount_(0),
302 defaultEnumIndex_(-1)
307 * Sets the option to only accept one of a fixed set of strings.
309 * \param[in] values Array of strings to accept.
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
315 * The strings are copied once the option is created.
317 template <size_t count>
318 MyClass &enumValue(const char *const (&values)[count])
320 GMX_ASSERT(enumValues_ == nullptr,
321 "Multiple sets of enumerated values specified");
322 enumValues_ = values;
323 enumValuesCount_ = count;
327 * Sets the option to only accept one of a fixed set of strings.
329 * \param[in] values Array of strings to accept, with a NULL pointer
330 * following the last string.
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.
338 MyClass &enumValueFromNullTerminatedArray(const char *const *values)
340 GMX_ASSERT(enumValues_ == nullptr,
341 "Multiple sets of enumerated values specified");
342 enumValues_ = values;
343 enumValuesCount_ = -1;
347 * Sets the default value using an index into the enumeration table.
349 * Cannot be specified without enumValue().
351 MyClass &defaultEnumIndex(int index)
353 GMX_ASSERT(index >= 0, "Invalid enumeration index");
354 defaultEnumIndex_ = index;
359 //! Creates a StringOptionStorage object.
360 virtual AbstractOptionStorage *createStorage(
361 const OptionManagerContainer &managers) const;
363 const char *const *enumValues_;
364 int enumValuesCount_;
365 int defaultEnumIndex_;
368 * Needed to initialize StringOptionStorage from this class without
369 * otherwise unnecessary accessors.
371 friend class StringOptionStorage;
381 * Type-specific implementation for IOptionValueStore for an enum option.
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...
388 * \ingroup module_options
390 template <typename EnumType>
391 class EnumIndexStore : public IOptionValueStore<int>
394 //! Initializes the storage for the given actual enum variables.
395 EnumIndexStore(EnumType *store, std::vector<EnumType> *storeVector)
396 : store_(store), storeVector_(storeVector)
398 if (storeVector_ != nullptr)
400 for (EnumType value : *storeVector_)
402 intStore_.push_back(static_cast<int>(value));
405 else if (store_ != nullptr)
407 // TODO: Copy more than one value if that would make sense.
408 intStore_.push_back(static_cast<int>(store_[0]));
412 virtual int valueCount() { return static_cast<int>(intStore_.size()); }
413 virtual ArrayRef<int> values() { return intStore_; }
417 if (storeVector_ != nullptr)
419 storeVector_->clear();
422 virtual void reserve(size_t count)
424 intStore_.reserve(intStore_.size() + count);
425 if (storeVector_ != nullptr)
427 storeVector_->reserve(storeVector_->size() + count);
430 virtual void append(const int &value)
432 const size_t count = intStore_.size();
433 intStore_.push_back(value);
434 if (store_ != nullptr)
436 store_[count] = static_cast<EnumType>(value);
438 if (storeVector_ != nullptr)
440 storeVector_->push_back(static_cast<EnumType>(value));
445 //! Stores the integer values for values().
446 std::vector<int> intStore_;
448 std::vector<EnumType> *storeVector_;
454 * Helper to create EnumOptionStorage instances.
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.
460 * \ingroup module_options
462 AbstractOptionStorage *
463 createEnumOptionStorage(const AbstractOption &option,
464 const char *const *enumValues, int count,
465 int defaultValue, int defaultValueIfSet,
466 IOptionValueStore<int> *store);
469 } // namespace internal
471 //! \addtogroup module_options
475 * Specifies an option that accepts enumerated string values and writes the
476 * selected index into an `enum` variable.
478 * \tparam EnumType Type of the variable that receives the values
479 * (can also be `int`).
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));
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.
500 * Public methods in this class do not throw.
504 template <typename EnumType>
505 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType> >
508 //! OptionInfo subclass corresponding to this option type.
509 typedef EnumOptionInfo InfoType;
511 // This needs to be duplicated from OptionTemplate because this class
513 //! Short-hand for the base class.
514 typedef OptionTemplate<EnumType, EnumOption<EnumType> > MyBase;
516 //! Initializes an option with the given name.
517 explicit EnumOption(const char *name)
518 : MyBase(name), enumValues_(nullptr), enumValuesCount_(0)
523 * Sets the option to only accept one of a fixed set of strings.
525 * \param[in] values Array of strings to accept.
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
531 * The strings are copied once the option is created.
533 template <size_t count>
534 EnumOption &enumValue(const char *const (&values)[count])
536 GMX_ASSERT(enumValues_ == nullptr,
537 "Multiple sets of enumerated values specified");
538 enumValues_ = values;
539 enumValuesCount_ = count;
543 * Sets the option to only accept one of a fixed set of strings.
545 * \param[in] values Array of strings to accept, with a NULL pointer
546 * following the last string.
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.
554 EnumOption &enumValueFromNullTerminatedArray(const char *const *values)
556 GMX_ASSERT(enumValues_ == nullptr,
557 "Multiple sets of enumerated values specified");
558 enumValues_ = values;
559 enumValuesCount_ = -1;
564 //! Helper function to convert default values for storate initialization.
565 static int convertToInt(const EnumType *defaultValue)
567 return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
570 //! Creates a EnumOptionStorage object.
571 virtual AbstractOptionStorage *createStorage(
572 const OptionManagerContainer & /*managers*/) const
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()));
583 const char *const *enumValues_;
584 int enumValuesCount_;
587 * Needed to initialize EnumOptionStorage from this class without
588 * otherwise unnecessary accessors.
590 friend class EnumOptionStorage;
593 //! Shorthand for an enumerated option that stores into an `int` variable.
594 typedef EnumOption<int> EnumIntOption;
597 * Wrapper class for accessing boolean option information.
601 class BooleanOptionInfo : public OptionInfo
604 //! Creates an option info object for the given option.
605 explicit BooleanOptionInfo(BooleanOptionStorage *option);
607 //! Returns the default value for this option.
608 bool defaultValue() const;
611 const BooleanOptionStorage &option() const;
615 * Wrapper class for accessing integer option information.
619 class IntegerOptionInfo : public OptionInfo
622 //! Creates an option info object for the given option.
623 explicit IntegerOptionInfo(IntegerOptionStorage *option);
627 * Wrapper class for accessing 64-bit integer option information.
631 class Int64OptionInfo : public OptionInfo
634 //! Creates an option info object for the given option.
635 explicit Int64OptionInfo(Int64OptionStorage *option);
639 * Wrapper class for accessing floating-point option information.
643 class DoubleOptionInfo : public OptionInfo
646 //! Creates an option info object for the given option.
647 explicit DoubleOptionInfo(DoubleOptionStorage *option);
649 //! Whether the option specifies a time value.
653 * Sets a scale factor for user-provided values.
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.
660 void setScaleFactor(double factor);
663 DoubleOptionStorage &option();
664 const DoubleOptionStorage &option() const;
668 * Wrapper class for accessing floating-point option information.
672 class FloatOptionInfo : public OptionInfo
675 //! Creates an option info object for the given option.
676 explicit FloatOptionInfo(FloatOptionStorage *option);
678 //! Whether the option specifies a time value.
681 //! \copydoc DoubleOptionInfo::setScaleFactor()
682 void setScaleFactor(double factor);
685 FloatOptionStorage &option();
686 const FloatOptionStorage &option() const;
690 * Wrapper class for accessing string option information.
694 class StringOptionInfo : public OptionInfo
697 //! Creates an option info object for the given option.
698 explicit StringOptionInfo(StringOptionStorage *option);
701 * Whether this option accepts an enumerated set of values.
703 * Returns true if StringOption::enumValues() was used when creating
706 bool isEnumerated() const;
708 * Returns the set of allowed values for this option.
710 * Returns an empty vector if isEnumerated() returns false.
712 const std::vector<std::string> &allowedValues() const;
715 const StringOptionStorage &option() const;
719 * Wrapper class for accessing enum option information.
723 class EnumOptionInfo : public OptionInfo
726 //! Creates an option info object for the given option.
727 explicit EnumOptionInfo(EnumOptionStorage *option);
730 * Returns the set of allowed values for this option.
732 const std::vector<std::string> &allowedValues() const;
735 const EnumOptionStorage &option() const;
738 /*! \typedef RealOption
740 * Typedef for either DoubleOption or FloatOption, depending on precision.
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.
745 /*! \typedef RealOptionInfo
747 * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
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.
753 typedef DoubleOption RealOption;
754 typedef DoubleOptionInfo RealOptionInfo;
756 typedef FloatOption RealOption;
757 typedef FloatOptionInfo RealOptionInfo;