1 #pragma once
2 
3 /// \file Settings.h
4 /// \brief Generic storage and input/output routines of settings.
5 /// \author Pavel Sevecek (sevecek at sirrah.troja.mff.cuni.cz)
6 /// \date 2016-2021
7 
8 #include "objects/Exceptions.h"
9 #include "objects/geometry/TracelessTensor.h"
10 #include "objects/utility/EnumMap.h"
11 #include "objects/wrappers/ClonePtr.h"
12 #include "objects/wrappers/Expected.h"
13 #include "objects/wrappers/Flags.h"
14 #include "objects/wrappers/Interval.h"
15 #include "objects/wrappers/Outcome.h"
16 #include "objects/wrappers/Variant.h"
17 #include <typeinfo>
18 
19 NAMESPACE_SPH_BEGIN
20 
21 class Path;
22 
23 template <typename TEnum>
24 class Settings;
25 
26 template <typename TEnum>
27 class SettingsIterator;
28 
29 /// Tag for initialization of empty settings object.
30 struct EmptySettingsTag {};
31 
32 const EmptySettingsTag EMPTY_SETTINGS;
33 
34 /// \brief Wrapper of an enum.
35 ///
36 /// Used to store an enum in settings while keeping the type safety.
37 struct EnumWrapper {
38     int value = 0;
39 
40     EnumIndex index = NOTHING;
41 
42     EnumWrapper() = default;
43 
44     template <typename TEnum>
EnumWrapperEnumWrapper45     explicit EnumWrapper(TEnum e)
46         : value(int(e))
47         , index(typeid(TEnum)) {
48         static_assert(std::is_enum<TEnum>::value, "Can be used only for enums");
49     }
50 
EnumWrapperEnumWrapper51     EnumWrapper(const int value, const EnumIndex& index)
52         : value(value)
53         , index(index) {}
54 
55     explicit operator int() const {
56         return value;
57     }
58 
59     template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
TEnumWrapper60     explicit operator T() const {
61         SPH_ASSERT(std::type_index(typeid(T)) == index);
62         return T(value);
63     }
64 
65     bool operator==(const EnumWrapper& other) const {
66         return value == other.value && index == other.index;
67     }
68 
69     template <typename TStream>
70     friend TStream& operator<<(TStream& ofs, const EnumWrapper& e) {
71         ofs << e.value << " (" << (e.index ? e.index->hash_code() : 0) << ")";
72         return ofs;
73     }
74 };
75 
76 /// \brief Exception thrown on invalid access to entries of a \ref Settings object.
77 class InvalidSettingsAccess : public Exception {
78 public:
79     template <typename TEnum>
InvalidSettingsAccess(const TEnum key)80     explicit InvalidSettingsAccess(const TEnum key)
81         : Exception("Error accessing parameter '" +
82                     Settings<TEnum>::getEntryName(key).valueOr("unknown parameter") + "'") {
83         static_assert(std::is_enum<TEnum>::value, "InvalidSettingsAccess can only be used with enums");
84     }
85 };
86 
87 template <typename TEnum>
checkSettingsAccess(const bool result,const TEnum key)88 INLINE void checkSettingsAccess(const bool result, const TEnum key) {
89     if (!result) {
90         throw InvalidSettingsAccess(key);
91     }
92 }
93 
94 /// \brief Generic object containing various settings and parameters of the run.
95 ///
96 /// Settings is a storage containing pairs key-value objects, where key is one of predefined enums. The value
97 /// can have multiple types within the same \ref Settings object. Currently following types can be stored:
98 /// bool, int, enums, float (or double), String, \ref Interval, \ref Vector, \ref SymmetricTensor, \ref
99 /// TracelessTensor.
100 ///
101 /// The template cannot be used directly as it is missing default values of parameters; instead
102 /// specializations for specific enums should be used. The code defines two base specializations:
103 ///     - \ref BodySettings (specialization with enum \ref BodySettingsId)
104 ///     - \ref RunSettings (specialization with enum \ref RunSettingsId)
105 template <typename TEnum>
106 class Settings {
107     template <typename>
108     friend class SettingsIterator;
109 
110 private:
111     /// \brief List of types that can be stored in settings
112     enum Types {
113         BOOL,
114         INT,
115         FLOAT,
116         INTERVAL,
117         STRING,
118         VECTOR,
119         SYMMETRIC_TENSOR,
120         TRACELESS_TENSOR,
121         ENUM,
122     };
123 
124     /// \brief Storage type of settings entries.
125     ///
126     /// Order of types in the variant must correspond to the values in enum \ref Types. It is possible to add
127     /// other types to the settings, but always to the END of the variant to keep the backwards compatibility
128     /// of serializer.
129     ///
130     /// \todo Possibly refactor by using some polymorphic holder (Any-type) rather than variant, this will
131     /// allow to add more types for other Settings specializations (GuiSettings, etc.)
132     using Value =
133         Variant<bool, int, Float, Interval, String, Vector, SymmetricTensor, TracelessTensor, EnumWrapper>;
134 
135     struct Entry {
136         /// Index of the property
137         TEnum id;
138 
139         /// Unique text identifier of the property
140         String name;
141 
142         /// Current value
143         Value value;
144 
145         /// Description of the property. Can be empty.
146         String desc;
147 
148         Entry() = default;
149 
150         Entry(TEnum id, const String& name, const Value& value, const String& desc = "")
idEntry151             : id(id)
152             , name(name)
153             , value(value)
154             , desc(desc) {}
155 
156         template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
157         Entry(TEnum id, const String& name, const T& value, const String& desc = "")
idEntry158             : id(id)
159             , name(name)
160             , value(EnumWrapper(value))
161             , desc(desc) {}
162 
163         template <typename T>
164         Entry(TEnum id, const String& name, Flags<T> flags, const String& desc = "")
idEntry165             : id(id)
166             , name(name)
167             , value(EnumWrapper(T(flags.value())))
168             , desc(desc) {}
169 
170         template <typename T>
171         INLINE bool hasType(std::enable_if_t<!std::is_enum<T>::value, int> = 0) const {
172             return value.has<T>();
173         }
174 
175         template <typename T>
176         INLINE bool hasType(std::enable_if_t<std::is_enum<T>::value, int> = 0) const {
177             return value.has<EnumWrapper>() && value.get<EnumWrapper>().index == std::type_index(typeid(T));
178         }
179     };
180 
181     FlatMap<TEnum, Entry> entries;
182 
183 public:
184     /// \brief Initialize settings by settings all value to their defaults.
185     Settings();
186 
187     /// Constructs settings from list of key-value pairs.
188     Settings(std::initializer_list<Entry> list);
189 
190     /// \brief Initialize empty settings object.
191     Settings(EmptySettingsTag);
192 
193     Settings(const Settings& other);
194 
195     Settings(Settings&& other);
196 
197     /// \brief Assigns a list of settings into the object, erasing all previous entries.
198     Settings& operator=(std::initializer_list<Entry> list);
199 
200     Settings& operator=(const Settings& other);
201 
202     Settings& operator=(Settings&& other);
203 
204     /// \brief Saves a value into the settings.
205     ///
206     /// Any previous value of the same ID is overriden.
207     /// \tparam TValue Type of the value to be saved. Does not have to be specified, type deduction can be
208     ///                used to determine it. Must be one of types listed in object description. Using other
209     ///                types will result in compile error.
210     /// \param idx Key identifying the value. This key can be used to retrive the value later.
211     /// \param value Value being stored into settings.
212     /// \returns Reference to the settings object, allowing to queue multiple set functions.
213     /// \throw InvalidSettingsAccess if settings value of different type than the one currently stored.
214     template <typename TValue>
215     Settings& set(const TEnum idx,
216         TValue&& value,
217         std::enable_if_t<!std::is_enum<std::decay_t<TValue>>::value, int> = 0) {
218         Optional<Entry&> entry = entries.tryGet(idx);
219         if (!entry) {
220             Entry& newEntry = entries.insert(idx, Entry{});
221             newEntry.value = std::forward<TValue>(value);
222         } else {
223             checkSettingsAccess(entry->template hasType<std::decay_t<TValue>>(), idx);
224             entry->value = std::forward<TValue>(value);
225         }
226         return *this;
227     }
228 
229     /// \copydoc set
230     template <typename TValue>
231     Settings& set(const TEnum idx,
232         TValue&& value,
233         std::enable_if_t<std::is_enum<std::decay_t<TValue>>::value, int> = 0) {
234         Optional<Entry&> entry = entries.tryGet(idx);
235         if (!entry) {
236             Entry& newEntry = entries.insert(idx, Entry{});
237             newEntry.value = EnumWrapper(value);
238         } else {
239             checkSettingsAccess(entry->template hasType<std::decay_t<TValue>>(), idx);
240             entry->value = EnumWrapper(value);
241         }
242         return *this;
243     }
244 
245     /// \brief Saves flags into the settings.
246     ///
247     /// Flags are not considered as a different type, they are internally saved as enum wrapper.
248     /// \returns Reference to the settings object.
249     /// \throw InvalidSettingsAccess if settings value of different type than the one currently stored.
250     template <typename TValue, typename = std::enable_if_t<std::is_enum<TValue>::value>>
set(const TEnum idx,const Flags<TValue> flags)251     Settings& set(const TEnum idx, const Flags<TValue> flags) {
252         return this->set(idx, EnumWrapper(TValue(flags.value())));
253     }
254 
255     /// \brief Clear flags of given parameter in settings.
256     ///
257     /// This function can be used only if the value is already stored in the settings.
258     /// \returns Reference to the settings object.
259     /// \throw InvalidSettingsAccess if the value is not stored or has a different type.
set(const TEnum idx,EmptyFlags)260     Settings& set(const TEnum idx, EmptyFlags) {
261         Optional<Entry&> entry = entries.tryGet(idx);
262         checkSettingsAccess(entry && entry->value.template has<EnumWrapper>(), idx);
263         entry->value.template get<EnumWrapper>().value = 0;
264         return *this;
265     }
266 
267     /// \brief Special setter for value of type EnumWrapper.
268     ///
269     /// While usually the enum can be stored directly, this overload is useful for deserialization, etc.
270     /// \returns Reference to the settings object.
271     /// \throw InvalidSettingsAccess if settings value of different type than the one currently stored.
set(const TEnum idx,const EnumWrapper ew)272     Settings& set(const TEnum idx, const EnumWrapper ew) {
273         Optional<Entry&> entry = entries.tryGet(idx);
274         if (entry) {
275             Optional<EnumWrapper> current = entry->value.template tryGet<EnumWrapper>();
276             checkSettingsAccess(current && current->index == ew.index, idx);
277         }
278         this->set(idx, ew, 0); // zero needed to call the other overload
279         return *this;
280     }
281 
282     /// \brief Adds entries from different \ref Settings object into this one, overriding current entries.
283     ///
284     /// Entries not stored in the given settings are kept unchanged.
285     /// \throw InvalidSettingsAccess if the settings share entries that differ in type.
addEntries(const Settings & settings)286     void addEntries(const Settings& settings) {
287         for (const typename SettingsIterator<TEnum>::IteratorValue& iv : settings) {
288             Optional<Entry&> entry = entries.tryGet(iv.id);
289             if (!entry) {
290                 Entry& newEntry = entries.insert(iv.id, getDefaults().entries[iv.id]);
291                 newEntry.value = iv.value;
292             } else {
293                 checkSettingsAccess(entry->value.getTypeIdx() == iv.value.getTypeIdx(), iv.id);
294                 entry->value = iv.value;
295             }
296         }
297     }
298 
299     /// \brief Removes given parameter from settings.
300     ///
301     /// If the parameter is not in settings, nothing happens (it isn't considered as an error).
unset(const TEnum idx)302     void unset(const TEnum idx) {
303         entries.tryRemove(idx);
304     }
305 
306     /// \brief Returns a value of given type from the settings.
307     ///
308     /// Value must be stored in settings and must have corresponding type.
309     /// \tparam TValue Type of the value we wish to return. This type must match the type of the saved
310     ///                quantity.
311     /// \param idx Key of the value.
312     /// \returns Value correponsing to given key.
313     /// \throw InvalidSettingsAccess if value is not stored in the settings or has a different type.
314     template <typename TValue>
315     TValue get(const TEnum idx, std::enable_if_t<!std::is_enum<std::decay_t<TValue>>::value, int> = 0) const {
316         Optional<const Entry&> entry = entries.tryGet(idx);
317         checkSettingsAccess(entry && entry->value.template has<TValue>(), idx);
318 
319         return entry->value.template get<TValue>();
320     }
321 
322     /// \copydoc get
323     template <typename TValue>
324     TValue get(const TEnum idx, std::enable_if_t<std::is_enum<std::decay_t<TValue>>::value, int> = 0) const {
325         Optional<const Entry&> entry = entries.tryGet(idx);
326         checkSettingsAccess(entry && entry->value.template has<EnumWrapper>(), idx);
327 
328         const EnumWrapper wrapper = entry->value.template get<EnumWrapper>();
329         checkSettingsAccess(wrapper.index == std::type_index(typeid(TValue)), idx);
330         return TValue(wrapper.value);
331     }
332 
333     /// \brief Returns Flags from underlying value stored in settings.
334     ///
335     /// Syntactic suggar, avoid cumbersome conversion to underlying type and then to Flags.
336     template <typename TValue>
getFlags(const TEnum idx)337     Flags<TValue> getFlags(const TEnum idx) const {
338         static_assert(std::is_enum<TValue>::value, "Can be only used for enums");
339         TValue value = this->get<TValue>(idx);
340         return Flags<TValue>::fromValue(std::underlying_type_t<TValue>(value));
341     }
342 
343     /// \brief Returns the human-readable name of the entry with given index.
344     ///
345     /// If the index does not correspond to any parameter, returns string NOTHING.
getEntryName(const TEnum idx)346     static Optional<String> getEntryName(const TEnum idx) {
347         const Settings& settings = getDefaults();
348         Optional<const Entry&> entry = settings.entries.tryGet(idx);
349         if (entry) {
350             return entry->name;
351         } else {
352             // idx might be invalid if loaded from older config file
353             return NOTHING;
354         }
355     }
356 
357     /// \brief Returns the type of the entry with given index.
358     ///
359     /// If the index does not correspond to any parameter, returns NOTHING.
getEntryType(const TEnum idx)360     static Optional<int> getEntryType(const TEnum idx) {
361         const Settings& settings = getDefaults();
362         Optional<const Entry&> entry = settings.entries.tryGet(idx);
363         if (entry) {
364             return entry->value.getTypeIdx();
365         } else {
366             return NOTHING;
367         }
368     }
369 
370     /// \brief Returns the string name for given type index.
371     ///
372     /// \throw Exception for unknown type index
373     static String typeToString(const int type);
374 
375     /// \brief Returns a description of the entry with given index.
376     ///
377     /// If the index does not correspond to any parameter, returns string NOTHING.
getEntryDesc(const TEnum idx)378     static Optional<String> getEntryDesc(const TEnum idx) {
379         const Settings& settings = getDefaults();
380         Optional<const Entry&> entry = settings.entries.tryGet(idx);
381         if (entry) {
382             return entry->desc;
383         } else {
384             // idx might be invalid if loaded from older config file
385             return NOTHING;
386         }
387     }
388 
389     /// \brief Returns an ID for given entry name.
390     ///
391     /// This is the inverse of function \ref getEntryName.
getEntryId(const String & name)392     static Optional<TEnum> getEntryId(const String& name) {
393         const Settings& settings = getDefaults();
394         for (const auto& p : settings.entries) {
395             if (p.value().name == name) {
396                 return p.key();
397             }
398         }
399         return NOTHING;
400     }
401 
402     /// \brief Checks if the given entry is stored in the settings.
has(const TEnum idx)403     bool has(const TEnum idx) const {
404         return entries.contains(idx);
405     }
406 
407     /// \brief Checks if the given entry has specified type.
408     ///
409     /// \throw InvalidSettingsAccess if the entry is not in settings.
410     template <typename TValue>
hasType(const TEnum idx)411     bool hasType(const TEnum idx) const {
412         Optional<const Entry&> entry = entries.tryGet(idx);
413         checkSettingsAccess(bool(entry), idx);
414         return entry->value.template has<TValue>();
415     }
416 
417     /// \brief Saves all values stored in settings into file.
418     ///
419     /// \param path Path (relative or absolute) to the file. The file will be created, any previous
420     ///             content will be overriden.
421     /// \returns SUCCESS if the file has been correctly written, otherwise returns encountered error.
422     Outcome saveToFile(const Path& path) const;
423 
424     /// \brief Loads the settings from file.
425     ///
426     /// Previous values stored in settings are removed. The file must have a valid settings format.
427     /// \param path Path to the file. The file must exist.
428     /// \returns SUCCESS if the settings were correctly parsed from the file, otherwise returns encountered
429     ///          error.
430     Outcome loadFromFile(const Path& path);
431 
432     /// \brief If the specified file exists, loads the settings from it, otherwise creates the file and saves
433     /// the current values.
434     ///
435     /// This is a standard behavior of configuration files used in the simulation. First time the simulation
436     /// is started, the configuration files are created with default values. The files can then be modified by
437     /// the user and the next time simulation is started, the parameters are parsed and used instead of the
438     /// defaults.
439     ///
440     /// For convenience, it is possible to pass a set of overrides, which are used instead of the values
441     /// loaded from the configuration file (or defaults, if the file does not exist). This can be used to
442     /// specify settings as command-line parameters, for example.
443     /// \param path Path to the configuration file.
444     /// \param overrides Set of overrides applied on the current values or after the settings are loaded.
445     /// \returns True if the settings have been successfully loaded, false if the configuration file did not
446     ///         exist, in which case the function attempted to create the file using current values (with
447     ///         applied overrides).
448     /// \throw Exception if loading of the file failed (invalid content, unknown parameters, ...).
449     ///
450     /// \note Function returns a valid result (false) even if the configuration file cannot be created, for
451     ///       example if the directory access is denied. This does not prohibit the simulation in any way, the
452     ///       settings object is in valid state.
453     bool tryLoadFileOrSaveCurrent(const Path& path, const Settings& overrides = EMPTY_SETTINGS);
454 
455     /// \brief Iterator to the first entry of the settings storage.
456     SettingsIterator<TEnum> begin() const;
457 
458     /// \brief Iterator to the one-past-end entry the settings storage.
459     SettingsIterator<TEnum> end() const;
460 
461     /// \brief Returns the number of entries in the settings.
462     ///
463     /// This includes default entries in case the object was not constructed with EMPTY_SETTINGS tag.
464     Size size() const;
465 
466     /// \\brief Returns a reference to object containing default values of all settings.
467     static const Settings& getDefaults();
468 
469 private:
470     bool setValueByType(Entry& entry, const Value& defaultValue, const String& str);
471 };
472 
473 /// \brief Returns the default settings.
474 ///
475 /// Needs to be specialized for each TEnum.
476 template <typename TEnum>
477 const Settings<TEnum>& getDefaultSettings();
478 
479 /// \brief Iterator useful for iterating over all entries in the settings.
480 template <typename TEnum>
481 class SettingsIterator {
482 private:
483     using ActIterator = Iterator<const typename FlatMap<TEnum, typename Settings<TEnum>::Entry>::Element>;
484 
485     ActIterator iter;
486 
487 public:
488     /// Constructs an iterator from iternal implementation; use Settings::begin and Settings::end.
489     SettingsIterator(const ActIterator& iter, Badge<Settings<TEnum>>);
490 
491     struct IteratorValue {
492         /// ID of settings entry
493         TEnum id;
494 
495         /// Variant holding the value of the entry
496         typename Settings<TEnum>::Value value;
497     };
498 
499     /// Dereference the iterator, yielding a pair of entry ID and its value.
500     IteratorValue operator*() const;
501 
502     /// Moves to next entry.
503     SettingsIterator& operator++();
504 
505     /// Equality operator between settings operators.
506     bool operator==(const SettingsIterator& other) const;
507 
508     /// Unequality operator between settings operators.
509     bool operator!=(const SettingsIterator& other) const;
510 };
511 
512 
513 enum class KernelEnum {
514     /// M4 B-spline (piecewise cubic polynomial)
515     CUBIC_SPLINE,
516 
517     /// M5 B-spline (piecewise 4th-order polynomial)
518     FOURTH_ORDER_SPLINE,
519 
520     /// Gaussian function
521     GAUSSIAN,
522 
523     /// Simple triangle (piecewise linear) kernel
524     TRIANGLE,
525 
526     /// Core Triangle (CT) kernel by Read et al. (2010)
527     CORE_TRIANGLE,
528 
529     /// Modification of the standard M4 B-spline kernel, used to avoid particle clustering
530     THOMAS_COUCHMAN,
531 
532     /// Wendland kernel C2
533     WENDLAND_C2,
534 
535     /// Wendland kernel C4
536     WENDLAND_C4,
537 
538     /// Wendland kernel C6
539     WENDLAND_C6,
540 };
541 
542 enum class TimesteppingEnum {
543     /// Explicit (forward) 1st-order integration
544     EULER_EXPLICIT,
545 
546     /// Leap-frog 2nd-order integration
547     LEAP_FROG,
548 
549     /// Runge-Kutta 4-th order integration
550     RUNGE_KUTTA,
551 
552     /// Predictor-corrector scheme
553     PREDICTOR_CORRECTOR,
554 
555     /// Modified midpoint method with constant number of substeps
556     MODIFIED_MIDPOINT,
557 
558     /// Bulirsch-Stoer integrator
559     BULIRSCH_STOER
560 };
561 
562 enum class TimeStepCriterionEnum {
563     /// Time step determined using CFL condition
564     COURANT = 1 << 1,
565 
566     /// Time step computed by limiting value-to-derivative ratio of quantiites.
567     DERIVATIVES = 1 << 2,
568 
569     /// Time step computed from ratio of acceleration and smoothing length.
570     ACCELERATION = 1 << 3,
571 
572     /// Time step computed from velocity divergence
573     DIVERGENCE = 1 << 4,
574 
575     /// Value for using all criteria.
576     ALL = COURANT | DERIVATIVES | ACCELERATION | DIVERGENCE,
577 };
578 
579 enum class FinderEnum {
580     /// Brute-force search by going through each pair of particles (O(N^2) complexity)
581     BRUTE_FORCE,
582 
583     /// Using K-d tree
584     KD_TREE,
585 
586     /// Using octree
587     OCTREE,
588 
589     /// Using linked list
590     LINKED_LIST,
591 
592     /// Partitioning particles into a grid uniform in space
593     UNIFORM_GRID,
594 
595     /// Using hash map
596     HASH_MAP,
597 };
598 
599 enum class BoundaryEnum {
600     /// Do not use any boundary conditions (= vacuum conditions)
601     NONE,
602 
603     /// Highest derivatives of all particles close to the boundary are set to zero.
604     FROZEN_PARTICLES,
605 
606     /// Create ghosts to keep particles inside domain.
607     GHOST_PARTICLES,
608 
609     /// Creates dummy particles along the boundary.
610     FIXED_PARTICLES,
611 
612     /// Extension of Frozen Particles, pushing particles inside the domain and removing them on the other end.
613     WIND_TUNNEL,
614 
615     /// Periodic boundary conditions
616     PERIODIC,
617 
618     /// Particles are duplicated along the z=0 plane
619     SYMMETRIC,
620 
621     /// Removes particles outside the domain
622     KILL_ESCAPERS,
623 
624     /// Project all movement onto a line, effectivelly reducing the simulation to 1D
625     PROJECT_1D
626 };
627 
628 enum class DomainEnum {
629     /// No computational domain (can only be used with BoundaryEnum::NONE)
630     NONE,
631 
632     /// Sphere with given radius
633     SPHERICAL,
634 
635     /// Axis-aligned ellipsoid
636     ELLIPSOIDAL,
637 
638     /// Block with edge sizes given by vector
639     BLOCK,
640 
641     /// Cylindrical domain aligned with z axis
642     CYLINDER,
643 
644     /// Gaussian random sphere
645     GAUSSIAN_SPHERE,
646 
647     /// Half-space z>0
648     HALF_SPACE,
649 };
650 
651 /// List of forces to compute by the solver. This does not include numerical terms, see
652 /// ArtificialViscosityEnum.
653 enum class ForceEnum {
654     /// Use force from pressure gradient in the solver.
655     PRESSURE = 1 << 0,
656 
657     /// Use force from stress divergence in the model. Must be used together with PRESSURE_GRADIENT.
658     /// Stress tensor is then evolved in time using Hooke's equation.
659     SOLID_STRESS = 1 << 1,
660 
661     /// Stress tensor for the simulation of fluids. Must be used together with PRESSURE_GRADIENT, cannot
662     /// be used together with solid stress force.
663     NAVIER_STOKES = 1 << 2,
664 
665     /// Use internal friction given by the viscosity in the material.
666     INTERNAL_FRICTION = 1 << 3,
667 
668     /// Use centrifugal force and Coriolis forces given by angular frequency of the coordinate frame.
669     INERTIAL = 1 << 4,
670 
671     /// Use gravitational force in the model
672     SELF_GRAVITY = 1 << 5,
673 
674     /// Surface force proportional to surface curvature
675     SURFACE_TENSION = 1 << 6,
676 };
677 
678 enum class ArtificialViscosityEnum {
679     /// No artificial viscosity
680     NONE,
681 
682     /// Standard artificial viscosity term by Monaghan (1989).
683     STANDARD,
684 
685     /// Artificial viscosity term analogous to Riemann solvers by Monaghan (1997)
686     RIEMANN,
687 
688     /// Time-dependent artificial viscosity by Morris & Monaghan (1997).
689     MORRIS_MONAGHAN,
690 };
691 
692 enum class SolverEnum {
693     /// SPH formulation using symmetrized evaluation of derivatives.
694     SYMMETRIC_SOLVER,
695 
696     /// Generic solver evaluating all derivatives asymmetrically.
697     ASYMMETRIC_SOLVER,
698 
699     /// Density is obtained by direct summation over nearest SPH particles.
700     SUMMATION_SOLVER,
701 
702     /// Special solver used to simulate deformations of perfectly elastic bodies
703     ELASTIC_DEFORMATION_SOLVER,
704 
705     /// Density independent solver by Saitoh & Makino (2013).
706     DENSITY_INDEPENDENT,
707 
708     /// Solver advancing internal energy using pair-wise work done by particles, by Owen (2009).
709     ENERGY_CONSERVING_SOLVER,
710 
711     /// Simple solver with pressure gradient only, mainly used for supporting purposes (benchmarking,
712     /// teaching, etc.)
713     SIMPLE_SOLVER,
714 };
715 
716 enum class ContinuityEnum {
717     /// Normal continuity equation, using velocity divergence computed from all neighbors.
718     STANDARD,
719 
720     /// Computes the velocity divergence using only undamaged neighbors. For fully damaged particle, the
721     /// standard continuity equation is used instead.
722     SUM_ONLY_UNDAMAGED,
723 };
724 
725 enum class DiscretizationEnum {
726     /// P_i / rho_i^2 + P_j / rho_j^2
727     STANDARD,
728 
729     /// (P_i + P_j) / (rho_i rho_j)
730     BENZ_ASPHAUG,
731 };
732 
733 enum class YieldingEnum {
734     /// Gass or material with no stress tensor
735     NONE,
736 
737     /// No yielding, just elastic deformations following Hooke's law
738     ELASTIC,
739 
740     /// Von Mises criterion
741     VON_MISES,
742 
743     /// Drucker-Prager pressure dependent yielding stress
744     DRUCKER_PRAGER,
745 
746     /// No stress tensor, only the pressure is limited to positive values.
747     DUST,
748 };
749 
750 enum class FractureEnum {
751     /// No fragmentation
752     NONE,
753 
754     /// Grady-Kipp model of fragmentation using scalar damage
755     SCALAR_GRADY_KIPP,
756 
757     /// Grady-Kipp model of fragmentation using tensor damage
758     TENSOR_GRADY_KIPP
759 };
760 
761 enum class SmoothingLengthEnum {
762     /// Smoothing length is evolved using continuity equation
763     CONTINUITY_EQUATION = 1 << 1,
764 
765     /// Number of neighbors is kept fixed by adding additional derivatives of smoothing length, scaled by
766     /// local sound speed
767     SOUND_SPEED_ENFORCING = 1 << 2
768 };
769 
770 enum class SignalSpeedEnum {
771     /// Signal speed given by the absolute value of pressure difference, as in Price (2008)
772     PRESSURE_DIFFERENCE,
773 
774     /// Signal speed given by relative velocity projected to the positive vector, as in Valdarnini (2018),
775     VELOCITY_DIFFERENCE,
776 };
777 
778 enum class GravityEnum {
779     /// Approximated gravity, assuming the matter is a simple homogeneous sphere.
780     SPHERICAL,
781 
782     /// Brute-force summation over all particle pairs (O(N^2) complexity)
783     BRUTE_FORCE,
784 
785     /// Use Barnes-Hut algorithm, approximating gravity by multipole expansion (up to octupole order)
786     BARNES_HUT,
787 };
788 
789 enum class GravityKernelEnum {
790     /// Point-like particles with zero radius
791     POINT_PARTICLES,
792 
793     /// Use gravity smoothing kernel corresponding to selected SPH kernel
794     SPH_KERNEL,
795 
796     /// Use kernel representing gravity of solid spheres. Useful for N-body simulations where overlaps are
797     /// allowed.
798     SOLID_SPHERES,
799 };
800 
801 enum class CollisionHandlerEnum {
802     /// No collision handling
803     NONE,
804 
805     /// All collided particles merge, creating larger spherical particles. Particles are merged
806     /// unconditionally, regardless of their relative velocity or their angular frequencies.
807     PERFECT_MERGING,
808 
809     /// Collided particles bounce with some energy dissipation, specified by the coefficients of restitution.
810     /// No merging, number of particles remains contant.
811     ELASTIC_BOUNCE,
812 
813     /// If the relative speed of the collided particles is lower than the escape velocity, the particles are
814     /// merged, otherwise the particle bounce. To ensure that the particles are always merged, set the
815     /// COLLISION_MERGE_LIMIT to zero, on the other hand large values make particles more difficult to merge.
816     MERGE_OR_BOUNCE,
817 };
818 
819 enum class OverlapEnum {
820     /// All overlaps are ignored
821     NONE,
822 
823     /// Overlapping particles are merged
824     FORCE_MERGE,
825 
826     /// Particles are shifted until no overlap happens
827     REPEL,
828 
829     /// Particles are either repeled (and bounced) or merged, based on the ratio of their relative velocity to
830     /// the escape velocity (similar to MERGE_OR_BOUNCE).
831     REPEL_OR_MERGE,
832 
833     /// Particles are allowed to overlap and they bounce if moving towards each other.
834     INTERNAL_BOUNCE,
835 
836     PASS_OR_MERGE,
837 };
838 
839 enum class LoggerEnum {
840     /// Do not log anything
841     NONE,
842 
843     /// Print log to standard output
844     STD_OUT,
845 
846     /// Print log to file
847     FILE
848 
849     /// \todo print using callback to gui application
850 };
851 
852 enum class IoEnum {
853     /// No input/output
854     NONE = 0,
855 
856     /// Formatted human-readable text file
857     TEXT_FILE = 1,
858 
859     /// Full binary output file. This data dump is lossless and can be use to restart run from saved snapshot.
860     /// Stores values, all derivatives and materials of the storage.
861     BINARY_FILE = 3,
862 
863     /// Compressed binary output file, containing only few selected quantities. This is the most convenient
864     /// format for storing full simulation in high resolution in time.
865     DATA_FILE = 4,
866 
867     /// File format used by Visualization Toolkit (VTK). Useful to view the results in Paraview and other
868     /// visualization tools.
869     VTK_FILE = 5,
870 
871     /// File format for storing scientific data. Currently tailored for files generated by the code
872     /// miluphcuda. Requires to build code with libhdf5.
873     HDF5_FILE = 6,
874 
875     /// Export from Minor Planet Center Orbit Database
876     MPCORP_FILE = 7,
877 
878     /// Pkdgrav input file.
879     PKDGRAV_INPUT = 8,
880 };
881 
882 /// \brief Returns the file extension associated with given IO type.
883 ///
884 /// Result NOTHING indicates there is no particular extension associated with the IO type.
885 Optional<String> getIoExtension(const IoEnum type);
886 
887 /// \brief Returns the file type from file extension.
888 ///
889 /// Result NOTHING indicates there is no file type associated with the extension.
890 Optional<IoEnum> getIoEnum(const String& ext);
891 
892 /// \brief Returns a short description of the file format.
893 String getIoDescription(const IoEnum type);
894 
895 enum class IoCapability {
896     /// The format can be used as file input
897     INPUT = 1 << 1,
898 
899     /// The format can be used as file output
900     OUTPUT = 1 << 2,
901 };
902 
903 /// \brief Returns the capabilities of given file format.
904 Flags<IoCapability> getIoCapabilities(const IoEnum type);
905 
906 
907 enum class OutputSpacing {
908     /// Constant time between consecutive output times
909     LINEAR,
910 
911     /// Constant ratio between consecutive output times
912     LOGARITHMIC,
913 
914     /// User-defined list of output times
915     CUSTOM,
916 };
917 
918 enum class RngEnum {
919     /// Mersenne Twister PRNG from Standard library
920     UNIFORM,
921 
922     /// Halton QRNG
923     HALTON,
924 
925     /// Same RNG as used in SPH5, used for 1-1 comparison
926     BENZ_ASPHAUG
927 };
928 
929 enum class UvMapEnum {
930     /// Planar mapping
931     PLANAR,
932 
933     /// Spherical mapping
934     SPHERICAL,
935 };
936 
937 /// Settings relevant for whole run of the simulation
938 enum class RunSettingsId {
939     /// User-specified name of the run, used in some output files
940     RUN_NAME,
941 
942     /// User-specified comment
943     RUN_COMMENT,
944 
945     /// Name of the person running the simulation
946     RUN_AUTHOR,
947 
948     /// E-mail of the person running the simulation.
949     RUN_EMAIL,
950 
951     /// Specifies the type of the simulation. Does not have to be specified to run the simulation; this
952     /// information is saved in output files and taken into account by visualization tools, for example.
953     RUN_TYPE,
954 
955     /// Selected format of the output file, see \ref IoEnum
956     RUN_OUTPUT_TYPE,
957 
958     /// Time interval of dumping data to disk.
959     RUN_OUTPUT_INTERVAL,
960 
961     /// Type of output spacing in time, see enum OutputSpacing
962     RUN_OUTPUT_SPACING,
963 
964     /// List of comma-separated output times, used when RUN_OUTPUT_SPACING is set to CUSTOM
965     RUN_OUTPUT_CUSTOM_TIMES,
966 
967     /// Index of the first generated output file. Might not be zero if the simulation is resumed.
968     RUN_OUTPUT_FIRST_INDEX,
969 
970     /// File name of the output file (including extension), where %d is a placeholder for output number.
971     RUN_OUTPUT_NAME,
972 
973     /// Path where all output files (dumps, logs, ...) will be written
974     RUN_OUTPUT_PATH,
975 
976     /// List of quantities to write to text output. Binary output always stores all quantitites.
977     RUN_OUTPUT_QUANTITIES,
978 
979     /// Number of threads used by the code. If 0, all available threads are used.
980     RUN_THREAD_CNT,
981 
982     /// Number of particles processed by one thread in a single batch. Lower number can help to distribute
983     /// tasks between threads more evenly, higher number means faster processing of particles within single
984     /// thread.
985     RUN_THREAD_GRANULARITY,
986 
987     /// Selected logger of a run, see LoggerEnum
988     RUN_LOGGER,
989 
990     /// Path of a file where the log is printed, used only when selected logger is LoggerEnum::FILE
991     RUN_LOGGER_FILE,
992 
993     /// Number specifying log verbosity. Can be between 0 and 3, going from least to most verbose.
994     RUN_LOGGER_VERBOSITY,
995 
996     /// Enables verbose log of a simulation.
997     RUN_VERBOSE_ENABLE,
998 
999     /// Path of a file where the verbose log is printed.
1000     RUN_VERBOSE_NAME,
1001 
1002     /// Starting time of the simulation in seconds. This is usually 0, although it can be set to a non-zero
1003     /// for simulations resumed from saved state.
1004     RUN_START_TIME,
1005 
1006     /// End time of the simulation in seconds. For new simulations (not resumed from saved state), this
1007     /// corresponds to the total duration of the simulation.
1008     RUN_END_TIME,
1009 
1010     /// Maximum number of timesteps after which run ends. 0 means run duration is not limited by number of
1011     /// timesteps. Note that if adaptive timestepping is used, run can end at different times for
1012     /// different initial conditions. This condition should only be used for debugging purposes.
1013     RUN_TIMESTEP_CNT,
1014 
1015     /// Maximum duration of the run in milliseconds, measured in real-world time. 0 means run duration is not
1016     /// limited by this value.
1017     RUN_WALLCLOCK_TIME,
1018 
1019     /// Selected random-number generator used within the run.
1020     RUN_RNG,
1021 
1022     /// Seed for the random-number generator
1023     RUN_RNG_SEED,
1024 
1025     /// Time period (in run time) of running diagnostics of the run. 0 means the diagnostics are run every
1026     /// time step.
1027     RUN_DIAGNOSTICS_INTERVAL,
1028 
1029     /// Selected solver for computing derivatives of physical variables.
1030     SPH_SOLVER_TYPE,
1031 
1032     /// List of forces to compute by the solver.
1033     SPH_SOLVER_FORCES,
1034 
1035     /// Solution for evolutions of the smoothing length
1036     SPH_ADAPTIVE_SMOOTHING_LENGTH,
1037 
1038     /// Maximum number of iterations for self-consistent density computation of summation solver.
1039     SPH_SUMMATION_MAX_ITERATIONS,
1040 
1041     /// Target relative difference of density in successive iterations. Density computation in summation
1042     /// solver is ended when the density changes by less than the delta or the iteration number exceeds
1043     /// SOLVER_SUMMATION_MAX_ITERATIONS.
1044     SPH_SUMMATION_DENSITY_DELTA,
1045 
1046     /// If true, the SPH solver computes a hash map connecting position in space with required search radius.
1047     /// Otherwise, the radius is determined from the maximal smoothing length in the simulation. Used only by
1048     /// the AsymmetricSolver.
1049     SPH_ASYMMETRIC_COMPUTE_RADII_HASH_MAP,
1050 
1051     /// Index of SPH Kernel, see KernelEnum
1052     SPH_KERNEL,
1053 
1054     /// Structure for searching nearest neighbors of particles
1055     SPH_FINDER,
1056 
1057     /// Specifies a discretization of SPH equations; see \ref DiscretizationEnum.
1058     SPH_DISCRETIZATION,
1059 
1060     /// If true, the kernel gradient for evaluation of strain rate will be corrected for each particle by an
1061     /// inversion of an SPH-discretized identity matrix. This generally improves stability of the run and
1062     /// conservation of total angular momentum, but comes at the cost of higher memory consumption and slower
1063     /// evaluation of SPH derivatives.
1064     SPH_STRAIN_RATE_CORRECTION_TENSOR,
1065 
1066     /// If true, derivatives with flag DerivativeFlag::SUM_ONLY_UNDAMAGED will evaluate only undamaged
1067     /// particles belonging to the same body. Otherwise, all particle are evaluated, regardless of derivative
1068     /// flags.
1069     SPH_SUM_ONLY_UNDAMAGED,
1070 
1071     /// Specifies how the density is evolved, see \ref ContinuityEnum.
1072     SPH_CONTINUITY_MODE,
1073 
1074     /// Evolve particle phase angle
1075     SPH_PHASE_ANGLE,
1076 
1077     /// Minimum and maximum number of neighbors SPH solver tries to enforce. Note that the solver cannot
1078     /// guarantee the actual number of neighbors will be within the range.
1079     SPH_NEIGHBOR_RANGE,
1080 
1081     /// Strength of enforcing neighbor number. Higher value makes enforcing more strict (number of neighbors
1082     /// gets into required range faster), but also makes code less stable. Can be a negative number, -INFTY
1083     /// technically disables enforcing altogether.
1084     SPH_NEIGHBOR_ENFORCING,
1085 
1086     /// Artificial viscosity alpha coefficient
1087     SPH_AV_ALPHA,
1088 
1089     /// Artificial viscosity beta coefficient
1090     SPH_AV_BETA,
1091 
1092     /// Minimal value of smoothing length
1093     SPH_SMOOTHING_LENGTH_MIN,
1094 
1095     /// Type of used artificial viscosity.
1096     SPH_AV_TYPE,
1097 
1098     /// Whether to use balsara switch for computing artificial viscosity dissipation. If no artificial
1099     /// viscosity is used, the value has no effect.
1100     SPH_AV_USE_BALSARA,
1101 
1102     /// If true, Balsara factors will be saved as quantity AV_BALSARA. Mainly for debugging purposes.
1103     SPH_AV_BALSARA_STORE,
1104 
1105     /// Enables the artificial thermal conductivity term.
1106     SPH_USE_AC,
1107 
1108     /// Artificial conductivity alpha coefficient
1109     SPH_AC_ALPHA,
1110 
1111     /// Artificial conductivity beta coefficient
1112     SPH_AC_BETA,
1113 
1114     /// Type of the signal speed used by artificial conductivity
1115     SPH_AC_SIGNAL_SPEED,
1116 
1117     /// Turn on the XSPH correction
1118     SPH_USE_XSPH,
1119 
1120     /// Epsilon-factor of XSPH correction (Monaghan, 1992). Value 0 turns off the correction, epsilon
1121     /// shouldn't be larger than 1.
1122     SPH_XSPH_EPSILON,
1123 
1124     /// Turn on the delta-SPH correction
1125     SPH_USE_DELTASPH,
1126 
1127     /// Delta-coefficient of the delta-SPH modification, see Marrone et al. 2011
1128     SPH_DENSITY_DIFFUSION_DELTA,
1129 
1130     /// Alpha-coefficient of the delta-SPH modification.
1131     SPH_VELOCITY_DIFFUSION_ALPHA,
1132 
1133     /// Whether to use artificial stress.
1134     SPH_AV_USE_STRESS,
1135 
1136     /// Weighting function exponent n in artificial stress term
1137     SPH_AV_STRESS_EXPONENT,
1138 
1139     /// Multiplicative factor of the artificial stress term (= strength of the viscosity)
1140     SPH_AV_STRESS_FACTOR,
1141 
1142     /// Damping coefficient of particle velocities, mainly intended for setting up initial conditions. Higher
1143     /// values damp the oscillation/instabilities faster, but may converge to incorrect (unstable)
1144     /// configuration. Lower values lead to (slower) convergence to correct (stable) configuration, but it may
1145     /// cause body dissintegration if the initial conditions are to far from the stable solution. Zero
1146     /// disables the damping.
1147     SPH_STABILIZATION_DAMPING,
1148 
1149     /// Alpha parameter of the density-independent solver.
1150     SPH_DI_ALPHA,
1151 
1152     /// Enables or disables scripted term.
1153     SPH_SCRIPT_ENABLE,
1154 
1155     /// Path of an arbitrary ChaiScript script executed each timestep.
1156     SPH_SCRIPT_FILE,
1157 
1158     /// Period or time point to execute the script. Zero means the time step is executed immediately or every
1159     /// time step, depending on the value of SPH_SCRIPT_ONESHOT.
1160     SPH_SCRIPT_PERIOD,
1161 
1162     /// Whether to execute the script only once or periodically.
1163     SPH_SCRIPT_ONESHOT,
1164 
1165     /// If true, all particles have also a moment of inertia, representing a non-homogeneous mass
1166     /// distribution. Otherwise, particles are spherical with inertia tensor I = 2/5 mr^2
1167     NBODY_INERTIA_TENSOR,
1168 
1169     /// \todo
1170     NBODY_MAX_ROTATION_ANGLE,
1171 
1172     /// If true, colliding particles form aggregates, which then move and rotate as rigid bodies. There are no
1173     /// collisions between particles belonging to the same aggregate, only collisions of different aggregates
1174     /// need to be handled. Note that enabling aggregates overrides handlers of collisions and overlaps.
1175     NBODY_AGGREGATES_ENABLE,
1176 
1177     /// Specifies the initial aggregates used in the simulation. See \ref AggregateEnum.
1178     NBODY_AGGREGATES_SOURCE,
1179 
1180     /// Algorithm to compute gravitational acceleration
1181     GRAVITY_SOLVER,
1182 
1183     /// Opening angle Theta for multipole approximation of gravity
1184     GRAVITY_OPENING_ANGLE,
1185 
1186     /// Order of multipole expansion
1187     GRAVITY_MULTIPOLE_ORDER,
1188 
1189     /// Gravity smoothing kernel
1190     GRAVITY_KERNEL,
1191 
1192     /// Gravitational constant. To be generalized.
1193     GRAVITY_CONSTANT,
1194 
1195     /// Period of gravity evaluation. If zero, gravity is computed every time step, for any positive value,
1196     /// gravitational acceleration is cached for each particle and used each time step until next
1197     /// recomputation.
1198     GRAVITY_RECOMPUTATION_PERIOD,
1199 
1200     /// Specifies how the collisions of particles should be handler; see CollisionHandlerEnum.
1201     COLLISION_HANDLER,
1202 
1203     /// Specifies how particle overlaps should be handled.
1204     COLLISION_OVERLAP,
1205 
1206     /// Coefficient of restitution for normal component (alongside particle direction vector) of velocity.
1207     /// Applicable only for bounce collisions.
1208     COLLISION_RESTITUTION_NORMAL,
1209 
1210     /// Coefficient of restitution for tangent component (perpendicular to particle direction vector) of
1211     /// velocity. Applicable only for bounce collisions.
1212     COLLISION_RESTITUTION_TANGENT,
1213 
1214     /// Relative particle overlap (0 for particles in contact, 1 for particles lying on top of each other) for
1215     /// which the collision is handled as overlap. Used to avoid very small (<EPS) overlaps not being handled
1216     /// as collision due to numerical imprecisions.
1217     COLLISION_ALLOWED_OVERLAP,
1218 
1219     /// Multiplier of the relative velocity, used when determining whether to merge the collided particles or
1220     /// reject the collision. If zero, particles are always merged. Larger values than 1 can be used to merge
1221     /// only very slowly moving particles.
1222     COLLISION_BOUNCE_MERGE_LIMIT,
1223 
1224     /// Parameter analogous to COLLISION_BOUNCE_MERGE_LIMIT, but used for the rotation of the merger.
1225     /// Particles can only be merged if the angular frequency multiplied by this parameter is lower than the
1226     /// breakup frequency. If zero, particles are always merged, values larger than 1 can be used to avoid
1227     /// fast rotators in the simulation.
1228     COLLISION_ROTATION_MERGE_LIMIT,
1229 
1230     /// Magnitude of the repel force for the soft-body solver
1231     SOFT_REPEL_STRENGTH,
1232 
1233     /// Magnitude of the friction force for the soft-body solver
1234     SOFT_FRICTION_STRENGTH,
1235 
1236     /// Selected timestepping integrator
1237     TIMESTEPPING_INTEGRATOR,
1238 
1239     /// Courant number
1240     TIMESTEPPING_COURANT_NUMBER,
1241 
1242     /// Upper limit of the time step. The timestep is guaranteed to never exceed this value for any timestep
1243     /// criterion. The lowest possible timestep is not set, timestep can be any positive value.
1244     TIMESTEPPING_MAX_TIMESTEP,
1245 
1246     /// Initial value of time step. If dynamic timestep is disabled, the run will keep the initial timestep
1247     /// for the whole duration. Some timestepping algorithms might not use the initial timestep and directly
1248     /// compute new value of timestep, in which case this parameter has no effect.
1249     TIMESTEPPING_INITIAL_TIMESTEP,
1250 
1251     /// Criterion used to determine value of time step. More criteria may be compined, in which case the
1252     /// smallest time step of all is selected.
1253     TIMESTEPPING_CRITERION,
1254 
1255     /// Multiplicative factor k for the derivative criterion; dt = k * v / dv
1256     TIMESTEPPING_DERIVATIVE_FACTOR,
1257 
1258     /// Multiplicative factor for the divergence criterion
1259     TIMESTEPPING_DIVERGENCE_FACTOR,
1260 
1261     /// Power of the generalized mean, used to compute the final timestep from timesteps of individual
1262     /// particles. Negative infinity means the minimal timestep is used. This value will also set statistics
1263     /// of the restricting particle, namely the particle index and the quantity value and corresponding
1264     /// derivative of the particle; these statistics are not saved for other powers.
1265     TIMESTEPPING_MEAN_POWER,
1266 
1267     /// Maximum relative increase of a timestep in two subsequent timesteps. Used to 'smooth' the timesteps,
1268     /// as it prevents very fast increase of the time step, especially if the initial time step is very low.
1269     /// Used only by \ref MultiCriterion.
1270     TIMESTEPPING_MAX_INCREASE,
1271 
1272     /// Number of sub-steps in the modified midpoint method.
1273     TIMESTEPPING_MIDPOINT_COUNT,
1274 
1275     /// Required relative accuracy of the Bulirsch-Stoer integrator.
1276     TIMESTEPPING_BS_ACCURACY,
1277 
1278     /// Global rotation of the coordinate system around axis (0, 0, 1) passing through origin. If non-zero,
1279     /// causes non-intertial acceleration.
1280     FRAME_ANGULAR_FREQUENCY,
1281 
1282     FRAME_CONSTANT_ACCELERATION,
1283 
1284     FRAME_TIDES_MASS,
1285 
1286     FRAME_TIDES_POSITION,
1287 
1288     /// Maximum number of particles in a leaf node.
1289     FINDER_LEAF_SIZE,
1290 
1291     /// Maximal in a a tree depth to be processed in parallel. While a larger value implies better
1292     /// distribution of work between threads, it also comes up with performance penalty due to scheduling
1293     /// overhead.
1294     FINDER_MAX_PARALLEL_DEPTH,
1295 
1296     /// Computational domain, enforced by boundary conditions
1297     DOMAIN_TYPE,
1298 
1299     /// Type of boundary conditions.
1300     DOMAIN_BOUNDARY,
1301 
1302     /// Center point of the domain
1303     DOMAIN_CENTER,
1304 
1305     /// Radius of a spherical and cylindrical domain
1306     DOMAIN_RADIUS,
1307 
1308     /// Height of a cylindrical domain
1309     DOMAIN_HEIGHT,
1310 
1311     /// (Vector) size of a block domain
1312     DOMAIN_SIZE,
1313 
1314     /// Minimal distance between a particle and its ghost, in units of smoothing length.
1315     DOMAIN_GHOST_MIN_DIST,
1316 
1317     /// Distance to the boundary in units of smoothing length under which the particles are frozen.
1318     DOMAIN_FROZEN_DIST,
1319 
1320     /// If true, the mapping coordinates will be computed and saved for all bodies in the simulation.
1321     GENERATE_UVWS,
1322 
1323     /// Type of the UV mapping
1324     UVW_MAPPING,
1325 };
1326 
1327 
1328 enum class DistributionEnum {
1329     /// Hexagonally close packing
1330     HEXAGONAL,
1331 
1332     /// Cubic close packing
1333     CUBIC,
1334 
1335     /// Random distribution of particles
1336     RANDOM,
1337 
1338     /// Isotropic uniform distribution by Diehl et al. (2012)
1339     DIEHL_ET_AL,
1340 
1341     /// Stratified distribution to reduce clustering
1342     STRATIFIED,
1343 
1344     /// Parametrized spiraling scheme by Saff & Kuijlaars (1997)
1345     PARAMETRIZED_SPIRALING,
1346 
1347     /// Distributes particles uniformly on line
1348     LINEAR
1349 };
1350 
1351 
1352 enum class EosEnum {
1353     /// No equation of state
1354     NONE,
1355 
1356     /// Equation of state for ideal gas
1357     IDEAL_GAS,
1358 
1359     /// Tait equation of state for simulations of liquids
1360     TAIT,
1361 
1362     /// Mie-Gruneisen equation of state
1363     MIE_GRUNEISEN,
1364 
1365     /// Tillotson (1962) equation of state
1366     TILLOTSON,
1367 
1368     /// Murnaghan equation of state
1369     MURNAGHAN,
1370 
1371     /// Simplified version of the Tillotson equation of state
1372     SIMPLIFIED_TILLOTSON,
1373 
1374     /// ANEOS given by look-up table
1375     ANEOS
1376 };
1377 
1378 /// \brief Settings of a single body / gas phase / ...
1379 ///
1380 /// Combines material parameters and numerical parameters of the SPH method specific for one body. Values of
1381 /// parameters CANNOT be changed to preserve backward compatibility of serializer. New IDs can be created as
1382 /// needed, parameters no longer needed can be removed.
1383 enum class BodySettingsId {
1384     /// Equation of state for this material, see EosEnum for options.
1385     EOS = 0,
1386 
1387     /// Initial distribution of SPH particles within the domain, see DistributionEnum for options.
1388     INITIAL_DISTRIBUTION = 1,
1389 
1390     /// If true, generated particles will be moved so that their center of mass corresponds to the center of
1391     /// selected domain. Note that this will potentially move some particles outside of the domain, which can
1392     /// clash with boundary conditions.
1393     CENTER_PARTICLES = 2,
1394 
1395     /// If true, particles are sorted using Morton code, preserving locality in memory.
1396     PARTICLE_SORTING = 3,
1397 
1398     /// Turns on 'SPH5 compatibility' mode when generating particle positions. This allows 1-1 comparison of
1399     /// generated arrays, but results in too many generated particles (by about factor 1.4). The option also
1400     /// implies CENTER_PARTICLES.
1401     DISTRIBUTE_MODE_SPH5 = 4,
1402 
1403     /// Strength parameter of the Diehl's distribution.
1404     DIEHL_STRENGTH = 5,
1405 
1406     /// Maximum allowed difference between the expected number of particles and the actual number of generated
1407     /// particles. Higher value speed up the generation of particle positions.
1408     DIEHL_MAX_DIFFERENCE = 6,
1409 
1410     /// Number of iterations of particle repelling.
1411     DIEHL_ITERATION_COUNT = 71,
1412 
1413     /// Eta-factor between smoothing length and particle concentration (h = eta * n^(-1/d) )
1414     SMOOTHING_LENGTH_ETA = 72,
1415 
1416     /// Density at zero pressure
1417     DENSITY = 7,
1418 
1419     /// Allowed range of density. Densities of all particles all clamped to fit in the range.
1420     DENSITY_RANGE = 8,
1421 
1422     /// Estimated minimal value of density. This value is NOT used to clamp densities, but for
1423     /// determining error of timestepping.
1424     DENSITY_MIN = 9,
1425 
1426     /// Initial specific internal energy
1427     ENERGY = 10,
1428 
1429     /// Allowed range of specific internal energy.
1430     ENERGY_RANGE = 11,
1431 
1432     /// Estimated minimal value of energy used to determine timestepping error.
1433     ENERGY_MIN = 12,
1434 
1435     /// Initial values of the deviatoric stress tensor
1436     STRESS_TENSOR = 13,
1437 
1438     /// Estimated minial value of stress tensor components used to determined timestepping error.
1439     STRESS_TENSOR_MIN = 14,
1440 
1441     /// Initial damage of the body.
1442     DAMAGE = 15,
1443 
1444     /// Allowed range of damage.
1445     DAMAGE_RANGE = 16,
1446 
1447     /// Estimate minimal value of damage used to determine timestepping error.
1448     DAMAGE_MIN = 17,
1449 
1450     /// Adiabatic index used by some equations of state (such as ideal gas)
1451     ADIABATIC_INDEX = 18,
1452 
1453     /// Exponent of density, representing a compressibility of a fluid. Used in Tait equation of state.
1454     TAIT_GAMMA = 19,
1455 
1456     /// Sound speed used in Tait equation of state
1457     TAIT_SOUND_SPEED = 20,
1458 
1459     /// Bulk modulus of the material
1460     BULK_MODULUS = 21,
1461 
1462     /// Coefficient B of the nonlinear compressive term in Tillotson equation
1463     TILLOTSON_NONLINEAR_B = 22,
1464 
1465     /// "Small a" coefficient in Tillotson equation
1466     TILLOTSON_SMALL_A = 23,
1467 
1468     /// "Small b" coefficient in Tillotson equation
1469     TILLOTSON_SMALL_B = 24,
1470 
1471     /// Alpha coefficient in expanded phase of Tillotson equation
1472     TILLOTSON_ALPHA = 25,
1473 
1474     /// Beta coefficient in expanded phase of Tillotson equation
1475     TILLOTSON_BETA = 26,
1476 
1477     /// Specific sublimation energy
1478     TILLOTSON_SUBLIMATION = 27,
1479 
1480     /// Specific energy of incipient vaporization
1481     TILLOTSON_ENERGY_IV = 28,
1482 
1483     /// Specific energy of complete vaporization
1484     TILLOTSON_ENERGY_CV = 29,
1485 
1486     /// Gruneisen's gamma paraemter used in Mie-Gruneisen equation of state
1487     GRUNEISEN_GAMMA = 30,
1488 
1489     /// Used in Mie-Gruneisen equations of state
1490     BULK_SOUND_SPEED = 31,
1491 
1492     /// Linear Hugoniot slope coefficient used in Mie-Gruneisen equation of state
1493     HUGONIOT_SLOPE = 32,
1494 
1495     /// Model of stress reducing used within the rheological model
1496     RHEOLOGY_YIELDING = 33,
1497 
1498     /// Model of fragmentation used within the rheological model
1499     RHEOLOGY_DAMAGE = 34,
1500 
1501     /// Shear modulus mu (a.k.a Lame's second parameter) of the material
1502     SHEAR_MODULUS = 35,
1503 
1504     /// Young modulus of the material
1505     YOUNG_MODULUS = 36,
1506 
1507     /// Elastic modulus lambda (a.k.a Lame's first parameter) of the material
1508     ELASTIC_MODULUS = 37,
1509 
1510     /// Elasticity limit of the von Mises yielding criterion
1511     ELASTICITY_LIMIT = 38,
1512 
1513     /// Melting energy, used for temperature-dependence of the stress tensor
1514     MELT_ENERGY = 39,
1515 
1516     /// Cohesion, yield strength at zero pressure
1517     COHESION = 40,
1518 
1519     /// Coefficient of friction for undamaged material
1520     INTERNAL_FRICTION = 41,
1521 
1522     /// Coefficient of friction for fully damaged material
1523     DRY_FRICTION = 42,
1524 
1525     /// Whether to use the acoustic fludization model.
1526     USE_ACOUSTIC_FLUDIZATION = 43,
1527 
1528     /// Characteristic decay time of acoustic oscillations in the material
1529     OSCILLATION_DECAY_TIME = 44,
1530 
1531     /// Regeneration efficiency of acoustric oscillations
1532     OSCILLATION_REGENERATION = 74,
1533 
1534     /// Effective viscosity of acoustic fludizations
1535     FLUIDIZATION_VISCOSITY = 45,
1536 
1537     /// Speed of crack growth, in units of local sound speed.
1538     RAYLEIGH_SOUND_SPEED = 47,
1539 
1540     /// Coefficient (multiplier) of the Weibull distribution of flaws
1541     WEIBULL_COEFFICIENT = 48,
1542 
1543     /// Exponent of the Weibull distribution of flaws
1544     WEIBULL_EXPONENT = 49,
1545 
1546     /// Whether to use precomputed distributions for flaw sampling. Otherwise, flaws are sampled using uniform
1547     /// random number generator, which may be prohibitively slow for large particle counts.
1548     WEIBULL_SAMPLE_DISTRIBUTIONS = 66,
1549 
1550     /// Initial value of the material distention, used in the P-alpha model.
1551     DISTENTION = 81,
1552 
1553 
1554     BULK_VISCOSITY = 50,
1555 
1556     SHEAR_VISCOSITY = 51,
1557 
1558     DAMPING_COEFFICIENT = 52,
1559 
1560     DIFFUSIVITY = 53,
1561 
1562     /// Coefficient of surface tension
1563     SURFACE_TENSION = 54,
1564 
1565     /// Number of SPH particles in the body
1566     PARTICLE_COUNT = 55,
1567 
1568     /// Minimal number of particles per one body. Used when creating 'sub-bodies' withing one 'parent' body,
1569     /// for example when creating rubble-pile asteroids, ice blocks inside an asteroid, etc. Parameter has no
1570     /// effect for creation of a single monolithic body; the number of particles from PARTICLE_COUNT is used
1571     /// in any case.
1572     MIN_PARTICLE_COUNT = 56,
1573 
1574     /// Initial alpha coefficient of the artificial viscosity. This is only used if the coefficient is
1575     /// different for each particle. For constant coefficient shared for all particles, use value from global
1576     /// settings.
1577     AV_ALPHA = 57,
1578 
1579     /// Lower and upper bound of the alpha coefficient, used only for time-dependent artificial viscosity.
1580     AV_ALPHA_RANGE = 58,
1581 
1582     /// Bulk (macro)porosity of the body
1583     BULK_POROSITY = 64,
1584 
1585     /// Heat capacity at constant pressure,
1586     HEAT_CAPACITY = 67,
1587 
1588     BODY_SHAPE_TYPE = 59,
1589 
1590     /// Center point of the body. Currently used only by \ref StabilizationSolver.
1591     BODY_CENTER = 61,
1592 
1593     BODY_RADIUS = 68,
1594 
1595     BODY_DIMENSIONS = 69,
1596 
1597     BODY_HEIGHT = 73,
1598 
1599     BODY_SPIN_RATE = 70,
1600 
1601     VISUALIZATION_TEXTURE = 80,
1602 
1603     /// Arbitrary string identifying this material
1604     IDENTIFIER = 99,
1605 };
1606 
1607 using RunSettings = Settings<RunSettingsId>;
1608 using BodySettings = Settings<BodySettingsId>;
1609 
1610 NAMESPACE_SPH_END
1611