SPH
Compare.cpp
Go to the documentation of this file.
1 #include "post/Compare.h"
4 #include "quantities/Iterate.h"
5 #include "thread/Scheduler.h"
6 
8 
9 Outcome Post::compareParticles(const Storage& test, const Storage& ref, const Float eps) {
10  if (test.getParticleCnt() != ref.getParticleCnt()) {
11  return makeFailed("Different number of particles.\nTest has ",
12  test.getParticleCnt(),
13  "\nReference has ",
14  ref.getParticleCnt());
15  }
16 
17  if (test.getQuantityCnt() != ref.getQuantityCnt()) {
18  return makeFailed("Different number of quantities.\nTest has ",
19  test.getQuantityCnt(),
20  "\nReference has ",
21  ref.getQuantityCnt());
22  }
23 
24  Outcome result = SUCCESS;
25  auto checkZeroOrder = [&](QuantityId id, const auto& px, const auto& cx) {
26  if (!result) {
27  // mismatch already found
28  return;
29  }
30  for (Size i = 0; i < px.size(); ++i) {
31  if (!almostEqual(px[i], cx[i], eps)) {
32  result = makeFailed(
33  "Difference in ", getMetadata(id).quantityName, "\n", px[i], " == ", cx[i], "\n\n");
34  return;
35  }
36  }
37  };
38  iteratePair<VisitorEnum::ZERO_ORDER>(test, ref, checkZeroOrder);
39 
40  auto checkFirstOrder = [&](QuantityId id,
41  const auto& px,
42  const auto& pdx,
43  const auto& cx,
44  const auto& cdx) {
45  if (!result) {
46  return;
47  }
48  for (Size i = 0; i < px.size(); ++i) {
49  if (!almostEqual(px[i], cx[i], eps)) {
50  result = makeFailed(
51  "Difference in ", getMetadata(id).quantityName, "\n", px[i], " == ", cx[i], "\n\n");
52  return;
53  }
54  if (!almostEqual(pdx[i], cdx[i], eps)) {
55  result = makeFailed(
56  "Difference in ", getMetadata(id).derivativeName, "\n", pdx[i], " == ", cdx[i], "\n\n");
57  return;
58  }
59  }
60  };
61  iteratePair<VisitorEnum::FIRST_ORDER>(test, ref, checkFirstOrder);
62 
63  auto checkSecondOrder = [&](QuantityId id,
64  const auto& px,
65  const auto& pdx,
66  const auto& pdv,
67  const auto& cx,
68  const auto& cdx,
69  const auto& cdv) {
70  if (!result) {
71  return;
72  }
73  for (Size i = 0; i < px.size(); ++i) {
74  if (!almostEqual(px[i], cx[i], eps)) {
75  result = makeFailed(
76  "Difference in ", getMetadata(id).quantityName, "\n", px[i], " == ", cx[i], "\n\n");
77  return;
78  }
79  if (!almostEqual(pdx[i], cdx[i], eps)) {
80  result = makeFailed(
81  "Difference in ", getMetadata(id).derivativeName, "\n", pdx[i], " == ", cdx[i], "\n\n");
82  return;
83  }
84  if (!almostEqual(pdv[i], cdv[i], eps)) {
85  result = makeFailed("Difference in ",
86  getMetadata(id).secondDerivativeName,
87  "\n",
88  pdv[i],
89  " == ",
90  cdv[i],
91  "\n\n");
92  return;
93  }
94  }
95  };
96  iteratePair<VisitorEnum::SECOND_ORDER>(test, ref, checkSecondOrder);
97 
98  return result;
99 }
100 
102  const Storage& ref,
103  const Float fraction,
104  const Float maxDeviation,
105  const Float eps) {
112 
113  const Size count = Size(max(r1.size(), r2.size()) * fraction);
114  if (count >= r1.size() || count >= r2.size()) {
115  return makeFailed("Number of particles differs significantly\n.Test has ",
116  r1.size(),
117  "\nReference has ",
118  r2.size());
119  }
120 
121  Order order = getOrder(m2, std::greater<Float>{});
122  KdTree<KdNode> tree;
124 
125  Array<NeighbourRecord> neighs;
126  for (Size i = 0; i < count; ++i) {
127  // reference index
128  const Size p2 = order[i];
129 
130  // find test particle
131  tree.findAll(r2[p2], maxDeviation, neighs);
132  bool matchFound = false;
133  for (const NeighbourRecord& n : neighs) {
134  const Size p1 = n.index;
135  if (!almostEqual(m1[p1], m2[p2], eps)) {
136  // mass does not match
137  continue;
138  }
139  if (!almostEqual(r1[p1][H], r2[p2][H], eps)) {
140  // radius does not match
141  continue;
142  }
143  if (!almostEqual(v1[p1], v2[p2], eps)) {
144  // velocities do not match
145  continue;
146  }
147  matchFound = true;
148  break;
149  }
150 
151  if (!matchFound) {
152  return makeFailed("No matching test particle found for the ",
153  i + 1,
154  "-th largest particle in the reference state.");
155  }
156  }
157  return SUCCESS;
158 }
159 
INLINE bool almostEqual(const AffineMatrix &m1, const AffineMatrix &m2, const Float eps=EPS)
Definition: AffineMatrix.h:278
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
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
Functions for iterating over individual quantities in Storage.
K-d tree for efficient search of neighbouring particles.
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
@ SKIP_RANK
The rank of particles is not created. 'Dummy' option that can be used to improve readability.
#define NAMESPACE_SPH_END
Definition: Object.h:12
Helper object defining permutation.
INLINE Order getOrder(ArrayView< const Float > values, const TLess less=TLess{})
Finds the order of values in given array.
Definition: Order.h:101
const SuccessTag SUCCESS
Global constant for successful outcome.
Definition: Outcome.h:141
INLINE Outcome makeFailed(TArgs &&... args)
Constructs failed object with error message.
Definition: Outcome.h:157
QuantityMetadata getMetadata(const QuantityId key)
Returns the quantity information using quantity ID.
Definition: QuantityIds.cpp:27
QuantityId
Unique IDs of basic quantities of SPH particles.
Definition: QuantityIds.h:19
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ MASS
Paricles masses, always a scalar quantity.
SequentialScheduler SEQUENTIAL
Global instance of the sequential scheduler.
Definition: Scheduler.cpp:43
Interface for executing tasks (potentially) asynchronously.
@ H
Definition: Vector.h:25
void build(IScheduler &scheduler, ArrayView< const Vector > points, Flags< FinderFlag > flags=FinderFlag::MAKE_RANK)
Constructs the struct with an array of vectors.
K-d tree, used for hierarchical clustering of particles and accelerated Kn queries.
Definition: KdTree.h:136
Permutation, i.e. (discrete) invertible function int->int.
Definition: Order.h:18
Container storing all quantities used within the simulations.
Definition: Storage.h:230
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Definition: Storage.cpp:217
Size getParticleCnt() const
Returns the number of particles.
Definition: Storage.cpp:445
Size getQuantityCnt() const
Returns the number of stored quantities.
Definition: Storage.cpp:441
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
Outcome compareLargeSpheres(const Storage &test, const Storage &ref, const Float fraction, const Float maxDeviation, const Float eps=1.e-6_f)
Compares the positions, velocities and radii of the largest particles in given states.
Definition: Compare.cpp:101
Outcome compareParticles(const Storage &test, const Storage &ref, const Float eps=1.e-6_f)
Compares particle positions and state quantities of two storages.
Definition: Compare.cpp:9
Holds information about a neighbour particles.