ported over barnes
This commit is contained in:
482
Tests/isa/Cprograms/benchmark/barnes/barnes_hut.c
Normal file
482
Tests/isa/Cprograms/benchmark/barnes/barnes_hut.c
Normal file
@@ -0,0 +1,482 @@
|
|||||||
|
/*
|
||||||
|
* File: barnes_hut.c
|
||||||
|
* --------------
|
||||||
|
* Implements the Barnes Hut algorithm for n-body
|
||||||
|
* simulation with galaxy-like initial conditions.
|
||||||
|
* Uses OpenGl and GLUT for graphics. Written by:
|
||||||
|
* Joel Backsell, Kim Torberntsson & Alexander Bilock.
|
||||||
|
* Source: https://github.com/KimTorberntsson/Barnes-Hut/blob/master/barnes_hut.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
// #include <time.h>
|
||||||
|
// #include <GLUT/glut.h>
|
||||||
|
|
||||||
|
#include "barnes_hut.h"
|
||||||
|
// #include "graphics.h"
|
||||||
|
|
||||||
|
void free(void *ptr);
|
||||||
|
void *malloc(size_t size);
|
||||||
|
|
||||||
|
//Some constants and global variables
|
||||||
|
int N = 10;
|
||||||
|
const double L = 1, W = 1, dt = 1e-3, alpha = 0.25, V = 50, epsilon = 1e-1, grav = 0.04; //grav should be 100/N
|
||||||
|
double *x, *y, *u, *v, *force_x, *force_y, *mass;
|
||||||
|
struct node_t *root;
|
||||||
|
|
||||||
|
// -------- Modified by Akilan ----------
|
||||||
|
|
||||||
|
double my_sqrt(double x) {
|
||||||
|
if (x <= 0) return 0;
|
||||||
|
|
||||||
|
double guess = x;
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
guess = 0.5 * (guess + x / guess);
|
||||||
|
}
|
||||||
|
return guess;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PI 3.141592653589793
|
||||||
|
|
||||||
|
double wrap_angle(double x) {
|
||||||
|
while (x > PI) x -= 2*PI;
|
||||||
|
while (x < -PI) x += 2*PI;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
double my_sin(double x) {
|
||||||
|
x = wrap_angle(x);
|
||||||
|
|
||||||
|
double x2 = x * x;
|
||||||
|
return x
|
||||||
|
- (x * x2) / 6
|
||||||
|
+ (x * x2 * x2) / 120
|
||||||
|
- (x * x2 * x2 * x2) / 5040;
|
||||||
|
}
|
||||||
|
|
||||||
|
double my_cos(double x) {
|
||||||
|
x = wrap_angle(x);
|
||||||
|
|
||||||
|
double x2 = x * x;
|
||||||
|
return 1
|
||||||
|
- x2 / 2
|
||||||
|
+ (x2 * x2) / 24
|
||||||
|
- (x2 * x2 * x2) / 720;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------
|
||||||
|
|
||||||
|
// -------- Modified by Akilan ----------
|
||||||
|
|
||||||
|
static unsigned int seed = 123456789; // must be initialized somehow
|
||||||
|
|
||||||
|
unsigned int rand_test(void)
|
||||||
|
{
|
||||||
|
seed = (1103515245 * seed + 12345);
|
||||||
|
return (seed >> 16) & 0x7FFF; // 15-bit result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function for producing a random number between two double values
|
||||||
|
*/
|
||||||
|
double frand(double xmin, double xmax) {
|
||||||
|
return xmin + (xmax-xmin)*rand_test()/RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints the time between two clocks in seconds
|
||||||
|
*/
|
||||||
|
// void print_time(clock_t s, clock_t e)
|
||||||
|
// {
|
||||||
|
// printf("Time: %f seconds\n", (double)(e-s)/CLOCKS_PER_SEC);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called every time GLUT refreshes the display.
|
||||||
|
*/
|
||||||
|
// void display(void) {
|
||||||
|
// //Do a time step
|
||||||
|
// time_step();
|
||||||
|
|
||||||
|
// //Draw points
|
||||||
|
// drawPoints(x, y, N);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Updates the positions of the particles of a time step.
|
||||||
|
*/
|
||||||
|
void time_step(void) {
|
||||||
|
//Allocate memory for root
|
||||||
|
root = malloc(sizeof(struct node_t));
|
||||||
|
set_node(root);
|
||||||
|
root->min_x = 0; root->max_x = 1; root->min_y = 0; root->max_y = 1;
|
||||||
|
|
||||||
|
//Put particles in tree
|
||||||
|
for(int i = 0; i < N; i++) {
|
||||||
|
put_particle_in_tree(i, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate mass and center of mass
|
||||||
|
calculate_mass(root);
|
||||||
|
calculate_center_of_mass_x(root);
|
||||||
|
calculate_center_of_mass_y(root);
|
||||||
|
|
||||||
|
//Calculate forces
|
||||||
|
update_forces();
|
||||||
|
|
||||||
|
//Update velocities and positions
|
||||||
|
for(int i = 0; i < N; i++) {
|
||||||
|
double ax = force_x[i]/mass[i];
|
||||||
|
double ay = force_y[i]/mass[i];
|
||||||
|
u[i] += ax*dt;
|
||||||
|
v[i] += ay*dt;
|
||||||
|
x[i] += u[i]*dt;
|
||||||
|
y[i] += v[i]*dt;
|
||||||
|
|
||||||
|
/* This of course doesn't make any sense physically,
|
||||||
|
* but makes sure that the particles stay within the
|
||||||
|
* bounds. Normally the particles won't leave the
|
||||||
|
* area anyway.
|
||||||
|
*/
|
||||||
|
bounce(&x[i], &y[i], &u[i], &v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Free memory
|
||||||
|
free_node(root);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a particle moves beyond any of the boundaries then bounce it back
|
||||||
|
*/
|
||||||
|
void bounce(double *x, double *y, double *u, double *v) {
|
||||||
|
double W = 1.0f, H = 1.0f;
|
||||||
|
if(*x > W) {
|
||||||
|
*x = 2*W - *x;
|
||||||
|
*u = -*u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*x < 0) {
|
||||||
|
*x = -*x;
|
||||||
|
*u = -*u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*y > H) {
|
||||||
|
*y = 2*H - *y;
|
||||||
|
*v = -*v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*y < 0) {
|
||||||
|
*y = -*y;
|
||||||
|
*v = -*v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Puts a particle recursively in the Barnes Hut quad-tree.
|
||||||
|
*/
|
||||||
|
void put_particle_in_tree(int new_particle, struct node_t *node) {
|
||||||
|
//If no particle is assigned to the node
|
||||||
|
if(!node->has_particle) {
|
||||||
|
node->particle = new_particle;
|
||||||
|
node->has_particle = 1;
|
||||||
|
}
|
||||||
|
//If the node has no children
|
||||||
|
else if(!node->has_children) {
|
||||||
|
//Allocate and initiate children
|
||||||
|
node->children = malloc(4*sizeof(struct node_t));
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
set_node(&node->children[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set boundaries for the children
|
||||||
|
node->children[0].min_x = node->min_x; node->children[0].max_x = (node->min_x + node->max_x)/2;
|
||||||
|
node->children[0].min_y = node->min_y; node->children[0].max_y = (node->min_y + node->max_y)/2;
|
||||||
|
|
||||||
|
node->children[1].min_x = (node->min_x + node->max_x)/2; node->children[1].max_x = node->max_x;
|
||||||
|
node->children[1].min_y = node->min_y; node->children[1].max_y = (node->min_y + node->max_y)/2;
|
||||||
|
|
||||||
|
node->children[2].min_x = node->min_x; node->children[2].max_x = (node->min_x + node->max_x)/2;
|
||||||
|
node->children[2].min_y = (node->min_y + node->max_y)/2; node->children[2].max_y = node->max_y;
|
||||||
|
|
||||||
|
node->children[3].min_x = (node->min_x + node->max_x)/2; node->children[3].max_x = node->max_x;
|
||||||
|
node->children[3].min_y = (node->min_y + node->max_y)/2; node->children[3].max_y = node->max_y;
|
||||||
|
|
||||||
|
//Put old particle into the appropriate child
|
||||||
|
place_particle(node->particle, node);
|
||||||
|
|
||||||
|
//Put new particle into the appropriate child
|
||||||
|
place_particle(new_particle, node);
|
||||||
|
|
||||||
|
//It now has children
|
||||||
|
node->has_children = 1;
|
||||||
|
}
|
||||||
|
//Add the new particle to the appropriate children
|
||||||
|
else {
|
||||||
|
//Put new particle into the appropriate child
|
||||||
|
place_particle(new_particle, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Puts a particle in the right child of a node with children.
|
||||||
|
*/
|
||||||
|
void place_particle(int particle, struct node_t *node) {
|
||||||
|
if(x[particle] <= (node->min_x + node->max_x)/2 && y[particle] <= (node->min_y + node->max_y)/2) {
|
||||||
|
put_particle_in_tree(particle, &node->children[0]);
|
||||||
|
} else if(x[particle] > (node->min_x + node->max_x)/2 && y[particle] < (node->min_y + node->max_y)/2) {
|
||||||
|
put_particle_in_tree(particle, &node->children[1]);
|
||||||
|
} else if(x[particle] < (node->min_x + node->max_x)/2 && y[particle] > (node->min_y + node->max_y)/2) {
|
||||||
|
put_particle_in_tree(particle, &node->children[2]);
|
||||||
|
} else {
|
||||||
|
put_particle_in_tree(particle, &node->children[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets initial values for a new node
|
||||||
|
*/
|
||||||
|
void set_node(struct node_t *node) {
|
||||||
|
node->has_particle = 0;
|
||||||
|
node->has_children = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frees memory for a node and its children recursively.
|
||||||
|
*/
|
||||||
|
void free_node(struct node_t *node){
|
||||||
|
if(node->has_children){
|
||||||
|
free_node(&node->children[0]);
|
||||||
|
free_node(&node->children[1]);
|
||||||
|
free_node(&node->children[2]);
|
||||||
|
free_node(&node->children[3]);
|
||||||
|
free(node->children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Displays the boundaries of the tree using OpenGL and GLUT.
|
||||||
|
* Used for debugging purposes.
|
||||||
|
*/
|
||||||
|
// void display_tree(struct node_t *node) {
|
||||||
|
// drawRect(node->min_x, node->max_x, node->min_y, node->max_y);
|
||||||
|
// if(node->has_children == 1) {
|
||||||
|
// for(int i = 0; i < 4; i++) {
|
||||||
|
// display_tree(&node->children[i]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the total mass for the node. It recursively updates the mass
|
||||||
|
* of itself and all of its children.
|
||||||
|
*/
|
||||||
|
double calculate_mass(struct node_t *node) {
|
||||||
|
if(!node->has_particle) {
|
||||||
|
node->total_mass = 0;
|
||||||
|
} else if(!node->has_children) {
|
||||||
|
node->total_mass = mass[node->particle];
|
||||||
|
} else {
|
||||||
|
node->total_mass = 0;
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
node->total_mass += calculate_mass(&node->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node->total_mass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the x-position of the centre of mass for the
|
||||||
|
* node. It recursively updates the position of itself and
|
||||||
|
* all of its children.
|
||||||
|
*/
|
||||||
|
double calculate_center_of_mass_x(struct node_t *node) {
|
||||||
|
if(!node->has_children) {
|
||||||
|
node->c_x = x[node->particle];
|
||||||
|
} else {
|
||||||
|
node->c_x = 0;
|
||||||
|
double m_tot = 0;
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
if(node->children[i].has_particle) {
|
||||||
|
node->c_x += node->children[i].total_mass*calculate_center_of_mass_x(&node->children[i]);
|
||||||
|
m_tot += node->children[i].total_mass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node->c_x /= m_tot;
|
||||||
|
}
|
||||||
|
return node->c_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the y-position of the centre of mass for the
|
||||||
|
* node. It recursively updates the position of itself and
|
||||||
|
* all of its children.
|
||||||
|
*/
|
||||||
|
double calculate_center_of_mass_y(struct node_t *node) {
|
||||||
|
if(!node->has_children) {
|
||||||
|
node->c_y = y[node->particle];
|
||||||
|
} else {
|
||||||
|
node->c_y = 0;
|
||||||
|
double m_tot = 0;
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
if(node->children[i].has_particle) {
|
||||||
|
node->c_y += node->children[i].total_mass*calculate_center_of_mass_y(&node->children[i]);
|
||||||
|
m_tot += node->children[i].total_mass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node->c_y /= m_tot;
|
||||||
|
}
|
||||||
|
return node->c_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the forces in a time step of all particles in
|
||||||
|
* the simulation using the Barnes Hut quad tree.
|
||||||
|
*/
|
||||||
|
void update_forces(){
|
||||||
|
for(int i = 0; i < N; i++) {
|
||||||
|
force_x[i] = 0;
|
||||||
|
force_y[i] = 0;
|
||||||
|
update_forces_help(i, root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Help function for calculating the forces recursively
|
||||||
|
* using the Barnes Hut quad tree.
|
||||||
|
*/
|
||||||
|
void update_forces_help(int particle, struct node_t *node) {
|
||||||
|
//The node is a leaf node with a particle and not the particle itself
|
||||||
|
if(!node->has_children && node->has_particle && node->particle != particle) {
|
||||||
|
double r = my_sqrt((x[particle] - node->c_x)*(x[particle] - node->c_x) + (y[particle] - node->c_y)*(y[particle] - node->c_y));
|
||||||
|
calculate_force(particle, node, r);
|
||||||
|
}
|
||||||
|
//The node has children
|
||||||
|
else if(node->has_children) {
|
||||||
|
//Calculate r and theta
|
||||||
|
double r = my_sqrt((x[particle] - node->c_x)*(x[particle] - node->c_x) + (y[particle] - node->c_y)*(y[particle] - node->c_y));
|
||||||
|
double theta = (node->max_x - node->min_x)/r;
|
||||||
|
|
||||||
|
/* If the distance to the node's centre of mass is far enough, calculate the force,
|
||||||
|
* otherwise traverse further down the tree
|
||||||
|
*/
|
||||||
|
if(theta < 0.5){
|
||||||
|
calculate_force(particle, node, r);
|
||||||
|
} else {
|
||||||
|
update_forces_help(particle, &node->children[0]);
|
||||||
|
update_forces_help(particle, &node->children[1]);
|
||||||
|
update_forces_help(particle, &node->children[2]);
|
||||||
|
update_forces_help(particle, &node->children[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates and updates the force of a particle from a node.
|
||||||
|
*/
|
||||||
|
void calculate_force(int particle, struct node_t *node, double r){
|
||||||
|
double temp = -grav*mass[particle]*node->total_mass/((r + epsilon)*(r + epsilon)*(r + epsilon));
|
||||||
|
force_x[particle] += (x[particle] - node->c_x)*temp;
|
||||||
|
force_y[particle] += (y[particle] - node->c_y)*temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main function.
|
||||||
|
*/
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
//The first arguments sets if the graphics should be used
|
||||||
|
// int graphics = 1;
|
||||||
|
// if (argc > 1) {
|
||||||
|
// graphics = atoi(argv[1]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//The second argument sets the number of time steps
|
||||||
|
int time_steps = 3;
|
||||||
|
// if (argc > 2) {
|
||||||
|
// time_steps = atoi(argv[2]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//Initiate memory for the vectors
|
||||||
|
x = (double *)malloc(N*sizeof(double));
|
||||||
|
y = (double *)malloc(N*sizeof(double));
|
||||||
|
u = (double *)malloc(N*sizeof(double));
|
||||||
|
v = (double *)malloc(N*sizeof(double));
|
||||||
|
// -------- Modified by Akilan ----------
|
||||||
|
force_x = (double *)malloc(N*sizeof(double));
|
||||||
|
force_y = (double *)malloc(N*sizeof(double));
|
||||||
|
// --------------------------------------
|
||||||
|
mass = (double *)malloc(N*sizeof(double));
|
||||||
|
|
||||||
|
//Set the initial values
|
||||||
|
// for(int i = 0; i < N; i++) {
|
||||||
|
// mass[i] = 1;
|
||||||
|
// double R = frand(0, L/4);
|
||||||
|
// double theta = frand(0, 2*M_PI);
|
||||||
|
// x[i] = L/2 + R*my_cos(theta);
|
||||||
|
// y[i] = W/2 + alpha*R*my_sin(theta);
|
||||||
|
// double R_prim = my_sqrt(pow(x[i] - L/2, 2) + pow(y[i] - W/2, 2));
|
||||||
|
// u[i] = -V*R_prim*my_sin(theta);
|
||||||
|
// v[i] = V*R_prim*my_cos(theta);
|
||||||
|
// }
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
mass[i] = 1;
|
||||||
|
|
||||||
|
double R = frand(0, L/4);
|
||||||
|
double theta = frand(0, 2*PI);
|
||||||
|
|
||||||
|
double c = my_cos(theta);
|
||||||
|
double s = my_sin(theta);
|
||||||
|
|
||||||
|
x[i] = L/2 + R * c;
|
||||||
|
y[i] = W/2 + alpha * R * s;
|
||||||
|
|
||||||
|
double dx = x[i] - L/2;
|
||||||
|
double dy = y[i] - W/2;
|
||||||
|
|
||||||
|
double R_prim = my_sqrt(dx*dx + dy*dy);
|
||||||
|
|
||||||
|
u[i] = -V * R_prim * s;
|
||||||
|
v[i] = V * R_prim * c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run the GLUT display function if the graphics mode is on.
|
||||||
|
* Otherwise just run the simulations without graphics
|
||||||
|
*/
|
||||||
|
// if (graphics) {
|
||||||
|
// // Initialize the graphics routines
|
||||||
|
// graphicsInit(&argc, argv, display);
|
||||||
|
|
||||||
|
// //Used for the display window
|
||||||
|
// glutMainLoop();
|
||||||
|
// } else {
|
||||||
|
//Begin taking time
|
||||||
|
// long start = clock();
|
||||||
|
|
||||||
|
//The main loop
|
||||||
|
for(int i = 0; i < time_steps; i++) {
|
||||||
|
time_step();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Stop taking time and print elapsed time
|
||||||
|
// long stop = clock();
|
||||||
|
// print_time(start, stop);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//Free memory
|
||||||
|
free(x);
|
||||||
|
free(y);
|
||||||
|
free(u);
|
||||||
|
free(v);
|
||||||
|
free(force_x);
|
||||||
|
free(force_y);
|
||||||
|
free(mass);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
55
Tests/isa/Cprograms/benchmark/barnes/barnes_hut.h
Normal file
55
Tests/isa/Cprograms/benchmark/barnes/barnes_hut.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* File: barnes_hut.h
|
||||||
|
* --------------
|
||||||
|
* Header file for barnes_hut.c
|
||||||
|
* Written by:
|
||||||
|
* Joel Backsell, Kim Torberntsson & Alexander Bilock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Barnes_Hut_barnes_hut_h
|
||||||
|
#define Barnes_Hut_barnes_hut_h
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct that represents a node of the Barnes Hut quad tree.
|
||||||
|
*/
|
||||||
|
struct node_t {
|
||||||
|
int particle;
|
||||||
|
int has_particle;
|
||||||
|
int has_children;
|
||||||
|
double min_x, max_x, min_y, max_y, total_mass, c_x, c_y;
|
||||||
|
struct node_t *children;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Function for producing a random number between two double values.
|
||||||
|
double frand(double xmin, double xmax);
|
||||||
|
|
||||||
|
//Prints the time between two clocks in seconds
|
||||||
|
// void print_time(clock_t s, clock_t e);
|
||||||
|
|
||||||
|
//OpenGL method for displaying the particles
|
||||||
|
// void display(void);
|
||||||
|
|
||||||
|
//Calculates the positions of a time step
|
||||||
|
// void time_step(void);
|
||||||
|
|
||||||
|
//If a particle moves beyond any of the boundaries then bounce it back
|
||||||
|
void bounce(double *x, double *y, double *u, double *v);
|
||||||
|
|
||||||
|
//Functions for handling the placement of particles in the tree
|
||||||
|
void put_particle_in_tree(int new_particle, struct node_t *node);
|
||||||
|
void place_particle(int particle, struct node_t *node);
|
||||||
|
void set_node(struct node_t *node);
|
||||||
|
void free_node(struct node_t *node);
|
||||||
|
void display_tree(struct node_t *node);
|
||||||
|
|
||||||
|
//Functions for calculating the mass and centre of mass of the tree
|
||||||
|
double calculate_mass(struct node_t *node);
|
||||||
|
double calculate_center_of_mass_x(struct node_t *node);
|
||||||
|
double calculate_center_of_mass_y(struct node_t *node);
|
||||||
|
|
||||||
|
//Functions for the force calculations
|
||||||
|
void update_forces();
|
||||||
|
void update_forces_help(int particle, struct node_t *node);
|
||||||
|
void calculate_force(int particle, struct node_t *node, double r);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,27 +8,15 @@
|
|||||||
# scp ../../test.S home-1:/home/akilan/
|
# scp ../../test.S home-1:/home/akilan/
|
||||||
# scp ../../test_macros.h home-1:/home/akilan/
|
# scp ../../test_macros.h home-1:/home/akilan/
|
||||||
# scp ../../malloc.c home-1:/home/akilan/
|
# scp ../../malloc.c home-1:/home/akilan/
|
||||||
# # scp ../../test.c home-1:/home/akilan/
|
# scp ../../test.c home-1:/home/akilan/
|
||||||
|
scp barnes_hut.c home-1:/home/akilan/
|
||||||
|
scp barnes_hut.h home-1:/home/akilan/
|
||||||
# # scp glibc.c home-1:/home/akilan/
|
|
||||||
|
|
||||||
# scp code_io.c home-1:/home/akilan/
|
|
||||||
# scp code.c home-1:/home/akilan/
|
|
||||||
# scp code.h home-1:/home/akilan/
|
|
||||||
# scp defs.h home-1:/home/akilan/
|
|
||||||
# scp getparam.c home-1:/home/akilan/
|
|
||||||
# scp grav.c home-1:/home/akilan/
|
|
||||||
scp load.c home-1:/home/akilan/
|
|
||||||
# scp stdinc.h home-1:/home/akilan/
|
|
||||||
# scp util.c home-1:/home/akilan/
|
|
||||||
# scp vectmath.h home-1:/home/akilan/
|
|
||||||
|
|
||||||
# GCC compile
|
# GCC compile
|
||||||
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
|
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
|
||||||
|
|
||||||
# Clang compile (architecture Regular RISCV)
|
# Clang compile (architecture Regular RISCV)
|
||||||
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -std=gnu89 -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -lm -T link.ld vm.c string.c malloc.c entry.S test.S code_io.c code.c getparam.c grav.c load.c util.c -o testC'
|
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S barnes_hut.c -o testC -lm -lgcc'
|
||||||
|
|
||||||
# Clang using the cheri clang compiler
|
# Clang using the cheri clang compiler
|
||||||
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
|
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
|
||||||
|
|||||||
@@ -1,841 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "code.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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Usage: BARNES <options> < inputfile
|
|
||||||
|
|
||||||
Command line options:
|
|
||||||
|
|
||||||
-h : Print out input file description
|
|
||||||
|
|
||||||
Input parameters should be placed in a file and redirected through
|
|
||||||
standard input. There are a total of twelve parameters, and all of
|
|
||||||
them have default values.
|
|
||||||
|
|
||||||
1) infile (char*) : The name of an input file that contains particle
|
|
||||||
data.
|
|
||||||
|
|
||||||
The format of the file is:
|
|
||||||
a) An int representing the number of particles in the distribution
|
|
||||||
b) An int representing the dimensionality of the problem (3-D)
|
|
||||||
c) A double representing the current time of the simulation
|
|
||||||
d) Doubles representing the masses of all the particles
|
|
||||||
e) A vector (length equal to the dimensionality) of doubles
|
|
||||||
representing the positions of all the particles
|
|
||||||
f) A vector (length equal to the dimensionality) of doubles
|
|
||||||
representing the velocities of all the particles
|
|
||||||
|
|
||||||
Each of these numbers can be separated by any amount of whitespace.
|
|
||||||
2) nbody (int) : If no input file is specified (the first line is
|
|
||||||
blank), this number specifies the number of particles to generate
|
|
||||||
under a plummer model. Default is 16384.
|
|
||||||
3) seed (int) : The seed used by the random number generator.
|
|
||||||
Default is 123.
|
|
||||||
4) outfile (char*) : The name of the file that snapshots will be
|
|
||||||
printed to. This feature has been disabled in the SPLASH release.
|
|
||||||
Default is NULL.
|
|
||||||
5) dtime (double) : The integration time-step.
|
|
||||||
Default is 0.025.
|
|
||||||
6) eps (double) : The usual potential softening
|
|
||||||
Default is 0.05.
|
|
||||||
7) tol (double) : The cell subdivision tolerance.
|
|
||||||
Default is 1.0.
|
|
||||||
8) fcells (double) : Number of cells created = fcells * number of
|
|
||||||
leaves.
|
|
||||||
Default is 2.0.
|
|
||||||
9) fleaves (double) : Number of leaves created = fleaves * nbody.
|
|
||||||
Default is 0.5.
|
|
||||||
10) tstop (double) : The time to stop integration.
|
|
||||||
Default is 0.075.
|
|
||||||
11) dtout (double) : The data-output interval.
|
|
||||||
Default is 0.25.
|
|
||||||
12) NPROC (int) : The number of processors.
|
|
||||||
Default is 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define global /* nada */
|
|
||||||
|
|
||||||
#include "code.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include <math.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "malloc.h"
|
|
||||||
|
|
||||||
// #define malloc MALLOCCHERI
|
|
||||||
// #define free FREECHERI
|
|
||||||
|
|
||||||
|
|
||||||
string defv[] = { /* DEFAULT PARAMETER VALUES */
|
|
||||||
/* file names for input/output */
|
|
||||||
"in=", /* snapshot of initial conditions */
|
|
||||||
"out=", /* stream of output snapshots */
|
|
||||||
|
|
||||||
/* params, used if no input specified, to make a Plummer Model */
|
|
||||||
"nbody=16384", /* number of particles to generate */
|
|
||||||
"seed=123", /* random number generator seed */
|
|
||||||
|
|
||||||
/* params to control N-body integration */
|
|
||||||
"dtime=0.025", /* integration time-step */
|
|
||||||
"eps=0.05", /* usual potential softening */
|
|
||||||
"tol=1.0", /* cell subdivision tolerence */
|
|
||||||
"fcells=2.0", /* cell allocation parameter */
|
|
||||||
"fleaves=0.5", /* leaf allocation parameter */
|
|
||||||
|
|
||||||
"tstop=0.075", /* time to stop integration */
|
|
||||||
"dtout=0.25", /* data-output interval */
|
|
||||||
|
|
||||||
"NPROC=1", /* number of processors */
|
|
||||||
};
|
|
||||||
|
|
||||||
void SlaveStart ();
|
|
||||||
void stepsystem (unsigned int ProcessId);
|
|
||||||
void ComputeForces ();
|
|
||||||
void Help();
|
|
||||||
FILE *fopen();
|
|
||||||
|
|
||||||
void* malloc(size_t);
|
|
||||||
void free(void*);
|
|
||||||
|
|
||||||
main(argc, argv)
|
|
||||||
int argc;
|
|
||||||
string argv[];
|
|
||||||
{
|
|
||||||
|
|
||||||
// INITREGULARALLOC(0);
|
|
||||||
|
|
||||||
unsigned ProcessId = 0;
|
|
||||||
int c;
|
|
||||||
// printf("Run this as\n BARNES < input \n for default values\n");
|
|
||||||
while ((c = getopt(argc, argv, "h")) != -1) {
|
|
||||||
switch(c) {
|
|
||||||
case 'h':
|
|
||||||
Help();
|
|
||||||
exit(-1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// fprintf(stderr, "Only valid option is \"-h\".\n");
|
|
||||||
exit(-1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ANLinit();
|
|
||||||
initparam(argv, defv);
|
|
||||||
startrun();
|
|
||||||
initoutput();
|
|
||||||
tab_init();
|
|
||||||
|
|
||||||
Global->tracktime = 0;
|
|
||||||
Global->partitiontime = 0;
|
|
||||||
Global->treebuildtime = 0;
|
|
||||||
Global->forcecalctime = 0;
|
|
||||||
|
|
||||||
/* Create the slave processes: number of processors less one,
|
|
||||||
since the master will do work as well */
|
|
||||||
Global->current_id = 0;
|
|
||||||
// for(ProcessId = 1; ProcessId < NPROC; ProcessId++) {
|
|
||||||
// {fprintf(stderr, "No more processors -- this is a uniprocessor version!\n"); exit(-1);};
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* Make the master do slave work so we don't waste the processor */
|
|
||||||
{long time(); (Global->computestart) = time(0);};
|
|
||||||
// printf("COMPUTESTART = %12u\n",Global->computestart);
|
|
||||||
SlaveStart();
|
|
||||||
|
|
||||||
{long time(); (Global->computeend) = time(0);};
|
|
||||||
|
|
||||||
{;};
|
|
||||||
|
|
||||||
// printf("COMPUTEEND = %12u\n",Global->computeend);
|
|
||||||
// printf("COMPUTETIME = %12u\n",Global->computeend - Global->computestart);
|
|
||||||
// printf("TRACKTIME = %12u\n",Global->tracktime);
|
|
||||||
// printf("PARTITIONTIME = %12u\t%5.2f\n",Global->partitiontime,
|
|
||||||
// ((float)Global->partitiontime)/Global->tracktime);
|
|
||||||
// printf("TREEBUILDTIME = %12u\t%5.2f\n",Global->treebuildtime,
|
|
||||||
// ((float)Global->treebuildtime)/Global->tracktime);
|
|
||||||
// printf("FORCECALCTIME = %12u\t%5.2f\n",Global->forcecalctime,
|
|
||||||
// ((float)Global->forcecalctime)/Global->tracktime);
|
|
||||||
// printf("RESTTIME = %12u\t%5.2f\n",
|
|
||||||
// Global->tracktime - Global->partitiontime -
|
|
||||||
// Global->treebuildtime - Global->forcecalctime,
|
|
||||||
// ((float)(Global->tracktime-Global->partitiontime-
|
|
||||||
// Global->treebuildtime-Global->forcecalctime))/
|
|
||||||
// Global->tracktime);
|
|
||||||
{exit(0);};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ANLINIT : initialize ANL macros
|
|
||||||
*/
|
|
||||||
ANLinit()
|
|
||||||
{
|
|
||||||
{;};
|
|
||||||
/* Allocate global, shared memory */
|
|
||||||
|
|
||||||
Global = (struct GlobalMemory *) malloc(sizeof(struct GlobalMemory));;
|
|
||||||
if (Global==NULL) error("No initialization for Global\n");
|
|
||||||
|
|
||||||
{;};
|
|
||||||
{;};
|
|
||||||
{;};
|
|
||||||
{;};
|
|
||||||
{;};
|
|
||||||
{;};
|
|
||||||
|
|
||||||
{;};
|
|
||||||
{;};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* INIT_ROOT: Processor 0 reinitialize the global root at each time step
|
|
||||||
*/
|
|
||||||
init_root (ProcessId)
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
Global->G_root=Local[0].ctab;
|
|
||||||
Type(Global->G_root) = CELL;
|
|
||||||
Done(Global->G_root) = FALSE;
|
|
||||||
Level(Global->G_root) = IMAX >> 1;
|
|
||||||
for (i = 0; i < NSUB; i++) {
|
|
||||||
Subp(Global->G_root)[i] = NULL;
|
|
||||||
}
|
|
||||||
Local[0].mynumcell=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Log_base_2(number)
|
|
||||||
int number;
|
|
||||||
{
|
|
||||||
int cumulative;
|
|
||||||
int out;
|
|
||||||
|
|
||||||
cumulative = 1;
|
|
||||||
for (out = 0; out < 20; out++) {
|
|
||||||
if (cumulative == number) {
|
|
||||||
return(out);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cumulative = cumulative * 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fprintf(stderr,"Log_base_2: couldn't find log2 of %d\n", number);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TAB_INIT : allocate body and cell data space
|
|
||||||
*/
|
|
||||||
|
|
||||||
tab_init()
|
|
||||||
{
|
|
||||||
cellptr pc;
|
|
||||||
int i;
|
|
||||||
char *starting_address, *ending_address;
|
|
||||||
|
|
||||||
/*allocate leaf/cell space */
|
|
||||||
maxleaf = (int) ((double) fleaves * nbody);
|
|
||||||
maxcell = fcells * maxleaf;
|
|
||||||
for (i = 0; i < NPROC; ++i) {
|
|
||||||
Local[i].ctab = (cellptr) malloc((maxcell / NPROC) * sizeof(cell));;
|
|
||||||
Local[i].ltab = (leafptr) malloc((maxleaf / NPROC) * sizeof(leaf));;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*allocate space for personal lists of body pointers */
|
|
||||||
maxmybody = (nbody+maxleaf*MAX_BODIES_PER_LEAF)/NPROC;
|
|
||||||
Local[0].mybodytab = (bodyptr*) malloc(NPROC*maxmybody*sizeof(bodyptr));;
|
|
||||||
/* space is allocated so that every */
|
|
||||||
/* process can have a maximum of maxmybody pointers to bodies */
|
|
||||||
/* then there is an array of bodies called bodytab which is */
|
|
||||||
/* allocated in the distribution generation or when the distr. */
|
|
||||||
/* file is read */
|
|
||||||
maxmycell = maxcell / NPROC;
|
|
||||||
maxmyleaf = maxleaf / NPROC;
|
|
||||||
Local[0].mycelltab = (cellptr*) malloc(NPROC*maxmycell*sizeof(cellptr));;
|
|
||||||
Local[0].myleaftab = (leafptr*) malloc(NPROC*maxmyleaf*sizeof(leafptr));;
|
|
||||||
|
|
||||||
CellLock = (struct CellLockType *) malloc(sizeof(struct CellLockType));;
|
|
||||||
{;};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SLAVESTART: main task for each processor
|
|
||||||
*/
|
|
||||||
void SlaveStart()
|
|
||||||
{
|
|
||||||
unsigned int ProcessId;
|
|
||||||
|
|
||||||
/* Get unique ProcessId */
|
|
||||||
{;};
|
|
||||||
ProcessId = Global->current_id++;
|
|
||||||
{;};
|
|
||||||
|
|
||||||
/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to
|
|
||||||
processors to avoid migration */
|
|
||||||
|
|
||||||
/* initialize mybodytabs */
|
|
||||||
Local[ProcessId].mybodytab = Local[0].mybodytab + (maxmybody * ProcessId);
|
|
||||||
/* note that every process has its own copy */
|
|
||||||
/* of mybodytab, which was initialized to the */
|
|
||||||
/* beginning of the whole array by proc. 0 */
|
|
||||||
/* before create */
|
|
||||||
Local[ProcessId].mycelltab = Local[0].mycelltab + (maxmycell * ProcessId);
|
|
||||||
Local[ProcessId].myleaftab = Local[0].myleaftab + (maxmyleaf * ProcessId);
|
|
||||||
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
|
|
||||||
data across physically distributed memories as desired.
|
|
||||||
|
|
||||||
One way to do this is as follows:
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (ProcessId == 0) {
|
|
||||||
for (i=0;i<NPROC;i++) {
|
|
||||||
Place all addresses x such that
|
|
||||||
&(Local[i]) <= x < &(Local[i])+
|
|
||||||
sizeof(struct local_memory) on node i
|
|
||||||
Place all addresses x such that
|
|
||||||
&(Local[i].mybodytab) <= x < &(Local[i].mybodytab)+
|
|
||||||
maxmybody * sizeof(bodyptr) - 1 on node i
|
|
||||||
Place all addresses x such that
|
|
||||||
&(Local[i].mycelltab) <= x < &(Local[i].mycelltab)+
|
|
||||||
maxmycell * sizeof(cellptr) - 1 on node i
|
|
||||||
Place all addresses x such that
|
|
||||||
&(Local[i].myleaftab) <= x < &(Local[i].myleaftab)+
|
|
||||||
maxmyleaf * sizeof(leafptr) - 1 on node i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
barrier(Global->Barstart,NPROC);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
Local[ProcessId].tout = Local[0].tout;
|
|
||||||
Local[ProcessId].tnow = Local[0].tnow;
|
|
||||||
Local[ProcessId].nstep = Local[0].nstep;
|
|
||||||
|
|
||||||
find_my_initial_bodies(bodytab, nbody, ProcessId);
|
|
||||||
|
|
||||||
/* main loop */
|
|
||||||
while (Local[ProcessId].tnow < tstop + 0.1 * dtime) {
|
|
||||||
stepsystem(ProcessId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STARTRUN: startup hierarchical N-body code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
startrun()
|
|
||||||
{
|
|
||||||
string getparam();
|
|
||||||
int getiparam();
|
|
||||||
bool getbparam();
|
|
||||||
double getdparam();
|
|
||||||
int seed;
|
|
||||||
infile = getparam("in");
|
|
||||||
|
|
||||||
if (*infile != NULL) {
|
|
||||||
inputdata();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nbody = getiparam("nbody");
|
|
||||||
if (nbody < 1) {
|
|
||||||
error("startrun: absurd nbody\n");
|
|
||||||
}
|
|
||||||
seed = getiparam("seed");
|
|
||||||
}
|
|
||||||
outfile = getparam("out");
|
|
||||||
dtime = getdparam("dtime");
|
|
||||||
dthf = 0.5 * dtime;
|
|
||||||
eps = getdparam("eps");
|
|
||||||
epssq = eps*eps;
|
|
||||||
tol = getdparam("tol");
|
|
||||||
tolsq = tol*tol;
|
|
||||||
fcells = getdparam("fcells");
|
|
||||||
fleaves = getdparam("fleaves");
|
|
||||||
tstop = getdparam("tstop");
|
|
||||||
dtout = getdparam("dtout");
|
|
||||||
NPROC = getiparam("NPROC");
|
|
||||||
Local[0].nstep = 0;
|
|
||||||
pranset(seed);
|
|
||||||
testdata();
|
|
||||||
setbound();
|
|
||||||
Local[0].tout = Local[0].tnow + dtout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TESTDATA: generate Plummer model initial conditions for test runs,
|
|
||||||
* scaled to units such that M = -4E = G = 1 (Henon, Hegge, etc).
|
|
||||||
* See Aarseth, SJ, Henon, M, & Wielen, R (1974) Astr & Ap, 37, 183.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MFRAC 0.999 /* mass cut off at MFRAC of total */
|
|
||||||
|
|
||||||
testdata()
|
|
||||||
{
|
|
||||||
real rsc, vsc, sqrt(), xrand(), pow(), rsq, r, v, x, y;
|
|
||||||
vector cmr, cmv;
|
|
||||||
register bodyptr p;
|
|
||||||
int rejects = 0;
|
|
||||||
int k;
|
|
||||||
int halfnbody, i;
|
|
||||||
float offset;
|
|
||||||
register bodyptr cp;
|
|
||||||
double tmp;
|
|
||||||
|
|
||||||
headline = "Hack code: Plummer model";
|
|
||||||
Local[0].tnow = 0.0;
|
|
||||||
bodytab = (bodyptr) malloc(nbody * sizeof(body));;
|
|
||||||
if (bodytab == NULL) {
|
|
||||||
error("testdata: not enuf memory\n");
|
|
||||||
}
|
|
||||||
rsc = 9 * PI / 16;
|
|
||||||
vsc = sqrt(1.0 / rsc);
|
|
||||||
|
|
||||||
CLRV(cmr);
|
|
||||||
CLRV(cmv);
|
|
||||||
|
|
||||||
halfnbody = nbody / 2;
|
|
||||||
if (nbody % 2 != 0) halfnbody++;
|
|
||||||
for (p = bodytab; p < bodytab+halfnbody; p++) {
|
|
||||||
Type(p) = BODY;
|
|
||||||
Mass(p) = 1.0 / nbody;
|
|
||||||
Cost(p) = 1;
|
|
||||||
|
|
||||||
r = 1 / sqrt(pow(xrand(0.0, MFRAC), -2.0/3.0) - 1);
|
|
||||||
/* reject radii greater than 10 */
|
|
||||||
while (r > 9.0) {
|
|
||||||
rejects++;
|
|
||||||
r = 1 / sqrt(pow(xrand(0.0, MFRAC), -2.0/3.0) - 1);
|
|
||||||
}
|
|
||||||
pickshell(Pos(p), rsc * r);
|
|
||||||
ADDV(cmr, cmr, Pos(p));
|
|
||||||
do {
|
|
||||||
x = xrand(0.0, 1.0);
|
|
||||||
y = xrand(0.0, 0.1);
|
|
||||||
|
|
||||||
} while (y > x*x * pow(1 - x*x, 3.5));
|
|
||||||
|
|
||||||
v = sqrt(2.0) * x / pow(1 + r*r, 0.25);
|
|
||||||
pickshell(Vel(p), vsc * v);
|
|
||||||
ADDV(cmv, cmv, Vel(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = 4.0;
|
|
||||||
|
|
||||||
for (p = bodytab + halfnbody; p < bodytab+nbody; p++) {
|
|
||||||
Type(p) = BODY;
|
|
||||||
Mass(p) = 1.0 / nbody;
|
|
||||||
Cost(p) = 1;
|
|
||||||
|
|
||||||
cp = p - halfnbody;
|
|
||||||
for (i = 0; i < NDIM; i++){
|
|
||||||
Pos(p)[i] = Pos(cp)[i] + offset;
|
|
||||||
ADDV(cmr, cmr, Pos(p));
|
|
||||||
Vel(p)[i] = Vel(cp)[i];
|
|
||||||
ADDV(cmv, cmv, Vel(p));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DIVVS(cmr, cmr, (real) nbody);
|
|
||||||
DIVVS(cmv, cmv, (real) nbody);
|
|
||||||
|
|
||||||
for (p = bodytab; p < bodytab+nbody; p++) {
|
|
||||||
SUBV(Pos(p), Pos(p), cmr);
|
|
||||||
SUBV(Vel(p), Vel(p), cmv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PICKSHELL: pick a random point on a sphere of specified radius.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pickshell(vec, rad)
|
|
||||||
real vec[]; /* coordinate vector chosen */
|
|
||||||
real rad; /* radius of chosen point */
|
|
||||||
{
|
|
||||||
register int k;
|
|
||||||
double rsq, xrand(), sqrt(), rsc;
|
|
||||||
|
|
||||||
do {
|
|
||||||
for (k = 0; k < NDIM; k++) {
|
|
||||||
vec[k] = xrand(-1.0, 1.0);
|
|
||||||
}
|
|
||||||
DOTVP(rsq, vec, vec);
|
|
||||||
} while (rsq > 1.0);
|
|
||||||
|
|
||||||
rsc = rad / sqrt(rsq);
|
|
||||||
MULVS(vec, vec, rsc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int intpow(i,j)
|
|
||||||
int i,j;
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
int temp = 1;
|
|
||||||
|
|
||||||
for (k = 0; k < j; k++)
|
|
||||||
temp = temp*i;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STEPSYSTEM: advance N-body system one time-step.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
stepsystem (ProcessId)
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
real Cavg;
|
|
||||||
bodyptr p,*pp;
|
|
||||||
vector acc1, dacc, dvel, vel1, dpos;
|
|
||||||
int intpow();
|
|
||||||
unsigned int time;
|
|
||||||
unsigned int trackstart, trackend;
|
|
||||||
unsigned int partitionstart, partitionend;
|
|
||||||
unsigned int treebuildstart, treebuildend;
|
|
||||||
unsigned int forcecalcstart, forcecalcend;
|
|
||||||
|
|
||||||
if (Local[ProcessId].nstep == 2) {
|
|
||||||
/* POSSIBLE ENHANCEMENT: Here is where one might reset the
|
|
||||||
statistics that one is measuring about the parallel execution */
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (trackstart) = time(0);};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ProcessId == 0) {
|
|
||||||
init_root(ProcessId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Local[ProcessId].mynumcell = 0;
|
|
||||||
Local[ProcessId].mynumleaf = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* start at same time */
|
|
||||||
{;};
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (treebuildstart) = time(0);};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load bodies into tree */
|
|
||||||
maketree(ProcessId);
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (treebuildend) = time(0);};
|
|
||||||
Global->treebuildtime += treebuildend - treebuildstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
Housekeep(ProcessId);
|
|
||||||
|
|
||||||
Cavg = (real) Cost(Global->G_root) / (real)NPROC ;
|
|
||||||
Local[ProcessId].workMin = (int) (Cavg * ProcessId);
|
|
||||||
Local[ProcessId].workMax = (int) (Cavg * (ProcessId + 1)
|
|
||||||
+ (ProcessId == (NPROC - 1)));
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (partitionstart) = time(0);};
|
|
||||||
}
|
|
||||||
|
|
||||||
Local[ProcessId].mynbody = 0;
|
|
||||||
find_my_bodies(Global->G_root, 0, BRC_FUC, ProcessId );
|
|
||||||
|
|
||||||
/* B*RRIER(Global->Barcom,NPROC); */
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (partitionend) = time(0);};
|
|
||||||
Global->partitiontime += partitionend - partitionstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (forcecalcstart) = time(0);};
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputeForces(ProcessId);
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (forcecalcend) = time(0);};
|
|
||||||
Global->forcecalctime += forcecalcend - forcecalcstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* advance my bodies */
|
|
||||||
for (pp = Local[ProcessId].mybodytab;
|
|
||||||
pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody; pp++) {
|
|
||||||
p = *pp;
|
|
||||||
MULVS(dvel, Acc(p), dthf);
|
|
||||||
ADDV(vel1, Vel(p), dvel);
|
|
||||||
MULVS(dpos, vel1, dtime);
|
|
||||||
ADDV(Pos(p), Pos(p), dpos);
|
|
||||||
ADDV(Vel(p), vel1, dvel);
|
|
||||||
|
|
||||||
for (i = 0; i < NDIM; i++) {
|
|
||||||
if (Pos(p)[i]<Local[ProcessId].min[i]) {
|
|
||||||
Local[ProcessId].min[i]=Pos(p)[i];
|
|
||||||
}
|
|
||||||
if (Pos(p)[i]>Local[ProcessId].max[i]) {
|
|
||||||
Local[ProcessId].max[i]=Pos(p)[i] ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{;};
|
|
||||||
for (i = 0; i < NDIM; i++) {
|
|
||||||
if (Global->min[i] > Local[ProcessId].min[i]) {
|
|
||||||
Global->min[i] = Local[ProcessId].min[i];
|
|
||||||
}
|
|
||||||
if (Global->max[i] < Local[ProcessId].max[i]) {
|
|
||||||
Global->max[i] = Local[ProcessId].max[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{;};
|
|
||||||
|
|
||||||
/* bar needed to make sure that every process has computed its min */
|
|
||||||
/* and max coordinates, and has accumulated them into the global */
|
|
||||||
/* min and max, before the new dimensions are computed */
|
|
||||||
{;};
|
|
||||||
|
|
||||||
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
|
|
||||||
{long time(); (trackend) = time(0);};
|
|
||||||
Global->tracktime += trackend - trackstart;
|
|
||||||
}
|
|
||||||
if (ProcessId==0) {
|
|
||||||
Global->rsize=0;
|
|
||||||
SUBV(Global->max,Global->max,Global->min);
|
|
||||||
for (i = 0; i < NDIM; i++) {
|
|
||||||
if (Global->rsize < Global->max[i]) {
|
|
||||||
Global->rsize = Global->max[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ADDVS(Global->rmin,Global->min,-Global->rsize/100000.0);
|
|
||||||
Global->rsize = 1.00002*Global->rsize;
|
|
||||||
SETVS(Global->min,1E99);
|
|
||||||
SETVS(Global->max,-1E99);
|
|
||||||
}
|
|
||||||
Local[ProcessId].nstep++;
|
|
||||||
Local[ProcessId].tnow = Local[ProcessId].tnow + dtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ComputeForces (ProcessId)
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
bodyptr p,*pp;
|
|
||||||
vector acc1, dacc, dvel, vel1, dpos;
|
|
||||||
|
|
||||||
for (pp = Local[ProcessId].mybodytab;
|
|
||||||
pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody;pp++) {
|
|
||||||
p = *pp;
|
|
||||||
SETV(acc1, Acc(p));
|
|
||||||
Cost(p)=0;
|
|
||||||
hackgrav(p,ProcessId);
|
|
||||||
Local[ProcessId].myn2bcalc += Local[ProcessId].myn2bterm;
|
|
||||||
Local[ProcessId].mynbccalc += Local[ProcessId].mynbcterm;
|
|
||||||
if (!Local[ProcessId].skipself) { /* did we miss self-int? */
|
|
||||||
Local[ProcessId].myselfint++; /* count another goofup */
|
|
||||||
}
|
|
||||||
if (Local[ProcessId].nstep > 0) {
|
|
||||||
/* use change in accel to make 2nd order correction to vel */
|
|
||||||
SUBV(dacc, Acc(p), acc1);
|
|
||||||
MULVS(dvel, dacc, dthf);
|
|
||||||
ADDV(Vel(p), Vel(p), dvel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIND_MY_INITIAL_BODIES: puts into mybodytab the initial list of bodies
|
|
||||||
* assigned to the processor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
find_my_initial_bodies(btab, nbody, ProcessId)
|
|
||||||
bodyptr btab;
|
|
||||||
int nbody;
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
int Myindex;
|
|
||||||
int intpow();
|
|
||||||
int equalbodies;
|
|
||||||
int extra,offset,i;
|
|
||||||
|
|
||||||
Local[ProcessId].mynbody = nbody / NPROC;
|
|
||||||
extra = nbody % NPROC;
|
|
||||||
if (ProcessId < extra) {
|
|
||||||
Local[ProcessId].mynbody++;
|
|
||||||
offset = Local[ProcessId].mynbody * ProcessId;
|
|
||||||
}
|
|
||||||
if (ProcessId >= extra) {
|
|
||||||
offset = (Local[ProcessId].mynbody+1) * extra + (ProcessId - extra)
|
|
||||||
* Local[ProcessId].mynbody;
|
|
||||||
}
|
|
||||||
for (i=0; i < Local[ProcessId].mynbody; i++) {
|
|
||||||
Local[ProcessId].mybodytab[i] = &(btab[offset+i]);
|
|
||||||
}
|
|
||||||
{;};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
find_my_bodies(mycell, work, direction, ProcessId)
|
|
||||||
nodeptr mycell;
|
|
||||||
int work;
|
|
||||||
int direction;
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
leafptr l;
|
|
||||||
nodeptr qptr;
|
|
||||||
|
|
||||||
if (Type(mycell) == LEAF) {
|
|
||||||
l = (leafptr) mycell;
|
|
||||||
for (i = 0; i < l->num_bodies; i++) {
|
|
||||||
if (work >= Local[ProcessId].workMin - .1) {
|
|
||||||
if((Local[ProcessId].mynbody+2) > maxmybody) {
|
|
||||||
error("find_my_bodies: Processor %d needs more than %d bodies; increase fleaves\n",ProcessId, maxmybody);
|
|
||||||
}
|
|
||||||
Local[ProcessId].mybodytab[Local[ProcessId].mynbody++] =
|
|
||||||
Bodyp(l)[i];
|
|
||||||
}
|
|
||||||
work += Cost(Bodyp(l)[i]);
|
|
||||||
if (work >= Local[ProcessId].workMax-.1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for(i = 0; (i < NSUB) && (work < (Local[ProcessId].workMax - .1)); i++){
|
|
||||||
qptr = Subp(mycell)[Child_Sequence[direction][i]];
|
|
||||||
if (qptr!=NULL) {
|
|
||||||
if ((work+Cost(qptr)) >= (Local[ProcessId].workMin -.1)) {
|
|
||||||
find_my_bodies(qptr,work, Direction_Sequence[direction][i],
|
|
||||||
ProcessId);
|
|
||||||
}
|
|
||||||
work += Cost(qptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HOUSEKEEP: reinitialize the different variables (in particular global
|
|
||||||
* variables) between each time step.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Housekeep(ProcessId)
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
Local[ProcessId].myn2bcalc = Local[ProcessId].mynbccalc
|
|
||||||
= Local[ProcessId].myselfint = 0;
|
|
||||||
SETVS(Local[ProcessId].min,1E99);
|
|
||||||
SETVS(Local[ProcessId].max,-1E99);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SETBOUND: Compute the initial size of the root of the tree; only done
|
|
||||||
* before first time step, and only processor 0 does it
|
|
||||||
*/
|
|
||||||
setbound()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
real side ;
|
|
||||||
bodyptr p;
|
|
||||||
|
|
||||||
SETVS(Local[0].min,1E99);
|
|
||||||
SETVS(Local[0].max,-1E99);
|
|
||||||
side=0;
|
|
||||||
|
|
||||||
for (p = bodytab; p < bodytab+nbody; p++) {
|
|
||||||
for (i=0; i<NDIM;i++) {
|
|
||||||
if (Pos(p)[i]<Local[0].min[i]) Local[0].min[i]=Pos(p)[i] ;
|
|
||||||
if (Pos(p)[i]>Local[0].max[i]) Local[0].max[i]=Pos(p)[i] ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBV(Local[0].max,Local[0].max,Local[0].min);
|
|
||||||
for (i=0; i<NDIM;i++) if (side<Local[0].max[i]) side=Local[0].max[i];
|
|
||||||
ADDVS(Global->rmin,Local[0].min,-side/100000.0);
|
|
||||||
Global->rsize = 1.00002*side;
|
|
||||||
SETVS(Global->max,-1E99);
|
|
||||||
SETVS(Global->min,1E99);
|
|
||||||
}
|
|
||||||
|
|
||||||
// void
|
|
||||||
// Help ()
|
|
||||||
// {
|
|
||||||
// printf("There are a total of twelve parameters, and all of them have default values.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("1) infile (char*) : The name of an input file that contains particle data. \n");
|
|
||||||
// printf(" The format of the file is:\n");
|
|
||||||
// printf("\ta) An int representing the number of particles in the distribution\n");
|
|
||||||
// printf("\tb) An int representing the dimensionality of the problem (3-D)\n");
|
|
||||||
// printf("\tc) A double representing the current time of the simulation\n");
|
|
||||||
// printf("\td) Doubles representing the masses of all the particles\n");
|
|
||||||
// printf("\te) A vector (length equal to the dimensionality) of doubles\n");
|
|
||||||
// printf("\t representing the positions of all the particles\n");
|
|
||||||
// printf("\tf) A vector (length equal to the dimensionality) of doubles\n");
|
|
||||||
// printf("\t representing the velocities of all the particles\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf(" Each of these numbers can be separated by any amount of whitespace.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("2) nbody (int) : If no input file is specified (the first line is blank), this\n");
|
|
||||||
// printf(" number specifies the number of particles to generate under a plummer model.\n");
|
|
||||||
// printf(" Default is 16384.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("3) seed (int) : The seed used by the random number generator.\n");
|
|
||||||
// printf(" Default is 123.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("4) outfile (char*) : The name of the file that snapshots will be printed to. \n");
|
|
||||||
// printf(" This feature has been disabled in the SPLASH release.\n");
|
|
||||||
// printf(" Default is NULL.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("5) dtime (double) : The integration time-step.\n");
|
|
||||||
// printf(" Default is 0.025.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("6) eps (double) : The usual potential softening\n");
|
|
||||||
// printf(" Default is 0.05.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("7) tol (double) : The cell subdivision tolerance.\n");
|
|
||||||
// printf(" Default is 1.0.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("8) fcells (double) : The total number of cells created is equal to \n");
|
|
||||||
// printf(" fcells * number of leaves.\n");
|
|
||||||
// printf(" Default is 2.0.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("9) fleaves (double) : The total number of leaves created is equal to \n");
|
|
||||||
// printf(" fleaves * nbody.\n");
|
|
||||||
// printf(" Default is 0.5.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("10) tstop (double) : The time to stop integration.\n");
|
|
||||||
// printf(" Default is 0.075.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("11) dtout (double) : The data-output interval.\n");
|
|
||||||
// printf(" Default is 0.25.\n");
|
|
||||||
// printf("\n");
|
|
||||||
// printf("12) NPROC (int) : The number of processors.\n");
|
|
||||||
// printf(" Default is 1.\n");
|
|
||||||
// }
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "code.H"
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* 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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CODE.H: define various global things for CODE.C.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _CODE_H_
|
|
||||||
#define _CODE_H_
|
|
||||||
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define PAD_SIZE (PAGE_SIZE / (sizeof(int)))
|
|
||||||
|
|
||||||
/* Defined by the input file */
|
|
||||||
global string headline; /* message describing calculation */
|
|
||||||
global string infile; /* file name for snapshot input */
|
|
||||||
global string outfile; /* file name for snapshot output */
|
|
||||||
global real dtime; /* timestep for leapfrog integrator */
|
|
||||||
global real dtout; /* time between data outputs */
|
|
||||||
global real tstop; /* time to stop calculation */
|
|
||||||
global int nbody; /* number of bodies in system */
|
|
||||||
global real fcells; /* ratio of cells/leaves allocated */
|
|
||||||
global real fleaves; /* ratio of leaves/bodies allocated */
|
|
||||||
global real tol; /* accuracy parameter: 0.0 => exact */
|
|
||||||
global real tolsq; /* square of previous */
|
|
||||||
global real eps; /* potential softening parameter */
|
|
||||||
global real epssq; /* square of previous */
|
|
||||||
global real dthf; /* half time step */
|
|
||||||
global int NPROC; /* Number of Processors */
|
|
||||||
|
|
||||||
global int maxcell; /* max number of cells allocated */
|
|
||||||
global int maxleaf; /* max number of leaves allocated */
|
|
||||||
global int maxmybody; /* max no. of bodies allocated per processor */
|
|
||||||
global int maxmycell; /* max num. of cells to be allocated */
|
|
||||||
global int maxmyleaf; /* max num. of leaves to be allocated */
|
|
||||||
global bodyptr bodytab; /* array size is exactly nbody bodies */
|
|
||||||
|
|
||||||
global struct CellLockType {
|
|
||||||
int (CL); /* locks on the cells*/
|
|
||||||
} *CellLock;
|
|
||||||
|
|
||||||
struct GlobalMemory { /* all this info is for the whole system */
|
|
||||||
int n2bcalc; /* total number of body/cell interactions */
|
|
||||||
int nbccalc; /* total number of body/body interactions */
|
|
||||||
int selfint; /* number of self interactions */
|
|
||||||
real mtot; /* total mass of N-body system */
|
|
||||||
real etot[3]; /* binding, kinetic, potential energy */
|
|
||||||
matrix keten; /* kinetic energy tensor */
|
|
||||||
matrix peten; /* potential energy tensor */
|
|
||||||
vector cmphase[2]; /* center of mass coordinates and velocity */
|
|
||||||
vector amvec; /* angular momentum vector */
|
|
||||||
cellptr G_root; /* root of the whole tree */
|
|
||||||
vector rmin; /* lower-left corner of coordinate box */
|
|
||||||
vector min; /* temporary lower-left corner of the box */
|
|
||||||
vector max; /* temporary upper right corner of the box */
|
|
||||||
real rsize; /* side-length of integer coordinate box */
|
|
||||||
int (Barstart); /* barrier at the beginning of stepsystem */
|
|
||||||
int (Bartree); /* barrier after loading the tree */
|
|
||||||
int (Barcom); /* barrier after computing the c. of m. */
|
|
||||||
int (Barload);
|
|
||||||
int (Baraccel); /* barrier after accel and before output */
|
|
||||||
int (Barpos); /* barrier after computing the new pos */
|
|
||||||
int (CountLock); /* Lock on the shared variables */
|
|
||||||
int (NcellLock); /* Lock on the counter of array of cells for loadtree */
|
|
||||||
int (NleafLock);/* Lock on the counter of array of leaves for loadtree */
|
|
||||||
int (io_lock);
|
|
||||||
unsigned int createstart,createend,computestart,computeend;
|
|
||||||
unsigned int trackstart, trackend, tracktime;
|
|
||||||
unsigned int partitionstart, partitionend, partitiontime;
|
|
||||||
unsigned int treebuildstart, treebuildend, treebuildtime;
|
|
||||||
unsigned int forcecalcstart, forcecalcend, forcecalctime;
|
|
||||||
unsigned int current_id;
|
|
||||||
volatile int k; /*for memory allocation in code.C */
|
|
||||||
};
|
|
||||||
global struct GlobalMemory *Global;
|
|
||||||
|
|
||||||
/* This structure is needed because under the sproc model there is no
|
|
||||||
* per processor private address space.
|
|
||||||
*/
|
|
||||||
struct local_memory {
|
|
||||||
/* Use padding so that each processor's variables are on their own page */
|
|
||||||
int pad_begin[PAD_SIZE];
|
|
||||||
|
|
||||||
real tnow; /* current value of simulation time */
|
|
||||||
real tout; /* time next output is due */
|
|
||||||
int nstep; /* number of integration steps so far */
|
|
||||||
|
|
||||||
int workMin, workMax;/* interval of cost to be treated by a proc */
|
|
||||||
|
|
||||||
vector min, max; /* min and max of coordinates for each Proc. */
|
|
||||||
|
|
||||||
int mynumcell; /* num. of cells used for this proc in ctab */
|
|
||||||
int mynumleaf; /* num. of leaves used for this proc in ctab */
|
|
||||||
int mynbody; /* num bodies allocated to the processor */
|
|
||||||
bodyptr* mybodytab; /* array of bodies allocated / processor */
|
|
||||||
int myncell; /* num cells allocated to the processor */
|
|
||||||
cellptr* mycelltab; /* array of cellptrs allocated to the processor */
|
|
||||||
int mynleaf; /* number of leaves allocated to the processor */
|
|
||||||
leafptr* myleaftab; /* array of leafptrs allocated to the processor */
|
|
||||||
cellptr ctab; /* array of cells used for the tree. */
|
|
||||||
leafptr ltab; /* array of cells used for the tree. */
|
|
||||||
|
|
||||||
int myn2bcalc; /* body-body force calculations for each processor */
|
|
||||||
int mynbccalc; /* body-cell force calculations for each processor */
|
|
||||||
int myselfint; /* count self-interactions for each processor */
|
|
||||||
int myn2bterm; /* count body-body terms for a body */
|
|
||||||
int mynbcterm; /* count body-cell terms for a body */
|
|
||||||
bool skipself; /* true if self-interaction skipped OK */
|
|
||||||
bodyptr pskip; /* body to skip in force evaluation */
|
|
||||||
vector pos0; /* point at which to evaluate field */
|
|
||||||
real phi0; /* computed potential at pos0 */
|
|
||||||
vector acc0; /* computed acceleration at pos0 */
|
|
||||||
vector dr; /* data to be shared */
|
|
||||||
real drsq; /* between gravsub and subdivp */
|
|
||||||
nodeptr pmem; /* remember particle data */
|
|
||||||
|
|
||||||
nodeptr Current_Root;
|
|
||||||
int Root_Coords[NDIM];
|
|
||||||
|
|
||||||
real mymtot; /* total mass of N-body system */
|
|
||||||
real myetot[3]; /* binding, kinetic, potential energy */
|
|
||||||
matrix myketen; /* kinetic energy tensor */
|
|
||||||
matrix mypeten; /* potential energy tensor */
|
|
||||||
vector mycmphase[2]; /* center of mass coordinates */
|
|
||||||
vector myamvec; /* angular momentum vector */
|
|
||||||
|
|
||||||
int pad_end[PAD_SIZE];
|
|
||||||
};
|
|
||||||
global struct local_memory Local[MAX_PROC];
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "code_io.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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CODE_IO.C:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define global extern
|
|
||||||
|
|
||||||
#include "code.h"
|
|
||||||
|
|
||||||
void* malloc(size_t);
|
|
||||||
void free(void*);
|
|
||||||
|
|
||||||
void in_int (), in_real (), in_vector ();
|
|
||||||
void out_int (), out_real (), out_vector ();
|
|
||||||
void diagnostics (unsigned int ProcessId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* INPUTDATA: read initial conditions from input file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
inputdata ()
|
|
||||||
{
|
|
||||||
stream instr;
|
|
||||||
permanent char headbuf[128];
|
|
||||||
int ndim,counter=0;
|
|
||||||
real tnow;
|
|
||||||
bodyptr p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// fprintf(stderr,"reading input file : %s\n",infile);
|
|
||||||
fflush(stderr);
|
|
||||||
instr = fopen(infile, "r");
|
|
||||||
if (instr == NULL)
|
|
||||||
error("inputdata: cannot find file %s\n", infile);
|
|
||||||
// sprintf(headbuf, "Hack code: input file %s\n", infile);
|
|
||||||
headline = headbuf;
|
|
||||||
in_int(instr, &nbody);
|
|
||||||
if (nbody < 1)
|
|
||||||
error("inputdata: nbody = %d is absurd\n", nbody);
|
|
||||||
in_int(instr, &ndim);
|
|
||||||
if (ndim != NDIM)
|
|
||||||
error("inputdata: NDIM = %d ndim = %d is absurd\n", NDIM,ndim);
|
|
||||||
in_real(instr, &tnow);
|
|
||||||
for (i = 0; i < MAX_PROC; i++) {
|
|
||||||
Local[i].tnow = tnow;
|
|
||||||
}
|
|
||||||
bodytab = (bodyptr) malloc(nbody * sizeof(body));;
|
|
||||||
if (bodytab == NULL)
|
|
||||||
error("inputdata: not enuf memory\n");
|
|
||||||
for (p = bodytab; p < bodytab+nbody; p++) {
|
|
||||||
Type(p) = BODY;
|
|
||||||
Cost(p) = 1;
|
|
||||||
Phi(p) = 0.0;
|
|
||||||
CLRV(Acc(p));
|
|
||||||
}
|
|
||||||
for (p = bodytab; p < bodytab+nbody; p++)
|
|
||||||
in_real(instr, &Mass(p));
|
|
||||||
for (p = bodytab; p < bodytab+nbody; p++)
|
|
||||||
in_vector(instr, Pos(p));
|
|
||||||
for (p = bodytab; p < bodytab+nbody; p++)
|
|
||||||
in_vector(instr, Vel(p));
|
|
||||||
fclose(instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* INITOUTPUT: initialize output routines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// initoutput()
|
|
||||||
// {
|
|
||||||
// printf("\n\t\t%s\n\n", headline);
|
|
||||||
// printf("%10s%10s%10s%10s%10s%10s%10s%10s\n",
|
|
||||||
// "nbody", "dtime", "eps", "tol", "dtout", "tstop","fcells","NPROC");
|
|
||||||
// printf("%10d%10.5f%10.4f%10.2f%10.3f%10.3f%10.2f%10d\n\n",
|
|
||||||
// nbody, dtime, eps, tol, dtout, tstop, fcells, NPROC);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STOPOUTPUT: finish up after a run.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OUTPUT: compute diagnostics and output data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
output (ProcessId)
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
int nttot, nbavg, ncavg,k;
|
|
||||||
double cputime();
|
|
||||||
bodyptr p, *pp;
|
|
||||||
vector tempv1,tempv2;
|
|
||||||
|
|
||||||
if ((Local[ProcessId].tout - 0.01 * dtime) <= Local[ProcessId].tnow) {
|
|
||||||
Local[ProcessId].tout += dtout;
|
|
||||||
}
|
|
||||||
|
|
||||||
diagnostics(ProcessId);
|
|
||||||
|
|
||||||
if (Local[ProcessId].mymtot!=0) {
|
|
||||||
{;};
|
|
||||||
Global->n2bcalc += Local[ProcessId].myn2bcalc;
|
|
||||||
Global->nbccalc += Local[ProcessId].mynbccalc;
|
|
||||||
Global->selfint += Local[ProcessId].myselfint;
|
|
||||||
ADDM(Global->keten, Global-> keten, Local[ProcessId].myketen);
|
|
||||||
ADDM(Global->peten, Global-> peten, Local[ProcessId].mypeten);
|
|
||||||
for (k=0;k<3;k++) Global->etot[k] += Local[ProcessId].myetot[k];
|
|
||||||
ADDV(Global->amvec, Global-> amvec, Local[ProcessId].myamvec);
|
|
||||||
|
|
||||||
MULVS(tempv1, Global->cmphase[0],Global->mtot);
|
|
||||||
MULVS(tempv2, Local[ProcessId].mycmphase[0], Local[ProcessId].mymtot);
|
|
||||||
ADDV(tempv1, tempv1, tempv2);
|
|
||||||
DIVVS(Global->cmphase[0], tempv1, Global->mtot+Local[ProcessId].mymtot);
|
|
||||||
|
|
||||||
MULVS(tempv1, Global->cmphase[1],Global->mtot);
|
|
||||||
MULVS(tempv2, Local[ProcessId].mycmphase[1], Local[ProcessId].mymtot);
|
|
||||||
ADDV(tempv1, tempv1, tempv2);
|
|
||||||
DIVVS(Global->cmphase[1], tempv1, Global->mtot+Local[ProcessId].mymtot);
|
|
||||||
Global->mtot +=Local[ProcessId].mymtot;
|
|
||||||
{;};
|
|
||||||
}
|
|
||||||
|
|
||||||
{;};
|
|
||||||
|
|
||||||
if (ProcessId==0) {
|
|
||||||
nttot = Global->n2bcalc + Global->nbccalc;
|
|
||||||
nbavg = (int) ((real) Global->n2bcalc / (real) nbody);
|
|
||||||
ncavg = (int) ((real) Global->nbccalc / (real) nbody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DIAGNOSTICS: compute set of dynamical diagnostics.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
diagnostics (ProcessId)
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
register bodyptr p,*pp;
|
|
||||||
real velsq;
|
|
||||||
vector tmpv;
|
|
||||||
matrix tmpt;
|
|
||||||
|
|
||||||
Local[ProcessId].mymtot = 0.0;
|
|
||||||
Local[ProcessId].myetot[1] = Local[ProcessId].myetot[2] = 0.0;
|
|
||||||
CLRM(Local[ProcessId].myketen);
|
|
||||||
CLRM(Local[ProcessId].mypeten);
|
|
||||||
CLRV(Local[ProcessId].mycmphase[0]);
|
|
||||||
CLRV(Local[ProcessId].mycmphase[1]);
|
|
||||||
CLRV(Local[ProcessId].myamvec);
|
|
||||||
for (pp = Local[ProcessId].mybodytab+Local[ProcessId].mynbody -1;
|
|
||||||
pp >= Local[ProcessId].mybodytab; pp--) {
|
|
||||||
p= *pp;
|
|
||||||
Local[ProcessId].mymtot += Mass(p);
|
|
||||||
DOTVP(velsq, Vel(p), Vel(p));
|
|
||||||
Local[ProcessId].myetot[1] += 0.5 * Mass(p) * velsq;
|
|
||||||
Local[ProcessId].myetot[2] += 0.5 * Mass(p) * Phi(p);
|
|
||||||
MULVS(tmpv, Vel(p), 0.5 * Mass(p));
|
|
||||||
OUTVP(tmpt, tmpv, Vel(p));
|
|
||||||
ADDM(Local[ProcessId].myketen, Local[ProcessId].myketen, tmpt);
|
|
||||||
MULVS(tmpv, Pos(p), Mass(p));
|
|
||||||
OUTVP(tmpt, tmpv, Acc(p));
|
|
||||||
ADDM(Local[ProcessId].mypeten, Local[ProcessId].mypeten, tmpt);
|
|
||||||
MULVS(tmpv, Pos(p), Mass(p));
|
|
||||||
ADDV(Local[ProcessId].mycmphase[0], Local[ProcessId].mycmphase[0], tmpv);
|
|
||||||
MULVS(tmpv, Vel(p), Mass(p));
|
|
||||||
ADDV(Local[ProcessId].mycmphase[1], Local[ProcessId].mycmphase[1], tmpv);
|
|
||||||
CROSSVP(tmpv, Pos(p), Vel(p));
|
|
||||||
MULVS(tmpv, tmpv, Mass(p));
|
|
||||||
ADDV(Local[ProcessId].myamvec, Local[ProcessId].myamvec, tmpv);
|
|
||||||
}
|
|
||||||
Local[ProcessId].myetot[0] = Local[ProcessId].myetot[1]
|
|
||||||
+ Local[ProcessId].myetot[2];
|
|
||||||
if (Local[ProcessId].mymtot!=0){
|
|
||||||
DIVVS(Local[ProcessId].mycmphase[0], Local[ProcessId].mycmphase[0],
|
|
||||||
Local[ProcessId].mymtot);
|
|
||||||
DIVVS(Local[ProcessId].mycmphase[1], Local[ProcessId].mycmphase[1],
|
|
||||||
Local[ProcessId].mymtot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Low-level input and output operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void in_int(str, iptr)
|
|
||||||
stream str;
|
|
||||||
int *iptr;
|
|
||||||
{
|
|
||||||
if (fscanf(str, "%d", iptr) != 1)
|
|
||||||
error("in_int: input conversion error\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void in_real(str, rptr)
|
|
||||||
stream str;
|
|
||||||
real *rptr;
|
|
||||||
{
|
|
||||||
double tmp;
|
|
||||||
|
|
||||||
if (fscanf(str, "%lf", &tmp) != 1)
|
|
||||||
error("in_real: input conversion error\n");
|
|
||||||
*rptr = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void in_vector(str, vec)
|
|
||||||
stream str;
|
|
||||||
vector vec;
|
|
||||||
{
|
|
||||||
double tmpx, tmpy, tmpz;
|
|
||||||
|
|
||||||
if (fscanf(str, "%lf%lf%lf", &tmpx, &tmpy, &tmpz) != 3)
|
|
||||||
error("in_vector: input conversion error\n");
|
|
||||||
vec[0] = tmpx; vec[1] = tmpy; vec[2] = tmpz;
|
|
||||||
}
|
|
||||||
|
|
||||||
// void out_int(str, ival)
|
|
||||||
// stream str;
|
|
||||||
// int ival;
|
|
||||||
// {
|
|
||||||
// fprintf(str, " %d\n", ival);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void out_real(str, rval)
|
|
||||||
// stream str;
|
|
||||||
// real rval;
|
|
||||||
// {
|
|
||||||
// fprintf(str, " %21.14E\n", rval);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void out_vector(str, vec)
|
|
||||||
// stream str;
|
|
||||||
// vector vec;
|
|
||||||
// {
|
|
||||||
// fprintf(str, " %21.14E %21.14E", vec[0], vec[1]);
|
|
||||||
// fprintf(str, " %21.14E\n",vec[2]);
|
|
||||||
// }
|
|
||||||
@@ -1,317 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "defs.H"
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* 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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _DEFS_H_
|
|
||||||
#define _DEFS_H_
|
|
||||||
|
|
||||||
#include "stdinc.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
//#include <ulocks.h>
|
|
||||||
|
|
||||||
#include "vectmath.h"
|
|
||||||
|
|
||||||
#define MAX_PROC 128
|
|
||||||
#define MAX_BODIES_PER_LEAF 10
|
|
||||||
#define MAXLOCK 2048 /* maximum number of locks on DASH */
|
|
||||||
#define PAGE_SIZE 4096 /* in bytes */
|
|
||||||
|
|
||||||
#define NSUB (1 << NDIM) /* subcells per cell */
|
|
||||||
|
|
||||||
/* The more complicated 3D case */
|
|
||||||
#define NUM_DIRECTIONS 32
|
|
||||||
#define BRC_FUC 0
|
|
||||||
#define BRC_FRA 1
|
|
||||||
#define BRA_FDA 2
|
|
||||||
#define BRA_FRC 3
|
|
||||||
#define BLC_FDC 4
|
|
||||||
#define BLC_FLA 5
|
|
||||||
#define BLA_FUA 6
|
|
||||||
#define BLA_FLC 7
|
|
||||||
#define BUC_FUA 8
|
|
||||||
#define BUC_FLC 9
|
|
||||||
#define BUA_FUC 10
|
|
||||||
#define BUA_FRA 11
|
|
||||||
#define BDC_FDA 12
|
|
||||||
#define BDC_FRC 13
|
|
||||||
#define BDA_FDC 14
|
|
||||||
#define BDA_FLA 15
|
|
||||||
|
|
||||||
#define FRC_BUC 16
|
|
||||||
#define FRC_BRA 17
|
|
||||||
#define FRA_BDA 18
|
|
||||||
#define FRA_BRC 19
|
|
||||||
#define FLC_BDC 20
|
|
||||||
#define FLC_BLA 21
|
|
||||||
#define FLA_BUA 22
|
|
||||||
#define FLA_BLC 23
|
|
||||||
#define FUC_BUA 24
|
|
||||||
#define FUC_BLC 25
|
|
||||||
#define FUA_BUC 26
|
|
||||||
#define FUA_BRA 27
|
|
||||||
#define FDC_BDA 28
|
|
||||||
#define FDC_BRC 29
|
|
||||||
#define FDA_BDC 30
|
|
||||||
#define FDA_BLA 31
|
|
||||||
|
|
||||||
static int Child_Sequence[NUM_DIRECTIONS][NSUB] =
|
|
||||||
{
|
|
||||||
{ 2, 5, 6, 1, 0, 3, 4, 7}, /* BRC_FUC */
|
|
||||||
{ 2, 5, 6, 1, 0, 7, 4, 3}, /* BRC_FRA */
|
|
||||||
{ 1, 6, 5, 2, 3, 0, 7, 4}, /* BRA_FDA */
|
|
||||||
{ 1, 6, 5, 2, 3, 4, 7, 0}, /* BRA_FRC */
|
|
||||||
{ 6, 1, 2, 5, 4, 7, 0, 3}, /* BLC_FDC */
|
|
||||||
{ 6, 1, 2, 5, 4, 3, 0, 7}, /* BLC_FLA */
|
|
||||||
{ 5, 2, 1, 6, 7, 4, 3, 0}, /* BLA_FUA */
|
|
||||||
{ 5, 2, 1, 6, 7, 0, 3, 4}, /* BLA_FLC */
|
|
||||||
{ 1, 2, 5, 6, 7, 4, 3, 0}, /* BUC_FUA */
|
|
||||||
{ 1, 2, 5, 6, 7, 0, 3, 4}, /* BUC_FLC */
|
|
||||||
{ 6, 5, 2, 1, 0, 3, 4, 7}, /* BUA_FUC */
|
|
||||||
{ 6, 5, 2, 1, 0, 7, 4, 3}, /* BUA_FRA */
|
|
||||||
{ 5, 6, 1, 2, 3, 0, 7, 4}, /* BDC_FDA */
|
|
||||||
{ 5, 6, 1, 2, 3, 4, 7, 0}, /* BDC_FRC */
|
|
||||||
{ 2, 1, 6, 5, 4, 7, 0, 3}, /* BDA_FDC */
|
|
||||||
{ 2, 1, 6, 5, 4, 3, 0, 7}, /* BDA_FLA */
|
|
||||||
|
|
||||||
{ 3, 4, 7, 0, 1, 2, 5, 6}, /* FRC_BUC */
|
|
||||||
{ 3, 4, 7, 0, 1, 6, 5, 2}, /* FRC_BRA */
|
|
||||||
{ 0, 7, 4, 3, 2, 1, 6, 5}, /* FRA_BDA */
|
|
||||||
{ 0, 7, 4, 3, 2, 5, 6, 1}, /* FRA_BRC */
|
|
||||||
{ 7, 0, 3, 4, 5, 6, 1, 2}, /* FLC_BDC */
|
|
||||||
{ 7, 0, 3, 4, 5, 2, 1, 6}, /* FLC_BLA */
|
|
||||||
{ 4, 3, 0, 7, 6, 5, 2, 1}, /* FLA_BUA */
|
|
||||||
{ 4, 3, 0, 7, 6, 1, 2, 5}, /* FLA_BLC */
|
|
||||||
{ 0, 3, 4, 7, 6, 5, 2, 1}, /* FUC_BUA */
|
|
||||||
{ 0, 3, 4, 7, 6, 1, 2, 5}, /* FUC_BLC */
|
|
||||||
{ 7, 4, 3, 0, 1, 2, 5, 6}, /* FUA_BUC */
|
|
||||||
{ 7, 4, 3, 0, 1, 6, 5, 2}, /* FUA_BRA */
|
|
||||||
{ 4, 7, 0, 3, 2, 1, 6, 5}, /* FDC_BDA */
|
|
||||||
{ 4, 7, 0, 3, 2, 5, 6, 1}, /* FDC_BRC */
|
|
||||||
{ 3, 0, 7, 4, 5, 6, 1, 2}, /* FDA_BDC */
|
|
||||||
{ 3, 0, 7, 4, 5, 2, 1, 6}, /* FDA_BLA */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int Direction_Sequence[NUM_DIRECTIONS][NSUB] =
|
|
||||||
{
|
|
||||||
{ FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
|
|
||||||
/* BRC_FUC */
|
|
||||||
{ FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA, BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC },
|
|
||||||
/* BRC_FRA */
|
|
||||||
{ FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC, BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC },
|
|
||||||
/* BRA_FDA */
|
|
||||||
{ FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
|
|
||||||
/* BRA_FRC */
|
|
||||||
{ FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA, BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA },
|
|
||||||
/* BLC_FDC */
|
|
||||||
{ FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA, BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC },
|
|
||||||
/* BLC_FLA */
|
|
||||||
{ FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC, BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC },
|
|
||||||
/* BLA_FUA */
|
|
||||||
{ FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC, BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA },
|
|
||||||
/* BLA_FLC */
|
|
||||||
{ FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA, BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC },
|
|
||||||
/* BUC_FUA */
|
|
||||||
{ FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA, BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA },
|
|
||||||
/* BUC_FLC */
|
|
||||||
{ FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
|
|
||||||
/* BUA_FUC */
|
|
||||||
{ FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC, BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC },
|
|
||||||
/* BUA_FRA */
|
|
||||||
{ FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA, BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC },
|
|
||||||
/* BDC_FDA */
|
|
||||||
{ FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
|
|
||||||
/* BDC_FRC */
|
|
||||||
{ FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC, BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA },
|
|
||||||
/* BDA_FDC */
|
|
||||||
{ FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC, BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC },
|
|
||||||
/* BDA_FLA */
|
|
||||||
|
|
||||||
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA },
|
|
||||||
/* FRC_BUC */
|
|
||||||
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC },
|
|
||||||
/* FRC_BRA */
|
|
||||||
{ BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC, FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC },
|
|
||||||
/* FRA_BDA */
|
|
||||||
{ BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC, FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA },
|
|
||||||
/* FRA_BRC */
|
|
||||||
{ BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA, FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA },
|
|
||||||
/* FLC_BDC */
|
|
||||||
{ BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA, FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC },
|
|
||||||
/* FLC_BLA */
|
|
||||||
{ BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC, FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC },
|
|
||||||
/* FLA_BUA */
|
|
||||||
{ BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC, FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA },
|
|
||||||
/* FLA_BLC */
|
|
||||||
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC },
|
|
||||||
/* FUC_BUA */
|
|
||||||
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA },
|
|
||||||
/* FUC_BLC */
|
|
||||||
{ BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC, FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA },
|
|
||||||
/* FUA_BUC */
|
|
||||||
{ BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC, FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC },
|
|
||||||
/* FUA_BRA */
|
|
||||||
{ BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA, FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC },
|
|
||||||
/* FDC_BDA */
|
|
||||||
{ BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA, FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA },
|
|
||||||
/* FDC_BRC */
|
|
||||||
{ BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC, FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA },
|
|
||||||
/* FDA_BDC */
|
|
||||||
{ BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC, FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC },
|
|
||||||
/* FDA_BLA */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BODY and CELL data structures are used to represent the tree:
|
|
||||||
*
|
|
||||||
* +-----------------------------------------------------------+
|
|
||||||
* root--> | CELL: mass, pos, cost, quad, /, o, /, /, /, /, o, /, done |
|
|
||||||
* +---------------------------------|--------------|----------+
|
|
||||||
* | |
|
|
||||||
* +--------------------------------------+ |
|
|
||||||
* | |
|
|
||||||
* | +--------------------------------------+ |
|
|
||||||
* +--> | BODY: mass, pos, cost, vel, acc, phi | |
|
|
||||||
* +--------------------------------------+ |
|
|
||||||
* |
|
|
||||||
* +-----------------------------------------------------+
|
|
||||||
* |
|
|
||||||
* | +-----------------------------------------------------------+
|
|
||||||
* +--> | CELL: mass, pos, cost, quad, o, /, /, o, /, /, o, /, done |
|
|
||||||
* +------------------------------|--------|--------|----------+
|
|
||||||
* etc etc etc
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NODE: data common to BODY and CELL structures.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _node {
|
|
||||||
short type; /* code for node type: body or cell */
|
|
||||||
real mass; /* total mass of node */
|
|
||||||
vector pos; /* position of node */
|
|
||||||
int cost; /* number of interactions computed */
|
|
||||||
int level;
|
|
||||||
struct _node *parent; /* ptr to parent of this node in tree */
|
|
||||||
int child_num; /* Index that this node should be put
|
|
||||||
at in parent cell */
|
|
||||||
} node;
|
|
||||||
|
|
||||||
typedef node* nodeptr;
|
|
||||||
|
|
||||||
#define Type(x) (((nodeptr) (x))->type)
|
|
||||||
#define Mass(x) (((nodeptr) (x))->mass)
|
|
||||||
#define Pos(x) (((nodeptr) (x))->pos)
|
|
||||||
#define Cost(x) (((nodeptr) (x))->cost)
|
|
||||||
#define Level(x) (((nodeptr) (x))->level)
|
|
||||||
#define Parent(x) (((nodeptr) (x))->parent)
|
|
||||||
#define ChildNum(x) (((nodeptr) (x))->child_num)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BODY: data structure used to represent particles.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _body* bodyptr;
|
|
||||||
typedef struct _leaf* leafptr;
|
|
||||||
typedef struct _cell* cellptr;
|
|
||||||
|
|
||||||
#define BODY 01 /* type code for bodies */
|
|
||||||
|
|
||||||
typedef struct _body {
|
|
||||||
short type;
|
|
||||||
real mass; /* mass of body */
|
|
||||||
vector pos; /* position of body */
|
|
||||||
int cost; /* number of interactions computed */
|
|
||||||
int level;
|
|
||||||
leafptr parent;
|
|
||||||
int child_num; /* Index that this node should be put */
|
|
||||||
vector vel; /* velocity of body */
|
|
||||||
vector acc; /* acceleration of body */
|
|
||||||
real phi; /* potential at body */
|
|
||||||
} body;
|
|
||||||
|
|
||||||
#define Vel(x) (((bodyptr) (x))->vel)
|
|
||||||
#define Acc(x) (((bodyptr) (x))->acc)
|
|
||||||
#define Phi(x) (((bodyptr) (x))->phi)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CELL: structure used to represent internal nodes of tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CELL 02 /* type code for cells */
|
|
||||||
|
|
||||||
typedef struct _cell {
|
|
||||||
short type;
|
|
||||||
real mass; /* total mass of cell */
|
|
||||||
vector pos; /* cm. position of cell */
|
|
||||||
int cost; /* number of interactions computed */
|
|
||||||
int level;
|
|
||||||
cellptr parent;
|
|
||||||
int child_num; /* Index [0..8] that this node should be put */
|
|
||||||
int processor; /* Used by partition code */
|
|
||||||
struct _cell *next, *prev; /* Used in the partition array */
|
|
||||||
unsigned long seqnum;
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
matrix quad; /* quad. moment of cell */
|
|
||||||
#endif
|
|
||||||
volatile short int done; /* flag to tell when the c.of.m is ready */
|
|
||||||
nodeptr subp[NSUB]; /* descendents of cell */
|
|
||||||
} cell;
|
|
||||||
|
|
||||||
#define Subp(x) (((cellptr) (x))->subp)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LEAF: structure used to represent leaf nodes of tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LEAF 03 /* type code for leaves */
|
|
||||||
|
|
||||||
typedef struct _leaf {
|
|
||||||
short type;
|
|
||||||
real mass; /* total mass of leaf */
|
|
||||||
vector pos; /* cm. position of leaf */
|
|
||||||
int cost; /* number of interactions computed */
|
|
||||||
int level;
|
|
||||||
cellptr parent;
|
|
||||||
int child_num; /* Index [0..8] that this node should be put */
|
|
||||||
int processor; /* Used by partition code */
|
|
||||||
struct _leaf *next, *prev; /* Used in the partition array */
|
|
||||||
unsigned long seqnum;
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
matrix quad; /* quad. moment of leaf */
|
|
||||||
#endif
|
|
||||||
volatile short int done; /* flag to tell when the c.of.m is ready */
|
|
||||||
unsigned int num_bodies;
|
|
||||||
bodyptr bodyp[MAX_BODIES_PER_LEAF]; /* bodies of leaf */
|
|
||||||
} leaf;
|
|
||||||
|
|
||||||
#define Bodyp(x) (((leafptr) (x))->bodyp)
|
|
||||||
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
#define Quad(x) (((cellptr) (x))->quad)
|
|
||||||
#endif
|
|
||||||
#define Done(x) (((cellptr) (x))->done)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Integerized coordinates: used to mantain body-tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAXLEVEL (8*sizeof(int)-2)
|
|
||||||
#define IMAX (1 << MAXLEVEL) /* highest bit of int coord */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "getparam.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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GETPARAM.C:
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "stdinc.h"
|
|
||||||
|
|
||||||
void* malloc(size_t);
|
|
||||||
void free(void*);
|
|
||||||
|
|
||||||
local string *defaults = NULL; /* vector of "name=value" strings */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* INITPARAM: ignore arg vector, remember defaults.
|
|
||||||
*/
|
|
||||||
|
|
||||||
initparam(argv, defv)
|
|
||||||
string *argv, *defv;
|
|
||||||
{
|
|
||||||
defaults = defv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GETPARAM: export version prompts user for value.
|
|
||||||
*/
|
|
||||||
|
|
||||||
string getparam(name)
|
|
||||||
string name; /* name of parameter */
|
|
||||||
{
|
|
||||||
int scanbind(), i, strlen(), leng;
|
|
||||||
string extrvalue(), def;
|
|
||||||
char buf[128], *strcpy();
|
|
||||||
char* temp;
|
|
||||||
|
|
||||||
if (defaults == NULL)
|
|
||||||
error("getparam: called before initparam\n");
|
|
||||||
i = scanbind(defaults, name);
|
|
||||||
if (i < 0)
|
|
||||||
error("getparam: %s unknown\n", name);
|
|
||||||
def = extrvalue(defaults[i]);
|
|
||||||
gets_s(buf,100);
|
|
||||||
leng = strlen(buf) + 1;
|
|
||||||
if (leng > 1) {
|
|
||||||
return (strcpy(malloc(leng), buf));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GETIPARAM, ..., GETDPARAM: get int, long, bool, or double parameters.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int getiparam(name)
|
|
||||||
string name; /* name of parameter */
|
|
||||||
{
|
|
||||||
string getparam(), val;
|
|
||||||
int atoi();
|
|
||||||
|
|
||||||
for (val = ""; *val == NULL;) {
|
|
||||||
val = getparam(name);
|
|
||||||
}
|
|
||||||
return (atoi(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
long getlparam(name)
|
|
||||||
string name; /* name of parameter */
|
|
||||||
{
|
|
||||||
string getparam(), val;
|
|
||||||
long atol();
|
|
||||||
|
|
||||||
for (val = ""; *val == NULL; )
|
|
||||||
val = getparam(name);
|
|
||||||
return (atol(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getbparam(name)
|
|
||||||
string name; /* name of parameter */
|
|
||||||
{
|
|
||||||
string getparam(), val;
|
|
||||||
|
|
||||||
for (val = ""; *val == NULL; )
|
|
||||||
val = getparam(name);
|
|
||||||
if (strchr("tTyY1", *val) != NULL) {
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
if (strchr("fFnN0", *val) != NULL) {
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
error("getbparam: %s=%s not bool\n", name, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
double getdparam(name)
|
|
||||||
string name; /* name of parameter */
|
|
||||||
{
|
|
||||||
string getparam(), val;
|
|
||||||
double atof();
|
|
||||||
|
|
||||||
for (val = ""; *val == NULL; ) {
|
|
||||||
val = getparam(name);
|
|
||||||
}
|
|
||||||
return (atof(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SCANBIND: scan binding vector for name, return index.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int scanbind(bvec, name)
|
|
||||||
string bvec[];
|
|
||||||
string name;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
bool matchname();
|
|
||||||
|
|
||||||
for (i = 0; bvec[i] != NULL; i++)
|
|
||||||
if (matchname(bvec[i], name))
|
|
||||||
return (i);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MATCHNAME: determine if "name=value" matches "name".
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool matchname(bind, name)
|
|
||||||
string bind, name;
|
|
||||||
{
|
|
||||||
char *bp, *np;
|
|
||||||
|
|
||||||
bp = bind;
|
|
||||||
np = name;
|
|
||||||
while (*bp == *np) {
|
|
||||||
bp++;
|
|
||||||
np++;
|
|
||||||
}
|
|
||||||
return (*bp == '=' && *np == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* EXTRVALUE: extract value from name=value string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
string extrvalue(arg)
|
|
||||||
string arg; /* string of the form "name=value" */
|
|
||||||
{
|
|
||||||
char *ap;
|
|
||||||
|
|
||||||
ap = (char *) arg;
|
|
||||||
while (*ap != NULL)
|
|
||||||
if (*ap++ == '=')
|
|
||||||
return ((string) ap);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "grav.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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GRAV.C:
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define global extern
|
|
||||||
|
|
||||||
#include "code.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HACKGRAV: evaluate grav field at a given particle.
|
|
||||||
*/
|
|
||||||
|
|
||||||
hackgrav(p,ProcessId)
|
|
||||||
bodyptr p;
|
|
||||||
unsigned ProcessId;
|
|
||||||
|
|
||||||
{
|
|
||||||
extern gravsub();
|
|
||||||
|
|
||||||
Local[ProcessId].pskip = p;
|
|
||||||
SETV(Local[ProcessId].pos0, Pos(p));
|
|
||||||
Local[ProcessId].phi0 = 0.0;
|
|
||||||
CLRV(Local[ProcessId].acc0);
|
|
||||||
Local[ProcessId].myn2bterm = 0;
|
|
||||||
Local[ProcessId].mynbcterm = 0;
|
|
||||||
Local[ProcessId].skipself = FALSE;
|
|
||||||
hackwalk(gravsub, ProcessId);
|
|
||||||
Phi(p) = Local[ProcessId].phi0;
|
|
||||||
SETV(Acc(p), Local[ProcessId].acc0);
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
Cost(p) = Local[ProcessId].myn2bterm + NDIM * Local[ProcessId].mynbcterm;
|
|
||||||
#else
|
|
||||||
Cost(p) = Local[ProcessId].myn2bterm + Local[ProcessId].mynbcterm;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GRAVSUB: compute a single body-body or body-cell interaction.
|
|
||||||
*/
|
|
||||||
|
|
||||||
gravsub(p, ProcessId, level)
|
|
||||||
register nodeptr p; /* body or cell to interact with */
|
|
||||||
unsigned ProcessId;
|
|
||||||
int level;
|
|
||||||
{
|
|
||||||
double sqrt();
|
|
||||||
real drabs, phii, mor3;
|
|
||||||
vector ai, quaddr;
|
|
||||||
real dr5inv, phiquad, drquaddr;
|
|
||||||
|
|
||||||
if (p != Local[ProcessId].pmem) {
|
|
||||||
SUBV(Local[ProcessId].dr, Pos(p), Local[ProcessId].pos0);
|
|
||||||
DOTVP(Local[ProcessId].drsq, Local[ProcessId].dr, Local[ProcessId].dr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Local[ProcessId].drsq += epssq;
|
|
||||||
drabs = sqrt((double) Local[ProcessId].drsq);
|
|
||||||
phii = Mass(p) / drabs;
|
|
||||||
Local[ProcessId].phi0 -= phii;
|
|
||||||
mor3 = phii / Local[ProcessId].drsq;
|
|
||||||
MULVS(ai, Local[ProcessId].dr, mor3);
|
|
||||||
ADDV(Local[ProcessId].acc0, Local[ProcessId].acc0, ai);
|
|
||||||
if(Type(p) != BODY) { /* a body-cell/leaf interaction? */
|
|
||||||
Local[ProcessId].mynbcterm++;
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
dr5inv = 1.0/(Local[ProcessId].drsq * Local[ProcessId].drsq * drabs);
|
|
||||||
MULMV(quaddr, Quad(p), Local[ProcessId].dr);
|
|
||||||
DOTVP(drquaddr, Local[ProcessId].dr, quaddr);
|
|
||||||
phiquad = -0.5 * dr5inv * drquaddr;
|
|
||||||
Local[ProcessId].phi0 += phiquad;
|
|
||||||
phiquad = 5.0 * phiquad / Local[ProcessId].drsq;
|
|
||||||
MULVS(ai, Local[ProcessId].dr, phiquad);
|
|
||||||
SUBV(Local[ProcessId].acc0, Local[ProcessId].acc0, ai);
|
|
||||||
MULVS(quaddr, quaddr, dr5inv);
|
|
||||||
SUBV(Local[ProcessId].acc0, Local[ProcessId].acc0, quaddr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else { /* a body-body interaction */
|
|
||||||
Local[ProcessId].myn2bterm++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HACKWALK: walk the tree opening cells too close to a given point.
|
|
||||||
*/
|
|
||||||
|
|
||||||
local proced hacksub;
|
|
||||||
|
|
||||||
hackwalk(sub, ProcessId)
|
|
||||||
proced sub; /* routine to do calculation */
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
walksub(Global->G_root, Global->rsize * Global->rsize, ProcessId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WALKSUB: recursive routine to do hackwalk operation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
walksub(n, dsq, ProcessId)
|
|
||||||
nodeptr n; /* pointer into body-tree */
|
|
||||||
real dsq; /* size of box squared */
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
bool subdivp();
|
|
||||||
nodeptr* nn;
|
|
||||||
leafptr l;
|
|
||||||
bodyptr p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (subdivp(n, dsq, ProcessId)) {
|
|
||||||
if (Type(n) == CELL) {
|
|
||||||
for (nn = Subp(n); nn < Subp(n) + NSUB; nn++) {
|
|
||||||
if (*nn != NULL) {
|
|
||||||
walksub(*nn, dsq / 4.0, ProcessId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
l = (leafptr) n;
|
|
||||||
for (i = 0; i < l->num_bodies; i++) {
|
|
||||||
p = Bodyp(l)[i];
|
|
||||||
if (p != Local[ProcessId].pskip) {
|
|
||||||
gravsub(p, ProcessId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Local[ProcessId].skipself = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gravsub(n, ProcessId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SUBDIVP: decide if a node should be opened.
|
|
||||||
* Side effects: sets pmem,dr, and drsq.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool subdivp(p, dsq, ProcessId)
|
|
||||||
register nodeptr p; /* body/cell to be tested */
|
|
||||||
real dsq; /* size of cell squared */
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
SUBV(Local[ProcessId].dr, Pos(p), Local[ProcessId].pos0);
|
|
||||||
DOTVP(Local[ProcessId].drsq, Local[ProcessId].dr, Local[ProcessId].dr);
|
|
||||||
Local[ProcessId].pmem = p;
|
|
||||||
return (tolsq * Local[ProcessId].drsq < dsq);
|
|
||||||
}
|
|
||||||
@@ -1,550 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "load.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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#define global extern
|
|
||||||
|
|
||||||
#include "code.h"
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
bool intcoord();
|
|
||||||
cellptr makecell(unsigned int ProcessId);
|
|
||||||
leafptr makeleaf(unsigned int ProcessId);
|
|
||||||
cellptr SubdivideLeaf(leafptr le, cellptr parent, unsigned int l,
|
|
||||||
unsigned int ProcessId);
|
|
||||||
|
|
||||||
cellptr InitCell(cellptr parent, unsigned int ProcessId);
|
|
||||||
leafptr InitLeaf(cellptr parent, unsigned int ProcessId);
|
|
||||||
nodeptr loadtree(bodyptr p, cellptr root, unsigned int ProcessId);
|
|
||||||
|
|
||||||
void hackcofm(int nc, unsigned ProcessId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MAKETREE: initialize tree structure for hack force calculation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
maketree(unsigned ProcessId)
|
|
||||||
{
|
|
||||||
bodyptr p, *pp;
|
|
||||||
|
|
||||||
Local[ProcessId].myncell = 0;
|
|
||||||
Local[ProcessId].mynleaf = 0;
|
|
||||||
if (ProcessId == 0) {
|
|
||||||
Local[ProcessId].mycelltab[Local[ProcessId].myncell++] = Global->G_root;
|
|
||||||
}
|
|
||||||
Local[ProcessId].Current_Root = (nodeptr) Global->G_root;
|
|
||||||
for (pp = Local[ProcessId].mybodytab;
|
|
||||||
pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody; pp++) {
|
|
||||||
p = *pp;
|
|
||||||
if (Mass(p) != 0.0) {
|
|
||||||
Local[ProcessId].Current_Root
|
|
||||||
= (nodeptr) loadtree(p, (cellptr) Local[ProcessId].Current_Root,
|
|
||||||
ProcessId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
{;};
|
|
||||||
// fprintf(stderr, "Process %d found body %d to have zero mass\n",
|
|
||||||
// ProcessId, (int) p);
|
|
||||||
{;};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{;};
|
|
||||||
hackcofm( 0, ProcessId );
|
|
||||||
{;};
|
|
||||||
}
|
|
||||||
|
|
||||||
cellptr InitCell(cellptr parent, unsigned ProcessId)
|
|
||||||
{
|
|
||||||
cellptr c;
|
|
||||||
int i, Mycell;
|
|
||||||
|
|
||||||
c = makecell(ProcessId);
|
|
||||||
c->processor = ProcessId;
|
|
||||||
c->next = NULL;
|
|
||||||
c->prev = NULL;
|
|
||||||
if (parent == NULL)
|
|
||||||
Level(c) = IMAX >> 1;
|
|
||||||
else
|
|
||||||
Level(c) = Level(parent) >> 1;
|
|
||||||
Parent(c) = (nodeptr) parent;
|
|
||||||
ChildNum(c) = 0;
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
leafptr InitLeaf(cellptr parent,unsigned ProcessId)
|
|
||||||
{
|
|
||||||
leafptr l;
|
|
||||||
int i, Mycell;
|
|
||||||
|
|
||||||
l = makeleaf(ProcessId);
|
|
||||||
l->processor = ProcessId;
|
|
||||||
l->next = NULL;
|
|
||||||
l->prev = NULL;
|
|
||||||
if (parent==NULL)
|
|
||||||
Level(l) = IMAX >> 1;
|
|
||||||
else
|
|
||||||
Level(l) = Level(parent) >> 1;
|
|
||||||
Parent(l) = (nodeptr) parent;
|
|
||||||
ChildNum(l) = 0;
|
|
||||||
return (l);
|
|
||||||
}
|
|
||||||
|
|
||||||
// printtree (n)
|
|
||||||
// nodeptr n;
|
|
||||||
// {
|
|
||||||
// int k;
|
|
||||||
// cellptr c;
|
|
||||||
// leafptr l;
|
|
||||||
// bodyptr p;
|
|
||||||
// nodeptr tmp;
|
|
||||||
// unsigned long nseq;
|
|
||||||
// int xp[NDIM];
|
|
||||||
|
|
||||||
// switch (Type(n)) {
|
|
||||||
// case CELL:
|
|
||||||
// c = (cellptr) n;
|
|
||||||
// nseq = c->seqnum;
|
|
||||||
// // printf("Cell : Cost = %d, ", Cost(c));
|
|
||||||
// // PRTV("Pos", Pos(n));
|
|
||||||
// // printf("\n");
|
|
||||||
// for (k = 0; k < NSUB; k++) {
|
|
||||||
// // printf("Child #%d: ", k);
|
|
||||||
// if (Subp(c)[k] == NULL) {
|
|
||||||
// // printf("NONE");
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// if (Type(Subp(c)[k]) == CELL) {
|
|
||||||
// nseq = ((cellptr) Subp(c)[k])->seqnum;
|
|
||||||
// // printf("C: Cost = %d, ", Cost(Subp(c)[k]));
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// nseq = ((leafptr) Subp(c)[k])->seqnum;
|
|
||||||
// // printf("L: # Bodies = %2d, Cost = %d, ",
|
|
||||||
// // ((leafptr) Subp(c)[k])->num_bodies, Cost(Subp(c)[k]));
|
|
||||||
// }
|
|
||||||
// tmp = Subp(c)[k];
|
|
||||||
// // PRTV("Pos", Pos(tmp));
|
|
||||||
// }
|
|
||||||
// // printf("\n");
|
|
||||||
// }
|
|
||||||
// for (k=0;k<NSUB;k++) {
|
|
||||||
// if (Subp(c)[k] != NULL) {
|
|
||||||
// // printtree(Subp(c)[k]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// case LEAF:
|
|
||||||
// l = (leafptr) n;
|
|
||||||
// nseq = l->seqnum;
|
|
||||||
// // printf("Leaf : # Bodies = %2d, Cost = %d, ", l->num_bodies, Cost(l));
|
|
||||||
// // PRTV("Pos", Pos(n));
|
|
||||||
// // printf("\n");
|
|
||||||
// for (k = 0; k < l->num_bodies; k++) {
|
|
||||||
// p = Bodyp(l)[k];
|
|
||||||
// // printf("Body #%2d: Num = %2d, Level = %o, ",
|
|
||||||
// // p - bodytab, k, Level(p));
|
|
||||||
// // PRTV("Pos",Pos(p));
|
|
||||||
// // printf("\n");
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// // fprintf(stderr, "Bad type\n");
|
|
||||||
// exit(-1);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// fflush(stdout);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LOADTREE: descend tree and insert particle.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nodeptr
|
|
||||||
loadtree(bodyptr p, cellptr root,unsigned ProcessId)
|
|
||||||
{
|
|
||||||
int l, xq[NDIM], xp[NDIM], xor[NDIM], subindex(), flag;
|
|
||||||
int i, j, root_level;
|
|
||||||
bool valid_root;
|
|
||||||
int kidIndex;
|
|
||||||
volatile nodeptr *volatile qptr, mynode;
|
|
||||||
cellptr c;
|
|
||||||
leafptr le;
|
|
||||||
|
|
||||||
intcoord(xp, Pos(p));
|
|
||||||
valid_root = TRUE;
|
|
||||||
for (i = 0; i < NDIM; i++) {
|
|
||||||
xor[i] = xp[i] ^ Local[ProcessId].Root_Coords[i];
|
|
||||||
}
|
|
||||||
for (i = IMAX >> 1; i > Level(root); i >>= 1) {
|
|
||||||
for (j = 0; j < NDIM; j++) {
|
|
||||||
if (xor[j] & i) {
|
|
||||||
valid_root = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!valid_root) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!valid_root) {
|
|
||||||
if (root != Global->G_root) {
|
|
||||||
root_level = Level(root);
|
|
||||||
for (j = i; j > root_level; j >>= 1) {
|
|
||||||
root = (cellptr) Parent(root);
|
|
||||||
}
|
|
||||||
valid_root = TRUE;
|
|
||||||
for (i = IMAX >> 1; i > Level(root); i >>= 1) {
|
|
||||||
for (j = 0; j < NDIM; j++) {
|
|
||||||
if (xor[j] & i) {
|
|
||||||
valid_root = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!valid_root) {
|
|
||||||
// printf("P%d body %d\n", ProcessId, p - bodytab);
|
|
||||||
root = Global->G_root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root = Global->G_root;
|
|
||||||
mynode = (nodeptr) root;
|
|
||||||
kidIndex = subindex(xp, Level(mynode));
|
|
||||||
qptr = &Subp(mynode)[kidIndex];
|
|
||||||
|
|
||||||
l = Level(mynode) >> 1;
|
|
||||||
|
|
||||||
flag = TRUE;
|
|
||||||
while (flag) { /* loop descending tree */
|
|
||||||
if (l == 0) {
|
|
||||||
// error("not enough levels in tree\n");
|
|
||||||
}
|
|
||||||
if (*qptr == NULL) {
|
|
||||||
/* lock the parent cell */
|
|
||||||
{;};
|
|
||||||
if (*qptr == NULL) {
|
|
||||||
le = InitLeaf((cellptr) mynode, ProcessId);
|
|
||||||
Parent(p) = (nodeptr) le;
|
|
||||||
Level(p) = l;
|
|
||||||
ChildNum(p) = le->num_bodies;
|
|
||||||
ChildNum(le) = kidIndex;
|
|
||||||
Bodyp(le)[le->num_bodies++] = p;
|
|
||||||
*qptr = (nodeptr) le;
|
|
||||||
flag = FALSE;
|
|
||||||
}
|
|
||||||
{;};
|
|
||||||
/* unlock the parent cell */
|
|
||||||
}
|
|
||||||
if (flag && *qptr && (Type(*qptr) == LEAF)) {
|
|
||||||
/* reached a "leaf"? */
|
|
||||||
{;};
|
|
||||||
/* lock the parent cell */
|
|
||||||
if (Type(*qptr) == LEAF) { /* still a "leaf"? */
|
|
||||||
le = (leafptr) *qptr;
|
|
||||||
if (le->num_bodies == MAX_BODIES_PER_LEAF) {
|
|
||||||
*qptr = (nodeptr) SubdivideLeaf(le, (cellptr) mynode, l,
|
|
||||||
ProcessId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Parent(p) = (nodeptr) le;
|
|
||||||
Level(p) = l;
|
|
||||||
ChildNum(p) = le->num_bodies;
|
|
||||||
Bodyp(le)[le->num_bodies++] = p;
|
|
||||||
flag = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{;};
|
|
||||||
/* unlock the node */
|
|
||||||
}
|
|
||||||
if (flag) {
|
|
||||||
mynode = *qptr;
|
|
||||||
kidIndex = subindex(xp, l);
|
|
||||||
qptr = &Subp(*qptr)[kidIndex]; /* move down one level */
|
|
||||||
l = l >> 1; /* and test next bit */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SETV(Local[ProcessId].Root_Coords, xp);
|
|
||||||
return Parent((leafptr) *qptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* * INTCOORD: compute integerized coordinates. * Returns: TRUE
|
|
||||||
unless rp was out of bounds. */
|
|
||||||
|
|
||||||
bool intcoord(xp, rp)
|
|
||||||
int xp[NDIM]; /* integerized coordinate vector [0,IMAX) */
|
|
||||||
vector rp; /* real coordinate vector (system coords) */
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
bool inb;
|
|
||||||
double xsc, floor();
|
|
||||||
|
|
||||||
inb = TRUE;
|
|
||||||
for (k = 0; k < NDIM; k++) {
|
|
||||||
xsc = (rp[k] - Global->rmin[k]) / Global->rsize;
|
|
||||||
if (0.0 <= xsc && xsc < 1.0) {
|
|
||||||
xp[k] = floor(IMAX * xsc);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
inb = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (inb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SUBINDEX: determine which subcell to select.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int subindex(x, l)
|
|
||||||
int x[NDIM]; /* integerized coordinates of particle */
|
|
||||||
int l; /* current level of tree */
|
|
||||||
{
|
|
||||||
int i, k;
|
|
||||||
int yes;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
yes = FALSE;
|
|
||||||
if (x[0] & l) {
|
|
||||||
i += NSUB >> 1;
|
|
||||||
yes = TRUE;
|
|
||||||
}
|
|
||||||
for (k = 1; k < NDIM; k++) {
|
|
||||||
if (((x[k] & l) && !yes) || (!(x[k] & l) && yes)) {
|
|
||||||
i += NSUB >> (k + 1);
|
|
||||||
yes = TRUE;
|
|
||||||
}
|
|
||||||
else yes = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HACKCOFM: descend tree finding center-of-mass coordinates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void hackcofm(int nc,unsigned ProcessId)
|
|
||||||
{
|
|
||||||
int i,Myindex;
|
|
||||||
nodeptr r;
|
|
||||||
leafptr l;
|
|
||||||
leafptr* ll;
|
|
||||||
bodyptr p;
|
|
||||||
cellptr q;
|
|
||||||
cellptr *cc;
|
|
||||||
vector tmpv, dr;
|
|
||||||
real drsq;
|
|
||||||
matrix drdr, Idrsq, tmpm;
|
|
||||||
|
|
||||||
/* get a cell using get*sub. Cells are got in reverse of the order in */
|
|
||||||
/* the cell array; i.e. reverse of the order in which they were created */
|
|
||||||
/* this way, we look at child cells before parents */
|
|
||||||
|
|
||||||
for (ll = Local[ProcessId].myleaftab + Local[ProcessId].mynleaf - 1;
|
|
||||||
ll >= Local[ProcessId].myleaftab; ll--) {
|
|
||||||
l = *ll;
|
|
||||||
Mass(l) = 0.0;
|
|
||||||
Cost(l) = 0;
|
|
||||||
CLRV(Pos(l));
|
|
||||||
for (i = 0; i < l->num_bodies; i++) {
|
|
||||||
p = Bodyp(l)[i];
|
|
||||||
Mass(l) += Mass(p);
|
|
||||||
Cost(l) += Cost(p);
|
|
||||||
MULVS(tmpv, Pos(p), Mass(p));
|
|
||||||
ADDV(Pos(l), Pos(l), tmpv);
|
|
||||||
}
|
|
||||||
DIVVS(Pos(l), Pos(l), Mass(l));
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
CLRM(Quad(l));
|
|
||||||
for (i = 0; i < l->num_bodies; i++) {
|
|
||||||
p = Bodyp(l)[i];
|
|
||||||
SUBV(dr, Pos(p), Pos(l));
|
|
||||||
OUTVP(drdr, dr, dr);
|
|
||||||
DOTVP(drsq, dr, dr);
|
|
||||||
SETMI(Idrsq);
|
|
||||||
MULMS(Idrsq, Idrsq, drsq);
|
|
||||||
MULMS(tmpm, drdr, 3.0);
|
|
||||||
SUBM(tmpm, tmpm, Idrsq);
|
|
||||||
MULMS(tmpm, tmpm, Mass(p));
|
|
||||||
ADDM(Quad(l), Quad(l), tmpm);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Done(l)=TRUE;
|
|
||||||
}
|
|
||||||
for (cc = Local[ProcessId].mycelltab+Local[ProcessId].myncell-1;
|
|
||||||
cc >= Local[ProcessId].mycelltab; cc--) {
|
|
||||||
q = *cc;
|
|
||||||
Mass(q) = 0.0;
|
|
||||||
Cost(q) = 0;
|
|
||||||
CLRV(Pos(q));
|
|
||||||
for (i = 0; i < NSUB; i++) {
|
|
||||||
r = Subp(q)[i];
|
|
||||||
if (r != NULL) {
|
|
||||||
while(!Done(r)) {
|
|
||||||
/* wait */
|
|
||||||
}
|
|
||||||
Mass(q) += Mass(r);
|
|
||||||
Cost(q) += Cost(r);
|
|
||||||
MULVS(tmpv, Pos(r), Mass(r));
|
|
||||||
ADDV(Pos(q), Pos(q), tmpv);
|
|
||||||
Done(r) = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DIVVS(Pos(q), Pos(q), Mass(q));
|
|
||||||
#ifdef QUADPOLE
|
|
||||||
CLRM(Quad(q));
|
|
||||||
for (i = 0; i < NSUB; i++) {
|
|
||||||
r = Subp(q)[i];
|
|
||||||
if (r != NULL) {
|
|
||||||
SUBV(dr, Pos(r), Pos(q));
|
|
||||||
OUTVP(drdr, dr, dr);
|
|
||||||
DOTVP(drsq, dr, dr);
|
|
||||||
SETMI(Idrsq);
|
|
||||||
MULMS(Idrsq, Idrsq, drsq);
|
|
||||||
MULMS(tmpm, drdr, 3.0);
|
|
||||||
SUBM(tmpm, tmpm, Idrsq);
|
|
||||||
MULMS(tmpm, tmpm, Mass(r));
|
|
||||||
ADDM(tmpm, tmpm, Quad(r));
|
|
||||||
ADDM(Quad(q), Quad(q), tmpm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Done(q)=TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cellptr
|
|
||||||
SubdivideLeaf (le, parent, l, ProcessId)
|
|
||||||
leafptr le;
|
|
||||||
cellptr parent;
|
|
||||||
unsigned int l;
|
|
||||||
unsigned int ProcessId;
|
|
||||||
{
|
|
||||||
cellptr c;
|
|
||||||
int i, index;
|
|
||||||
int xp[NDIM];
|
|
||||||
bodyptr bodies[MAX_BODIES_PER_LEAF];
|
|
||||||
int num_bodies;
|
|
||||||
bodyptr p;
|
|
||||||
|
|
||||||
/* first copy leaf's bodies to temp array, so we can reuse the leaf */
|
|
||||||
num_bodies = le->num_bodies;
|
|
||||||
for (i = 0; i < num_bodies; i++) {
|
|
||||||
bodies[i] = Bodyp(le)[i];
|
|
||||||
Bodyp(le)[i] = NULL;
|
|
||||||
}
|
|
||||||
le->num_bodies = 0;
|
|
||||||
/* create the parent cell for this subtree */
|
|
||||||
c = InitCell(parent, ProcessId);
|
|
||||||
ChildNum(c) = ChildNum(le);
|
|
||||||
/* do first particle separately, so we can reuse le */
|
|
||||||
p = bodies[0];
|
|
||||||
intcoord(xp, Pos(p));
|
|
||||||
index = subindex(xp, l);
|
|
||||||
Subp(c)[index] = (nodeptr) le;
|
|
||||||
ChildNum(le) = index;
|
|
||||||
Parent(le) = (nodeptr) c;
|
|
||||||
Level(le) = l >> 1;
|
|
||||||
/* set stuff for body */
|
|
||||||
Parent(p) = (nodeptr) le;
|
|
||||||
ChildNum(p) = le->num_bodies;
|
|
||||||
Level(p) = l >> 1;
|
|
||||||
/* insert the body */
|
|
||||||
Bodyp(le)[le->num_bodies++] = p;
|
|
||||||
/* now handle the rest */
|
|
||||||
for (i = 1; i < num_bodies; i++) {
|
|
||||||
p = bodies[i];
|
|
||||||
intcoord(xp, Pos(p));
|
|
||||||
index = subindex(xp, l);
|
|
||||||
if (!Subp(c)[index]) {
|
|
||||||
le = InitLeaf(c, ProcessId);
|
|
||||||
ChildNum(le) = index;
|
|
||||||
Subp(c)[index] = (nodeptr) le;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
le = (leafptr) Subp(c)[index];
|
|
||||||
}
|
|
||||||
Parent(p) = (nodeptr) le;
|
|
||||||
ChildNum(p) = le->num_bodies;
|
|
||||||
Level(p) = l >> 1;
|
|
||||||
Bodyp(le)[le->num_bodies++] = p;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MAKECELL: allocation routine for cells.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cellptr makecell(ProcessId)
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
cellptr c;
|
|
||||||
int i, Mycell;
|
|
||||||
|
|
||||||
if (Local[ProcessId].mynumcell == maxmycell) {
|
|
||||||
// error("makecell: Proc %d needs more than %d cells; increase fcells\n",
|
|
||||||
// ProcessId,maxmycell);
|
|
||||||
}
|
|
||||||
Mycell = Local[ProcessId].mynumcell++;
|
|
||||||
c = Local[ProcessId].ctab + Mycell;
|
|
||||||
c->seqnum = ProcessId*maxmycell+Mycell;
|
|
||||||
Type(c) = CELL;
|
|
||||||
Done(c) = FALSE;
|
|
||||||
Mass(c) = 0.0;
|
|
||||||
for (i = 0; i < NSUB; i++) {
|
|
||||||
Subp(c)[i] = NULL;
|
|
||||||
}
|
|
||||||
Local[ProcessId].mycelltab[Local[ProcessId].myncell++] = c;
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MAKELEAF: allocation routine for leaves.
|
|
||||||
*/
|
|
||||||
|
|
||||||
leafptr makeleaf(ProcessId)
|
|
||||||
unsigned ProcessId;
|
|
||||||
{
|
|
||||||
leafptr le;
|
|
||||||
int i, Myleaf;
|
|
||||||
|
|
||||||
if (Local[ProcessId].mynumleaf == maxmyleaf) {
|
|
||||||
// error("makeleaf: Proc %d needs more than %d leaves; increase fleaves\n",
|
|
||||||
// ProcessId,maxmyleaf);
|
|
||||||
}
|
|
||||||
Myleaf = Local[ProcessId].mynumleaf++;
|
|
||||||
le = Local[ProcessId].ltab + Myleaf;
|
|
||||||
le->seqnum = ProcessId * maxmyleaf + Myleaf;
|
|
||||||
Type(le) = LEAF;
|
|
||||||
Done(le) = FALSE;
|
|
||||||
Mass(le) = 0.0;
|
|
||||||
le->num_bodies = 0;
|
|
||||||
for (i = 0; i < MAX_BODIES_PER_LEAF; i++) {
|
|
||||||
Bodyp(le)[i] = NULL;
|
|
||||||
}
|
|
||||||
Local[ProcessId].myleaftab[Local[ProcessId].mynleaf++] = le;
|
|
||||||
return (le);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "stdinc.H"
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* 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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STDINC.H: standard include file for C programs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _STDINC_H_
|
|
||||||
#define _STDINC_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If not already loaded, include stdio.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STREAM: a replacement for FILE *.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef FILE *stream;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NULL: denotes a pointer to no object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BOOL, TRUE and FALSE: standard names for logical values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef int bool;
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
|
|
||||||
#define FALSE 0
|
|
||||||
#define TRUE 1
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BYTE: a short name for a handy chunk of bits.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef unsigned char byte;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STRING: for null-terminated strings which are not taken apart.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef char *string;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REAL: default type is double;
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef double real, *realptr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PROC, IPROC, RPROC: pointers to procedures, integer functions, and
|
|
||||||
* real-valued functions, respectively.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void (*proced)();
|
|
||||||
typedef int (*iproc)();
|
|
||||||
typedef real (*rproc)();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LOCAL: declare something to be local to a file.
|
|
||||||
* PERMANENT: declare something to be permanent data within a function.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define local static
|
|
||||||
#define permanent static
|
|
||||||
|
|
||||||
/*
|
|
||||||
* STREQ: handy string-equality macro.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define streq(x,y) (strcmp((x), (y)) == 0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PI, etc. -- mathematical constants
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PI 3.14159265358979323846
|
|
||||||
#define TWO_PI 6.28318530717958647693
|
|
||||||
#define FOUR_PI 12.56637061435917295385
|
|
||||||
#define HALF_PI 1.57079632679489661923
|
|
||||||
#define FRTHRD_PI 4.18879020478639098462
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ABS: returns the absolute value of its argument
|
|
||||||
* MAX: returns the argument with the highest value
|
|
||||||
* MIN: returns the argument with the lowest value
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ABS(x) (((x) < 0) ? -(x) : (x))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "util.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 <errno.h>
|
|
||||||
#include "stdinc.h"
|
|
||||||
|
|
||||||
#define HZ 60.0
|
|
||||||
#define MULT 1103515245
|
|
||||||
#define ADD 12345
|
|
||||||
#define MASK (0x7FFFFFFF)
|
|
||||||
#define TWOTO31 2147483648.0
|
|
||||||
|
|
||||||
local int A = 1;
|
|
||||||
local int B = 0;
|
|
||||||
local int randx = 1;
|
|
||||||
local int lastrand; /* the last random number */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XRAND: generate floating-point random number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
double prand();
|
|
||||||
|
|
||||||
double xrand(xl, xh)
|
|
||||||
double xl, xh; /* lower, upper bounds on number */
|
|
||||||
{
|
|
||||||
long random ();
|
|
||||||
double x;
|
|
||||||
|
|
||||||
return (xl + (xh - xl) * prand());
|
|
||||||
}
|
|
||||||
|
|
||||||
void pranset(int seed)
|
|
||||||
{
|
|
||||||
int proc;
|
|
||||||
|
|
||||||
A = 1;
|
|
||||||
B = 0;
|
|
||||||
randx = (A*seed+B) & MASK;
|
|
||||||
A = (MULT * A) & MASK;
|
|
||||||
B = (MULT*B + ADD) & MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
prand()
|
|
||||||
/*
|
|
||||||
Return a random double in [0, 1.0)
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
lastrand = randx;
|
|
||||||
randx = (A*randx+B) & MASK;
|
|
||||||
return((double)lastrand/TWOTO31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CPUTIME: compute CPU time in min.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// #include <sys/types.h>
|
|
||||||
// #include <sys/times.h>
|
|
||||||
|
|
||||||
|
|
||||||
// double cputime()
|
|
||||||
// {
|
|
||||||
// struct tms buffer;
|
|
||||||
|
|
||||||
// if (times(&buffer) == -1)
|
|
||||||
// error("times() call failed\n");
|
|
||||||
// return (buffer.tms_utime / (60.0 * HZ));
|
|
||||||
// }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ERROR: scream and die quickly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// error(msg, a1, a2, a3, a4)
|
|
||||||
// char *msg, *a1, *a2, *a3, *a4;
|
|
||||||
// {
|
|
||||||
// extern int errno;
|
|
||||||
|
|
||||||
// // fprintf(stderr, msg, a1, a2, a3, a4);
|
|
||||||
// // if (errno != 0)
|
|
||||||
// // perror("Error");
|
|
||||||
// // exit(0);
|
|
||||||
// }
|
|
||||||
@@ -1,307 +0,0 @@
|
|||||||
#line 95 "./null_macros/c.m4.null"
|
|
||||||
|
|
||||||
#line 1 "vectmath.H"
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* 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. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* VECTMATH.H: include file for vector/matrix operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _VECMATH_H_
|
|
||||||
#define _VECMATH_H_
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# define NDIM 3
|
|
||||||
|
|
||||||
typedef real vector[NDIM], matrix[NDIM][NDIM];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Vector operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CLRV(v) /* CLeaR Vector */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] = 0.0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UNITV(v,j) /* UNIT Vector */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] = (_i == (j) ? 1.0 : 0.0); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SETV(v,u) /* SET Vector */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] = (u)[_i]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ADDV(v,u,w) /* ADD Vector */ \
|
|
||||||
{ \
|
|
||||||
register real *_vp = (v), *_up = (u), *_wp = (w); \
|
|
||||||
*_vp++ = (*_up++) + (*_wp++); \
|
|
||||||
*_vp++ = (*_up++) + (*_wp++); \
|
|
||||||
*_vp = (*_up ) + (*_wp ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SUBV(v,u,w) /* SUBtract Vector */ \
|
|
||||||
{ \
|
|
||||||
register real *_vp = (v), *_up = (u), *_wp = (w); \
|
|
||||||
*_vp++ = (*_up++) - (*_wp++); \
|
|
||||||
*_vp++ = (*_up++) - (*_wp++); \
|
|
||||||
*_vp = (*_up ) - (*_wp ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MULVS(v,u,s) /* MULtiply Vector by Scalar */ \
|
|
||||||
{ \
|
|
||||||
register real *_vp = (v), *_up = (u); \
|
|
||||||
*_vp++ = (*_up++) * (s); \
|
|
||||||
*_vp++ = (*_up++) * (s); \
|
|
||||||
*_vp = (*_up ) * (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define DIVVS(v,u,s) /* DIVide Vector by Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] = (u)[_i] / (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define DOTVP(s,v,u) /* DOT Vector Product */ \
|
|
||||||
{ \
|
|
||||||
register real *_vp = (v), *_up = (u); \
|
|
||||||
(s) = (*_vp++) * (*_up++); \
|
|
||||||
(s) += (*_vp++) * (*_up++); \
|
|
||||||
(s) += (*_vp ) * (*_up ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ABSV(s,v) /* ABSolute value of a Vector */ \
|
|
||||||
{ \
|
|
||||||
double _tmp, sqrt(); \
|
|
||||||
register int _i; \
|
|
||||||
_tmp = 0.0; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
_tmp += (v)[_i] * (v)[_i]; \
|
|
||||||
(s) = sqrt(_tmp); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DISTV(s,u,v) /* DISTance between Vectors */ \
|
|
||||||
{ \
|
|
||||||
double _tmp, sqrt(); \
|
|
||||||
register int _i; \
|
|
||||||
_tmp = 0.0; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
_tmp += ((u)[_i]-(v)[_i]) * ((u)[_i]-(v)[_i]); \
|
|
||||||
(s) = sqrt(_tmp); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CROSSVP(v,u,w) /* CROSS Vector Product */ \
|
|
||||||
{ \
|
|
||||||
(v)[0] = (u)[1]*(w)[2] - (u)[2]*(w)[1]; \
|
|
||||||
(v)[1] = (u)[2]*(w)[0] - (u)[0]*(w)[2]; \
|
|
||||||
(v)[2] = (u)[0]*(w)[1] - (u)[1]*(w)[0]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define INCADDV(v,u) /* INCrementally ADD Vector */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] += (u)[_i]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INCSUBV(v,u) /* INCrementally SUBtract Vector */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] -= (u)[_i]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INCMULVS(v,s) /* INCrementally MULtiply Vector by Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] *= (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INCDIVVS(v,s) /* INCrementally DIVide Vector by Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] /= (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Matrix operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CLRM(p) /* CLeaR Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = 0.0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SETMI(p) /* SET Matrix to Identity */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (_i == _j ? 1.0 : 0.0); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SETM(p,q) /* SET Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (q)[_i][_j]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TRANM(p,q) /* TRANspose Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (q)[_j][_i]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ADDM(p,q,r) /* ADD Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (q)[_i][_j] + (r)[_i][_j]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SUBM(p,q,r) /* SUBtract Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (q)[_i][_j] - (r)[_i][_j]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MULM(p,q,r) /* Multiply Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j, _k; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) { \
|
|
||||||
(p)[_i][_j] = 0.0; \
|
|
||||||
for (_k = 0; _k < NDIM; _k++) \
|
|
||||||
(p)[_i][_j] += (q)[_i][_k] * (r)[_k][_j]; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MULMS(p,q,s) /* MULtiply Matrix by Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (q)[_i][_j] * (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DIVMS(p,q,s) /* DIVide Matrix by Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (q)[_i][_j] / (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MULMV(v,p,u) /* MULtiply Matrix by Vector */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) { \
|
|
||||||
(v)[_i] = 0.0; \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(v)[_i] += (p)[_i][_j] * (u)[_j]; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define OUTVP(p,v,u) /* OUTer Vector Product */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (v)[_i] * (u)[_j]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TRACEM(s,p) /* TRACE of Matrix */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
(s) = 0.0; \
|
|
||||||
for (_i = 0.0; _i < NDIM; _i++) \
|
|
||||||
(s) += (p)[_i][_i]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Misc. impure operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SETVS(v,s) /* SET Vector to Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] = (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ADDVS(v,u,s) /* ADD Vector and Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
(v)[_i] = (u)[_i] + (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SETMS(p,s) /* SET Matrix to Scalar */ \
|
|
||||||
{ \
|
|
||||||
register int _i, _j; \
|
|
||||||
for (_i = 0; _i < NDIM; _i++) \
|
|
||||||
for (_j = 0; _j < NDIM; _j++) \
|
|
||||||
(p)[_i][_j] = (s); \
|
|
||||||
}
|
|
||||||
|
|
||||||
// #define PRTV(name, vec) /* PRinT Vector */ \
|
|
||||||
// { \
|
|
||||||
// fprintf(stdout,"%s = [%9.4f,%9.4f,%9.4f] ",name,vec[0],vec[1],vec[2]); \
|
|
||||||
// }
|
|
||||||
// #define PRIV(name, vec) /* PRint Integer Vector */ \
|
|
||||||
// { \
|
|
||||||
// fprintf(stdout,"%s = [%d,%d,%d] ",name,vec[0],vec[1],vec[2]); \
|
|
||||||
// }
|
|
||||||
// #define PROV(name, vec) /* PRint Integer Vector */ \
|
|
||||||
// { \
|
|
||||||
// fprintf(stdout,"%s = [%o,%o,%o] ",name,vec[0],vec[1],vec[2]); \
|
|
||||||
// }
|
|
||||||
// #define PRHV(name, vec) /* PRint Integer Vector */ \
|
|
||||||
// { \
|
|
||||||
// fprintf(stdout,"%s = [%x,%x,%x] ",name,vec[0],vec[1],vec[2]); \
|
|
||||||
// }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Source: https://github.com/ivanbgd/Matrix-Multiplication-MatMul-C/blob/master/matmul_1d_seq.c
|
||||||
#define MATMUL_1D
|
#define MATMUL_1D
|
||||||
#ifdef MATMUL_1D
|
#ifdef MATMUL_1D
|
||||||
|
|
||||||
|
|||||||
BIN
Tests/isa/testC
BIN
Tests/isa/testC
Binary file not shown.
Reference in New Issue
Block a user