SPH
Accumulated.cpp
Go to the documentation of this file.
2 #include "quantities/Quantity.h"
3 #include "quantities/Storage.h"
4 #include "thread/Scheduler.h"
5 
7 
8 template <typename TValue>
9 void Accumulated::insert(const QuantityId id, const OrderEnum order, const BufferSource source) {
10  // add the buffer if not already present
11  if (!this->hasBuffer(id, order)) {
12  buffers.push(Element{ id, order, Array<TValue>() });
13  }
14 
15  // check if we didn't call this more then once for 'unique' buffers
16  auto recordIter = std::find_if(records.begin(), records.end(), [id](QuantityRecord& r) { //
17  return r.id == id;
18  });
19  if (recordIter == records.end()) {
20  records.push(QuantityRecord{ id, source == BufferSource::UNIQUE });
21  } else {
22  SPH_ASSERT(recordIter->id == id);
23  if (source == BufferSource::UNIQUE || recordIter->unique) {
24  // either the previous record was unique and we are adding another one, or the previous one
25  // was shared and now we are adding unique
26  SPH_ASSERT(false, "Another derivatives accumulates to quantity marked as unique");
27  }
28  }
29 }
30 
31 template void Accumulated::insert<Size>(const QuantityId, const OrderEnum, const BufferSource);
32 template void Accumulated::insert<Float>(const QuantityId, const OrderEnum, const BufferSource);
33 template void Accumulated::insert<Vector>(const QuantityId, const OrderEnum, const BufferSource);
34 template void Accumulated::insert<SymmetricTensor>(const QuantityId, const OrderEnum, const BufferSource);
35 template void Accumulated::insert<TracelessTensor>(const QuantityId, const OrderEnum, const BufferSource);
36 
37 void Accumulated::initialize(const Size size) {
38  for (Element& e : buffers) {
39  forValue(e.buffer, [size](auto& values) {
40  using T = typename std::decay_t<decltype(values)>::Type;
41  if (values.size() != size) {
42  values.resize(size);
43  values.fill(T(0._f));
44  } else {
45  // check that the array is really cleared
46  SPH_ASSERT(std::count(values.begin(), values.end(), T(0._f)) == values.size());
47  }
48  });
49  }
50 }
51 
52 template <typename TValue>
54  for (Element& e : buffers) {
55  if (e.id == id) {
56  SPH_ASSERT(e.order == order);
57  Array<TValue>& values = e.buffer;
58  SPH_ASSERT(!values.empty());
59  return values;
60  }
61  }
62  STOP;
63 }
64 
70 
72  for (Element& e : buffers) {
73  forValue(e.buffer, [this, &e, &others](auto& buffer) INL { //
74  this->sumBuffer(buffer, e.id, others);
75  });
76  }
77 }
78 
80  for (Element& e : buffers) {
81  forValue(e.buffer, [this, &scheduler, &e, &others](auto& buffer) INL { //
82  this->sumBuffer(scheduler, buffer, e.id, others);
83  });
84  }
85 }
86 void Accumulated::store(Storage& storage) {
87  for (Element& e : buffers) {
88  forValue(e.buffer, [&e, &storage](auto& buffer) {
89  using T = typename std::decay_t<decltype(buffer)>::Type;
90  // storage must already have the quantity, we cannot add quantities during the run because of
91  // timestepping
92  SPH_ASSERT(storage.has(e.id), getMetadata(e.id).quantityName);
93  SPH_ASSERT(Size(storage.getQuantity(e.id).getOrderEnum()) >= Size(e.order));
94  storage.getAll<T>(e.id)[Size(e.order)] = std::move(buffer);
95  buffer.fill(T(0._f));
96  });
97  }
98 }
99 
101  return buffers.size();
102 }
103 
104 template <typename Type>
105 Array<Iterator<Type>> Accumulated::getBufferIterators(const QuantityId id, ArrayView<Accumulated*> others) {
106  Array<Iterator<Type>> iterators;
107  for (Accumulated* other : others) {
108  auto iter = std::find_if(other->buffers.begin(), other->buffers.end(), [id](const Element& e) { //
109  return e.id == id;
110  });
111  SPH_ASSERT(iter != other->buffers.end());
112  Array<Type>& buffer2 = iter->buffer;
113  iterators.push(buffer2.begin());
114  }
115  return iterators;
116 }
117 
118 template <typename Type>
119 void Accumulated::sumBuffer(Array<Type>& buffer1, const QuantityId id, ArrayView<Accumulated*> others) {
120  Array<Iterator<Type>> iterators = this->getBufferIterators<Type>(id, others);
121  const Type zero = Type(0._f);
122  for (Size i = 0; i < buffer1.size(); ++i) {
123  Type sum = zero;
124  for (Iterator<Type>& iter : iterators) {
125  if (*iter != zero) {
126  sum += *iter;
127  *iter = zero;
128  }
129  ++iter;
130  }
131  buffer1[i] += sum;
132  }
133 }
134 
135 template <typename Type>
136 void Accumulated::sumBuffer(IScheduler& scheduler,
137  Array<Type>& buffer1,
138  const QuantityId id,
139  ArrayView<Accumulated*> others) {
140  Array<Iterator<Type>> iterators = this->getBufferIterators<Type>(id, others);
141  auto functor = [&iterators, &buffer1](const Size i) INL {
142  Type sum(0._f);
143  for (Iterator<Type> iter : iterators) {
144  Type& x = *(iter + i);
145  if (x != Type(0._f)) {
146  sum += x;
147  x = Type(0._f);
148  }
149  }
150  buffer1[i] += sum;
151  };
152  parallelFor(scheduler, 0, buffer1.size(), functor);
153 }
154 
155 bool Accumulated::hasBuffer(const QuantityId id, const OrderEnum order) const {
156  for (const Element& e : buffers) {
157  if (e.id == id) {
158  // already used
159  SPH_ASSERT(e.order == order, "Cannot accumulate both values and derivatives of quantity");
160  return true;
161  }
162  }
163  return false;
164 }
165 
Buffer storing quantity values accumulated by summing over particle pairs.
BufferSource
Definition: Accumulated.h:18
@ UNIQUE
Only a single derivative accumulates to this buffer.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define STOP
Definition: Assert.h:106
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
#define NAMESPACE_SPH_END
Definition: Object.h:12
#define INL
Definition: Object.h:32
QuantityId
Unique IDs of basic quantities of SPH particles.
Definition: QuantityIds.h:19
Holder of quantity values and their temporal derivatives.
OrderEnum
Definition: Quantity.h:15
Interface for executing tasks (potentially) asynchronously.
INLINE void parallelFor(IScheduler &scheduler, const Size from, const Size to, TFunctor &&functor)
Executes a functor concurrently from all available threads.
Definition: Scheduler.h:98
Container for storing particle quantities and materials.
decltype(auto) INLINE forValue(Variant< TArgs... > &variant, TFunctor &&functor)
Definition: Variant.h:428
Storage for accumulating derivatives.
Definition: Accumulated.h:30
void initialize(const Size size)
Initialize all storages.
Definition: Accumulated.cpp:37
void sum(ArrayView< Accumulated * > others)
Sums values of a list of storages.
Definition: Accumulated.cpp:71
Array< TValue > & getBuffer(const QuantityId id, const OrderEnum order)
Returns the buffer of given quantity and given order.
Definition: Accumulated.cpp:53
Size getBufferCnt() const
void store(Storage &storage)
Stores accumulated values to corresponding quantities.
Definition: Accumulated.cpp:86
void insert(const QuantityId id, const OrderEnum order, const BufferSource source)
Creates a new storage with given ID.
Object providing safe access to continuous memory of data.
Definition: ArrayView.h:17
INLINE Iterator< StorageType > end() noexcept
Definition: Array.h:462
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
Definition: Array.h:306
INLINE TCounter size() const noexcept
Definition: Array.h:193
INLINE bool empty() const noexcept
Definition: Array.h:201
INLINE Iterator< StorageType > begin() noexcept
Definition: Array.h:450
Interface that allows unified implementation of sequential and parallelized versions of algorithms.
Definition: Scheduler.h:27
Simple (forward) iterator over continuous array of objects of type T.
Definition: Iterator.h:18
Container storing all quantities used within the simulations.
Definition: Storage.h:230