Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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