Beispiel #1
0
local void stepsystem(void) {
  bodyptr p1, p2, p;

  p1 = bodytab + MAX(nstatic, 0);		// set dynamic body range
  p2 = bodytab + nbody + MIN(nstatic, 0);
  for (p = p1; p < p2; p++) {			// loop over body range	
    ADDMULVS(Vel(p), Acc(p), 0.5 * dtime);	// advance v by 1/2 step
    ADDMULVS(Pos(p), Vel(p), dtime);		// advance r by 1 step
  }
  treeforce();
  for (p = p1; p < p2; p++) {			// loop over body range	
    ADDMULVS(Vel(p), Acc(p), 0.5 * dtime);	// advance v by 1/2 step
  }
  nstep++;					// count another time step
  tnow = tnow + dtime;				// finally, advance time
}
Beispiel #2
0
int main(int argc, string argv[])
{
  initparam(argv, defv);			// initialize param access
  headline = defv[0] + 1;			// use default headline
  startrun();					// get params & input data
  startoutput();				// activate output code
  if (nstep == 0) {				// if data just initialized
    treeforce();				// calculate initial forces
    output();					// generate initial output
  }
  if (dtime != 0.0)				// if time steps requested
    while (tstop - tnow > 0.01 * dtime) {	// while not past tstop
      stepsystem();				// advance step by step
      output();					// output results each time
    }
  return (0);					// end with proper status
}
Beispiel #3
0
int main(int argc, string argv[]) {
  initparam(argv, defv);			// initialize param access
  headline = defv[0] + 1;			// use default headline
  startrun();					// get params & input data
  startoutput();				// activate output code
  if (nstep == 0) {				// if data just initialized
    treeforce_initial_0 = wtime();
    treeforce();				// calculate initial forces
    treeforce_initial_1 = wtime();
    output();					// generate initial output
  }
  if (dtime != 0.0)				// if time steps requested
    // TODO: make this work in timesteps?
    treeforce_0 = wtime();
    while (nstep <= timesteps) { // while not past tstop
      stepsystem();       // advance step by step
      output();         // output results each time
    }
    // while (tstop - tnow > 0.01 * dtime) {	// while not past tstop
    //   stepsystem();				// advance step by step
    //   output();					// output results each time
    // }
    treeforce_1 = wtime();
  finaloutput();
  bodyptr p;
  bodyptr q;
  float phi = 0.0f;
  for (p = bodytab; p < bodytab+nbody; p++) {// loop over all bodies
    for (q = bodytab; q < bodytab+nbody; q++) {// loop over all bodies
    //  printf("Pos(p) = (%.8f,%.8f,%.8f)\n",  Pos(p)[0], Pos(p)[1], Pos(p)[2]);
    //  printf("Pos(q) = (%.8f,%.8f,%.8f)\n",  Pos(q)[0], Pos(q)[1], Pos(q)[2]);
      float rx = Pos(q)[0] - Pos(p)[0];
      float ry = Pos(q)[1] - Pos(p)[1];
      float rz = Pos(q)[2] - Pos(p)[2];
      float r2 = rx*rx + ry*ry + rz*rz + eps;
      float r2inv = 1.0 / sqrt(r2);
      float r6inv = r2inv * r2inv * r2inv;
      float mass = Mass(q);
      phi += mass * r6inv;
    }
  }
  printf(" Answer = %f\n", phi);
  return (0);					// end with proper status
}
main()
{
      
/******************************************************************************/
/*  BUILDING DISK POSITION DISTRIBUTION                                       */
/******************************************************************************/

    std::cout << "Building disk\n";         //  printing disk parameters
    std::cout << "  Mdisk = " << Md << "\n";
    std::cout << "  Ndisk = " << Ndisk << "\n";
    std::cout << "  Radial Scale Length h = " << h << "\n";
    std::cout << "  Vertical Scale Length z0 = " << z0 << "\n";
    std::cout << "  Radial Cutoff = " << diskcut << "\n";
    std::cout << "  Vertical Cutoff = " << thickcut << "\n";
    
    std::vector<Vector> disk(Ndisk, Vector(3)); //  array of disk positions
    
    min = 0.0, max = diskcut;               //  setting max and min radii
    topbound = findtopbound(surfacedist, min, max);   //  finding topbound
    
    for (int i = 0; i < Ndisk; i++)         //  for each particle in disk
    {
        r = rejectionsample(surfacedist, min, max, topbound); //  choose
                                            //  random radius
        disk[i][0] = r;                     //  assigning as such
        disk[i][1] = randomreal(0.0, 2.0*PI); //  randomize azimuthal angle
    }                                       
    
    min = -thickcut;                        //  setting min and max
    max = thickcut;                         //  heights
    topbound = findtopbound(diskthick, min, max);   //  finding topbound
    for (int i = 0; i < Ndisk; i++)         //  for each disk particle
    {
        disk[i][2] = rejectionsample(diskthick, min, max, topbound);    //
                                            //  choosing height randomly
        bodies[i].mass = Md / ((double)Ndisk);  //  assigning masses such that
                                            //  total mass is correct
        bodies[i].pos = cyltocart(disk[i]); //  transforming to cartesian coords
        bodies[i].id = i;                   //  assigning particle id
        bodies[i].DM = false;               //  these are not dark
    }
    

/******************************************************************************/
/*  BUILDING HALO POSITION DISTRIBUTION                                       */
/******************************************************************************/
    
    std::cout << "Building Halo\n";         //  printing parameters
    std::cout << "  Mhalo = " << Mh << "\n";
    std::cout << "  Nhalo = " << Nhalo << "\n";
    std::cout << "  Scale Length rc = " << rc << "\n";
    std::cout << "  Scale Length gamma = " << g << "\n";
    std::cout << "  Cutoff Radius = " << halocut << "\n";

    std::vector<Vector> halo(Nhalo, Vector(3)); //  array of halo positions
    
    min = 0.0, max = halocut;               //  max and min for distribution
    topbound = findtopbound(hernquisthalo, min, max);   //  finding topbound
    for (int i = 0; i < Nhalo; i++)         //  for each bulge particle
    {
        r = rejectionsample(hernquisthalo, min, max, topbound);  //  select r from
                                            //  distribution
        bodies[Ndisk + i].pos = randomsphere(r);    //  randomize position
                                            //  on sphere
        bodies[Ndisk + i].mass = Mh / ((double)Nhalo);  //  normalizing mass
        bodies[Ndisk + i].id = Ndisk + i;   //  setting appropriate ID
        bodies[Ndisk + i].DM = true;        //  these are dark
        halo[i] = carttosphere(bodies[Ndisk + i].pos);  //  saving copy in
                                            //  spherical coords for later
    }
    

/******************************************************************************/
/*  BUILDING BULGE POSITION DISTRIBUTION                                      */
/******************************************************************************/

    std::cout << "Building Bulge\n";
    std::cout << "  Mbulge = " << Mb << "\n";
    std::cout << "  Nbulge = " << Nbulge << "\n";
    std::cout << "  Scale Length a = " << a << "\n";
    std::cout << "  Cutoff Radius = " << bulgecut << "\n";
    
    std::vector<Vector> bulge(Nbulge, Vector(3));   //  array of bulge positions
    
    min = 0.0; max = bulgecut;              //  distribution max and min
    topbound = findtopbound(bulgedist, min, max);   //  finding topbound
    for (int i = 0; i < Nbulge; i++)        //  for each particle
    {
        r = rejectionsample(bulgedist, min, max, topbound);  //  select r from
                                            //  distribution
        bodies[Ndisk + Nhalo + i].pos = randomsphere(r);    //  randomize sphere
                                            //  position
        bodies[Ndisk + Nhalo + i].mass = Mb / (double)Nbulge;   //  setting mass
        bodies[Ndisk + Nhalo + i].id = Ndisk + Nhalo + i;   //  setting IDs
        bulge[i] = carttosphere(bodies[Ndisk + Nhalo + i].pos); //  saving copy
                                            //  in spherical coordinates
    }

    
/******************************************************************************/
/*  Approximating Cumulative Mass Distribution M(r)                           */
/******************************************************************************/
    
    dr = halocut / ((double) massbins);     //  setting separation between mass
                                            //  bins
    
    std::cout << "Approximating Cumulative Mass Distribution M(r)\n";
    std::cout << "  Number of bins = " << massbins << "\n";
    std::cout << "  dr = " << dr << "\n";
    
    std::vector <Vector> Massatr(massbins, Vector(2));  //  Array to hold
                                            //  radius and value of cumulative
                                            //  mass distribution
    
    for (int i = 0; i < massbins; i++)      //  for each mass bin
    {
        Massatr[i][1] = ((double)(i+1))*dr; //  setting radius
        Massatr[i][0] = 0.0;                //  clearing total mass
        
        for (int j = 0; j < Ndisk; j++)     //  for each disk mass
        {
            r = sqrt(disk[j][0]*disk[j][0] + disk[j][2]*disk[j][2]);    // radius
                                            //  in spherical coordinates
            if((r < (double)(i+1)*dr))      //  if radius less than bin radius
            {
                Massatr[i][0] += Md / (double)Ndisk;    //  add mass
            }
        }
        
        for (int j = 0; j < Nhalo; j++)     //  for each halo mass
        {
            r = halo[j][0];                 //  radius
            if((r < (double)(i+1)*dr))      // if radius less than bin radius
            {
                Massatr[i][0] += Mh / (double)Nhalo;    //  add mass
            }
        }
        
        for (int j = 0; j < Nbulge; j++)    // for each bulge mass
        {
            r = bulge[j][0];                //  radius
            if((r < (double)(i+1)*dr))      //  if radius less than bin radius
            {
                Massatr[i][0] += Mb / (double)Nbulge;   //  add mass
            }
        }
    }
    
    
/******************************************************************************/
/*  Setting Halo Velocities                                                   */
/******************************************************************************/
    
    std::cout << "Setting Halo Velocities\n";
    
    double v;                               //  variable to hold speed
    double vesc;                            //  variable to hold escape speed
    
    std::vector<Vector> halovels(Nhalo, Vector(3)); //  Vector to hold halo
                                            //  velocities
    
    for (int i = 0; i < Nhalo; i++)         //  for each halo mass
    {
        r = halo[i][0];                     //  radius
        
        startbin = floor(r/dr);             //  starting index is floor of r/dr
        
        vesc = sqrt(2.0*Massatr[startbin][0]/r);    //  escape velocity
        
        vr2 = 0.0;                          //  clearing radial dispersion
        for (int j = startbin; j < massbins; j++)   //  for each mass bin
        {
            vr2 += hernquisthalo(Massatr[j][1])*dr*Massatr[j][0];   //  add 
        }                                   //  contribution
        vr2 /= (hernquisthalo(r)/(r*r));    //  dividing by halo density at r
        
        
        min = 0.0;                          //  distribution min
        max = 0.95*vesc;                    //  distribution max is 0.95 of
                                            //  escape velocity
        topbound = vr2 / 2.71828;           //  topbound is vr^2 / e
        
        v = rejectionsample(halospeeddist, min, max, topbound); //  selecting
                                            //  absolute speed
        halovels[i] = randomsphere(v);      //  randomizing cartesian velocities
                                            //  on a sphere of radius v
        bodies[Ndisk + i].vel = halovels[i];//  assigning velocities as such
        
    }
    
    
/******************************************************************************/
/*  Setting Bulge Velocities                                                  */
/******************************************************************************/

    
    std::cout << "Setting Bulge Velocities\n";
    
    std::vector<Vector> bulgevels(Nbulge, Vector(3));   // Vector to hold bulge
                                             // velocities
    
    for (int i = 0; i < Nbulge; i++)        //  for each particle
    {
        r = bulge[i][0];                    //  radius
        
        startbin = floor(r / dr);           //  starting index
        
        vesc = sqrt(2.0*Massatr[startbin][0]/r);    //  escape velocity
        
        vr2 = 0.0;                          //  clearing radial dispersion
        
        for (int j = startbin; j < massbins; j++)   //  for each mass bin
        {
            vr2 += bulgedist(Massatr[j][1])*dr*Massatr[j][0];   // add
                                            //  contribution
        }
        vr2 /= bulgedist(r)/(r*r);          //  dividing by halo density at r
        
        
        min = 0.0;                          //  distribution min
        max = 0.95*vesc;                    //  max is 0.95 of escape velocity
        topbound = vr2 / 2.71828;           //  topbound is vr^2 /e
        
        v = rejectionsample(bulgedist, min, max, topbound); //  selecting absolute
                                            //  absolute speed
        bulgevels[i] = randomsphere(v);     //  randomizing constrained cartesian
                                            //  velocities
        bodies[Ndisk + Nhalo + i].vel = bulgevels[i];   //  assining data as such
    }

    
/******************************************************************************/
/*  Setting Disk Velocities                                                   */
/******************************************************************************/

    std::cout << "Setting Disk Velocities\n";
    std::cout << "  Q = " << Q << "\n";
    std::cout << "  Reference radius = " << rref << "\n";
    std::vector<Vector> diskvels(Ndisk, Vector(3)); //  Vector to hold disk
                                            //  velocities
    
    double vz2;                             //  vertical dispersion
    double vc;                              //  circular speed
    double ar;                              //  radial acceleration
    double k;                               //  epicyclic frequency
    double sigmaz2;                         //  azimuthal velocity dispersion
    double sigmaavg;                        //  average dispersion
    double Omega;                           //  angular frequency
    double A;                               //  radial dispersion constant
    int count;                              //  count variable for averaging
    Vector acc(3);                          //  vector to store acceleration
    double as = 0.25*h;
    
    
    maketree(bodies, Ntot, root);           //  making tree
    
    // NORMALIZING RADIAL DISPERSION
    std::cout << "  Normalizing Radial Distribution\n";
    dr = diskcut / 1000.0;                  //  width of annulus in which
                                            //  to average dispersion
    sigmaavg = 0.0;                         //  zeroing average
    for (int i = 0; i < Ndisk; i++)         //  for each disk particle
    {
        r = disk[i][0];                     //  radius
        if (fabs(r - rref) < dr)            //  if radius in annulus
        {                                   //  calculate epicylclic frequency
            k = epicyclicfrequency(bodies, Ntot, i, root, eps, theta, 0.05*dr);
            sigmaavg += 3.36*Sigma(r)/k;    //  calculate dispersion and add to
                                            //  average
            count += 1;                     //  up count
        }  
    }
    
    sigmaavg /= (double)count;              //  divide total by count
    sigmaavg *= Q;                          //  adjust by Q
    
    A = sigmaavg*sigmaavg / Sigma(rref);    //  setting norm constant
    
    
    //  ASSIGNING VELOCITIES
    std::cout << "  Setting particle velocities\n";
    for (int i = 0; i < Ndisk; i++)         //  for every particle
    {
        r = disk[i][0];                     //  radius
        vz2 = PI*z0*Sigma(sqrt(r*r + 2.0*as*as));    //  vertical dispersion
        diskvels[i][2] = gaussianrandom(sqrt(vz2)); //  randomizing vertical
                                            //  with this dispersion
        
        vr2 = A*Sigma(sqrt(r*r + 2.0*as*as));   //  assigning radial dispersion
        diskvels[i][0] = gaussianrandom(sqrt(vr2)); //  randomizing radial
                                            //  dispersion
        
        acc = treeforce(&bodies[i], root, eps, theta);  //  acceleration
        ar = (acc[0]*bodies[i].pos[0] + acc[1]*bodies[i].pos[1])/r; //
                                            //  radial acceleration
        Omega = sqrt(fabs(ar)/r);           //  angular frequency
        k = epicyclicfrequency(bodies, Ntot, i, root, eps, theta, dr);  //
                                            //  epicyclic frequency
        vc = Omega*r;                       //  circular speed
        v = sqrt(fabs(vc*vc + vr2*(1.0 - (k*k)/(4.0*Omega*Omega) - 2.0*r/h)));  //
                                            //  azimuthal streaming velocity
        sigmaz2 = vr2*k*k/(4.0*Omega*Omega);//  azimuthal dispersion
        v += gaussianrandom(sqrt(sigmaz2)); //  adding random azimuthal component
        diskvels[i][1] = v;                 //  assigning azimuthal velocity 
        
                                            //  transforming to cartesian coords
        bodies[i].vel[0] = diskvels[i][0]*cos(disk[i][1])
                            - diskvels[i][1]*sin(disk[i][1]);
        bodies[i].vel[1] = diskvels[i][0]*sin(disk[i][1])
                            + diskvels[i][1]*cos(disk[i][1]);
        bodies[i].vel[2] = diskvels[i][2];
    }
    
    
/******************************************************************************/
/*  Reporting Average Disk Speed                                              */
/******************************************************************************/
    
    v = 0.0;
    
    for (int i = 0; i < Ndisk; i++)
    {
        v += bodies[i].vel.norm();
    }
    
    v /= (double)Ndisk;
    
    std::cout << "Average Disk Particle Speed: " << v << "\n";
    std::cout << "Disk Size: " << diskcut << "\n";
    std::cout << "Disk Crossing Time: " << diskcut / v << "\n";
    
    
    writeinitfile(Ntot, Nhalo, bodies, "data/initfile.txt");
    
    
 
}