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