2017-04-26 17:20:15 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Copyright (c) 1994 Stanford University */
|
|
|
|
/* */
|
|
|
|
/* All rights reserved. */
|
|
|
|
/* */
|
|
|
|
/* Permission is given to use, copy, and modify this software for any */
|
|
|
|
/* non-commercial purpose as long as this copyright notice is not */
|
|
|
|
/* removed. All other uses, including redistribution in whole or in */
|
|
|
|
/* part, are forbidden without prior written permission. */
|
|
|
|
/* */
|
|
|
|
/* This software is provided with absolutely no warranty and no */
|
|
|
|
/* support. */
|
|
|
|
/* */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
2017-04-26 18:03:02 +02:00
|
|
|
#include <stdio.h>
|
2017-04-26 17:20:15 +02:00
|
|
|
#include <unistd.h>
|
2017-04-26 18:03:02 +02:00
|
|
|
#include <stdlib.h>
|
2017-04-26 17:20:15 +02:00
|
|
|
#include "defs.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "particle.h"
|
|
|
|
|
|
|
|
#define ONE_EV ((real) 1.6e-19)
|
|
|
|
#define MAX_FRAC 0.999
|
|
|
|
#define RANDOM_SIZE 256
|
|
|
|
|
|
|
|
#if !defined(M_PI)
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* How many particles can fit on one line */
|
|
|
|
#define PARTICLES_PER_LINE 8
|
|
|
|
|
|
|
|
long Total_Particles;
|
|
|
|
|
|
|
|
/* Used to keep track of all the particles. Array in is order of inc id. */
|
|
|
|
static particle **Particle_List;
|
|
|
|
|
|
|
|
particle *InitParticle(real charge, real mass);
|
|
|
|
void PickShell(vector *v, real radius);
|
|
|
|
real XRand(real low, real high);
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
CreateDistribution (cluster_type cluster, model_type model)
|
|
|
|
{
|
|
|
|
particle *particle_array;
|
|
|
|
long global_num_particles;
|
|
|
|
particle *new_particle;
|
|
|
|
// char particle_state[RANDOM_SIZE];
|
|
|
|
real charge;
|
|
|
|
real r_scale;
|
|
|
|
real v_scale;
|
|
|
|
vector r_sum;
|
|
|
|
vector v_sum;
|
|
|
|
long end_limit = 0;
|
|
|
|
long i;
|
|
|
|
real temp_r;
|
|
|
|
real radius = 0.0;
|
|
|
|
real x_vel;
|
|
|
|
real y_vel;
|
|
|
|
real vel;
|
|
|
|
real offset = 0.0;
|
|
|
|
particle *twin_particle;
|
|
|
|
|
|
|
|
particle_array = (particle *) G_MALLOC(Total_Particles * sizeof(particle));
|
|
|
|
|
|
|
|
Particle_List = (particle **) G_MALLOC(Total_Particles * sizeof(particle *));
|
|
|
|
for (i = 0; i < Total_Particles; i++)
|
|
|
|
Particle_List[i] = &particle_array[i];
|
|
|
|
|
|
|
|
r_scale = 3 * M_PI / 16;
|
|
|
|
v_scale = (real) sqrt(1.0 / (double) r_scale);
|
|
|
|
r_sum.x = (real) 0.0;
|
|
|
|
r_sum.y = (real) 0.0;
|
|
|
|
v_sum.x = (real) 0.0;
|
|
|
|
v_sum.y = (real) 0.0;
|
|
|
|
// initstate(0, particle_state, RANDOM_SIZE);
|
|
|
|
|
|
|
|
switch (cluster) {
|
|
|
|
case ONE_CLUSTER:
|
|
|
|
end_limit = Total_Particles;
|
|
|
|
switch (model) {
|
|
|
|
case UNIFORM:
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("Creating a one cluster, uniform distribution for %ld ", Total_Particles);
|
|
|
|
printf("particles\n");
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
case PLUMMER:
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("Creating a one cluster, non uniform distribution for %ld ", Total_Particles);
|
|
|
|
printf("particles\n");
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TWO_CLUSTER:
|
|
|
|
end_limit = (Total_Particles / 2) + (Total_Particles & 0x1);
|
|
|
|
switch (model) {
|
|
|
|
case UNIFORM:
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("Creating a two cluster, uniform distribution for %ld ", Total_Particles);
|
|
|
|
printf("particles\n");
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
case PLUMMER:
|
2017-04-26 18:03:02 +02:00
|
|
|
printf("Creating a two cluster, non uniform distribution for %ld ", Total_Particles);
|
|
|
|
printf("particles\n");
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// setstate(particle_state);
|
|
|
|
global_num_particles = 0;
|
|
|
|
charge = 1.0 / Total_Particles;
|
|
|
|
charge /= Total_Particles;
|
|
|
|
for (i = 0; i < end_limit; i++) {
|
|
|
|
new_particle = InitParticle(charge, charge);
|
|
|
|
switch (model) {
|
|
|
|
case UNIFORM:
|
2017-04-26 18:03:02 +02:00
|
|
|
do {
|
|
|
|
new_particle->pos.x = XRand(-1.0, 1.0);
|
|
|
|
new_particle->pos.y = XRand(-1.0, 1.0);
|
|
|
|
temp_r = DOT_PRODUCT((new_particle->pos), (new_particle->pos));
|
|
|
|
}
|
|
|
|
while (temp_r > (real) 1.0);
|
|
|
|
radius = sqrt(temp_r);
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
case PLUMMER:
|
2017-04-26 18:03:02 +02:00
|
|
|
do
|
|
|
|
radius = (real) 1.0 / (real) sqrt(pow(XRand(0.0, MAX_FRAC),
|
|
|
|
-2.0/3.0) - 1);
|
|
|
|
while (radius > 9.0);
|
|
|
|
PickShell(&(new_particle->pos), r_scale * radius);
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
VECTOR_ADD(r_sum, r_sum, (new_particle->pos));
|
|
|
|
|
|
|
|
do {
|
2017-04-26 18:03:02 +02:00
|
|
|
x_vel = XRand(0.0, 1.0);
|
|
|
|
y_vel = XRand(0.0, 0.1);
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
while (y_vel > x_vel * x_vel * (real) pow(1.0 - (x_vel * x_vel), 3.5));
|
|
|
|
vel = (real) sqrt(2.0) * x_vel / pow(1.0 + (radius * radius), 0.25);
|
|
|
|
PickShell(&(new_particle->vel), v_scale * vel);
|
|
|
|
VECTOR_ADD(v_sum, v_sum, (new_particle->vel));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cluster == TWO_CLUSTER) {
|
|
|
|
switch (model) {
|
|
|
|
case UNIFORM:
|
2017-04-26 18:03:02 +02:00
|
|
|
offset = 1.5;
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
case PLUMMER:
|
2017-04-26 18:03:02 +02:00
|
|
|
offset = 2.0;
|
|
|
|
break;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
for (i = end_limit; i < Total_Particles; i++) {
|
2017-04-26 18:03:02 +02:00
|
|
|
new_particle = InitParticle(charge, charge);
|
|
|
|
twin_particle = Particle_List[i - end_limit];
|
|
|
|
new_particle->pos.x = twin_particle->pos.x + offset;
|
|
|
|
new_particle->pos.y = twin_particle->pos.y + offset;
|
|
|
|
VECTOR_ADD(r_sum, r_sum, (new_particle->pos));
|
|
|
|
new_particle->vel.x = twin_particle->vel.x;
|
|
|
|
new_particle->vel.y = twin_particle->vel.y;
|
|
|
|
VECTOR_ADD(v_sum, v_sum, (new_particle->vel));
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VECTOR_DIV(r_sum, r_sum, (real) Total_Particles);
|
|
|
|
VECTOR_DIV(v_sum, v_sum, (real) Total_Particles);
|
|
|
|
for (i = 0; i < Total_Particles; i++) {
|
|
|
|
new_particle = Particle_List[i];
|
|
|
|
VECTOR_SUB((new_particle->pos), (new_particle->pos), r_sum);
|
|
|
|
VECTOR_SUB((new_particle->vel), (new_particle->vel), v_sum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
CreateParticleList (long my_id, long length)
|
|
|
|
{
|
|
|
|
LOCK(G_Memory->mal_lock);
|
|
|
|
Local[my_id].Particles = (particle **) G_MALLOC(length
|
2017-04-26 18:03:02 +02:00
|
|
|
* sizeof(particle *));
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
|
|
|
|
Particles data across physically distributed memories as desired.
|
|
|
|
|
|
|
|
One way to do this is as follows:
|
|
|
|
|
|
|
|
char *starting_address;
|
|
|
|
char *ending_address;
|
|
|
|
|
|
|
|
starting_address = (char *) Local[my_id].Particles;
|
|
|
|
ending_address = (((char *) Local[my_id].Particles)
|
2017-04-26 18:03:02 +02:00
|
|
|
+ (length * sizeof(particle *)) - 1);
|
2017-04-26 17:20:15 +02:00
|
|
|
|
|
|
|
Place all addresses x such that (starting_address <= x < ending_address)
|
|
|
|
on node my_id
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
UNLOCK(G_Memory->mal_lock);
|
|
|
|
Local[my_id].Max_Particles = length;
|
|
|
|
Local[my_id].Num_Particles = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
InitParticleList (long my_id, long num_assigned, long starting_id)
|
|
|
|
{
|
|
|
|
long i;
|
|
|
|
|
|
|
|
for (i = 0; i < num_assigned; i++)
|
|
|
|
Local[my_id].Particles[i] = Particle_List[i + starting_id];
|
|
|
|
Local[my_id].Num_Particles = num_assigned;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PrintParticle (particle *p)
|
|
|
|
*
|
|
|
|
* Args : the address of a particle, p.
|
|
|
|
*
|
|
|
|
* Returns : nothing.
|
|
|
|
*
|
|
|
|
* Side Effects : Prints to stdout the information stored for p.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
PrintParticle (particle *p)
|
|
|
|
{
|
|
|
|
if (p != NULL) {
|
|
|
|
printf("P %6ld :", p->id);
|
|
|
|
printf(" Pos = ");
|
|
|
|
PrintVector(&(p->pos));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf("Particle has not been initialized yet.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
PrintAllParticles ()
|
|
|
|
{
|
|
|
|
long i;
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
printf(" PARTICLE POSITIONS\n\n");
|
|
|
|
for (i = 0; i < Total_Particles; i++) {
|
|
|
|
PrintParticle(Particle_List[i]);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
PrintParticleArrayIds (particle **p_array, long num_particles)
|
|
|
|
{
|
|
|
|
long tab_count = PARTICLES_PER_LINE;
|
|
|
|
long i = 0;
|
|
|
|
|
|
|
|
if (num_particles == 0)
|
|
|
|
printf("NONE\n");
|
|
|
|
else {
|
|
|
|
for (i = 0; i < num_particles; i++) {
|
2017-04-26 18:03:02 +02:00
|
|
|
if (tab_count == 0) {
|
|
|
|
tab_count = PARTICLES_PER_LINE;
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
printf("\tP%ld", p_array[i]->id);
|
|
|
|
tab_count -= 1;
|
2017-04-26 17:20:15 +02:00
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* InitParticle (long my_id, real x_pos, real y_pos, real charge)
|
|
|
|
*
|
|
|
|
* Args : the x_pos, y_pos, and charge (in eV) of the particle.
|
|
|
|
*
|
|
|
|
* Returns : the address of the newly created particle.
|
|
|
|
*
|
|
|
|
* Side Effects : Initializes field to 0, and sets the particle ID to a
|
|
|
|
* unique number. Also converts charge to coulombs from eV.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
particle *
|
|
|
|
InitParticle (real charge, real mass)
|
|
|
|
{
|
|
|
|
particle *p;
|
|
|
|
static long particle_id = 0;
|
|
|
|
|
|
|
|
p = Particle_List[particle_id];
|
|
|
|
p->id = particle_id++;
|
|
|
|
p->charge = charge;
|
|
|
|
p->mass = mass;
|
|
|
|
p->pos.x = (real) 0.0;
|
|
|
|
p->pos.y = (real) 0.0;
|
|
|
|
p->vel.x = (real) 0.0;
|
|
|
|
p->vel.y = (real) 0.0;
|
|
|
|
p->acc.x = (real) 0.0;
|
|
|
|
p->acc.y = (real) 0.0;
|
|
|
|
p->field.r = (real) 0.0;
|
|
|
|
p->field.i = (real) 0.0;
|
|
|
|
p->cost = 1;
|
|
|
|
p->box = 0.0;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
PickShell (vector *v, real radius)
|
|
|
|
{
|
|
|
|
real temp_r;
|
|
|
|
real r_scale;
|
|
|
|
|
|
|
|
do {
|
|
|
|
v->x = XRand(-1.0, 1.0);
|
|
|
|
v->y = XRand(-1.0, 1.0);
|
|
|
|
temp_r = DOT_PRODUCT((*v), (*v));
|
|
|
|
}
|
|
|
|
while (temp_r >1.0);
|
|
|
|
r_scale = radius / (real) sqrt(temp_r);
|
|
|
|
VECTOR_MUL((*v), (*v), r_scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
real
|
|
|
|
XRand (real low, real high)
|
|
|
|
{
|
|
|
|
real ret_val;
|
|
|
|
|
|
|
|
ret_val = low + (high - low) * ((real) rand/*om*/() / 2147483647.0);
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#undef PARTICLES_PER_LINE
|
|
|
|
#undef MAX_FRAC
|
|
|
|
#undef RANDOM_SIZE
|
|
|
|
#undef ONE_EV
|