Take over management of OpenCL context from PME and NBNXM
[gromacs.git] / src / gromacs / options / basicoptions.h
blob75d8e2d4549972d01e8c5d0143b75d78bd3debca
1 /*
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.
36 /*! \file
37 * \brief
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>
44 * \inpublicapi
45 * \ingroup module_options
47 #ifndef GMX_OPTIONS_BASICOPTIONS_H
48 #define GMX_OPTIONS_BASICOPTIONS_H
50 #include <memory>
51 #include <string>
52 #include <vector>
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"
61 namespace gmx
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;
76 class EnumOptionInfo;
77 class EnumOptionStorage;
79 //! \addtogroup module_options
80 //! \{
82 /*! \brief
83 * Specifies an option that provides boolean values.
85 * Example:
86 * \code
87 bool bPBC;
88 using gmx::BooleanOption;
89 options.addOption(BooleanOption("pbc").store(&bPBC));
90 * \endcode
92 * Public methods in this class do not throw.
94 * \inpublicapi
96 class BooleanOption : public OptionTemplate<bool, BooleanOption>
98 public:
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) {}
105 private:
106 //! Creates a BooleanOptionStorage object.
107 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
110 /*! \brief
111 * Specifies an option that provides integer values.
113 * Examples:
114 * \code
115 using gmx::IntegerOption;
116 // Simple option
117 int rcut = 0;
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());
122 * \endcode
124 * Public methods in this class do not throw.
126 * \inpublicapi
128 class IntegerOption : public OptionTemplate<int, IntegerOption>
130 public:
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) {}
137 /*! \brief
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
143 * vector.
145 MyClass& vector()
147 setVector();
148 return me();
151 private:
152 //! Creates an IntegerOptionStorage object.
153 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
155 /*! \brief
156 * Needed to initialize IntegerOptionStorage from this class without
157 * otherwise unnecessary accessors.
159 friend class IntegerOptionStorage;
162 /*! \brief
163 * Specifies an option that provides 64-bit integer values.
165 * Public methods in this class do not throw.
167 * \see IntegerOption
169 * \inpublicapi
171 class Int64Option : public OptionTemplate<int64_t, Int64Option>
173 public:
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) {}
180 private:
181 //! Creates an Int64OptionStorage object.
182 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
184 /*! \brief
185 * Needed to initialize Int64OptionStorage from this class without
186 * otherwise unnecessary accessors.
188 friend class Int64OptionStorage;
191 /*! \brief
192 * Specifies an option that provides floating-point (double) values.
194 * Public methods in this class do not throw.
196 * \inpublicapi
198 class DoubleOption : public OptionTemplate<double, DoubleOption>
200 public:
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()
208 MyClass& vector()
210 setVector();
211 return me();
213 /*! \brief
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
223 * TimeUnitManager.
225 MyClass& timeValue()
227 bTime_ = true;
228 return me();
231 private:
232 //! Creates a DoubleOptionStorage object.
233 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
235 bool bTime_;
237 /*! \brief
238 * Needed to initialize DoubleOptionStorage from this class without
239 * otherwise unnecessary accessors.
241 friend class DoubleOptionStorage;
244 /*! \brief
245 * Specifies an option that provides floating-point (float) values.
247 * Public methods in this class do not throw.
249 * \see DoubleOption
251 * \inpublicapi
253 class FloatOption : public OptionTemplate<float, FloatOption>
255 public:
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()
263 MyClass& vector()
265 setVector();
266 return me();
268 //! \copydoc DoubleOption::timeValue()
269 MyClass& timeValue()
271 bTime_ = true;
272 return me();
275 private:
276 //! Creates a FloatOptionStorage object.
277 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
279 bool bTime_;
281 /*! \brief
282 * Needed to initialize FloatOptionStorage from this class without
283 * otherwise unnecessary accessors.
285 friend class FloatOptionStorage;
288 /*! \brief
289 * Specifies an option that provides string values.
291 * Examples:
292 * \code
293 using gmx::StringOption;
294 // Simple option
295 std::string str;
296 options.addOption(StringOption("str").store(&str));
297 // Option that only accepts predefined values
298 const char * const allowed[] = { "atom", "residue", "molecule" };
299 std::string str;
300 options.addOption(StringOption("type").enumValue(allowed).store(&str));
301 * \endcode
303 * Public methods in this class do not throw.
305 * \inpublicapi
307 class StringOption : public OptionTemplate<std::string, StringOption>
309 public:
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) :
315 MyBase(name),
316 enumValues_(nullptr),
317 enumValuesCount_(0),
318 defaultEnumIndex_(-1)
322 /*! \brief
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
329 * first one is).
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;
339 return me();
341 /*! \brief
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.
351 * \see enumValue()
353 MyClass& enumValueFromNullTerminatedArray(const char* const* values)
355 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
356 enumValues_ = values;
357 enumValuesCount_ = -1;
358 return me();
360 /*! \brief
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;
369 return me();
372 private:
373 //! Creates a StringOptionStorage object.
374 AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
376 const char* const* enumValues_;
377 int enumValuesCount_;
378 int defaultEnumIndex_;
380 /*! \brief
381 * Needed to initialize StringOptionStorage from this class without
382 * otherwise unnecessary accessors.
384 friend class StringOptionStorage;
387 //! \}
389 namespace internal
392 /*! \internal
393 * \brief
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>
406 public:
407 //! Initializes the storage for the given actual enum variables.
408 EnumIndexStore(EnumType* store, std::vector<EnumType>* storeVector) :
409 store_(store),
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
430 intStore_.clear();
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));
458 private:
459 //! Stores the integer values for values().
460 std::vector<int> intStore_;
461 EnumType* store_;
462 std::vector<EnumType>* storeVector_;
465 //! \cond internal
466 /*! \internal
467 * \brief
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,
478 int count,
479 int defaultValue,
480 int defaultValueIfSet,
481 std::unique_ptr<IOptionValueStore<int>> store);
482 //! \endcond
484 } // namespace internal
486 //! \addtogroup module_options
487 //! \{
489 /*! \brief
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`).
496 * Examples:
497 * \code
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));
503 * \endcode
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.
517 * \inpublicapi
519 template<typename EnumType>
520 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType>>
522 public:
523 //! OptionInfo subclass corresponding to this option type.
524 typedef EnumOptionInfo InfoType;
526 // This needs to be duplicated from OptionTemplate because this class
527 // is a template.
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)
536 /*! \brief
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
543 * first one is).
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;
553 return MyBase::me();
555 /*! \brief
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.
565 * \see enumValue()
567 EnumOption& enumValueFromNullTerminatedArray(const char* const* values)
569 GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
570 enumValues_ = values;
571 enumValuesCount_ = -1;
572 return MyBase::me();
575 private:
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_;
596 /*! \brief
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;
606 /*! \brief
607 * Wrapper class for accessing boolean option information.
609 * \inpublicapi
611 class BooleanOptionInfo : public OptionInfo
613 public:
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;
620 private:
621 const BooleanOptionStorage& option() const;
624 /*! \brief
625 * Wrapper class for accessing integer option information.
627 * \inpublicapi
629 class IntegerOptionInfo : public OptionInfo
631 public:
632 //! Creates an option info object for the given option.
633 explicit IntegerOptionInfo(IntegerOptionStorage* option);
636 /*! \brief
637 * Wrapper class for accessing 64-bit integer option information.
639 * \inpublicapi
641 class Int64OptionInfo : public OptionInfo
643 public:
644 //! Creates an option info object for the given option.
645 explicit Int64OptionInfo(Int64OptionStorage* option);
648 /*! \brief
649 * Wrapper class for accessing floating-point option information.
651 * \inpublicapi
653 class DoubleOptionInfo : public OptionInfo
655 public:
656 //! Creates an option info object for the given option.
657 explicit DoubleOptionInfo(DoubleOptionStorage* option);
659 //! Whether the option specifies a time value.
660 bool isTime() const;
662 /*! \brief
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);
672 private:
673 DoubleOptionStorage& option();
674 const DoubleOptionStorage& option() const;
677 /*! \brief
678 * Wrapper class for accessing floating-point option information.
680 * \inpublicapi
682 class FloatOptionInfo : public OptionInfo
684 public:
685 //! Creates an option info object for the given option.
686 explicit FloatOptionInfo(FloatOptionStorage* option);
688 //! Whether the option specifies a time value.
689 bool isTime() const;
691 //! \copydoc DoubleOptionInfo::setScaleFactor()
692 void setScaleFactor(double factor);
694 private:
695 FloatOptionStorage& option();
696 const FloatOptionStorage& option() const;
699 /*! \brief
700 * Wrapper class for accessing string option information.
702 * \inpublicapi
704 class StringOptionInfo : public OptionInfo
706 public:
707 //! Creates an option info object for the given option.
708 explicit StringOptionInfo(StringOptionStorage* option);
710 /*! \brief
711 * Whether this option accepts an enumerated set of values.
713 * Returns true if StringOption::enumValues() was used when creating
714 * this option.
716 bool isEnumerated() const;
717 /*! \brief
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;
724 private:
725 const StringOptionStorage& option() const;
728 /*! \brief
729 * Wrapper class for accessing enum option information.
731 * \inpublicapi
733 class EnumOptionInfo : public OptionInfo
735 public:
736 //! Creates an option info object for the given option.
737 explicit EnumOptionInfo(EnumOptionStorage* option);
739 /*! \brief
740 * Returns the set of allowed values for this option.
742 const std::vector<std::string>& allowedValues() const;
744 private:
745 const EnumOptionStorage& option() const;
748 /*! \typedef RealOption
749 * \brief
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
756 * \brief
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.
762 #if GMX_DOUBLE
763 typedef DoubleOption RealOption;
764 typedef DoubleOptionInfo RealOptionInfo;
765 #else
766 typedef FloatOption RealOption;
767 typedef FloatOptionInfo RealOptionInfo;
768 #endif
770 //! \}
772 } // namespace gmx
774 #endif