SPH
SymmetricSolver.cpp
Go to the documentation of this file.
2 #include "objects/Exceptions.h"
4 #include "quantities/IMaterial.h"
7 #include "sph/kernel/Kernel.h"
8 #include "system/Factory.h"
9 #include "system/Profiler.h"
10 #include "system/Statistics.h"
11 
13 
14 template <Size Dim>
16  const RunSettings& settings,
17  const EquationHolder& eqs,
19  : scheduler(scheduler)
20  , threadData(scheduler)
21  , bc(std::move(bc)) {
25  kernel = Factory::getKernel<Dim>(settings);
26 
27  // Find all neighbours within kernel support. Since we are only searching for particles with
28  // smaller h, we know that symmetrized lengths (h_i + h_j)/2 will be ALWAYS smaller or equal
29  // to h_i, and we thus never "miss" a particle.
30  finder = Factory::getFinder(settings);
31 
32  equations += eqs;
33 
34  // add term counting number of neighbours
35  equations += makeTerm<NeighbourCountTerm>();
36 
37  // initialize all derivatives
38  for (ThreadData& data : threadData) {
39  equations.setDerivatives(data.derivatives, settings);
40 
41  // all derivatives must be symmetric!
42  if (!data.derivatives.isSymmetric()) {
43  throw InvalidSetup("Asymmetric derivative used within symmetric solver");
44  }
45  }
46 }
47 
48 template <Size Dim>
50  const RunSettings& settings,
51  const EquationHolder& eqs)
52  : SymmetricSolver(scheduler, settings, eqs, Factory::getBoundaryConditions(settings)) {}
53 
54 template <Size Dim>
56 
57 template <Size Dim>
59  // initialize all materials (compute pressure, apply yielding and damage, ...)
60  for (Size i = 0; i < storage.getMaterialCnt(); ++i) {
61  PROFILE_SCOPE("SymmetricSolver initialize materials")
62  MaterialView material = storage.getMaterial(i);
63  material->initialize(scheduler, storage, material.sequence());
64  }
65 
66  const Float t = stats.getOr<Float>(StatisticsId::RUN_TIME, 0._f);
67 
68  // initialize all equation terms (applies dependencies between quantities)
69  equations.initialize(scheduler, storage, t);
70 
71  // apply boundary conditions before the loop
72  bc->initialize(storage);
73 
74  // initialize accumulate storages & derivatives
75  this->beforeLoop(storage, stats);
76 
77  // main loop over pairs of interacting particles
78  this->loop(storage, stats);
79 
80  // sum up accumulated storage, compute statistics
81  this->afterLoop(storage, stats);
82 
83  // integrate all equations
84  equations.finalize(scheduler, storage, t);
85 
86  // apply boundary conditions after the loop
87  bc->finalize(storage);
88 
89  // finalize all materials (integrate fragmentation model)
90  for (Size i = 0; i < storage.getMaterialCnt(); ++i) {
91  PROFILE_SCOPE("SymmetricSolver finalize materials")
92  MaterialView material = storage.getMaterial(i);
93  material->finalize(scheduler, storage, material.sequence());
94  }
95 }
96 
97 template <Size Dim>
98 void SymmetricSolver<Dim>::create(Storage& storage, IMaterial& material) const {
99  storage.insert<Size>(QuantityId::NEIGHBOUR_CNT, OrderEnum::ZERO, 0);
100 
101  // create necessary quantities
102  equations.create(storage, material);
103 
104  // check equations and create quantities
105  this->sanityCheck(storage);
106 }
107 
108 template <Size Dim>
110  MEASURE_SCOPE("SymmetricSolver::loop");
111  // (re)build neighbour-finding structure; this needs to be done after all equations
112  // are initialized in case some of them modify smoothing lengths
114  finder->build(scheduler, r);
115 
116  // here we use a kernel symmetrized in smoothing lengths:
117  // \f$ W_ij(r_i - r_j, 0.5(h[i] + h[j]) \f$
118  SymmetrizeSmoothingLengths<LutKernel<Dim>> symmetrizedKernel(kernel);
119 
120  auto functor = [this, r, &symmetrizedKernel](const Size i, ThreadData& data) {
121  finder->findLowerRank(i, r[i][H] * kernel.radius(), data.neighs);
122  data.grads.clear();
123  data.idxs.clear();
124  for (auto& n : data.neighs) {
125  const Size j = n.index;
126  const Float hbar = 0.5_f * (r[i][H] + r[j][H]);
127  SPH_ASSERT(hbar > EPS && hbar <= r[i][H], hbar, r[i][H]);
128  if (getSqrLength(r[i] - r[j]) >= sqr(kernel.radius() * hbar)) {
129  // aren't actual neighbours
130  continue;
131  }
132  const Vector gr = symmetrizedKernel.grad(r[i], r[j]);
133  SPH_ASSERT(isReal(gr) && dot(gr, r[i] - r[j]) <= 0._f, gr, getLength(r[i] - r[j]));
134  data.grads.emplaceBack(gr);
135  data.idxs.emplaceBack(j);
136  }
137  data.derivatives.evalSymmetric(i, data.idxs, data.grads);
138  };
139  PROFILE_SCOPE("GenericSolver main loop");
140  parallelFor(scheduler, threadData, 0, r.size(), functor);
141 }
142 
143 template <Size Dim>
145  // clear thread local storages
146  PROFILE_SCOPE("GenericSolver::beforeLoop");
147  for (ThreadData& data : threadData) {
148  data.derivatives.initialize(storage);
149  }
150 }
151 
152 template <Size Dim>
154  Accumulated* first = nullptr;
155 
156  // sum up thread local accumulated values
157  Array<Accumulated*> threadLocalAccumulated;
158  for (ThreadData& data : threadData) {
159  if (!first) {
160  first = &data.derivatives.getAccumulated();
161  } else {
162  SPH_ASSERT(first != nullptr);
163  threadLocalAccumulated.push(&data.derivatives.getAccumulated());
164  }
165  }
166  SPH_ASSERT(first != nullptr);
167  first->sum(scheduler, threadLocalAccumulated);
168 
169  // store them to storage
170  first->store(storage);
171 
172  // compute neighbour statistics
173  MinMaxMean neighs;
175  const Size size = storage.getParticleCnt();
176  for (Size i = 0; i < size; ++i) {
177  neighs.accumulate(neighCnts[i]);
178  }
179  stats.set(StatisticsId::NEIGHBOUR_COUNT, neighs);
180 }
181 
182 template <Size Dim>
185  finder->build(scheduler, r);
186  return &*finder;
187 }
188 
189 template <Size Dim>
190 void SymmetricSolver<Dim>::sanityCheck(const Storage& UNUSED(storage)) const {
191  // we must solve smoothing length somehow
192  if (!equations.contains<AdaptiveSmoothingLength>() && !equations.contains<ConstSmoothingLength>()) {
193  throw InvalidSetup(
194  "No solver of smoothing length specified; add either ConstSmootingLength or "
195  "AdaptiveSmootingLength into the list of equations");
196  }
197 }
198 
199 template class SymmetricSolver<1>;
200 template class SymmetricSolver<2>;
201 template class SymmetricSolver<3>;
202 
INLINE bool isReal(const AntisymmetricTensor &t)
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Boundary conditions.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Additional equation terms computing SPH statistics rather than physical quantities.
Base class for all particle materials.
SPH kernels.
AutoPtr< IMaterial > getMaterial(const MaterialEnum type)
Definition: Materials.cpp:91
constexpr Float EPS
Definition: MathUtils.h:30
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
Tool to measure time spent in functions and profile the code.
#define MEASURE_SCOPE(name)
Definition: Profiler.h:70
#define PROFILE_SCOPE(name)
Definition: Profiler.h:175
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ NEIGHBOUR_CNT
Number of neighbouring particles (in radius h * kernel.radius)
@ ZERO
Quantity without derivatives, or "zero order" of quantity.
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
Statistics gathered and periodically displayed during the run.
@ NEIGHBOUR_COUNT
Number of neighbours (min, max, mean)
@ RUN_TIME
Current time of the simulation in code units. Does not necessarily have to be 0 when run starts.
Basic SPH solver, evaluating all interactions symmetrically.
INLINE Float getLength(const Vector &v)
Returns the length of the vector. Enabled only for vectors of floating-point precision.
Definition: Vector.h:579
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
INLINE float dot(const BasicVector< float > &v1, const BasicVector< float > &v2)
Make sure the vector is trivially constructible and destructible, needed for fast initialization of a...
Definition: Vector.h:548
@ H
Definition: Vector.h:25
Storage for accumulating derivatives.
Definition: Accumulated.h:30
void sum(ArrayView< Accumulated * > others)
Sums values of a list of storages.
Definition: Accumulated.cpp:71
void store(Storage &storage)
Stores accumulated values to corresponding quantities.
Definition: Accumulated.cpp:86
Evolutionary equation for the (scalar) smoothing length.
Definition: EquationTerm.h:65
Object providing safe access to continuous memory of data.
Definition: ArrayView.h:17
INLINE TCounter size() const
Definition: ArrayView.h:101
Generic dynamically allocated resizable storage.
Definition: Array.h:43
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
Definition: Array.h:306
Helper term to keep smoothing length constant during the simulation.
Definition: EquationTerm.h:219
Container holding equation terms.
Definition: EquationTerm.h:238
void setDerivatives(DerivativeHolder &derivatives, const RunSettings &settings) const
Calls EquationTerm::setDerivatives for all stored equation terms.
Definition: EquationTerm.h:277
Material settings and functions specific for one material.
Definition: IMaterial.h:110
Interface that allows unified implementation of sequential and parallelized versions of algorithms.
Definition: Scheduler.h:27
Thrown when components of the run are mutually incompatible.
Definition: Exceptions.h:24
Non-owning wrapper of a material and particles with this material.
Definition: IMaterial.h:30
INLINE IndexSequence sequence()
Returns iterable index sequence.
Definition: IMaterial.h:75
Helper class for statistics, accumulating minimal, maximal and mean value of a set of numbers.
Definition: Means.h:172
INLINE void accumulate(const Float value)
Definition: Means.h:180
Non-owning wrapper of pointer.
Definition: RawPtr.h:19
Object holding various statistics about current run.
Definition: Statistics.h:22
Statistics & set(const StatisticsId idx, TValue &&value)
Sets new values of a statistic.
Definition: Statistics.h:52
TValue getOr(const StatisticsId idx, const TValue &other) const
Returns value of a statistic, or a given value if the statistic is not stored.
Definition: Statistics.h:98
Container storing all quantities used within the simulations.
Definition: Storage.h:230
Size getMaterialCnt() const
Return the number of materials in the storage.
Definition: Storage.cpp:437
Size getParticleCnt() const
Returns the number of particles.
Definition: Storage.cpp:445
MaterialView getMaterial(const Size matIdx) const
Returns an object containing a reference to given material.
Definition: Storage.cpp:366
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
Basic solver for integration of SPH equations.
virtual void create(Storage &storage, IMaterial &material) const override
Initializes all quantities needed by the solver in the storage.
LutKernel< Dim > kernel
Selected SPH kernel.
virtual void sanityCheck(const Storage &storage) const
Used to check internal consistency of the solver.
ThreadLocal< ThreadData > threadData
Thread-local structure caching all buffers needed to compute derivatives.
virtual void afterLoop(Storage &storage, Statistics &stats)
AutoPtr< ISymmetricFinder > finder
Structure used to search for neighbouring particles.
EquationHolder equations
Holds all equation terms evaluated by the solver.
virtual RawPtr< const IBasicFinder > getFinder(ArrayView< const Vector > r)
virtual void integrate(Storage &storage, Statistics &stats) override
Computes derivatives of all time-dependent quantities.
SymmetricSolver(IScheduler &scheduler, const RunSettings &settings, const EquationHolder &eqs, AutoPtr< IBoundaryCondition > &&bc)
Creates a symmetric solver, given the list of equations to solve.
virtual void beforeLoop(Storage &storage, Statistics &stats)
virtual void loop(Storage &storage, Statistics &stats)
INLINE Vector grad(const Vector &r1, const Vector &r2) const
Definition: Kernel.h:578
Creating code components based on values from settings.
Provides a convenient way to construct objects from settings.
Definition: Factory.h:46
AutoPtr< ISymmetricFinder > getFinder(const RunSettings &settings)
Definition: Factory.cpp:156
AutoPtr< IBoundaryCondition > getBoundaryConditions(const RunSettings &settings, SharedPtr< IDomain > domain)
Definition: Factory.cpp:460
Overload of std::swap for Sph::Array.
Definition: Array.h:578