2017-04-26 17:20:15 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* 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. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
2017-04-26 17:20:15 +02:00
|
|
|
#include "defs.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "particle.h"
|
2017-04-26 18:03:02 +02:00
|
|
|
#include "box.h"
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
/* How many boxes can fit on one line */
|
|
|
|
#define BOXES_PER_LINE 4
|
|
|
|
#define TERMS_PER_LINE 2
|
|
|
|
|
|
|
|
box *Grid = NULL;
|
|
|
|
|
|
|
|
void ZeroBox(long my_id, box *b);
|
|
|
|
|
|
|
|
void
|
|
|
|
CreateBoxes (long my_id, long num_boxes)
|
|
|
|
{
|
|
|
|
long 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)
|
2017-04-26 18:03:02 +02:00
|
|
|
+ (num_boxes * sizeof(particle *)) - 1);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
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 (long my_id)
|
|
|
|
{
|
|
|
|
long 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 (long my_id, box *b)
|
|
|
|
{
|
|
|
|
long 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 (long my_id, real x_center, real y_center, real length, long 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 (long 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)
|
|
|
|
{
|
|
|
|
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 = %ld\n", b->level);
|
|
|
|
printf(" Type = %d\n", b->type);
|
|
|
|
printf(" Child Num = %ld\n", b->child_num);
|
|
|
|
if (b->parent == NULL)
|
2017-04-26 18:03:02 +02:00
|
|
|
printf(" Parent = NONE\n");
|
2017-04-26 17:20:15 +02:00
|
|
|
else
|
2017-04-26 18:03:02 +02:00
|
|
|
printf(" Parent = B%f\n", b->parent->id);
|
2017-04-26 17:20:15 +02:00
|
|
|
printf(" Children's IDs : ");
|
|
|
|
if (b->num_children != 0)
|
2017-04-26 18:03:02 +02:00
|
|
|
PrintBoxArrayIds(b->children, b->num_children);
|
2017-04-26 17:20:15 +02:00
|
|
|
else
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("NONE\n");
|
2017-04-26 17:20:15 +02:00
|
|
|
printf(" Sibling's IDs : ");
|
|
|
|
if (b->num_siblings != 0)
|
2017-04-26 18:03:02 +02:00
|
|
|
PrintBoxArrayIds(b->siblings, b->num_siblings);
|
2017-04-26 17:20:15 +02:00
|
|
|
else
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("NONE\n");
|
2017-04-26 17:20:15 +02:00
|
|
|
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 = %ld\n", b->num_particles);
|
|
|
|
printf(" Particles' IDs : ");
|
|
|
|
PrintParticleArrayIds(b->particles, b->num_particles);
|
|
|
|
printf(" Assigned Process ID : %ld\n", b->proc);
|
|
|
|
printf(" Cost : %ld\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[], long 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[], long array_length)
|
|
|
|
{
|
|
|
|
long i;
|
|
|
|
long tab_count;
|
|
|
|
|
|
|
|
tab_count = 0;
|
|
|
|
for (i = 0; i < array_length; i++) {
|
|
|
|
if (tab_count == 0) {
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("\n");
|
|
|
|
tab_count = BOXES_PER_LINE;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
if (b_array[i] != NULL)
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("\tB%f", b_array[i]->id);
|
2017-04-26 17:20:15 +02:00
|
|
|
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[])
|
|
|
|
{
|
|
|
|
long i;
|
|
|
|
long tab_count = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < Expansion_Terms; i++) {
|
|
|
|
if (tab_count == 0) {
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("\n");
|
|
|
|
tab_count = TERMS_PER_LINE;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
if (expansion[i].i >= (real) 0.0)
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("\ta%ld = %.3e + %.3ei", i, expansion[i].r, expansion[i].i);
|
2017-04-26 17:20:15 +02:00
|
|
|
else
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("\ta%ld = %.3e - %.3ei", i, expansion[i].r, -expansion[i].i);
|
2017-04-26 17:20:15 +02:00
|
|
|
tab_count -= 1;
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ListIterate (long my_id, box *b, box **list, long length, list_function function)
|
|
|
|
{
|
|
|
|
long i;
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
if (list[i] == NULL) {
|
2017-04-26 18:03:02 +02:00
|
|
|
LockedPrint("ERROR (P%d) : NULL list entry\n", my_id);
|
|
|
|
exit(-1);
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
(*function)(my_id, list[i], b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* AdjacentBoxes (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.
|
|
|
|
*/
|
|
|
|
long
|
|
|
|
AdjacentBoxes (box *b1, box *b2)
|
|
|
|
{
|
|
|
|
real exact_separation;
|
|
|
|
real x_separation;
|
|
|
|
real y_separation;
|
|
|
|
long 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) &&
|
2017-04-26 18:03:02 +02:00
|
|
|
(x_separation <= exact_separation))
|
|
|
|
ret_val = TRUE;
|
2017-04-26 17:20:15 +02:00
|
|
|
else
|
2017-04-26 18:03:02 +02:00
|
|
|
ret_val = FALSE;
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* WellSeparatedBoxes (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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
long
|
|
|
|
WellSeparatedBoxes (box *b1, box *b2)
|
|
|
|
{
|
|
|
|
real min_ws_distance;
|
|
|
|
real x_separation;
|
|
|
|
real y_separation;
|
|
|
|
long 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
|
|
|
|
|