blob: 471aa059a82019e644e22fb4d0c8bc24ae2d7955 [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 <math.h>
#include "defs.h"
#include "memory.h"
#include "particle.h"
#include "box.h"
/* How many boxes can fit on one line */
#define BOXES_PER_LINE 4
#define TERMS_PER_LINE 2
box *Grid = NULL;
void ZeroBox(int my_id, box *b);
void PrintExpansionTerms();
void
CreateBoxes (int my_id, int num_boxes)
{
int cluster_no;
int i;
LOCK(G_Memory->mal_lock);
Local[my_id].B_Heap = (box *) G_MALLOC(num_boxes * sizeof(box));
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
B_Heap data across physically distributed memories as desired.
One way to do this is as follows:
char *starting_address;
char *ending_address;
starting_address = (char *) Local[my_id].B_Heap;
ending_address = (((char *) Local[my_id].B_Heap)
+ (num_boxes * sizeof(particle *)) - 1);
Place all addresses x such that (starting_address <= x < ending_address)
on node my_id
*/
UNLOCK(G_Memory->mal_lock);
Local[my_id].Max_B_Heap = num_boxes;
Local[my_id].Index_B_Heap = 0;
for (i = 0; i < num_boxes; i++) {
Local[my_id].B_Heap[i].exp_lock_index = i % (MAX_LOCKS - 1);
Local[my_id].B_Heap[i].particle_lock_index = i % (MAX_LOCKS - 1);
Local[my_id].B_Heap[i].id = i + ((double) my_id / ID_LIMIT);
ZeroBox(my_id, &Local[my_id].B_Heap[i]);
}
}
void
FreeBoxes (int my_id)
{
int i;
box *b_array;
b_array = Local[my_id].B_Heap;
for (i = 0; i < Local[my_id].Index_B_Heap; i++)
ZeroBox(my_id, &b_array[i]);
Local[my_id].Index_B_Heap = 0;
}
void
ZeroBox (int my_id, box *b)
{
int i;
b->type = CHILDLESS;
b->num_particles = 0;
for (i = 0; i < MAX_PARTICLES_PER_BOX; i++)
b->particles[i] = NULL;
b->parent = NULL;
for (i = 0; i < NUM_OFFSPRING; i++) {
b->children[i] = NULL;
b->shadow[i] = NULL;
}
b->num_children = 0;
b->construct_synch = 0;
b->interaction_synch = 0;
b->cost = 0;
b->proc = my_id;
b->subtree_cost = 0;
b->next = NULL;
b->prev = NULL;
}
/*
* InitBox (int my_id, real x_center, real y_center, real length, int level, box *parent)
*
* Args : the x_center and y_center of the center of the box;
* the length of the box;
* the level of the box;
* the address of b's parent.
*
* Returns : the address of the newly created box.
*
* Side Effects : Initializes num_particles to 0, all other pointers to NULL,
* and sets the box ID to a unique number. It also creates the space for
* the two expansion arrays.
*
*/
box *
InitBox (int my_id, real x_center, real y_center, real length, box *parent)
{
box *b;
if (Local[my_id].Index_B_Heap == Local[my_id].Max_B_Heap) {
LockedPrint("ERROR (P%d) : Ran out of boxes\n", my_id);
exit(-1);
}
b = &Local[my_id].B_Heap[Local[my_id].Index_B_Heap++];
b->x_center = x_center;
b->y_center = y_center;
b->length = length;
b->parent = parent;
if (parent == NULL)
b->level = 0;
else
b->level = parent->level + 1;
return b;
}
/*
* PrintBox (box *b)
*
* Args : the address of a box, b.
*
* Returns : nothing.
*
* Side Effects : Prints to stdout the information stored for b.
*
*/
void
PrintBox (box *b)
{
int i;
LOCK(G_Memory->io_lock);
fflush(stdout);
if (b != NULL) {
printf("Info for B%f :\n", b->id);
printf(" X center = %.40g\n", b->x_center);
printf(" Y center = %.40g\n", b->y_center);
printf(" Length = %.40g\n", b->length);
printf(" Level = %d\n", b->level);
printf(" Type = %d\n", b->type);
printf(" Child Num = %d\n", b->child_num);
if (b->parent == NULL)
printf(" Parent = NONE\n");
else
printf(" Parent = B%f\n", b->parent->id);
printf(" Children's IDs : ");
if (b->num_children != 0)
PrintBoxArrayIds(b->children, b->num_children);
else
printf("NONE\n");
printf(" Sibling's IDs : ");
if (b->num_siblings != 0)
PrintBoxArrayIds(b->siblings, b->num_siblings);
else
printf("NONE\n");
printf(" Colleagues' IDs : ");
PrintBoxArrayIds(b->colleagues, b->num_colleagues);
printf(" U List IDs : ");
PrintBoxArrayIds(b->u_list, b->num_u_list);
printf(" V List IDs : ");
PrintBoxArrayIds(b->v_list, b->num_v_list);
printf(" W List IDs : ");
PrintBoxArrayIds(b->w_list, b->num_w_list);
printf(" # of Particles = %d\n", b->num_particles);
printf(" Particles' IDs : ");
PrintParticleArrayIds(b->particles, b->num_particles);
printf(" Assigned Process ID : %d\n", b->proc);
printf(" Cost : %d\n", b->cost);
printf("\n");
}
else
printf("Box has not been initialized yet.\n\n");
UNLOCK(G_Memory->io_lock);
}
/*
* PrintBoxArrayIds (box_node *b_array[], int array_length)
*
* Args : the address of the box array, b_array;
* the length of the array, array_length.
*
* Returns : nothing.
*
* Side Effects : Prints to stdout just the id numbers for every box in
* b_array.
*
*/
void
PrintBoxArrayIds (box *b_array[], int array_length)
{
int i;
int tab_count;
tab_count = 0;
for (i = 0; i < array_length; i++) {
if (tab_count == 0) {
printf("\n");
tab_count = BOXES_PER_LINE;
}
if (b_array[i] != NULL)
printf("\tB%f", b_array[i]->id);
tab_count -= 1;
}
printf("\n");
}
/*
* PrintExpansionTerms (real expansion[])
*
* Args : the array of expansion terms, expansion.
*
* Returns : nothing.
*
* Side Effects : Prints to stdout the contents of expansion.
*
*/
void
PrintExpansionTerms (complex expansion[])
{
int i;
int tab_count = 0;
for (i = 0; i < Expansion_Terms; i++) {
if (tab_count == 0) {
printf("\n");
tab_count = TERMS_PER_LINE;
}
if (expansion[i].i >= (real) 0.0)
printf("\ta%d = %.3e + %.3ei", i, expansion[i].r, expansion[i].i);
else
printf("\ta%d = %.3e - %.3ei", i, expansion[i].r, -expansion[i].i);
tab_count -= 1;
}
printf("\n");
}
void
ListIterate (int my_id, box *b, box **list, int length, list_function function)
{
int i;
for (i = 0; i < length; i++) {
if (list[i] == NULL) {
LockedPrint("ERROR (P%d) : NULL list entry\n", my_id);
exit(-1);
}
(*function)(my_id, list[i], b);
}
}
/*
* AdjacentBoxes (int my_id, box *b1, box *b2)
*
* Args : two potentially adjacent boxes, b1 and b2.
*
* Returns : TRUE, if boxes are adjacent, FALSE if not.
*
* Side Effects : none.
*
* Comments : Two boxes are adjacent if their centers are separated in either
* the x or y directions by (1/2 the length of b1) + (1/2 length of b2),
* and separated in the other direction by a distance less than or equal
* to (1/2 the length of b1) + (1/2 the length of b2).
*
* NOTE : By this definition, parents are NOT adjacent to their children.
*/
int
AdjacentBoxes (int my_id, box *b1, box *b2)
{
real exact_separation;
real x_separation;
real y_separation;
int ret_val;
exact_separation = (b1->length / (real) 2.0) + (b2->length / (real) 2.0);
x_separation = (real) fabs((double)(b1->x_center - b2->x_center));
y_separation = (real) fabs((double)(b1->y_center - b2->y_center));
if ((x_separation == exact_separation) &&
(y_separation <= exact_separation))
ret_val = TRUE;
else
if ((y_separation == exact_separation) &&
(x_separation <= exact_separation))
ret_val = TRUE;
else
ret_val = FALSE;
return ret_val;
}
/*
* WellSeparatedBoxes (int my_id, box *b1, box *b2)
*
* Args : Two potentially well separated boxes, b1 and b2.
*
* Returns : TRUE, if the two boxes are well separated, and FALSE if not.
*
* Side Effects : none.
*
* Comments : Well separated means that the two boxes are separated by the
* length of the boxes. If one of the boxes is bigger than the other,
* the smaller box is given the length of the larger box. This means
* that the centers of the two boxes, regardless of their relative size,
* must be separated in the x or y direction (or both) by at least
* twice the length of the biggest box.
*
*/
int
WellSeparatedBoxes (int my_id, box *b1, box *b2)
{
real min_ws_distance;
real x_separation;
real y_separation;
int ret_val;
if (b1->length > b2->length)
min_ws_distance = b1->length * (real) 2.0;
else
min_ws_distance = b2->length * (real) 2.0;
x_separation = (real) fabs((double)(b1->x_center - b2->x_center));
y_separation = (real) fabs((double)(b1->y_center - b2->y_center));
if ((x_separation >= min_ws_distance) || (y_separation >= min_ws_distance))
ret_val = TRUE;
else
ret_val = FALSE;
return ret_val;
}
#undef BOXES_PER_LINE
#undef TERMS_PER_LINE