ported over barnes

This commit is contained in:
2026-04-16 13:51:31 +01:00
parent b14264eb45
commit 12ce7e7ade
15 changed files with 542 additions and 3012 deletions

View 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;
}

View 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

View File

@@ -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'

View File

@@ -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");
// }

View File

@@ -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

View File

@@ -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]);
// }

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
// }

View File

@@ -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

View File

@@ -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

Binary file not shown.