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
38template<int Dim, typename ForceFunc, bool UseForcePrime>
39class DTreeWSPDCallback;
40
41template<int Dim>
43public:
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>
77
79 int numPoints() const { return m_numPoints; };
80
82 const WSPD& wspd() const;
83
85 const Tree& tree() const;
86
87private:
89 struct PointData {
91 double mass;
92
94 double force[Dim];
95
97 };
98
100 struct NodeData {
102 double mass;
103
106
108 double force[Dim];
109
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
134
137
140
143
146};
147
148template<int Dim, typename ForceFunc, bool UseForcePrime>
149class DTreeWSPDCallback : public IWSPD {
150public:
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
184};
185
186template<int Dim>
187DTreeForce<Dim>::DTreeForce(int numPoints) : m_numPoints(numPoints) {
188 // get the memory
189 allocate();
190
192}
193
194template<int Dim>
196 // free the mem
197 deallocate();
198}
199
200template<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
212template<int Dim>
214 delete m_pWSPD;
215 delete[] m_nodeData;
216 delete[] m_pointData;
217}
218
219template<int Dim>
221 return *m_pWSPD;
222}
223
224template<int Dim>
226 return *m_pWSPD;
227}
228
229template<int Dim>
231 return wspd().tree();
232}
233
234template<int Dim>
235double DTreeForce<Dim>::position(int i, int d) const {
236 return wspd().point(i).x[d];
237}
238
239template<int Dim>
240void DTreeForce<Dim>::setPosition(int i, int d, double c) {
241 wspd().setPoint(i, d, c);
242}
243
244template<int Dim>
245double DTreeForce<Dim>::mass(int i) const {
246 return m_pointData[i].mass;
247}
248
249template<int Dim>
250void DTreeForce<Dim>::setMass(int i, double m) {
251 m_pointData[i].mass = m;
252}
253
254template<int Dim>
255double DTreeForce<Dim>::force(int i, int d) const {
256 return m_pointData[i].force[d];
257}
258
259template<int Dim>
260double DTreeForce<Dim>::force_prime(int i) const {
261 return m_pointData[i].force_prime;
262}
263
264template<int Dim>
265template<typename ForceFunc, bool UseForcePrime>
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
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
289template<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
340template<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
378template<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}
void setMass(int i, double m)
sets the mass of the i-th point
Definition DTreeForce.h:250
void bottomUpPhase(int curr)
internal function for computing the mass and center of mass of quadtree nodes
Definition DTreeForce.h:290
const WSPD & wspd() const
returns a const ref to the wspd
Definition DTreeForce.h:220
void deallocate()
internal for allocating mem
Definition DTreeForce.h:213
void topDownPhase(int curr)
internal function for accumulating forces in the leaves
Definition DTreeForce.h:341
const Tree & tree() const
returns a const reference to the tree
Definition DTreeForce.h:230
WSPD * m_pWSPD
the WSPD instance
Definition DTreeForce.h:145
NodeData * m_nodeData
array for the node related data
Definition DTreeForce.h:139
void allocate()
internal for allocating mem
Definition DTreeForce.h:201
void resetPointForces()
reset the point forces
Definition DTreeForce.h:379
int numPoints() const
returns the number of points
Definition DTreeForce.h:79
PointData * m_pointData
array for the point related data
Definition DTreeForce.h:136
void setPosition(int i, int d, double c)
sets the d-th coordinate of the i-th point
Definition DTreeForce.h:240
double mass(int i) const
returns the mass of the i-th point
Definition DTreeForce.h:245
void computeForces(ForceFunc forceFunc)
main call
Definition DTreeForce.h:266
void resetTreeNodes()
reset the tree nodes
int m_numPoints
the number of points
Definition DTreeForce.h:142
double position(int i, int d) const
returns d-th coordinate of the i-th point
Definition DTreeForce.h:235
double force(int i, int d) const
returns d-th coordinate of the i-th force vector
Definition DTreeForce.h:255
DTreeForce(int numPoints)
constructs a new WSPD (well-separated pair decomposition) for numPoints
Definition DTreeForce.h:187
double force_prime(int i) const
returns derivation of the d-th coordinate of the i-th force vector
Definition DTreeForce.h:260
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:155
DTreeWSPDCallback(DTreeForce< Dim > &treeForce, ForceFunc forceFunc)
Definition DTreeForce.h:151
const Tree & tree() const
returns the corresponding Dtree
Definition DTreeWSPD.h:81
DTree< IntType, Dim > Tree
Definition DTreeWSPD.h:48
void setSeparationFactor(double s)
sets the parameter s of the WSPD (default is 1.0)
Definition DTreeWSPD.h:99
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
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:111
double centerOfMass[Dim]
center of mass of the subtree
Definition DTreeForce.h:105