Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
DTreeForce.h
Go to the documentation of this file.
1
29#pragma once
30
33
34namespace ogdf {
35namespace energybased {
36namespace dtree {
37
38
39template<int Dim>
41public:
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
85private:
87 struct PointData {
89 double mass;
90
92 double force[Dim];
93
95 };
96
98 struct NodeData {
100 double mass;
101
103 double centerOfMass[Dim];
104
106 double force[Dim];
107
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
132
135
138
141
144};
145
146template<int Dim, typename ForceFunc, bool UseForcePrime>
147class DTreeWSPDCallback : public IWSPD {
148public:
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
184template<int Dim>
185DTreeForce<Dim>::DTreeForce(int numPoints) : m_numPoints(numPoints) {
186 // get the memory
187 allocate();
188
190}
191
192template<int Dim>
194 // free the mem
195 deallocate();
196}
197
198template<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
210template<int Dim>
212 delete m_pWSPD;
213 delete[] m_nodeData;
214 delete[] m_pointData;
215}
216
217template<int Dim>
219 return *m_pWSPD;
220}
221
222template<int Dim>
224 return *m_pWSPD;
225}
226
227template<int Dim>
229 return wspd().tree();
230}
231
232template<int Dim>
233double DTreeForce<Dim>::position(int i, int d) const {
234 return wspd().point(i).x[d];
235}
236
237template<int Dim>
238void DTreeForce<Dim>::setPosition(int i, int d, double c) {
239 wspd().setPoint(i, d, c);
240}
241
242template<int Dim>
243double DTreeForce<Dim>::mass(int i) const {
244 return m_pointData[i].mass;
245}
246
247template<int Dim>
248void DTreeForce<Dim>::setMass(int i, double m) {
249 m_pointData[i].mass = m;
250}
251
252template<int Dim>
253double DTreeForce<Dim>::force(int i, int d) const {
254 return m_pointData[i].force[d];
255}
256
257template<int Dim>
258double DTreeForce<Dim>::force_prime(int i) const {
259 return m_pointData[i].force_prime;
260}
261
262template<int Dim>
263template<typename ForceFunc, bool UseForcePrime>
264void 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
287template<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
338template<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
376template<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}
void setMass(int i, double m)
sets the mass of the i-th point
Definition DTreeForce.h:248
void bottomUpPhase(int curr)
internal function for computing the mass and center of mass of quadtree nodes
Definition DTreeForce.h:288
const WSPD & wspd() const
returns a const ref to the wspd
Definition DTreeForce.h:218
void deallocate()
internal for allocating mem
Definition DTreeForce.h:211
void topDownPhase(int curr)
internal function for accumulating forces in the leaves
Definition DTreeForce.h:339
const Tree & tree() const
returns a const reference to the tree
Definition DTreeForce.h:228
WSPD * m_pWSPD
the WSPD instance
Definition DTreeForce.h:143
NodeData * m_nodeData
array for the node related data
Definition DTreeForce.h:137
void allocate()
internal for allocating mem
Definition DTreeForce.h:199
void resetPointForces()
reset the point forces
Definition DTreeForce.h:377
int numPoints() const
returns the number of points
Definition DTreeForce.h:77
PointData * m_pointData
array for the point related data
Definition DTreeForce.h:134
void setPosition(int i, int d, double c)
sets the d-th coordinate of the i-th point
Definition DTreeForce.h:238
double mass(int i) const
returns the mass of the i-th point
Definition DTreeForce.h:243
void computeForces(ForceFunc forceFunc)
main call
Definition DTreeForce.h:264
void resetTreeNodes()
reset the tree nodes
int m_numPoints
the number of points
Definition DTreeForce.h:140
double position(int i, int d) const
returns d-th coordinate of the i-th point
Definition DTreeForce.h:233
double force(int i, int d) const
returns d-th coordinate of the i-th force vector
Definition DTreeForce.h:253
DTreeForce(int numPoints)
constructs a new WSPD (well-separated pair decomposition) for numPoints
Definition DTreeForce.h:185
double force_prime(int i) const
returns derivation of the d-th coordinate of the i-th force vector
Definition DTreeForce.h:258
int point(int i, int j) const
returns the index of the jth point covered by i's subtree.
Definition DTree.h:103
virtual void onWellSeparatedPair(int a, int b)
called by the WSPD for well separated pair
Definition DTreeForce.h:153
DTreeWSPDCallback(DTreeForce< Dim > &treeForce, ForceFunc forceFunc)
Definition DTreeForce.h:149
const Tree & tree() const
returns the corresponding Dtree
Definition DTreeWSPD.h:84
DTree< IntType, Dim > Tree
Definition DTreeWSPD.h:51
void setSeparationFactor(double s)
sets the parameter s of the WSPD (default is 1.0)
Definition DTreeWSPD.h:102
The namespace for all OGDF objects.
@ tree
for every hyperedge e a minimal subcubic tree connecting all hypernodes incident with e together is a...
double force_prime
the first derivation of the distance based force function
Definition DTreeForce.h:109
double centerOfMass[Dim]
center of mass of the subtree
Definition DTreeForce.h:103