SPH
Handoff.cpp
Go to the documentation of this file.
1 #include "sph/handoff/Handoff.h"
4 #include "physics/Integrals.h"
5 #include "post/Analysis.h"
6 #include "quantities/Quantity.h"
7 #include "sph/Materials.h"
9 #include "sph/initial/Initial.h"
10 #include "sph/kernel/Kernel.h"
11 #include "system/Factory.h"
12 #include "thread/Scheduler.h"
13 
15 
17 class SphDomain : public IDomain {
18 private:
20  const Storage& storage;
21 
24 
26  Array<Vector> positions;
27 
28  AutoPtr<IBasicFinder> finder;
29  LutKernel<3> kernel;
30  Float level;
31 
32 public:
33  explicit SphDomain(const Storage& storage, ArrayView<const Size> idxs, const RunSettings& settings)
34  : storage(storage)
35  , idxs(std::move(idxs)) {
36  finder = Factory::getFinder(settings);
37  kernel = Factory::getKernel<3>(settings);
38  level = 0.15_f;
39 
41  for (Size i : this->idxs) {
42  positions.push(r[i]);
43  }
44 
45  // build the finder only with selected particles
46  finder->build(SEQUENTIAL, positions);
47  }
48 
49  virtual Vector getCenter() const override {
52  Vector r_com(0._f);
53  Float m_tot(0._f);
54  for (Size i : idxs) {
55  m_tot += m[i];
56  r_com += m[i] * r[i];
57  }
58  SPH_ASSERT(m_tot != 0._f);
59  return r_com / m_tot;
60  }
61 
62  virtual Box getBoundingBox() const override {
63  return Sph::getBoundingBox(storage);
64  }
65 
66  virtual Float getVolume() const override {
69  Float volume = 0._f;
70  for (Size i : idxs) {
71  volume += m[i] / rho[i];
72  }
73  return volume;
74  }
75 
76  virtual Float getSurfaceArea() const override {
78  return 0._f;
79  }
80 
81  virtual bool contains(const Vector& v) const override {
85 
86  Float h_max = 0._f;
87  for (Size i : idxs) {
88  h_max = max(h_max, r[i][H]);
89  }
90 
92  const Float radius = kernel.radius() * h_max;
93  finder->findAll(v, radius, neighs);
94 
95  Float field = 0._f;
96  for (auto& n : neighs) {
97  // note that n.index is an index with idxs (or positions) array
98  const Size j = idxs[n.index];
99  field += m[j] / rho[j] * kernel.value(v - r[j], r[j][H]);
100  }
101  return field > level;
102  }
103 
104  virtual void getSubset(ArrayView<const Vector>, Array<Size>&, const SubsetType) const override {
106  }
107 
110  }
111 
112  virtual void project(ArrayView<Vector>, Optional<ArrayView<Size>>) const override {
114  }
115 
116  virtual void addGhosts(ArrayView<const Vector>, Array<Ghost>&, const Float, const Float) const override {
118  }
119 };
120 
125  const Vector& r_com,
126  const Vector& v_com) {
127  // currently Post::getAngularFrequency cannot work with subsets, so we need to duplicate the buffers :(
128  Array<Vector> r_lr, v_lr;
129  Array<Float> m_lr;
130  for (Size i : idxs) {
131  r_lr.push(r[i]);
132  v_lr.push(v[i]);
133  m_lr.push(m[i]);
134  }
135 
136  return Post::getAngularFrequency(m_lr, r_lr, v_lr, r_com, v_com);
137 }
138 
139 Storage convertSphToSpheres(const Storage& sph, const RunSettings& settings, const HandoffParams& params) {
140  // clone required quantities
141  Array<Vector> r_nbody = sph.getValue<Vector>(QuantityId::POSITION).clone();
142  Array<Vector> v_nbody = sph.getDt<Vector>(QuantityId::POSITION).clone();
143  Array<Float> m_nbody = sph.getValue<Float>(QuantityId::MASS).clone();
144 
145  // radii handoff
148  SPH_ASSERT(r_nbody.size() == rho_sph.size());
149  for (Size i = 0; i < r_nbody.size(); ++i) {
150  switch (params.radius) {
152  r_nbody[i][H] = cbrt(3._f * m_sph[i] / (4._f * PI * rho_sph[i]));
153  break;
155  r_nbody[i][H] = params.radiusMultiplier * r_nbody[i][H];
156  break;
157  default:
159  }
160  }
161 
162  // remove all sublimated particles
164  /*Array<Size> toRemove;
165  ArrayView<const Float> u = sph.getValue<Float>(QuantityId::ENERGY);
166  for (Size matId = 0; matId < sph.getMaterialCnt(); ++matId) {
167  MaterialView mat = sph.getMaterial(matId);
168  for (Size i : mat.sequence()) {
169  if (u[i] > params.sublimationEnergy) {
170  toRemove.push(i);
171  }
172  }
173  } */
174 
175  if (params.centerOfMassSystem) {
176  moveToCenterOfMassSystem(m_nbody, v_nbody);
177  moveToCenterOfMassSystem(m_nbody, r_nbody);
178  }
179 
180  if (params.largestRemnant) {
182  SPH_ASSERT(std::is_sorted(idxs.begin(), idxs.end()));
183 
184  // find mass, COM and velocity of the largest remnant
185  Float m_tot = 0._f;
186  Vector r_com(0._f);
187  Vector v_com(0._f);
188  for (Size i : idxs) {
189  m_tot += m_nbody[i];
190  v_com += m_nbody[i] * v_nbody[i];
191  r_com += m_nbody[i] * r_nbody[i];
192  }
193  r_com /= m_tot;
194  v_com /= m_tot;
195 
196  // generate new particles for LR
197  const Size particleCnt = params.largestRemnant->particleOverride.valueOr(idxs.size());
198  SphDomain domain(sph, idxs, settings);
199  Array<Vector> r_lr = params.largestRemnant->distribution->generate(SEQUENTIAL, particleCnt, domain);
200 
201  // distribute the total mass uniformly
202  Array<Float> m_lr(r_lr.size());
203  m_lr.fill(m_tot / r_lr.size());
204 
205  // set the velocities as if LR was a rigid body
206  Array<Vector> v_lr(r_lr.size());
207  const Vector omega = getAngularFrequency(idxs, m_nbody, r_nbody, v_nbody, r_com, v_com);
208  for (Size i = 0; i < r_lr.size(); ++i) {
209  v_lr[i] = v_com + cross(omega, r_lr[i]);
210  }
211 
212  // remove all old particles
213  r_nbody.remove(idxs);
214  v_nbody.remove(idxs);
215  m_nbody.remove(idxs);
216 
217  // add the new particles
218  r_nbody.pushAll(r_lr);
219  v_nbody.pushAll(v_lr);
220  m_nbody.pushAll(m_lr);
221  }
222 
223 
224  Storage storage(makeAuto<NullMaterial>(EMPTY_SETTINGS));
225  storage.insert<Vector>(QuantityId::POSITION, OrderEnum::SECOND, std::move(r_nbody));
226  storage.getDt<Vector>(QuantityId::POSITION) = std::move(v_nbody);
227  storage.insert<Float>(QuantityId::MASS, OrderEnum::ZERO, std::move(m_nbody));
228  return storage;
229 }
230 
Various function for interpretation of the results of a simulation.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
const float radius
Definition: CurveDialog.cpp:18
Filling spatial domain with SPH particles.
Object defining computational domain.
SubsetType
Definition: Domain.h:16
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
Storage convertSphToSpheres(const Storage &sph, const RunSettings &settings, const HandoffParams &params)
Definition: Handoff.cpp:139
Utility functions for handing-off the results of SPH simulations to N-body integrator.
Vector moveToCenterOfMassSystem(ArrayView< const Float > m, ArrayView< Vector > r)
Modifies particle positions so that their center of mass lies at the origin.
Definition: Initial.cpp:363
Generating initial conditions of SPH particles.
Integrals of motion and other integral quantities.
SPH kernels.
SPH-specific implementation of particle materials.
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
INLINE Float cbrt(const Float f)
Returns a cubed root of a value.
Definition: MathUtils.h:84
constexpr Float PI
Mathematical constants.
Definition: MathUtils.h:361
#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.
Holder of quantity values and their temporal derivatives.
@ SECOND
Quantity with 1st and 2nd derivative.
@ ZERO
Quantity without derivatives, or "zero order" of quantity.
SequentialScheduler SEQUENTIAL
Global instance of the sequential scheduler.
Definition: Scheduler.cpp:43
Interface for executing tasks (potentially) asynchronously.
Box getBoundingBox(const Storage &storage, const Float radius)
Convenience function to get the bounding box of all particles.
Definition: Storage.cpp:832
INLINE BasicVector< float > cross(const BasicVector< float > &v1, const BasicVector< float > &v2)
Cross product between two vectors.
Definition: Vector.h:559
@ H
Definition: Vector.h:25
Generic dynamically allocated resizable storage.
Definition: Array.h:43
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
void remove(const TCounter idx)
Removes an element with given index from the array.
Definition: Array.h:383
void fill(const T &t)
Sets all elements of the array to given value.
Definition: Array.h:187
INLINE TCounter size() const noexcept
Definition: Array.h:193
INLINE Iterator< StorageType > begin() noexcept
Definition: Array.h:450
void pushAll(const TIter first, const TIter last)
Definition: Array.h:312
Helper object defining three-dimensional interval (box).
Definition: Box.h:17
void build(IScheduler &scheduler, ArrayView< const Vector > points)
Constructs the struct with an array of vectors.
virtual Size findAll(const Size index, const Float radius, Array< NeighbourRecord > &neighbours) const =0
Finds all neighbours within given radius from the point given by index.
Base class for computational domains.
Definition: Domain.h:29
INLINE Float value(const Vector &r, const Float h) const noexcept
Definition: Kernel.h:26
INLINE Float radius() const noexcept
Definition: Kernel.h:107
Wrapper of type value of which may or may not be present.
Definition: Optional.h:23
Domain represented by SPH particles.
Definition: Handoff.cpp:17
virtual void project(ArrayView< Vector >, Optional< ArrayView< Size >>) const override
Projects vectors outside of the domain onto its boundary.
Definition: Handoff.cpp:112
virtual void getSubset(ArrayView< const Vector >, Array< Size > &, const SubsetType) const override
Returns an array of indices, marking vectors with given property by their index.
Definition: Handoff.cpp:104
virtual Vector getCenter() const override
Returns the center of the domain.
Definition: Handoff.cpp:49
virtual Float getVolume() const override
Returns the total volume of the domain.
Definition: Handoff.cpp:66
virtual void getDistanceToBoundary(ArrayView< const Vector >, Array< Float > &) const override
Returns distances of particles lying close to the boundary.
Definition: Handoff.cpp:108
virtual bool contains(const Vector &v) const override
Checks if the given point lies inside the domain.
Definition: Handoff.cpp:81
virtual Box getBoundingBox() const override
Returns the bounding box of the domain.
Definition: Handoff.cpp:62
virtual Float getSurfaceArea() const override
Returns the surface area of the domain.
Definition: Handoff.cpp:76
virtual void addGhosts(ArrayView< const Vector >, Array< Ghost > &, const Float, const Float) const override
Duplicates positions located close to the boundary, placing copies ("ghosts") symmetrically to the ot...
Definition: Handoff.cpp:116
SphDomain(const Storage &storage, ArrayView< const Size > idxs, const RunSettings &settings)
Definition: Handoff.cpp:33
Container storing all quantities used within the simulations.
Definition: Storage.h:230
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
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Definition: Storage.cpp:217
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
Creating code components based on values from settings.
const EmptySettingsTag EMPTY_SETTINGS
Definition: Settings.h:32
AutoPtr< ISymmetricFinder > getFinder(const RunSettings &settings)
Definition: Factory.cpp:156
Array< Size > findLargestComponent(const Storage &storage, const Float particleRadius, const Flags< ComponentFlag > flags)
Returns the indices of particles belonging to the largest remnant.
Definition: Analysis.cpp:216
Vector getAngularFrequency(ArrayView< const Float > m, ArrayView< const Vector > r, ArrayView< const Vector > v, const Vector &r0, const Vector &v0, ArrayView< const Size > idxs=nullptr)
Computes the immediate vector of angular frequency of a rigid body.
Definition: Analysis.cpp:514
Overload of std::swap for Sph::Array.
Definition: Array.h:578
Float radiusMultiplier
Conversion factor between smoothing length and particle radius.
Definition: Handoff.h:31
@ EQUAL_VOLUME
The created sphere has the same volume as the SPH particles (=mass/density)
@ SMOOTHING_LENGTH
The radius is proportional to the smoothing length of the particles.
Optional< LargestRemnant > largestRemnant
Definition: Handoff.h:57
bool centerOfMassSystem
If true, the particles are moved to a system where the center of mass is at the origin.
Definition: Handoff.h:37
Radius radius
Definition: Handoff.h:26