SPH
SummationSolver.cpp
Go to the documentation of this file.
3 #include "quantities/IMaterial.h"
6 #include "sph/kernel/Kernel.h"
7 #include "system/Factory.h"
8 #include "system/Statistics.h"
9 #include "thread/AtomicFloat.h"
10 
12 
13 static EquationHolder getEquations(const RunSettings& settings) {
15  EquationHolder equations;
16  if (forces.has(ForceEnum::PRESSURE)) {
17  equations += makeTerm<PressureForce>();
18  }
19  if (forces.has(ForceEnum::SOLID_STRESS)) {
20  equations += makeTerm<SolidStressForce>(settings);
21  }
22  if (auto av = Factory::getArtificialViscosity(settings)) {
23  equations += EquationHolder(std::move(av));
24  }
25 
26  // we evolve density and smoothing length ourselves (outside the equation framework),
27  // so make sure it does not change outside the solver
28  equations += makeTerm<ConstSmoothingLength>();
29 
30  SPH_ASSERT(
31  !forces.has(ForceEnum::SELF_GRAVITY), "Summation solver cannot be currently used with gravity");
32 
33  return equations;
34 }
35 
36 template <Size Dim>
38  const RunSettings& settings,
39  const EquationHolder& additionalEquations,
41  : SymmetricSolver<Dim>(scheduler, settings, getEquations(settings) + additionalEquations, std::move(bc)) {
42 
43  targetDensityDifference = settings.get<Float>(RunSettingsId::SPH_SUMMATION_DENSITY_DELTA);
44  densityKernel = Factory::getKernel<Dim>(settings);
47  adaptiveH = (flags != EMPTY_FLAGS);
48  maxIteration = adaptiveH ? settings.get<int>(RunSettingsId::SPH_SUMMATION_MAX_ITERATIONS) : 1;
49 }
50 
51 template <Size Dim>
53  const RunSettings& settings,
54  const EquationHolder& additionalEquations)
55  : SummationSolver(scheduler, settings, additionalEquations, Factory::getBoundaryConditions(settings)) {}
56 
57 template <Size Dim>
58 void SummationSolver<Dim>::create(Storage& storage, IMaterial& material) const {
59  const Float rho0 = material.getParam<Float>(BodySettingsId::DENSITY);
63  this->equations.create(storage, material);
64 }
65 
66 template <Size Dim>
68  SymmetricSolver<Dim>::beforeLoop(storage, stats);
71 
72  // initialize density estimate
73  rho.resize(r.size());
74  rho.fill(EPS);
75 
76  // initialize smoothing length to current values
77  h.resize(r.size());
78  for (Size i = 0; i < r.size(); ++i) {
79  h[i] = r[i][H];
80  SPH_ASSERT(h[i] > 0._f);
81  }
82 
83  Float eta = 0._f;
84  for (Size matId = 0; matId < storage.getMaterialCnt(); ++matId) {
85  // all eta's should be the same, but let's use max to be sure
86  eta = max(eta, storage.getMaterial(matId)->getParam<Float>(BodySettingsId::SMOOTHING_LENGTH_ETA));
87  }
88 
89  Atomic<Float> totalDiff = 0._f;
90  auto functor = [this, r, m, eta, &totalDiff](const Size i, ThreadData& data) {
92  // find all neighbours
93  this->finder->findAll(i, h[i] * densityKernel.radius(), data.neighs);
94  SPH_ASSERT(data.neighs.size() > 0, data.neighs.size());
95  // find density and smoothing length by self-consistent solution.
96  const Float rho0 = rho[i];
97  rho[i] = 0._f;
98  for (auto& n : data.neighs) {
99  const Size j = n.index;
101  rho[i] += m[j] * densityKernel.value(r[i] - r[j], h[i]);
102  }
103  SPH_ASSERT(rho[i] > 0._f, rho[i]);
104  h[i] = eta * root<Dim>(m[i] / rho[i]);
105  SPH_ASSERT(h[i] > 0._f);
106  totalDiff += abs(rho[i] - rho0) / (rho[i] + rho0);
107  };
108 
109  this->finder->build(this->scheduler, r);
110  Size iterationIdx = 0;
111  for (; iterationIdx < maxIteration; ++iterationIdx) {
112  parallelFor(this->scheduler, this->threadData, 0, r.size(), functor);
113  const Float diff = totalDiff / r.size();
114  if (diff < targetDensityDifference) {
115  break;
116  }
117  }
118  stats.set(StatisticsId::SOLVER_SUMMATION_ITERATIONS, int(iterationIdx));
119  // save computed values
121  if (adaptiveH) {
122  for (Size i = 0; i < r.size(); ++i) {
123  r[i][H] = h[i];
124  SPH_ASSERT(r[i][H] > 0._f);
125  }
126  }
127 }
128 
129 template <Size Dim>
130 void SummationSolver<Dim>::sanityCheck(const Storage& UNUSED(storage)) const {
131  // we handle smoothing lengths ourselves, bypass the check of equations
132 }
133 
134 template class SummationSolver<1>;
135 template class SummationSolver<2>;
136 template class SummationSolver<3>;
137 
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
Implementation of number with atomic operators.
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Boundary conditions.
const EmptyFlags EMPTY_FLAGS
Definition: Flags.h:16
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
Base class for all particle materials.
SPH kernels.
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
constexpr Float EPS
Definition: MathUtils.h:30
INLINE auto abs(const T &f)
Definition: MathUtils.h:276
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ DENSITY
Density, always a scalar quantity.
@ MASS
Paricles masses, always a scalar 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
Standard SPH artificial viscosity.
Statistics gathered and periodically displayed during the run.
@ SOLVER_SUMMATION_ITERATIONS
Number of iterations used to compute density and smoothing length in summation solver.
Solver using direction summation to compute density and smoothing length.
@ H
Definition: Vector.h:25
Object providing safe access to continuous memory of data.
Definition: ArrayView.h:17
INLINE TCounter size() const
Definition: ArrayView.h:101
void resize(const TCounter newSize)
Resizes the array to new size.
Definition: Array.h:215
Atomic value implemented using compare-exchange.
Definition: AtomicFloat.h:19
Container holding equation terms.
Definition: EquationTerm.h:238
Wrapper of an integral value providing functions for reading and modifying individual bits.
Definition: Flags.h:20
constexpr INLINE bool has(const TEnum flag) const
Checks if the object has a given flag.
Definition: Flags.h:77
Material settings and functions specific for one material.
Definition: IMaterial.h:110
INLINE TValue getParam(const BodySettingsId paramIdx) const
Returns a parameter associated with given particle.
Definition: IMaterial.h:137
void setRange(const QuantityId id, const Interval &range, const Float minimal)
Sets the timestepping parameters of given quantity.
Definition: IMaterial.cpp:17
Interface that allows unified implementation of sequential and parallelized versions of algorithms.
Definition: Scheduler.h:27
TValue get(const TEnum idx, std::enable_if_t<!std::is_enum< std::decay_t< TValue >>::value, int >=0) const
Returns a value of given type from the settings.
Definition: Settings.h:326
Flags< TValue > getFlags(const TEnum idx) const
Returns Flags from underlying value stored in settings.
Definition: Settings.h:348
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
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
Quantity & insert(const QuantityId key, const OrderEnum order, const TValue &defaultValue)
Creates a quantity in the storage, given its key, value type and order.
Definition: Storage.cpp:270
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
SPH solver using density and specific energy as independent variables.
virtual void create(Storage &storage, IMaterial &material) const override
Initializes all quantities needed by the solver in the storage.
SummationSolver(IScheduler &scheduler, const RunSettings &settings, const EquationHolder &additionalEquations={})
Basic solver for integration of SPH equations.
virtual void beforeLoop(Storage &storage, Statistics &stats)
Creating code components based on values from settings.
ForceEnum
Definition: Settings.h:658
@ PRESSURE
Use force from pressure gradient in the solver.
@ SELF_GRAVITY
Use gravitational force in the model.
@ DENSITY_RANGE
Allowed range of density. Densities of all particles all clamped to fit in the range.
@ DENSITY
Density at zero pressure.
@ SMOOTHING_LENGTH_ETA
Eta-factor between smoothing length and particle concentration (h = eta * n^(-1/d) )
SmoothingLengthEnum
Definition: Settings.h:768
@ SPH_SUMMATION_MAX_ITERATIONS
Maximum number of iterations for self-consistent density computation of summation solver.
@ SPH_SOLVER_FORCES
List of forces to compute by the solver.
@ SPH_ADAPTIVE_SMOOTHING_LENGTH
Solution for evolutions of the smoothing length.
@ SPH_SUMMATION_DENSITY_DELTA
Provides a convenient way to construct objects from settings.
Definition: Factory.h:46
AutoPtr< IEquationTerm > getArtificialViscosity(const RunSettings &settings)
Definition: Factory.cpp:108
AutoPtr< IBoundaryCondition > getBoundaryConditions(const RunSettings &settings, SharedPtr< IDomain > domain)
Definition: Factory.cpp:460
Overload of std::swap for Sph::Array.
Definition: Array.h:578
void swap(Sph::Array< T, TCounter > &ar1, Sph::Array< T, TCounter > &ar2)
Definition: Array.h:580