Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

DTreeForce.h
Go to the documentation of this file.
1 
29 #pragma once
30 
33 
34 namespace ogdf {
35 namespace energybased {
36 namespace dtree {
37 
38 template<int Dim, typename ForceFunc, bool UseForcePrime>
40 
41 template<int Dim>
42 class DTreeForce {
43 public:
44  template<int _Dim, typename ForceFunc, bool UseForcePrime>
45  friend class DTreeWSPDCallback;
46 
48  using Tree = typename WSPD::Tree;
49 
51  explicit DTreeForce(int numPoints);
52 
54  virtual ~DTreeForce();
55 
57  double position(int i, int d) const;
58 
60  void setPosition(int i, int d, double c);
61 
63  double mass(int i) const;
64 
66  void setMass(int i, double m);
67 
69  double force(int i, int d) const;
70 
72  double force_prime(int i) const;
73 
75  template<typename ForceFunc, bool UseForcePrime>
76  void computeForces(ForceFunc forceFunc);
77 
79  int numPoints() const { return m_numPoints; };
80 
82  const WSPD& wspd() const;
83 
85  const Tree& tree() const;
86 
87 private:
89  struct PointData {
91  double mass;
92 
94  double force[Dim];
95 
96  double force_prime;
97  };
98 
100  struct NodeData {
102  double mass;
103 
105  double centerOfMass[Dim];
106 
108  double force[Dim];
109 
111  double force_prime;
112  };
113 
115  WSPD& wspd();
116 
118  void allocate();
119 
121  void deallocate();
122 
124  void bottomUpPhase(int curr);
125 
127  void topDownPhase(int curr);
128 
130  void resetPointForces();
131 
133  void resetTreeNodes();
134 
137 
140 
143 
146 };
147 
148 template<int Dim, typename ForceFunc, bool UseForcePrime>
149 class DTreeWSPDCallback : public IWSPD {
150 public:
151  DTreeWSPDCallback(DTreeForce<Dim>& treeForce, ForceFunc forceFunc)
152  : m_treeForce(treeForce), m_forceFunc(forceFunc) { }
153 
155  virtual void onWellSeparatedPair(int a, int b) {
156  // force vector
157  double delta[Dim];
158  double force;
159  double force_prime;
160 
161  double dist = computeDeltaAndDistance<Dim>(m_treeForce.m_nodeData[a].centerOfMass,
162  m_treeForce.m_nodeData[b].centerOfMass, delta);
163  m_forceFunc(dist, force, force_prime);
164 #if 0
165  m_forceFunc(m_treeForce.m_nodeData[a].centerOfMass, m_treeForce.m_nodeData[b].centerOfMass, force, force_prime);
166 #endif
167 
168  // compute the force vector for each dim
169  for (int d = 0; d < Dim; d++) {
170  m_treeForce.m_nodeData[a].force[d] +=
171  force * delta[d] / dist * m_treeForce.m_nodeData[b].mass;
172  m_treeForce.m_nodeData[b].force[d] -=
173  force * delta[d] / dist * m_treeForce.m_nodeData[a].mass;
174  };
175 
176  if (UseForcePrime) {
177  m_treeForce.m_nodeData[a].force_prime += force_prime * m_treeForce.m_nodeData[b].mass;
178  m_treeForce.m_nodeData[b].force_prime += force_prime * m_treeForce.m_nodeData[a].mass;
179  }
180  }
181 
183  ForceFunc m_forceFunc;
184 };
185 
186 template<int Dim>
187 DTreeForce<Dim>::DTreeForce(int numPoints) : m_numPoints(numPoints) {
188  // get the memory
189  allocate();
190 
192 }
193 
194 template<int Dim>
196  // free the mem
197  deallocate();
198 }
199 
200 template<int Dim>
202  m_pWSPD = new WSPD(m_numPoints);
203  m_nodeData = new NodeData[tree().maxNumNodes()];
204  m_pointData = new PointData[m_numPoints];
205 
206  // initial mass setting for a point
207  for (int i = 0; i < m_numPoints; i++) {
208  m_pointData[i].mass = 1.0;
209  }
210 }
211 
212 template<int Dim>
214  delete m_pWSPD;
215  delete[] m_nodeData;
216  delete[] m_pointData;
217 }
218 
219 template<int Dim>
221  return *m_pWSPD;
222 }
223 
224 template<int Dim>
226  return *m_pWSPD;
227 }
228 
229 template<int Dim>
231  return wspd().tree();
232 }
233 
234 template<int Dim>
235 double DTreeForce<Dim>::position(int i, int d) const {
236  return wspd().point(i).x[d];
237 }
238 
239 template<int Dim>
240 void DTreeForce<Dim>::setPosition(int i, int d, double c) {
241  wspd().setPoint(i, d, c);
242 }
243 
244 template<int Dim>
245 double DTreeForce<Dim>::mass(int i) const {
246  return m_pointData[i].mass;
247 }
248 
249 template<int Dim>
250 void DTreeForce<Dim>::setMass(int i, double m) {
251  m_pointData[i].mass = m;
252 }
253 
254 template<int Dim>
255 double DTreeForce<Dim>::force(int i, int d) const {
256  return m_pointData[i].force[d];
257 }
258 
259 template<int Dim>
260 double DTreeForce<Dim>::force_prime(int i) const {
261  return m_pointData[i].force_prime;
262 }
263 
264 template<int Dim>
265 template<typename ForceFunc, bool UseForcePrime>
266 void DTreeForce<Dim>::computeForces(ForceFunc forceFunc) {
267  // reset all point forces
268  resetPointForces();
269 
270  if (numPoints() <= 1) {
271  return;
272  }
273 
274  // first let the WSPD instance update the quadtre
275  wspd().update();
276 
277  // now do the bottom up phase
278  bottomUpPhase(tree().rootIndex());
279 
280  DTreeWSPDCallback<Dim, ForceFunc, UseForcePrime> wspdCallBack(*this, forceFunc);
281 
282  // run the WSPD cell cell interaction
283  wspd().computeWSPD(&wspdCallBack);
284 
285  // finally, push down the forces
286  topDownPhase(tree().rootIndex());
287 }
288 
289 template<int Dim>
291  // reset the force and the center of mass
292  for (int d = 0; d < Dim; d++) {
293  m_nodeData[curr].force[d] = 0.0;
294  m_nodeData[curr].force_prime = 0.0;
295  m_nodeData[curr].centerOfMass[d] = 0.0;
296  }
297 
298  // reset the mass
299  m_nodeData[curr].mass = 0.0;
300 
301  // if this is an inner node
302  if (tree().numChilds(curr)) {
303  // iterate over the children
304  for (int i = 0; i < tree().numChilds(curr); i++) {
305  // the child index
306  const int child = tree().child(curr, i);
307 
308  // compute the size of the subtree
309  bottomUpPhase(child);
310 
311  // node curr
312  for (int d = 0; d < Dim; d++) {
313  // sum up the center of mass coordinates
314  m_nodeData[curr].centerOfMass[d] +=
315  m_nodeData[child].centerOfMass[d] * m_nodeData[child].mass;
316  }
317 
318  // add the mass
319  m_nodeData[curr].mass += m_nodeData[child].mass;
320  };
321  } // else it is a leaf
322  else {
323  // and the remaining points
324  for (int i = 0; i < tree().numPoints(curr); ++i) {
325  int pointIndex = tree().point(curr, i);
326  // node curr
327  for (int d = 0; d < Dim; d++) {
328  m_nodeData[curr].centerOfMass[d] += position(pointIndex, d) * mass(pointIndex);
329  }
330 
331  m_nodeData[curr].mass += mass(pointIndex);
332  }
333  }
334  // node curr
335  for (int d = 0; d < Dim; d++) {
336  m_nodeData[curr].centerOfMass[d] /= m_nodeData[curr].mass;
337  }
338 }
339 
340 template<int Dim>
342  // if this is an inner node
343  if (tree().numChilds(curr)) {
344  // iterate over the children
345  for (int i = 0; i < tree().numChilds(curr); i++) {
346  // the child index
347  const int child = tree().child(curr, i);
348 
349  // node curr
350  for (int d = 0; d < Dim; d++) {
351  // push the force down to the child
352  m_nodeData[child].force[d] += m_nodeData[curr].force[d];
353  }
354 
355  m_nodeData[child].force_prime += m_nodeData[curr].force_prime;
356 
357  // compute the size of the subtree
358  topDownPhase(child);
359  };
360  } // else it is a leaf
361  else {
362  // and the remaining points
363  for (int i = 0; i < tree().numPoints(curr); ++i) {
364  // node curr
365  int pointIndex = tree().point(curr, i);
366 
367  // node curr
368  for (int d = 0; d < Dim; d++) {
369  // push the force down to the child
370  m_pointData[pointIndex].force[d] = m_nodeData[curr].force[d] * mass(pointIndex);
371  }
372 
373  m_pointData[pointIndex].force_prime = m_nodeData[curr].force_prime * mass(pointIndex);
374  }
375  }
376 }
377 
378 template<int Dim>
380  for (int i = 0; i < m_numPoints; i++) {
381  for (int d = 0; d < Dim; d++) {
382  m_pointData[i].force[d] = 0.0;
383  }
384  m_pointData[i].force_prime = 0.0;
385  }
386 }
387 
388 }
389 }
390 }
ogdf
The namespace for all OGDF objects.
Definition: AugmentationModule.h:36
DTreeForceTypes.h
ogdf::energybased::dtree::DTreeForce::PointData::force
double force[Dim]
the force
Definition: DTreeForce.h:94
ogdf::energybased::dtree::DTreeForce::NodeData::force
double force[Dim]
the force
Definition: DTreeForce.h:108
ogdf::energybased::dtree::DTreeForce::~DTreeForce
virtual ~DTreeForce()
destructor
Definition: DTreeForce.h:195
ogdf::energybased::dtree::DTreeForce::m_numPoints
int m_numPoints
the number of points
Definition: DTreeForce.h:142
ogdf::energybased::dtree::DTreeForce::bottomUpPhase
void bottomUpPhase(int curr)
internal function for computing the mass and center of mass of quadtree nodes
Definition: DTreeForce.h:290
ogdf::energybased::dtree::DTreeForce::numPoints
int numPoints() const
returns the number of points
Definition: DTreeForce.h:79
ogdf::energybased::dtree::DTreeForce::mass
double mass(int i) const
returns the mass of the i-th point
Definition: DTreeForce.h:245
ogdf::energybased::dtree::DTreeForce::NodeData
the node data
Definition: DTreeForce.h:100
ogdf::energybased::dtree::DTreeWSPD::setSeparationFactor
void setSeparationFactor(double s)
sets the parameter s of the WSPD (default is 1.0)
Definition: DTreeWSPD.h:99
ogdf::energybased::dtree::DTreeForce::DTreeForce
DTreeForce(int numPoints)
constructs a new WSPD (well-separated pair decomposition) for numPoints
Definition: DTreeForce.h:187
ogdf::energybased::dtree::DTreeForce::m_nodeData
NodeData * m_nodeData
array for the node related data
Definition: DTreeForce.h:139
ogdf::energybased::dtree::DTreeWSPDCallback::onWellSeparatedPair
virtual void onWellSeparatedPair(int a, int b)
called by the WSPD for well separated pair
Definition: DTreeForce.h:155
ogdf::energybased::dtree::DTreeForce::PointData::force_prime
double force_prime
Definition: DTreeForce.h:96
ogdf::energybased::dtree::DTreeForce::deallocate
void deallocate()
internal for allocating mem
Definition: DTreeForce.h:213
ogdf::energybased::dtree::DTreeForce::Tree
typename WSPD::Tree Tree
Definition: DTreeForce.h:48
ogdf::energybased::dtree::DTreeForce::m_pWSPD
WSPD * m_pWSPD
the WSPD instance
Definition: DTreeForce.h:145
ogdf::energybased::dtree::DTreeForce::NodeData::force_prime
double force_prime
the first derivation of the distance based force function
Definition: DTreeForce.h:111
ogdf::energybased::dtree::DTreeForce
Definition: DTreeForce.h:42
ogdf::energybased::dtree::DTreeForce::setPosition
void setPosition(int i, int d, double c)
sets the d-th coordinate of the i-th point
Definition: DTreeForce.h:240
ogdf::energybased::dtree::DTreeWSPD::Tree
DTree< IntType, Dim > Tree
Definition: DTreeWSPD.h:48
ogdf::energybased::dtree::IWSPD
Definition: DTreeWSPD.h:38
ogdf::energybased::dtree::DTreeForce::computeForces
void computeForces(ForceFunc forceFunc)
main call
Definition: DTreeForce.h:266
ogdf::energybased::dtree::DTreeForce::force_prime
double force_prime(int i) const
returns derivation of the d-th coordinate of the i-th force vector
Definition: DTreeForce.h:260
ogdf::energybased::dtree::DTreeForce::wspd
const WSPD & wspd() const
returns a const ref to the wspd
Definition: DTreeForce.h:220
ogdf::energybased::dtree::DTreeWSPDCallback::DTreeWSPDCallback
DTreeWSPDCallback(DTreeForce< Dim > &treeForce, ForceFunc forceFunc)
Definition: DTreeForce.h:151
ogdf::energybased::dtree::DTreeForce::WSPD
DTreeWSPD< Dim > WSPD
Definition: DTreeForce.h:47
ogdf::EdgeStandardType::tree
@ tree
for every hyperedge e a minimal subcubic tree connecting all hypernodes incident with e together is a...
ogdf::energybased::dtree::DTreeForce::NodeData::mass
double mass
mass of this node
Definition: DTreeForce.h:102
ogdf::energybased::dtree::DTreeForce::allocate
void allocate()
internal for allocating mem
Definition: DTreeForce.h:201
ogdf::energybased::dtree::DTreeForce::m_pointData
PointData * m_pointData
array for the point related data
Definition: DTreeForce.h:136
ogdf::energybased::dtree::DTreeForce::resetTreeNodes
void resetTreeNodes()
reset the tree nodes
ogdf::energybased::dtree::DTreeForce::PointData::mass
double mass
mass of this point
Definition: DTreeForce.h:91
ogdf::energybased::dtree::DTreeWSPDCallback
Definition: DTreeForce.h:39
ogdf::energybased::dtree::DTreeForce::topDownPhase
void topDownPhase(int curr)
internal function for accumulating forces in the leaves
Definition: DTreeForce.h:341
ogdf::energybased::dtree::DTreeWSPDCallback::m_forceFunc
ForceFunc m_forceFunc
Definition: DTreeForce.h:183
DTreeWSPD.h
ogdf::energybased::dtree::DTreeWSPD
Definition: DTreeWSPD.h:45
ogdf::energybased::dtree::DTreeWSPDCallback::m_treeForce
DTreeForce< Dim > & m_treeForce
Definition: DTreeForce.h:182
ogdf::energybased::dtree::DTreeForce::tree
const Tree & tree() const
returns a const reference to the tree
Definition: DTreeForce.h:230
ogdf::energybased::dtree::DTreeForce::PointData
the point data
Definition: DTreeForce.h:89
ogdf::energybased::dtree::DTreeForce::setMass
void setMass(int i, double m)
sets the mass of the i-th point
Definition: DTreeForce.h:250
ogdf::energybased::dtree::DTreeForce::position
double position(int i, int d) const
returns d-th coordinate of the i-th point
Definition: DTreeForce.h:235
ogdf::energybased::dtree::DTreeForce::force
double force(int i, int d) const
returns d-th coordinate of the i-th force vector
Definition: DTreeForce.h:255
ogdf::energybased::dtree::DTreeForce::resetPointForces
void resetPointForces()
reset the point forces
Definition: DTreeForce.h:379
ogdf::energybased::dtree::DTreeForce::NodeData::centerOfMass
double centerOfMass[Dim]
center of mass of the subtree
Definition: DTreeForce.h:105