gem5/splash2/codes/apps/fmm/construct_grid.C

1120 lines
30 KiB
C

/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
#include <stdio.h>
#include <float.h>
#include "defs.h"
#include "memory.h"
#include "particle.h"
#include "box.h"
#include "partition_grid.h"
#include "construct_grid.h"
#define MY_PARTICLES (Local[my_id].Particles)
#define MY_NUM_PARTICLES (Local[my_id].Num_Particles)
#define MY_MAX_PARTICLES (Local[my_id].Max_Particles)
void DetermineGridSize(long my_id);
void DetermineLocalGridSize(long my_id);
void MergeLocalGridSize(long my_id);
void ConstructLocalGrid(long my_id);
box *InitGrid(long my_id);
void InsertParticlesInTree(long my_id, particle **p_list, long num_of_particles, box *root);
box *FindHome(long my_id, particle *p, box *current_home);
box *FindInitialRoot(particle *p, box *current_home);
box *CreateChild(long my_id, box *pb, long new_child_num);
void SubdivideBox(long my_id, box *b);
void MergeLocalGrid(long my_id);
void MLGHelper(long my_id, box *local_box, box *global_box, box *global_parent);
void MergeLocalParticles(long my_id, particle **p_array, long num_of_particles, box *pb);
void SplitParticles(particle **p_array, long length, particle **p_dist, long num_p_dist[NUM_OFFSPRING], box *pb);
box *CreateLeaf(long my_id, box *pb, long new_child_num, particle **p_array, long length);
void InsertParticlesInLeaf(long my_id, particle **p_array, long length, box *b);
long InsertBoxInGrid(long my_id, box *b, box *pb);
long RemoveBoxFromGrid(box *b, box *pb);
void InsertSubtreeInPartition(long my_id, box *b);
void CleanupGrid(long my_id);
void SetSiblings(box *b);
void SetColleagues(long my_id, box *b);
void ConstructGridLists(long my_id, box *b);
void ConstructInteractionLists(long my_id, box *b);
void SetVList(long my_id, box *b);
void SetUList(long my_id, box *b);
void SetUListHelper(long my_id, box *b, box *pb);
long AncestorBox(box *b, box *ancestor_box);
void SetWList(long my_id, box *b);
void InsertNonAdjChildren(long my_id, box *b, box *pb);
void
ConstructGrid (long my_id, time_info *local_time, long time_all)
{
unsigned long init = 0, start = 0, finish;
if (time_all)
CLOCK(init);
DetermineGridSize(my_id); /* Finds the four corners of the grid. */
FreeBoxes(my_id);
InitPartition(my_id);
if (time_all)
CLOCK(start);
if (MY_NUM_PARTICLES > 0) {
ConstructLocalGrid(my_id); /* Each processor constructs their own tree
based on only their particles */
MergeLocalGrid(my_id); /* The processors combine their trees into one
global tree. This step contains
communication between processors. */
}
BARRIER(G_Memory->synch, Number_Of_Processors);
CleanupGrid(my_id);
if (time_all)
CLOCK(finish);
if (time_all) {
local_time[MY_TIME_STEP].other_time = start - init;
local_time[MY_TIME_STEP].construct_time = finish - start;
}
}
void
ConstructLists (long my_id, time_info *local_time, long time_all)
{
unsigned long start, finish;
if (time_all)
CLOCK(start);
PartitionIterate(my_id, ConstructGridLists, TOP);
BARRIER(G_Memory->synch, Number_Of_Processors);
PartitionIterate(my_id, ConstructInteractionLists, BOTTOM);
if (time_all)
CLOCK(finish);
if (time_all) {
local_time[MY_TIME_STEP].list_time = finish - start;
}
}
void
DestroyGrid (long my_id, time_info *local_time, long time_all)
{
box *b_scan, *tb;
particle *p;
long i;
long particle_cost;
unsigned long start = 0, finish;
if (time_all)
CLOCK(start);
b_scan = Local[my_id].Childless_Partition;
MY_NUM_PARTICLES = 0;
while (b_scan != NULL) {
tb = b_scan;
b_scan = b_scan->next;
particle_cost = tb->cost / tb->num_particles;
for (i = 0; i < tb->num_particles; i++) {
if (MY_MAX_PARTICLES <= MY_NUM_PARTICLES) {
LockedPrint("ERROR (P%d) : Too many particles in local array\n", my_id);
exit(-1);
}
p = tb->particles[i];
p->cost = particle_cost;
MY_PARTICLES[MY_NUM_PARTICLES++] = p;
}
}
if (my_id == 0)
Grid = NULL;
if (time_all) {
CLOCK(finish);
local_time[MY_TIME_STEP].other_time += finish - start;
}
}
/*
* PrintGrid (long my_id)
*
* Args : none.
*
* Returns : nothing.
*
* Side Effects : Prints the entire box structure of the grid to stdout.
*
*/
void
PrintGrid (long my_id)
{
if (Grid != NULL) {
if (my_id == 0) {
printf("Info for Adaptive Grid :\n");
printf("Boxes :\n\n");
}
fflush(stdout);
BARRIER(G_Memory->synch, Number_Of_Processors);
PartitionIterate(my_id, PrintBox, TOP);
BARRIER(G_Memory->synch, Number_Of_Processors);
if (my_id == 0) {
printf("\n");
}
fflush(stdout);
BARRIER(G_Memory->synch, Number_Of_Processors);
}
else
printf("Adaptive grid has not been initialized yet.\n");
}
void
DetermineGridSize (long my_id)
{
DetermineLocalGridSize(my_id); /* Processor looks at its own particles and
finds the x and y max and min */
MergeLocalGridSize(my_id); /* Processors shares info with others and each
one computes the global max and min */
}
/* This code is pretty straightforward. A processor scans through its list of
particles and finds the x_max, x_min, y_max, y_min. The only interesting
thing is that particles are looked at two at a time, and compared to each
other before looking at the current best max and min. This speeds up the
running time of the algorithm from 2n to 3/2n. */
void
DetermineLocalGridSize (long my_id)
{
real x_pos1, x_pos2, y_pos1, y_pos2;
real x_max_challenger, x_min_challenger, y_max_challenger, y_min_challenger;
long i;
Local[my_id].Local_X_Max = -MAX_REAL;
Local[my_id].Local_X_Min = MAX_REAL;
Local[my_id].Local_Y_Max = -MAX_REAL;
Local[my_id].Local_Y_Min = MAX_REAL;
for (i = 0; i < MY_NUM_PARTICLES - 1; i += 2) {
x_pos1 = MY_PARTICLES[i]->pos.x;
y_pos1 = MY_PARTICLES[i]->pos.y;
x_pos2 = MY_PARTICLES[i + 1]->pos.x;
y_pos2 = MY_PARTICLES[i + 1]->pos.y;
if (x_pos1 > x_pos2) {
x_max_challenger = x_pos1;
x_min_challenger = x_pos2;
}
else {
x_max_challenger = x_pos2;
x_min_challenger = x_pos1;
}
if (y_pos1 > y_pos2) {
y_max_challenger = y_pos1;
y_min_challenger = y_pos2;
}
else {
y_max_challenger = y_pos2;
y_min_challenger = y_pos1;
}
if (x_max_challenger > Local[my_id].Local_X_Max)
Local[my_id].Local_X_Max = x_max_challenger;
if (x_min_challenger < Local[my_id].Local_X_Min)
Local[my_id].Local_X_Min = x_min_challenger;
if (y_max_challenger > Local[my_id].Local_Y_Max)
Local[my_id].Local_Y_Max = y_max_challenger;
if (y_min_challenger < Local[my_id].Local_Y_Min)
Local[my_id].Local_Y_Min = y_min_challenger;
}
if (i == (MY_NUM_PARTICLES - 1)) {
x_max_challenger = MY_PARTICLES[i]->pos.x;
x_min_challenger = MY_PARTICLES[i]->pos.x;
y_max_challenger = MY_PARTICLES[i]->pos.y;
y_min_challenger = MY_PARTICLES[i]->pos.y;
if (x_max_challenger > Local[my_id].Local_X_Max)
Local[my_id].Local_X_Max = x_max_challenger;
if (x_min_challenger < Local[my_id].Local_X_Min)
Local[my_id].Local_X_Min = x_min_challenger;
if (y_max_challenger > Local[my_id].Local_Y_Max)
Local[my_id].Local_Y_Max = y_max_challenger;
if (y_min_challenger < Local[my_id].Local_Y_Min)
Local[my_id].Local_Y_Min = y_min_challenger;
}
}
/* Each processor writes its best to a global
array, then they read everyone else's and find the absolute best. */
void
MergeLocalGridSize (long my_id)
{
real *my_f_array, *their_f_array;
real x_max_challenger, x_min_challenger, y_max_challenger, y_min_challenger;
long i;
my_f_array = G_Memory->f_array[my_id];
my_f_array[0] = Local[my_id].Local_X_Max;
my_f_array[1] = Local[my_id].Local_X_Min;
my_f_array[2] = Local[my_id].Local_Y_Max;
my_f_array[3] = Local[my_id].Local_Y_Min;
BARRIER(G_Memory->synch, Number_Of_Processors);
for (i = 0; i < Number_Of_Processors; i++) {
their_f_array = G_Memory->f_array[i];
x_max_challenger = their_f_array[0];
x_min_challenger = their_f_array[1];
y_max_challenger = their_f_array[2];
y_min_challenger = their_f_array[3];
if (x_max_challenger > Local[my_id].Local_X_Max)
Local[my_id].Local_X_Max = x_max_challenger;
if (x_min_challenger < Local[my_id].Local_X_Min)
Local[my_id].Local_X_Min = x_min_challenger;
if (y_max_challenger > Local[my_id].Local_Y_Max)
Local[my_id].Local_Y_Max = y_max_challenger;
if (y_min_challenger < Local[my_id].Local_Y_Min)
Local[my_id].Local_Y_Min = y_min_challenger;
}
}
void
ConstructLocalGrid (long my_id)
{
Local[my_id].Local_Grid = InitGrid(my_id); /* Create the root box */
InsertParticlesInTree(my_id, MY_PARTICLES, MY_NUM_PARTICLES,
Local[my_id].Local_Grid);
/* Put all of your particles into your local tree */
}
box *
InitGrid (long my_id)
{
real x_length, y_length;
real grid_length, grid_x_center, grid_y_center;
long exp;
box *ret_box;
frexp(Local[my_id].Local_X_Max, &exp);
if (Local[my_id].Local_X_Max > 0)
Local[my_id].Local_X_Max = ldexp(1.0, exp);
else {
if (Local[my_id].Local_X_Max < 0)
Local[my_id].Local_X_Max = -ldexp(1.0, exp - 1);
}
frexp(Local[my_id].Local_X_Min, &exp);
if (Local[my_id].Local_X_Min < 0)
Local[my_id].Local_X_Min = -ldexp(1.0, exp);
else {
if (Local[my_id].Local_X_Min > 0)
Local[my_id].Local_X_Min = ldexp(1.0, exp - 1);
}
frexp(Local[my_id].Local_Y_Max, &exp);
if (Local[my_id].Local_Y_Max > 0)
Local[my_id].Local_Y_Max = ldexp(1.0, exp);
else {
if (Local[my_id].Local_Y_Max < 0)
Local[my_id].Local_Y_Max = -ldexp(1.0, exp - 1);
}
frexp(Local[my_id].Local_Y_Min, &exp);
if (Local[my_id].Local_Y_Min < 0)
Local[my_id].Local_Y_Min = -ldexp(1.0, exp);
else {
if (Local[my_id].Local_Y_Min > 0)
Local[my_id].Local_Y_Min = ldexp(1.0, exp - 1);
}
x_length = Local[my_id].Local_X_Max - Local[my_id].Local_X_Min;
y_length = Local[my_id].Local_Y_Max - Local[my_id].Local_Y_Min;
if (x_length > y_length)
grid_length = x_length;
else
grid_length = y_length;
grid_x_center = (grid_length / (real) 2.0) + Local[my_id].Local_X_Min;
grid_y_center = (grid_length / (real) 2.0) + Local[my_id].Local_Y_Min;
ret_box = InitBox(my_id, grid_x_center, grid_y_center, grid_length, NULL);
return ret_box;
}
/* All this procedure does is put the particles in p_list into the tree pointed
to by root. For each particle, you find out which childless (ie body) box
the particle is supposed to go into, and insert it. Because childless boxes
in this code can have 40 particles in them, instead of one for B-H, I have
to check that. B-H is the same as having a MAX_PARTICLES_PER_BOX of 1. When
that value is exceeded, the childless box is subdivided and the particles
are divided up amongst the children. Note that all the particles may be put
into one child, in which case that child must be subdivided as well, and so
on until there is more than one child. */
void
InsertParticlesInTree (long my_id, particle **p_list, long num_of_particles, box *root)
{
particle *p;
box *dest_box;
long i, j;
dest_box = root;
for (i = 0; i < num_of_particles; i++) {
p = p_list[i];
dest_box = FindHome(my_id, p, dest_box);
dest_box->particles[dest_box->num_particles++] = p;
while (dest_box->num_particles > MAX_PARTICLES_PER_BOX) {
SubdivideBox(my_id, dest_box);
if (dest_box->num_children == 1) {
for (j = 0; dest_box->children[j] == NULL; j++)
;
dest_box = dest_box->children[j];
}
}
}
}
/* This function compares the particles position to the center of the parent
(or cell) box and chooses the appropriate child to move down to, until
either a child box or a null pointer is reached. In the first case, the box
is returned, and in the second, a new child box is created for the parent,
and that box is returned. */
box *
FindHome (long my_id, particle *p, box *current_home)
{
box *pb;
pb = FindInitialRoot(p, current_home);
while (pb->type == PARENT) {
if (p->pos.y > pb->y_center) {
if (p->pos.x > pb->x_center) {
if (pb->children[0] == NULL)
CreateChild(my_id, pb, 0);
pb = pb->children[0];
}
else {
if (pb->children[1] == NULL)
CreateChild(my_id, pb, 1);
pb = pb->children[1];
}
}
else {
if (p->pos.x > pb->x_center) {
if (pb->children[3] == NULL)
CreateChild(my_id, pb, 3);
pb = pb->children[3];
}
else {
if (pb->children[2] == NULL)
CreateChild(my_id, pb, 2);
pb = pb->children[2];
}
}
}
return pb;
}
box *
FindInitialRoot (particle *p, box *current_home)
{
long found;
real x_center_distance, y_center_distance;
found = FALSE;
while (found == FALSE) {
x_center_distance = p->pos.x - current_home->x_center;
y_center_distance = p->pos.y - current_home->y_center;
if (x_center_distance < 0)
x_center_distance = -x_center_distance;
if (y_center_distance < 0)
y_center_distance = -y_center_distance;
if ((x_center_distance > (current_home->length / 2.0)) ||
(y_center_distance > (current_home->length / 2.0)))
current_home = current_home->parent;
else
found = TRUE;
}
return current_home;
}
/* Simply creates a new box and sets the parent and child pointers correctly.
The child's spot in the parent's children array determines its position.
So, 0 is upper right, 1 is upper left, 2 is bottom left, and 3 is bottom
right. That's how I know how to set the location of the child box's center
just by knowing the child number. */
box *
CreateChild (long my_id, box *pb, long new_child_num)
{
real child_length, child_offset;
box *ret_box;
child_length = pb->length / (real) NUM_DIMENSIONS;
child_offset = pb->length / (real) NUM_OFFSPRING;
if (new_child_num == 0) {
pb->children[0] = InitBox(my_id, (pb->x_center + child_offset),
(pb->y_center + child_offset), child_length,
pb);
pb->shadow[0] = pb->children[0];
}
if (new_child_num == 1) {
pb->children[1] = InitBox(my_id, (pb->x_center - child_offset),
(pb->y_center + child_offset), child_length,
pb);
pb->shadow[1] = pb->children[1];
}
if (new_child_num == 2) {
pb->children[2] = InitBox(my_id, (pb->x_center - child_offset),
(pb->y_center - child_offset), child_length,
pb);
pb->shadow[2] = pb->children[2];
}
if (new_child_num == 3) {
pb->children[3] = InitBox(my_id, (pb->x_center + child_offset),
(pb->y_center - child_offset), child_length,
pb);
pb->shadow[3] = pb->children[3];
}
pb->children[new_child_num]->child_num = new_child_num;
ret_box = pb->children[new_child_num];
pb->num_children += 1;
return ret_box;
}
/* Looks at all the particles of the parent box and distributes them amongst
the children. If the child does not exist, one is created. */
void
SubdivideBox (long my_id, box *b)
{
particle *p;
box *child;
long i;
for (i = 0; i < b->num_particles; i++) {
p = b->particles[i];
if (p->pos.y > b->y_center) {
if (p->pos.x > b->x_center) {
child = b->children[0];
if (child == NULL)
child = CreateChild(my_id, b, 0);
}
else {
child = b->children[1];
if (child == NULL)
child = CreateChild(my_id, b, 1);
}
}
else {
if (p->pos.x > b->x_center) {
child = b->children[3];
if (child == NULL)
child = CreateChild(my_id, b, 3);
}
else {
child = b->children[2];
if (child == NULL)
child = CreateChild(my_id, b, 2);
}
}
child->particles[child->num_particles++] = p;
b->particles[i] = NULL;
}
b->num_particles = 0;
b->type = PARENT;
}
/* Each processor keeps track of the boxes that it has inserted into the tree.
This list is called a partition because when construction is over, every box
in the global tree will also reside in one and only one of the processors'
partitions. This is needed for list construction (which you don't have to
worry about) and cost zone computation (which you will). */
void
MergeLocalGrid (long my_id)
{
MLGHelper(my_id, Local[my_id].Local_Grid, Grid, NULL);
}
void
MLGHelper (long my_id, box *local_box, box *global_box, box *global_parent)
{
long success;
long i;
success = FALSE;
while (success == FALSE) {
if (local_box->type == PARENT) {
if (global_box == NULL) {
success = InsertBoxInGrid(my_id, local_box, global_parent);
}
else {
if (global_box->type == PARENT) {
success = TRUE;
for (i = 0; i < NUM_OFFSPRING; i++) {
if (local_box->children[i] != NULL)
MLGHelper(my_id, local_box->children[i],
global_box->children[i], global_box);
}
}
else {
success = RemoveBoxFromGrid(global_box, global_parent);
if (success == TRUE) {
InsertParticlesInTree(my_id, global_box->particles,
global_box->num_particles, local_box);
success = InsertBoxInGrid(my_id, local_box, global_parent);
}
}
}
}
else {
if (global_box == NULL) {
success = InsertBoxInGrid(my_id, local_box, global_parent);
}
else {
if (global_box->type == PARENT) {
MergeLocalParticles(my_id, local_box->particles,
local_box->num_particles, global_box);
success = TRUE;
}
else {
success = RemoveBoxFromGrid(global_box, global_parent);
if (success == TRUE) {
InsertParticlesInLeaf(my_id, global_box->particles,
global_box->num_particles, local_box);
success = InsertBoxInGrid(my_id, local_box, global_parent);
}
}
}
}
if (success == FALSE) {
if (global_parent == NULL)
global_box = Grid;
else
global_box = global_parent->children[local_box->child_num];
}
}
}
void
MergeLocalParticles (long my_id, particle **p_array, long num_of_particles, box *pb)
{
particle *(p_dist)[NUM_OFFSPRING][MAX_PARTICLES_PER_BOX];
long num_p_dist[NUM_OFFSPRING];
box *child;
long success;
long i;
SplitParticles(p_array, num_of_particles,
(particle **) p_dist, num_p_dist, pb);
for (i= 0; i < NUM_OFFSPRING; i++) {
if (num_p_dist[i] > 0) {
child = pb->children[i];
if (child == NULL) {
child = CreateLeaf(my_id, pb, i, p_dist[i], num_p_dist[i]);
success = InsertBoxInGrid(my_id, child, pb);
}
else {
if (child->type == PARENT) {
MergeLocalParticles(my_id, p_dist[i], num_p_dist[i], child);
success = TRUE;
}
else {
success = RemoveBoxFromGrid(child, pb);
if (success == TRUE) {
InsertParticlesInLeaf(my_id, p_dist[i], num_p_dist[i], child);
success = InsertBoxInGrid(my_id, child, pb);
}
else
child = CreateLeaf(my_id, pb, i, p_dist[i], num_p_dist[i]);
}
}
if (success == FALSE) {
MLGHelper(my_id, child, pb->children[child->child_num], pb);
}
}
}
}
void
SplitParticles (particle **p_array, long length, particle **p_dist,
long num_p_dist[NUM_OFFSPRING], box *pb)
{
particle *p;
long i;
for (i = 0; i < NUM_OFFSPRING; i++)
num_p_dist[i] = 0;
for (i = 0; i < length; i++) {
p = p_array[i];
if (p->pos.y > pb->y_center) {
if (p->pos.x > pb->x_center)
*(p_dist + num_p_dist[0]++) = p;
else
*(p_dist + MAX_PARTICLES_PER_BOX + num_p_dist[1]++) = p;
}
else {
if (p->pos.x > pb->x_center)
*(p_dist + (3 * MAX_PARTICLES_PER_BOX) + num_p_dist[3]++) = p;
else
*(p_dist + (2 * MAX_PARTICLES_PER_BOX) + num_p_dist[2]++) = p;
}
}
}
box *
CreateLeaf (long my_id, box *pb, long new_child_num, particle **p_array, long length)
{
real child_length, child_offset;
box *ret_box = NULL;
long i;
child_length = pb->length / (real) NUM_DIMENSIONS;
child_offset = pb->length / (real) NUM_OFFSPRING;
if (new_child_num == 0) {
ret_box = InitBox(my_id, (pb->x_center + child_offset),
(pb->y_center + child_offset), child_length,
pb);
}
if (new_child_num == 1) {
ret_box = InitBox(my_id, (pb->x_center - child_offset),
(pb->y_center + child_offset), child_length,
pb);
}
if (new_child_num == 2) {
ret_box = InitBox(my_id, (pb->x_center - child_offset),
(pb->y_center - child_offset), child_length,
pb);
}
if (new_child_num == 3) {
ret_box = InitBox(my_id, (pb->x_center + child_offset),
(pb->y_center - child_offset), child_length,
pb);
}
ret_box->child_num = new_child_num;
for (i = 0; i < length; i++) {
ret_box->particles[i] = p_array[i];
}
ret_box->num_particles = length;
return ret_box;
}
void
InsertParticlesInLeaf (long my_id, particle **p_array, long length, box *b)
{
long i, j;
long offset;
if ((length + b->num_particles) > MAX_PARTICLES_PER_BOX) {
for (i = b->num_particles, j = length - 1; i < MAX_PARTICLES_PER_BOX;
i++, j--)
b->particles[i] = p_array[j];
b->num_particles = MAX_PARTICLES_PER_BOX;
length = j + 1;
InsertParticlesInTree(my_id, p_array, length, b);
}
else {
offset = b->num_particles;
for (i = 0; i < length; i++)
b->particles[i + offset] = p_array[i];
b->num_particles += length;
}
}
long
InsertBoxInGrid (long my_id, box *b, box *pb)
{
long success;
if (pb == NULL) {
LOCK(G_Memory->single_lock);
if (Grid == NULL) {
Grid = b;
success = TRUE;
}
else
success = FALSE;
UNLOCK(G_Memory->single_lock);
}
else {
ALOCK(G_Memory->lock_array, pb->particle_lock_index);
if (pb->children[b->child_num] == NULL) {
pb->children[b->child_num] = b;
pb->num_children += 1;
b->parent = pb;
success = TRUE;
}
else
success = FALSE;
AULOCK(G_Memory->lock_array, pb->particle_lock_index);
}
if (success == TRUE)
InsertSubtreeInPartition(my_id, b);
return success;
}
long
RemoveBoxFromGrid (box *b, box *pb)
{
long success;
if (pb == NULL) {
LOCK(G_Memory->single_lock);
if (Grid == b) {
Grid = NULL;
success = TRUE;
}
else
success = FALSE;
UNLOCK(G_Memory->single_lock);
}
else {
ALOCK(G_Memory->lock_array, pb->particle_lock_index);
if (pb->children[b->child_num] == b) {
pb->children[b->child_num] = NULL;
b->parent = NULL;
pb->num_children -= 1;
success = TRUE;
}
else
success = FALSE;
AULOCK(G_Memory->lock_array, pb->particle_lock_index);
}
return success;
}
void
InsertSubtreeInPartition (long my_id, box *b)
{
long i;
box *child;
if (b->proc == my_id) {
InsertBoxInPartition(my_id, b);
}
if (b->type == PARENT) {
for (i = 0; i < NUM_OFFSPRING; i++) {
child = b->children[i];
if (child == NULL)
child = b->shadow[i];
if (child != NULL)
InsertSubtreeInPartition(my_id, child);
}
}
}
void
CleanupGrid (long my_id)
{
box *b_scan, *tb;
b_scan = Local[my_id].Childless_Partition;
while (b_scan != NULL) {
if (((b_scan->parent != NULL) || (b_scan == Grid))
&& (b_scan->type == CHILDLESS))
b_scan = b_scan->next;
else {
tb = b_scan;
b_scan = b_scan->next;
if (tb->type == PARENT) {
tb->type = CHILDLESS;
RemoveBoxFromPartition(my_id, tb);
tb->type = PARENT;
if ((tb->parent != NULL) || (tb == Grid)) {
InsertBoxInPartition(my_id, tb);
}
}
else
RemoveBoxFromPartition(my_id, tb);
}
}
}
void
ConstructGridLists (long my_id, box *b)
{
SetSiblings(b);
SetColleagues(my_id, b);
}
void
SetSiblings (box *b)
{
box *pb, *sb;
long i;
b->num_siblings = 0;
pb = b->parent;
if (pb != NULL) {
for (i = 0; i < NUM_OFFSPRING; i++) {
sb = pb->children[i];
if ((sb != NULL) && (sb != b))
b->siblings[b->num_siblings++] = sb;
}
}
}
void
SetColleagues (long my_id, box *b)
{
box *pb, *cb, *cousin;
long i, j;
b->num_colleagues = 0;
pb = b->parent;
if (pb != NULL) {
for (i = 0; i < b->num_siblings; i++)
b->colleagues[b->num_colleagues++] = b->siblings[i];
while (b->construct_synch == 0) {
/* wait */;
}
b->construct_synch = 0;
for (i = 0; i < pb->num_colleagues; i++) {
cb = pb->colleagues[i];
for (j = 0; j < NUM_OFFSPRING; j++) {
cousin = cb->children[j];
if (cousin != NULL) {
if (AdjacentBoxes(b, cousin) == TRUE)
b->colleagues[b->num_colleagues++] = cousin;
}
}
}
}
if (b->type == PARENT) {
for (i = 0; i < NUM_OFFSPRING; i++) {
if (b->children[i] != NULL) {
b->children[i]->construct_synch = 1;
}
}
}
}
/*
* ConstructInteractionLists (long my_id, box *b)
*
* Args : a box, b.
*
* Returns : nothing.
*
* Side Effects : Creates b's colleagues, u_list,
* v_list, and w_list.
*
*/
void
ConstructInteractionLists (long my_id, box *b)
{
SetVList(my_id, b);
if (b->type == CHILDLESS) {
SetUList(my_id, b);
SetWList(my_id, b);
}
}
void
SetVList (long my_id, box *b)
{
box *pb, *cb, *cousin;
long i, j;
b->num_v_list = 0;
pb = b->parent;
if (pb != NULL) {
for (i = 0; i < pb->num_colleagues; i++) {
cb = pb->colleagues[i];
for (j = 0; j < NUM_OFFSPRING; j++) {
cousin = cb->children[j];
if (cousin != NULL) {
if (WellSeparatedBoxes(b, cousin) == TRUE)
b->v_list[b->num_v_list++] = cousin;
}
}
}
}
}
/*
* SetUList (long my_id, box *b)
*
* Args : a box, b.
*
* Returns : nothing.
*
* Side Effects : Sets b's adjacency interaction list.
*
* Comments : The helper function is used to enable recursion.
*
*/
void
SetUList (long my_id, box *b)
{
b->num_u_list = 0;
SetUListHelper(my_id, b, Grid);
}
/*
* SetUListHelper (long my_id, box *b, box *pb)
*
* Args : a box, b, and a parent box, pb.
*
* Returns : nothing.
*
* Side Effects : Sets b's adjacency interaction list.
*
* Comments :
*
*/
void
SetUListHelper (long my_id, box *b, box *pb)
{
box *child;
long i;
for (i = 0; i < NUM_OFFSPRING; i++) {
child = pb->children[i];
if (child != NULL) {
if (AdjacentBoxes(b, child) == TRUE) {
if (child->type == CHILDLESS)
b->u_list[b->num_u_list++] = child;
else
SetUListHelper(my_id, b, child);
}
else {
if (AncestorBox(b, child) == TRUE)
SetUListHelper(my_id, b, child);
}
}
}
}
/*
* AncestorBox (box *b, box *ancestor_box)
*
* Args : a box, b, and its possible ancestor box, ancestor_box.
*
* Returns : TRUE, if ancestor_box is an ancestor of b, FALSE if not.
*
* Side Effects : none.
*
* Comments : A box is NOT the ancestor of himself. So, AncestorBox(b,b)
* always returns FALSE. So, ancestor_box is indeed the ancestor of b
* if their sizes are not equal and if b's center lies within the boundaries
* of ancestor_box.
*
*/
long
AncestorBox (box *b, box *ancestor_box)
{
real x_center_distance;
real y_center_distance;
long ret_val = TRUE;
if (b->length != ancestor_box->length) {
x_center_distance = fabs((double)(b->x_center - ancestor_box->x_center));
y_center_distance = fabs((double)(b->y_center - ancestor_box->y_center));
if ((x_center_distance > (ancestor_box->length / 2.0)) ||
(y_center_distance > (ancestor_box->length / 2.0)))
ret_val = FALSE;
}
else
ret_val = FALSE;
return ret_val;
}
/*
* SetWList (long my_id, box *b)
*
* Args : a box, b.
*
* Returns : nothing.
*
* Side Effects : Sets b's w_list.
*
* Comments : This list contains all descedants of b's colleagues whose
* parents are adjacent to b, but who are not adjacent to b themeselves.
* This list should only be computed for childless boxes.
*
*/
void
SetWList (long my_id, box *b)
{
box *co_search;
long i;
b->num_w_list = 0;
for (i = 0; i < b->num_colleagues; i++) {
co_search = b->colleagues[i];
if (co_search->type == PARENT)
InsertNonAdjChildren(my_id, b, co_search);
}
}
/*
* InsertNonAdjChildren (long my_id, box *b, box *pb)
*
* Args : a parent box, pb, and the box with the weak iteraction list, b.
*
* Returns : nothing.
*
* Side Effects : Inserts all non-adjacent children of adjacent box pb into
* b's weak interaction list.
*
* Comments : This function recursively calls itself on every child that is
* also adjacent to b and a parent.
*
*/
void
InsertNonAdjChildren (long my_id, box *b, box *pb)
{
long i;
box *child;
for (i = 0; i < pb->num_children; i++) {
child = pb->children[i];
if (child != NULL) {
if (AdjacentBoxes(b, child) == TRUE) {
if (child->type == PARENT)
InsertNonAdjChildren(my_id, b, child);
}
else
b->w_list[b->num_w_list++] = child;
}
}
}