blob: f3f475a94856b133914c0a3fb7a7fe60bd37b493 [file] [log] [blame]
/*************************************************************************/
/* */
/* 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 <values.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(int my_id);
void DetermineLocalGridSize(int my_id);
void MergeLocalGridSize(int my_id);
void ConstructLocalGrid(int my_id);
box *InitGrid(int my_id);
void InsertParticlesInTree(int my_id, particle **p_list, int num_of_particles,
box *root);
box *FindHome(int my_id, particle *p, box *current_home);
box *FindInitialRoot(int my_id, particle *p, box *current_home);
box *CreateChild(int my_id, box *pb, int new_child_num);
void SubdivideBox(int my_id, box *b);
void MergeLocalGrid(int my_id);
void MLGHelper(int my_id, box *local_box, box *global_box, box *global_parent);
void MergeLocalParticles(int my_id, particle **p_array, int num_of_particles,
box *pb);
void SplitParticles(int my_id, particle **p_array, int length,
particle **p_dist, int num_p_dist[NUM_OFFSPRING], box *pb);
box *CreateLeaf(int my_id, box *pb, int new_child_num, particle **p_array,
int length);
void InsertParticlesInLeaf(int my_id, particle **p_array, int length, box *b);
int InsertBoxInGrid(int my_id, box *b, box *pb);
int RemoveBoxFromGrid(int my_id, box *b, box *pb);
void InsertSubtreeInPartition(int my_id, box *b);
void CleanupGrid(int my_id);
void SetSiblings(int my_id, box *b);
void SetColleagues(int my_id, box *b);
void ConstructGridLists(int my_id, box *b);
void ConstructInteractionLists(int my_id, box *b);
void SetVList(int my_id, box *b);
void SetUList(int my_id, box *b);
void SetUListHelper(int my_id, box *b, box *pb);
int AncestorBox(int my_id, box *b, box *ancestor_box);
void SetWList(int my_id, box *b);
void InsertNonAdjChildren(int my_id, box *b, box *pb);
void
ConstructGrid (int my_id, time_info *local_time, int time_all)
{
unsigned long init, start, finish;
int i;
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 (int my_id, time_info *local_time, int 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 (int my_id, time_info *local_time, int time_all)
{
box *b_scan, *tb;
particle *p;
int i;
int particle_cost;
unsigned long start, 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 (int my_id)
*
* Args : none.
*
* Returns : nothing.
*
* Side Effects : Prints the entire box structure of the grid to stdout.
*
*/
void
PrintGrid (int 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 (int 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 (int my_id)
{
real x_pos1, x_pos2, y_pos1, y_pos2;
real x_max_challenger, x_min_challenger, y_max_challenger, y_min_challenger;
int 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 (int my_id)
{
real *my_f_array, *their_f_array;
real x_max_challenger, x_min_challenger, y_max_challenger, y_min_challenger;
int 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 (int 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 (int my_id)
{
real x_length, y_length;
real grid_length, grid_x_center, grid_y_center;
int 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 (int my_id, particle **p_list, int num_of_particles, box *root)
{
particle *p;
box *dest_box;
int 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 (int my_id, particle *p, box *current_home)
{
box *pb;
pb = FindInitialRoot(my_id, 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 (int my_id, particle *p, box *current_home)
{
int 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 (int my_id, box *pb, int 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 (int my_id, box *b)
{
particle *p;
box *child;
int 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 (int my_id)
{
MLGHelper(my_id, Local[my_id].Local_Grid, Grid, NULL);
}
void
MLGHelper (int my_id, box *local_box, box *global_box, box *global_parent)
{
int success;
int 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(my_id, 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(my_id, 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 (int my_id, particle **p_array, int num_of_particles, box *pb)
{
particle *(p_dist)[NUM_OFFSPRING][MAX_PARTICLES_PER_BOX];
int num_p_dist[NUM_OFFSPRING];
box *child;
box *new_box;
int success;
int i, j, k;
SplitParticles(my_id, 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(my_id, 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 (int my_id, particle **p_array, int length, particle **p_dist,
int num_p_dist[NUM_OFFSPRING], box *pb)
{
particle *p;
int 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 (int my_id, box *pb, int new_child_num, particle **p_array, int length)
{
real child_length, child_offset;
box *ret_box;
int 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 (int my_id, particle **p_array, int length, box *b)
{
int i, j;
int 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;
}
}
int
InsertBoxInGrid (int my_id, box *b, box *pb)
{
int 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;
}
int
RemoveBoxFromGrid (int my_id, box *b, box *pb)
{
int 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 (int my_id, box *b)
{
int 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 (int my_id)
{
box *b_scan, *tb;
int i;
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 (int my_id, box *b)
{
SetSiblings(my_id, b);
SetColleagues(my_id, b);
}
void
SetSiblings (int my_id, box *b)
{
box *pb, *sb;
int 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 (int my_id, box *b)
{
box *pb, *cb, *cousin;
int 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(my_id, 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 (int 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 (int my_id, box *b)
{
SetVList(my_id, b);
if (b->type == CHILDLESS) {
SetUList(my_id, b);
SetWList(my_id, b);
}
}
void
SetVList (int my_id, box *b)
{
box *pb, *cb, *cousin;
int 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(my_id, b, cousin) == TRUE)
b->v_list[b->num_v_list++] = cousin;
}
}
}
}
}
/*
* SetUList (int 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 (int my_id, box *b)
{
b->num_u_list = 0;
SetUListHelper(my_id, b, Grid);
}
/*
* SetUListHelper (int 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 (int my_id, box *b, box *pb)
{
box *child;
int i;
for (i = 0; i < NUM_OFFSPRING; i++) {
child = pb->children[i];
if (child != NULL) {
if (AdjacentBoxes(my_id, b, child) == TRUE) {
if (child->type == CHILDLESS)
b->u_list[b->num_u_list++] = child;
else
SetUListHelper(my_id, b, child);
}
else {
if (AncestorBox(my_id, b, child) == TRUE)
SetUListHelper(my_id, b, child);
}
}
}
}
/*
* AncestorBox (int my_id, 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(my_id, 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.
*
*/
int
AncestorBox (int my_id, box *b, box *ancestor_box)
{
real x_center_distance;
real y_center_distance;
int 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 (int 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 (int my_id, box *b)
{
box *co_search;
int 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 (int 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 (int my_id, box *b, box *pb)
{
int i;
box *child;
for (i = 0; i < pb->num_children; i++) {
child = pb->children[i];
if (child != NULL) {
if (AdjacentBoxes(my_id, b, child) == TRUE) {
if (child->type == PARENT)
InsertNonAdjChildren(my_id, b, child);
}
else
b->w_list[b->num_w_list++] = child;
}
}
}