1 /*************************************************************************/
3 /* Copyright (c) 1994 Stanford University */
5 /* All rights reserved. */
7 /* Permission is given to use, copy, and modify this software for any */
8 /* non-commercial purpose as long as this copyright notice is not */
9 /* removed. All other uses, including redistribution in whole or in */
10 /* part, are forbidden without prior written permission. */
12 /* This software is provided with absolutely no warranty and no */
15 /*************************************************************************/
24 cellptr makecell(unsigned int ProcessId);
25 leafptr makeleaf(unsigned int ProcessId);
26 cellptr SubdivideLeaf(leafptr le, cellptr parent, unsigned int l,
27 unsigned int ProcessId);
29 cellptr InitCell(cellptr parent, unsigned int ProcessId);
30 leafptr InitLeaf(cellptr parent, unsigned int ProcessId);
31 nodeptr loadtree(bodyptr p, cellptr root, unsigned int ProcessId);
34 * MAKETREE: initialize tree structure for hack force calculation.
42 Local[ProcessId].myncell = 0;
43 Local[ProcessId].mynleaf = 0;
45 Local[ProcessId].mycelltab[Local[ProcessId].myncell++] = Global->G_root;
47 Local[ProcessId].Current_Root = (nodeptr) Global->G_root;
48 for (pp = Local[ProcessId].mybodytab;
49 pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody; pp++) {
52 Local[ProcessId].Current_Root
53 = (nodeptr) loadtree(p, (cellptr) Local[ProcessId].Current_Root,
57 LOCK(Global->io_lock);
58 fprintf(stderr, "Process %d found body %d to have zero mass\n",
60 UNLOCK(Global->io_lock);
63 BARRIER(Global->Bartree,NPROC);
64 hackcofm( 0, ProcessId );
65 BARRIER(Global->Barcom,NPROC);
68 cellptr InitCell(parent, ProcessId)
75 c = makecell(ProcessId);
76 c->processor = ProcessId;
82 Level(c) = Level(parent) >> 1;
83 Parent(c) = (nodeptr) parent;
88 leafptr InitLeaf(parent, ProcessId)
95 l = makeleaf(ProcessId);
96 l->processor = ProcessId;
100 Level(l) = IMAX >> 1;
102 Level(l) = Level(parent) >> 1;
103 Parent(l) = (nodeptr) parent;
123 printf("Cell : Cost = %d, ", Cost(c));
126 for (k = 0; k < NSUB; k++) {
127 printf("Child #%d: ", k);
128 if (Subp(c)[k] == NULL) {
132 if (Type(Subp(c)[k]) == CELL) {
133 nseq = ((cellptr) Subp(c)[k])->seqnum;
134 printf("C: Cost = %d, ", Cost(Subp(c)[k]));
137 nseq = ((leafptr) Subp(c)[k])->seqnum;
138 printf("L: # Bodies = %2d, Cost = %d, ",
139 ((leafptr) Subp(c)[k])->num_bodies, Cost(Subp(c)[k]));
142 PRTV("Pos", Pos(tmp));
146 for (k=0;k<NSUB;k++) {
147 if (Subp(c)[k] != NULL) {
148 printtree(Subp(c)[k]);
155 printf("Leaf : # Bodies = %2d, Cost = %d, ", l->num_bodies, Cost(l));
158 for (k = 0; k < l->num_bodies; k++) {
160 printf("Body #%2d: Num = %2d, Level = %o, ",
161 p - bodytab, k, Level(p));
167 fprintf(stderr, "Bad type\n");
175 * LOADTREE: descend tree and insert particle.
179 loadtree(p, root, ProcessId)
180 bodyptr p; /* body to load into tree */
184 int l, xq[NDIM], xp[NDIM], xor[NDIM], subindex(), flag;
185 int i, j, root_level;
188 volatile nodeptr *volatile qptr, mynode;
192 intcoord(xp, Pos(p));
194 for (i = 0; i < NDIM; i++) {
195 xor[i] = xp[i] ^ Local[ProcessId].Root_Coords[i];
197 for (i = IMAX >> 1; i > Level(root); i >>= 1) {
198 for (j = 0; j < NDIM; j++) {
209 if (root != Global->G_root) {
210 root_level = Level(root);
211 for (j = i; j > root_level; j >>= 1) {
212 root = (cellptr) Parent(root);
215 for (i = IMAX >> 1; i > Level(root); i >>= 1) {
216 for (j = 0; j < NDIM; j++) {
223 printf("P%d body %d\n", ProcessId, p - bodytab);
224 root = Global->G_root;
229 root = Global->G_root;
230 mynode = (nodeptr) root;
231 kidIndex = subindex(xp, Level(mynode));
232 qptr = &Subp(mynode)[kidIndex];
234 l = Level(mynode) >> 1;
237 while (flag) { /* loop descending tree */
239 error("not enough levels in tree\n");
242 /* lock the parent cell */
243 ALOCK(CellLock->CL, ((cellptr) mynode)->seqnum % MAXLOCK);
245 le = InitLeaf((cellptr) mynode, ProcessId);
246 Parent(p) = (nodeptr) le;
248 ChildNum(p) = le->num_bodies;
249 ChildNum(le) = kidIndex;
250 Bodyp(le)[le->num_bodies++] = p;
251 *qptr = (nodeptr) le;
254 AULOCK(CellLock->CL, ((cellptr) mynode)->seqnum % MAXLOCK);
255 /* unlock the parent cell */
257 if (flag && *qptr && (Type(*qptr) == LEAF)) {
258 /* reached a "leaf"? */
259 ALOCK(CellLock->CL, ((cellptr) mynode)->seqnum % MAXLOCK);
260 /* lock the parent cell */
261 if (Type(*qptr) == LEAF) { /* still a "leaf"? */
262 le = (leafptr) *qptr;
263 if (le->num_bodies == MAX_BODIES_PER_LEAF) {
264 *qptr = (nodeptr) SubdivideLeaf(le, (cellptr) mynode, l,
268 Parent(p) = (nodeptr) le;
270 ChildNum(p) = le->num_bodies;
271 Bodyp(le)[le->num_bodies++] = p;
275 AULOCK(CellLock->CL, ((cellptr) mynode)->seqnum % MAXLOCK);
276 /* unlock the node */
280 kidIndex = subindex(xp, l);
281 qptr = &Subp(*qptr)[kidIndex]; /* move down one level */
282 l = l >> 1; /* and test next bit */
285 SETV(Local[ProcessId].Root_Coords, xp);
286 return Parent((leafptr) *qptr);
290 /* * INTCOORD: compute integerized coordinates. * Returns: TRUE
291 unless rp was out of bounds. */
293 bool intcoord(xp, rp)
294 int xp[NDIM]; /* integerized coordinate vector [0,IMAX) */
295 vector rp; /* real coordinate vector (system coords) */
303 for (k = 0; k < NDIM; k++) {
304 xsc = (rp[k] - Global->rmin[k]) / Global->rsize;
305 if (0.0 <= xsc && xsc < 1.0) {
317 * SUBINDEX: determine which subcell to select.
321 int x[NDIM]; /* integerized coordinates of particle */
322 int l; /* current level of tree */
333 for (k = 1; k < NDIM; k++) {
334 if (((x[k] & l) && !yes) || (!(x[k] & l) && yes)) {
335 i += NSUB >> (k + 1);
347 * HACKCOFM: descend tree finding center-of-mass coordinates.
350 hackcofm(nc, ProcessId)
363 matrix drdr, Idrsq, tmpm;
365 /* get a cell using get*sub. Cells are got in reverse of the order in */
366 /* the cell array; i.e. reverse of the order in which they were created */
367 /* this way, we look at child cells before parents */
369 for (ll = Local[ProcessId].myleaftab + Local[ProcessId].mynleaf - 1;
370 ll >= Local[ProcessId].myleaftab; ll--) {
375 for (i = 0; i < l->num_bodies; i++) {
379 MULVS(tmpv, Pos(p), Mass(p));
380 ADDV(Pos(l), Pos(l), tmpv);
382 DIVVS(Pos(l), Pos(l), Mass(l));
385 for (i = 0; i < l->num_bodies; i++) {
387 SUBV(dr, Pos(p), Pos(l));
391 MULMS(Idrsq, Idrsq, drsq);
392 MULMS(tmpm, drdr, 3.0);
393 SUBM(tmpm, tmpm, Idrsq);
394 MULMS(tmpm, tmpm, Mass(p));
395 ADDM(Quad(l), Quad(l), tmpm);
400 for (cc = Local[ProcessId].mycelltab+Local[ProcessId].myncell-1;
401 cc >= Local[ProcessId].mycelltab; cc--) {
406 for (i = 0; i < NSUB; i++) {
414 MULVS(tmpv, Pos(r), Mass(r));
415 ADDV(Pos(q), Pos(q), tmpv);
419 DIVVS(Pos(q), Pos(q), Mass(q));
422 for (i = 0; i < NSUB; i++) {
425 SUBV(dr, Pos(r), Pos(q));
429 MULMS(Idrsq, Idrsq, drsq);
430 MULMS(tmpm, drdr, 3.0);
431 SUBM(tmpm, tmpm, Idrsq);
432 MULMS(tmpm, tmpm, Mass(r));
433 ADDM(tmpm, tmpm, Quad(r));
434 ADDM(Quad(q), Quad(q), tmpm);
443 SubdivideLeaf (le, parent, l, ProcessId)
447 unsigned int ProcessId;
452 bodyptr bodies[MAX_BODIES_PER_LEAF];
456 /* first copy leaf's bodies to temp array, so we can reuse the leaf */
457 num_bodies = le->num_bodies;
458 for (i = 0; i < num_bodies; i++) {
459 bodies[i] = Bodyp(le)[i];
463 /* create the parent cell for this subtree */
464 c = InitCell(parent, ProcessId);
465 ChildNum(c) = ChildNum(le);
466 /* do first particle separately, so we can reuse le */
468 intcoord(xp, Pos(p));
469 index = subindex(xp, l);
470 Subp(c)[index] = (nodeptr) le;
471 ChildNum(le) = index;
472 Parent(le) = (nodeptr) c;
474 /* set stuff for body */
475 Parent(p) = (nodeptr) le;
476 ChildNum(p) = le->num_bodies;
478 /* insert the body */
479 Bodyp(le)[le->num_bodies++] = p;
480 /* now handle the rest */
481 for (i = 1; i < num_bodies; i++) {
483 intcoord(xp, Pos(p));
484 index = subindex(xp, l);
485 if (!Subp(c)[index]) {
486 le = InitLeaf(c, ProcessId);
487 ChildNum(le) = index;
488 Subp(c)[index] = (nodeptr) le;
491 le = (leafptr) Subp(c)[index];
493 Parent(p) = (nodeptr) le;
494 ChildNum(p) = le->num_bodies;
496 Bodyp(le)[le->num_bodies++] = p;
502 * MAKECELL: allocation routine for cells.
505 cellptr makecell(ProcessId)
511 if (Local[ProcessId].mynumcell == maxmycell) {
512 error("makecell: Proc %d needs more than %d cells; increase fcells\n",
513 ProcessId,maxmycell);
515 Mycell = Local[ProcessId].mynumcell++;
516 c = Local[ProcessId].ctab + Mycell;
517 c->seqnum = ProcessId*maxmycell+Mycell;
521 for (i = 0; i < NSUB; i++) {
524 Local[ProcessId].mycelltab[Local[ProcessId].myncell++] = c;
529 * MAKELEAF: allocation routine for leaves.
532 leafptr makeleaf(ProcessId)
538 if (Local[ProcessId].mynumleaf == maxmyleaf) {
539 error("makeleaf: Proc %d needs more than %d leaves; increase fleaves\n",
540 ProcessId,maxmyleaf);
542 Myleaf = Local[ProcessId].mynumleaf++;
543 le = Local[ProcessId].ltab + Myleaf;
544 le->seqnum = ProcessId * maxmyleaf + Myleaf;
549 for (i = 0; i < MAX_BODIES_PER_LEAF; i++) {
552 Local[ProcessId].myleaftab[Local[ProcessId].mynleaf++] = le;