SPH
Colorizer.cpp
Go to the documentation of this file.
2 
4 
6  : palette(palette)
7  , axis(axis) {
8  SPH_ASSERT(almostEqual(getLength(axis), 1._f));
9  // compute 2 perpendicular directions
10  Vector ref;
11  if (almostEqual(axis, Vector(0._f, 0._f, 1._f)) || almostEqual(axis, Vector(0._f, 0._f, -1._f))) {
12  ref = Vector(0._f, 1._f, 0._f);
13  } else {
14  ref = Vector(0._f, 0._f, 1._f);
15  }
16  dir1 = getNormalized(cross(axis, ref));
17  dir2 = cross(axis, dir1);
18  SPH_ASSERT(almostEqual(getLength(dir2), 1._f));
19 }
20 
22  SPH_ASSERT(this->isInitialized());
23  const Vector projected = values[idx] - dot(values[idx], axis) * axis;
24  const Float x = dot(projected, dir1);
25  const Float y = dot(projected - x * dir1, dir2);
26  return float(PI + atan2(y, x));
27 }
28 
29 static thread_local Array<NeighbourRecord> neighs;
30 
32  : palette(std::move(palette)) {
33  finder = Factory::getFinder(settings);
34  kernel = Factory::getKernel<3>(settings);
35 }
36 
37 void SummedDensityColorizer::initialize(const Storage& storage, const RefEnum ref) {
38  m = makeArrayRef(storage.getValue<Float>(QuantityId::MASS), ref);
40 
41  finder->build(SEQUENTIAL, r);
42 }
43 
44 float SummedDensityColorizer::sum(const Size idx) const {
45  finder->findAll(idx, r[idx][H] * kernel.radius(), neighs);
46  Float rho = 0._f;
47  for (const auto& n : neighs) {
48  rho += m[n.index] * kernel.value(r[idx] - r[n.index], r[idx][H]);
49  }
50  return float(rho);
51 }
52 
53 void CorotatingVelocityColorizer::initialize(const Storage& storage, const RefEnum ref) {
55  v = makeArrayRef(storage.getDt<Vector>(QuantityId::POSITION), ref);
56  matIds = makeArrayRef(storage.getValue<Size>(QuantityId::MATERIAL_ID), ref);
57 
61  data.resize(storage.getMaterialCnt());
62 
63  for (Size i = 0; i < data.size(); ++i) {
64  MaterialView mat = storage.getMaterial(i);
65  const Size from = *mat.sequence().begin();
66  const Size to = *mat.sequence().end();
67  const Size size = to - from;
68  data[i].center = Post::getCenterOfMass(m.subset(from, size), rv.subset(from, size));
69  data[i].omega =
70  Post::getAngularFrequency(m.subset(from, size), rv.subset(from, size), vv.subset(from, size));
71  }
72 }
73 
74 bool DamageActivationColorizer::hasData(const Storage& storage) const {
75  return storage.has(QuantityId::DEVIATORIC_STRESS) && storage.has(QuantityId::PRESSURE) &&
76  storage.has(QuantityId::EPS_MIN) && storage.has(QuantityId::DAMAGE);
77 }
78 
79 void DamageActivationColorizer::initialize(const Storage& storage, const RefEnum UNUSED(ref)) {
84 
85  ratio.resize(p.size());
87  for (Size matId = 0; matId < storage.getMaterialCnt(); ++matId) {
88  MaterialView mat = storage.getMaterial(matId);
89  const Float young = mat->getParam<Float>(BodySettingsId::YOUNG_MODULUS);
90 
92  for (Size i : mat.sequence()) {
93  const SymmetricTensor sigma = SymmetricTensor(s[i]) - p[i] * SymmetricTensor::identity();
94  Float sig1, sig2, sig3;
95  tie(sig1, sig2, sig3) = findEigenvalues(sigma);
96  const Float sigMax = max(sig1, sig2, sig3);
97  const Float young_red = max((1._f - pow<3>(damage[i])) * young, 1.e-20_f);
98  const Float strain = sigMax / young_red;
99  ratio[i] = float(strain / eps_min[i]);
100  }
101  }
102 }
103 
105  palette = Palette({ { u_0, Rgba(0.5f, 0.5f, 0.5) },
106  { u_glow, Rgba(0.5f, 0.5f, 0.5f) },
107  { u_red, Rgba(0.8f, 0.f, 0.f) },
108  { u_yellow, Rgba(1.f, 1.f, 0.6f) } },
110  f_glow = (log10(u_glow) - log10(u_0)) / (log10(u_yellow) - log10(u_0));
111 }
112 
113 BoundaryColorizer::BoundaryColorizer(const Detection detection, const Float threshold)
114  : detection(detection) {
115  if (detection == Detection::NEIGBOUR_THRESHOLD) {
116  neighbours.threshold = Size(threshold);
117  } else {
118  normals.threshold = threshold;
119  }
120 }
121 
122 bool BoundaryColorizer::hasData(const Storage& storage) const {
123  if (detection == Detection::NORMAL_BASED) {
124  return storage.has(QuantityId::SURFACE_NORMAL);
125  } else {
126  return storage.has(QuantityId::NEIGHBOUR_CNT);
127  }
128 }
129 
130 void BoundaryColorizer::initialize(const Storage& storage, const RefEnum ref) {
131  if (detection == Detection::NORMAL_BASED) {
132  normals.values = makeArrayRef(storage.getValue<Vector>(QuantityId::SURFACE_NORMAL), ref);
133  } else {
134  neighbours.values = makeArrayRef(storage.getValue<Size>(QuantityId::NEIGHBOUR_CNT), ref);
135  }
136 }
137 
139  return (detection == Detection::NORMAL_BASED && !normals.values.empty()) ||
140  (detection == Detection::NEIGBOUR_THRESHOLD && !neighbours.values.empty());
141 }
142 
144  if (isBoundary(idx)) {
145  return Rgba::red();
146  } else {
147  return Rgba::gray();
148  }
149 }
150 
151 bool BoundaryColorizer::isBoundary(const Size idx) const {
152  switch (detection) {
154  SPH_ASSERT(!neighbours.values.empty());
155  return neighbours.values[idx] < neighbours.threshold;
157  SPH_ASSERT(!normals.values.empty());
158  return getLength(normals.values[idx]) > normals.threshold;
159  default:
161  }
162 }
163 
164 
166 static uint64_t getHash(const uint64_t value, const Size seed) {
167  // https://stackoverflow.com/questions/8317508/hash-function-for-a-string
168  constexpr int A = 54059;
169  constexpr int B = 76963;
170  constexpr int FIRST = 37;
171 
172  uint64_t hash = FIRST + seed;
173  StaticArray<uint8_t, sizeof(uint64_t)> data;
174  std::memcpy(&data[0], &value, data.size());
175  for (uint i = 0; i < sizeof(uint64_t); ++i) {
176  hash = (hash * A) ^ (data[i] * B);
177  }
178  return hash;
179 }
180 
181 static Rgba getRandomizedColor(const Size idx, const Size seed = 0) {
182  const uint64_t hash = getHash(idx, seed);
183  const uint8_t r = (hash & 0x00000000FFFF);
184  const uint8_t g = (hash & 0x0000FFFF0000) >> 16;
185  const uint8_t b = (hash & 0xFFFF00000000) >> 32;
186  return Rgba(r / 255.f, g / 255.f, b / 255.f);
187 }
188 
189 template <typename TDerived>
191  const Optional<Size> id = static_cast<const TDerived*>(this)->evalId(idx);
192  if (!id) {
193  return Rgba::gray();
194  }
195  const Rgba color = getRandomizedColor(id.value(), seed);
196  return color;
197 }
198 
199 template <typename TDerived>
201  Particle particle(idx);
202  const Optional<Size> id = static_cast<const TDerived*>(this)->evalId(idx);
203  if (id) {
204  particle.addValue(QuantityId::FLAG, id.value());
205  }
206  return particle;
207 }
208 
213 
214 void ParticleIdColorizer::initialize(const Storage& storage, const RefEnum ref) {
215  if (storage.has(QuantityId::PERSISTENT_INDEX)) {
216  persistentIdxs = makeArrayRef(storage.getValue<Size>(QuantityId::PERSISTENT_INDEX), ref);
217  }
218 }
219 
221  Particle particle(idx);
222  particle.addValue(QuantityId::FLAG, idx);
223  if (!persistentIdxs.empty() && idx < persistentIdxs.size()) {
224  particle.addValue(QuantityId::PERSISTENT_INDEX, persistentIdxs[idx]);
225  }
226  return particle;
227 }
228 
229 
231  const Flags<Post::ComponentFlag> connectivity,
232  const Optional<Size> highlightIdx)
234  , connectivity(connectivity)
235  , highlightIdx(highlightIdx) {}
236 
238  if (newHighlightIdx) {
239  highlightIdx = min(newHighlightIdx.value(), components.size() - 1);
240  } else {
241  highlightIdx = NOTHING;
242  }
243 }
244 
246  if (highlightIdx) {
247  if (highlightIdx.value() == components[idx]) {
248  return Rgba(1.f, 0.65f, 0.f);
249  } else {
250  return Rgba::gray(0.3f);
251  }
252  } else {
254  }
255 }
256 
258  Particle particle(idx);
259  const Optional<Size> id = this->evalId(idx);
260  particle.addValue(QuantityId::FLAG, id.value());
261 
262  Array<Size> indices;
263  for (Size i = 0; i < r.size(); ++i) {
264  if (components[i] == id.value()) {
265  indices.push(i);
266  }
267  }
268  if (indices.size() > 1) {
269  const Vector omega = Post::getAngularFrequency(m, r, v, indices);
271  }
272  return particle;
273 }
274 
275 bool ComponentIdColorizer::hasData(const Storage& storage) const {
276  return hasVelocity(storage);
277 }
278 
279 void ComponentIdColorizer::initialize(const Storage& storage, const RefEnum ref) {
280  const Array<Vector>& current = storage.getValue<Vector>(QuantityId::POSITION);
281  if (current == cached.r) {
282  // optimization, very poorly done
283  return;
284  }
285 
286  m = makeArrayRef(storage.getValue<Float>(QuantityId::MASS), ref);
287  r = makeArrayRef(storage.getValue<Vector>(QuantityId::POSITION), ref);
288  v = makeArrayRef(storage.getDt<Vector>(QuantityId::POSITION), ref);
289 
290  cached.r = current.clone();
291 
292  Post::findComponents(storage, 2._f, connectivity, components);
293 }
294 
295 std::string ComponentIdColorizer::name() const {
296  if (connectivity.has(Post::ComponentFlag::ESCAPE_VELOCITY)) {
297  return "Bound component ID";
298  } else if (connectivity.has(Post::ComponentFlag::SEPARATE_BY_FLAG)) {
299  return "Component ID (flag)";
300  } else {
301  return "Component ID";
302  }
303 }
304 
305 void MaterialColorizer::initialize(const Storage& storage, const RefEnum ref) {
306  IndexColorizer::initialize(storage, ref);
307 
308  const Size matCnt = storage.getMaterialCnt();
309  eosNames.resize(matCnt);
310  rheoNames.resize(matCnt);
311  for (Size matId = 0; matId < matCnt; ++matId) {
312  const IMaterial& mat = storage.getMaterial(matId);
313  const EosEnum eos = mat.getParam<EosEnum>(BodySettingsId::EOS);
315  eosNames[matId] = EnumMap::toString(eos);
316  rheoNames[matId] = EnumMap::toString(yield);
317  }
318 }
319 
321  Particle particle(idx);
322  const Optional<Size> id = IndexColorizer::evalId(idx);
323  if (id) {
324  particle.addValue(QuantityId::MATERIAL_ID, id.value());
325  particle.addParameter(BodySettingsId::EOS, eosNames[id.value()]);
326  particle.addParameter(BodySettingsId::RHEOLOGY_YIELDING, rheoNames[id.value()]);
327  }
328  return particle;
329 }
330 
INLINE bool almostEqual(const AffineMatrix &m1, const AffineMatrix &m2, const Float eps=EPS)
Definition: AffineMatrix.h:278
RefEnum
Definition: ArrayRef.h:7
ArrayRef< T > makeArrayRef(Array< T > &data, const RefEnum type)
Definition: ArrayRef.h:138
#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
Object converting quantity values of particles into colors.
bool hasVelocity(const Storage &storage)
Definition: Colorizer.h:222
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
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
constexpr INLINE Float pow< 3 >(const Float v)
Definition: MathUtils.h:132
INLINE T log10(const T f)
Definition: MathUtils.h:331
INLINE T atan2(const T y, const T x)
Definition: MathUtils.h:321
constexpr Float PI
Mathematical constants.
Definition: MathUtils.h:361
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
const NothingType NOTHING
Definition: Optional.h:16
@ LOGARITHMIC
Control points are interpolated on logarithmic scale. All points must be positive!
@ FLAG
ID of original body, used to implement discontinuities between bodies in SPH.
@ DEVIATORIC_STRESS
Deviatoric stress tensor, always a traceless tensor.
@ PRESSURE
Pressure, affected by yielding and fragmentation model, always a scalar quantity.
@ DAMAGE
Damage.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ SURFACE_NORMAL
Vector approximating surface normal.
@ MASS
Paricles masses, always a scalar quantity.
@ NEIGHBOUR_CNT
Number of neighbouring particles (in radius h * kernel.radius)
@ MATERIAL_ID
Index of material of the particle. Can be generally different than the flag value.
@ EPS_MIN
Activation strait rate.
SequentialScheduler SEQUENTIAL
Global instance of the sequential scheduler.
Definition: Scheduler.cpp:43
StaticArray< T0 &, sizeof...(TArgs)+1 > tie(T0 &t0, TArgs &... rest)
Creates a static array from a list of l-value references.
Definition: StaticArray.h:281
INLINE StaticArray< Float, 3 > findEigenvalues(const SymmetricTensor &t)
Returns three eigenvalue of symmetric matrix.
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 BasicVector< float > cross(const BasicVector< float > &v1, const BasicVector< float > &v2)
Cross product between two vectors.
Definition: Vector.h:559
BasicVector< Float > Vector
Definition: Vector.h:539
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
INLINE Vector getNormalized(const Vector &v)
Definition: Vector.h:590
@ H
Definition: Vector.h:25
INLINE bool empty() const
Definition: ArrayRef.h:66
INLINE Size size() const
Definition: ArrayRef.h:62
INLINE ArrayView subset(const TCounter start, const TCounter length) const
Returns a subset of the arrayview.
Definition: ArrayView.h:110
void resize(const TCounter newSize)
Resizes the array to new size.
Definition: Array.h:215
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
Array clone() const
Performs a deep copy of all elements of the array.
Definition: Array.h:147
virtual bool isInitialized() const override
Checks if the colorizer has been initialized.
Definition: Colorizer.cpp:138
virtual Rgba evalColor(const Size idx) const override
Returns the color of idx-th particle.
Definition: Colorizer.cpp:143
virtual bool hasData(const Storage &storage) const override
Checks if the storage constains all data necessary to initialize the colorizer.
Definition: Colorizer.cpp:122
BoundaryColorizer(const Detection detection, const Float threshold=15._f)
Definition: Colorizer.cpp:113
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:130
virtual std::string name() const override
Returns the name of the colorizer.
Definition: Colorizer.cpp:295
void setHighlightIdx(const Optional< Size > newHighlightIdx)
Definition: Colorizer.cpp:237
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:279
ComponentIdColorizer(const GuiSettings &gui, const Flags< Post::ComponentFlag > connectivity, const Optional< Size > highlightIdx=NOTHING)
Definition: Colorizer.cpp:230
INLINE Optional< Size > evalId(const Size idx) const
Definition: Colorizer.h:961
virtual bool hasData(const Storage &storage) const override
Checks if the storage constains all data necessary to initialize the colorizer.
Definition: Colorizer.cpp:275
virtual Rgba evalColor(const Size idx) const override
Returns the color of idx-th particle.
Definition: Colorizer.cpp:245
virtual Optional< Particle > getParticle(const Size idx) const override
Returns the original value of the displayed quantity.
Definition: Colorizer.cpp:257
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:53
virtual bool hasData(const Storage &storage) const override
Checks if the storage constains all data necessary to initialize the colorizer.
Definition: Colorizer.cpp:74
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:79
virtual bool isInitialized() const override
Checks if the colorizer has been initialized.
Definition: Colorizer.h:297
DirectionColorizer(const Vector &axis, const Palette &palette)
Definition: Colorizer.cpp:5
virtual Optional< float > evalScalar(const Size idx) const override
Definition: Colorizer.cpp:21
static std::string toString(const TEnum value)
Definition: EnumMap.h:67
constexpr INLINE bool has(const TEnum flag) const
Checks if the object has a given flag.
Definition: Flags.h:77
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.
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
virtual Optional< Particle > getParticle(const Size idx) const override
Returns the original value of the displayed quantity.
Definition: Colorizer.cpp:200
virtual Rgba evalColor(const Size idx) const override
Returns the color of idx-th particle.
Definition: Colorizer.cpp:190
INLINE Optional< Size > evalId(const Size idx) const
Definition: Colorizer.h:1022
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.h:1030
INLINE IndexIterator begin() const
INLINE IndexIterator end() const
INLINE Float value(const Vector &r, const Float h) const noexcept
Definition: Kernel.h:26
INLINE Float radius() const noexcept
Definition: Kernel.h:107
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:305
virtual Optional< Particle > getParticle(const Size idx) const override
Returns the original value of the displayed quantity.
Definition: Colorizer.cpp:320
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
INLINE Type & value()
Returns the reference to the stored value.
Definition: Optional.h:172
Represents a color palette, used for mapping arbitrary number to a color.
Definition: Palette.h:25
virtual Optional< Particle > getParticle(const Size idx) const override
Returns the original value of the displayed quantity.
Definition: Colorizer.cpp:220
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:214
Object holding information about single particle.
Definition: Particle.h:17
Particle & addParameter(const BodySettingsId id, const Dynamic &value)
Adds another material parameter or updates the one stored previously.
Definition: Particle.cpp:92
Particle & addValue(const QuantityId id, const Dynamic &value)
Adds another quantity value or updates the value of quantity previously stored.
Definition: Particle.cpp:68
Definition: Color.h:8
static Rgba gray(const float value=0.5f)
Definition: Color.h:198
static Rgba red()
Definition: Color.h:178
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
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
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Definition: Storage.cpp:217
MaterialView getMaterial(const Size matIdx) const
Returns an object containing a reference to given material.
Definition: Storage.cpp:366
bool has(const QuantityId key) const
Checks if the storage contains quantity with given key.
Definition: Storage.cpp:130
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
virtual void initialize(const Storage &storage, const RefEnum ref) override
Initialize the colorizer before by getting necessary quantities from storage.
Definition: Colorizer.cpp:37
SummedDensityColorizer(const RunSettings &settings, Palette palette)
Definition: Colorizer.cpp:31
Symmetric tensor of 2nd order.
static INLINE SymmetricTensor identity()
Returns an identity tensor.
Symmetric traceless 2nd order tensor.
YieldingEnum
Definition: Settings.h:743
EosEnum
Definition: Settings.h:1363
@ YOUNG_MODULUS
Young modulus of the material.
@ EOS
Equation of state for this material, see EosEnum for options.
@ RHEOLOGY_YIELDING
Model of stress reducing used within the rheological model.
AutoPtr< ISymmetricFinder > getFinder(const RunSettings &settings)
Definition: Factory.cpp:156
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
@ SEPARATE_BY_FLAG
Specifies that particles with different flag belong to different component, even if they overlap.
Size findComponents(const Storage &storage, const Float particleRadius, const Flags< ComponentFlag > flags, Array< Size > &indices)
Finds and marks connected components (a.k.a. separated bodies) in the array of vertices.
Definition: Analysis.cpp:86
Vector getCenterOfMass(ArrayView< const Float > m, ArrayView< const Vector > r, ArrayView< const Size > idxs=nullptr)
Computes the center of mass.
Definition: Analysis.cpp:461
Overload of std::swap for Sph::Array.
Definition: Array.h:578