1 #pragma once 2 3 /// \file Accumulated.h 4 /// \brief Buffer storing quantity values accumulated by summing over particle pairs 5 /// \author Pavel Sevecek (sevecek at sirrah.troja.mff.cuni.cz) 6 /// \date 2016-2021 7 8 #include "common/ForwardDecl.h" 9 #include "objects/containers/Array.h" 10 #include "objects/geometry/TracelessTensor.h" 11 #include "objects/wrappers/Variant.h" 12 #include "quantities/QuantityIds.h" 13 14 NAMESPACE_SPH_BEGIN 15 16 enum class OrderEnum; 17 18 enum class BufferSource { 19 /// Only a single derivative accumulates to this buffer 20 UNIQUE, 21 22 /// Multiple derivatives may accumulate into the buffer 23 SHARED, 24 }; 25 26 /// \brief Storage for accumulating derivatives. 27 /// 28 /// Each thread shall own its own Accumulated storage. Each accumulated buffer is associated with a quantity 29 /// using QuantityId. 30 class Accumulated { 31 private: 32 template <typename... TArgs> 33 using HolderVariant = Variant<Array<TArgs>...>; 34 35 using Buffer = HolderVariant<Size, Float, Vector, TracelessTensor, SymmetricTensor>; 36 37 struct Element { 38 /// ID of accumulated quantity, used to stored the quantity into the storage 39 QuantityId id; 40 41 /// Order, specifying whether we are accumulating values or derivatives 42 OrderEnum order; 43 44 /// Accumulated data 45 Buffer buffer; 46 }; 47 Array<Element> buffers; 48 49 struct QuantityRecord { 50 QuantityId id; 51 bool unique; 52 }; 53 54 /// Debug array, holding IDs of all quantities to check for uniqueness. 55 Array<QuantityRecord> records; 56 57 public: 58 /// \brief Creates a new storage with given ID. 59 /// 60 /// Should be called once for each thread when the solver is initialized. 61 /// \param id ID of the accumulated quantity 62 /// \param order Order of the quantity. Only highest order can be accumulated, this parameter is used to 63 /// ensure the derivative is used consistently. 64 /// \param unique Whether this buffer is being accumulated by a single derivative. It has no effect on 65 /// the simulation, but ensures a consistency of the run (that we don't accumulate two 66 /// different velocity gradients, for example). 67 template <typename TValue> 68 void insert(const QuantityId id, const OrderEnum order, const BufferSource source); 69 70 /// \brief Initialize all storages. 71 /// 72 /// Storages are resized if needed and cleared out of all previously accumulated values. 73 void initialize(const Size size); 74 75 /// \brief Returns the buffer of given quantity and given order. 76 /// 77 /// \note Accumulated can store only one buffer per quantity, so the order is not neccesary to retrive the 78 /// buffer, but it is required to check that we are indeed returning the required order of quantity. It 79 /// also makes the code more readable. 80 template <typename TValue> 81 Array<TValue>& getBuffer(const QuantityId id, const OrderEnum order); 82 83 /// \brief Sums values of a list of storages. 84 /// 85 /// Storages must have the same number of buffers and the matching buffers must have the same type and 86 /// same size. 87 void sum(ArrayView<Accumulated*> others); 88 89 /// \brief Sums values, concurently over different quantities 90 void sum(IScheduler& scheduler, ArrayView<Accumulated*> others); 91 92 /// \brief Stores accumulated values to corresponding quantities. 93 /// 94 /// The accumulated quantity must already exist in the storage and its order must be at least the order of 95 /// the accumulated buffer. The accumulated buffer is cleared (filled with zeroes) after storing the 96 /// values into the storage. 97 void store(IScheduler& scheduler, Storage& storage); 98 99 Size getBufferCnt() const; 100 101 private: 102 template <typename Type> 103 Array<Iterator<Type>> getBufferIterators(const QuantityId id, ArrayView<Accumulated*> others); 104 105 template <typename Type> 106 void sumBuffer(Array<Type>& buffer1, const QuantityId id, ArrayView<Accumulated*> others); 107 108 template <typename Type> 109 void sumBuffer(IScheduler& scheduler, 110 Array<Type>& buffer1, 111 const QuantityId id, 112 ArrayView<Accumulated*> others); 113 114 bool hasBuffer(const QuantityId id, const OrderEnum order) const; 115 }; 116 117 118 NAMESPACE_SPH_END 119