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_macros.h home-1:/home/akilan/
|
||||
# scp ../../malloc.c home-1:/home/akilan/
|
||||
# # scp ../../test.c 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/
|
||||
# scp ../../test.c home-1:/home/akilan/
|
||||
scp barnes_hut.c home-1:/home/akilan/
|
||||
scp barnes_hut.h home-1:/home/akilan/
|
||||
|
||||
# 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'
|
||||
|
||||
# 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
|
||||
# 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
|
||||
#ifdef MATMUL_1D
|
||||
|
||||
|
||||
BIN
Tests/isa/testC
BIN
Tests/isa/testC
Binary file not shown.
Reference in New Issue
Block a user