source: proiecte/NBody/Tree codes/treecode.c @ 170

Last change on this file since 170 was 170, checked in by (none), 14 years ago
File size: 11.3 KB
Line 
1/****************************************************************************/
2/* TREECODE.C: new hierarchical N-body code.                                */
3/* Copyright (c) 2001 by Joshua E. Barnes, Honolulu, Hawai`i.               */
4/****************************************************************************/
5
6#include "stdinc.h"
7#include "mathfns.h"
8#include "vectmath.h"
9#include "getparam.h"
10#define global                                  /* don't default to extern  */
11#include "treecode.h"
12
13/*
14 * Default values for input parameters.
15 */
16
17string defv[] = {               ";Hierarchical N-body code "
18#if defined(QUICKSCAN)
19                                    "(quick scan)",
20#else
21                                    "(theta scan)",
22#endif
23    "in=",                      ";Input file with initial conditions",
24    "out=",                     ";Output file of N-body frames",
25#if defined(USEFREQ)
26    "freq=32.0",                ";Leapfrog integration frequency",
27#else
28    "dtime=1/32",               ";Leapfrog integration timestep",
29#endif
30    "eps=0.025",                ";Density smoothing length",
31#if !defined(QUICKSCAN)
32    "theta=1.0",                ";Force accuracy parameter",
33#endif
34    "usequad=false",            ";If true, use quad moments",
35    "options=",                 ";Various control options",
36    "tstop=2.0",                ";Time to stop integration",
37#if defined(USEFREQ)
38    "freqout=4.0",              ";Data output frequency",
39#else
40    "dtout=1/4",                ";Data output timestep",
41#endif
42    "nbody=4096",               ";Number of bodies for test run",
43    "seed=123",                 ";Random number seed for test run",
44    "save=",                    ";Write state file as code runs",
45    "restore=",                 ";Continue run from state file",
46    "VERSION=1.4",              ";Joshua Barnes  February 21 2001",
47    NULL,
48};
49
50/* Prototypes for local procedures. */
51
52local void treeforce(void);                     /* do force calculation     */
53local void stepsystem(void);                    /* advance by one time-step */
54local void startrun(void);                      /* initialize system state  */
55local void testdata(void);                      /* generate test data       */
56
57/*
58 * MAIN: toplevel routine for hierarchical N-body code.
59 */
60
61int main(int argc, string argv[])
62{
63    initparam(argv, defv);                      /* initialize param access  */
64    headline = defv[0] + 1;                     /* skip ";" in headline     */
65    startrun();                                 /* get params & input data  */
66    startoutput();                              /* activate output code     */   
67    if (nstep == 0) {                           /* if data just initialized */
68        treeforce();                            /* do complete calculation  */
69        //output();                               /* and report diagnostics   */
70         //write_diagnostics(nstep);
71    }
72#if defined(USEFREQ)
73    if (freq != 0.0)                            /* if time steps requested  */
74        while (tstop - tnow > 0.01/freq) {      /* while not past tstop     */
75            stepsystem();                       /* advance step by step     */
76            //output();                           /* and output results       */
77        }
78#else
79    if (dtime != 0.0)                           /* if time steps requested  */
80        while (tstop - tnow > 0.01 * dtime) {   /* while not past tstop     */     
81            stepsystem();                       /* advance step by step     */
82            //output();                           /* and output results       */
83           //write_diagnostics(nstep);     
84        }
85#endif
86    return (0);                                 /* end with proper status   */
87}
88
89/*
90 * TREEFORCE: common parts of force calculation.
91 */
92void write_diagnostics(int step)
93{
94     double ekin = 0;                      // kinetic energy of the n-body system     
95      bodyptr p;
96      int i = 0;
97      double epot = 0;
98      //epot = Phi(root);
99    for (p = bodytab; p < bodytab+nbody; p++)
100    {
101      if(Type(p) == BODY)     
102      {
103        for (i = 0; i < NDIM ; i++)
104        ekin += 0.5 * Mass(p) * Vel(p)[i] * Vel(p)[i];
105        //fprintf(stdout, "ekin = %f\n", ekin);
106        epot += Phi(p);
107      }
108    }
109     double etot = ekin + epot;             // total energy of the n-body system
110     
111        if (step == 0)  // at first pass, pass the initial
112          einit = etot;                    // energy back to the calling function
113           
114        fprintf(stdout, "At time t = %f , after  %d  steps :\n",dtime, step );
115        fprintf(stdout,"Einit = %f\n", einit);
116        fprintf(stdout,"E_kin = %f\n", ekin);
117        fprintf(stdout,"E_pot = %f\n ", epot);
118        fprintf(stdout,"E_tot = %f\n", etot);
119        fprintf(stdout,"Absolute energy error: E_tot - E_init = %f\n",etot - einit);
120        fprintf(stdout, "Relative energy error: (E_tot - E_init) / E_init = %f\n", (etot - einit) / einit);
121}
122local void treeforce(void)
123{
124    bodyptr p;
125
126    for (p = bodytab; p < bodytab+nbody; p++)   /* loop over all bodies     */
127        Update(p) = TRUE;                       /* update all forces        */
128    maketree(bodytab, nbody);                   /* construct tree structure */
129    gravcalc();                                 /* compute initial forces   */
130    forcereport();                              /* print force statistics   */
131}
132
133/*
134 * STEPSYSTEM: advance N-body system using simple leap-frog.
135 */
136
137local void stepsystem(void)
138{
139#if defined(USEFREQ)
140    real dtime = 1.0 / freq;                    /* set basic time-step      */
141#endif
142    bodyptr p;
143
144    for (p = bodytab; p < bodytab+nbody; p++) { /* loop over all bodies     */
145        ADDMULVS(Vel(p), Acc(p), 0.5 * dtime);  /* advance v by 1/2 step    */
146        ADDMULVS(Pos(p), Vel(p), dtime);        /* advance r by 1 step      */
147    }
148    treeforce();                                /* perform force calc.      */
149    for (p = bodytab; p < bodytab+nbody; p++) { /* loop over all bodies     */
150        ADDMULVS(Vel(p), Acc(p), 0.5 * dtime);  /* advance v by 1/2 step    */
151    }
152    nstep++;                                    /* count another time step  */
153    tnow = tnow + dtime;                        /* finally, advance time    */
154}
155
156/*
157 * STARTRUN: startup hierarchical N-body code.
158 */
159
160local void startrun(void)
161{
162#if !defined(USEFREQ)
163    double dt1, dt2;
164#endif
165
166    infile = getparam("in");                    /* set I/O file names       */
167    outfile = getparam("out");
168    savefile = getparam("save");
169    if (strnull(getparam("restore"))) {         /* if starting a new run    */
170        eps = getdparam("eps");                 /* get input parameters     */
171#if defined(USEFREQ)
172        freq = getdparam("freq");
173#else
174        dtime = (sscanf(getparam("dtime"), "%lf/%lf", &dt1, &dt2) == 2 ?
175                 dt1 / dt2 : getdparam("dtime"));
176#endif
177#if !defined(QUICKSCAN)
178        theta = getdparam("theta");
179#endif
180        usequad = getbparam("usequad");
181        tstop = getdparam("tstop");
182#if defined(USEFREQ)
183        freqout = getdparam("freqout");
184#else
185        dtout = (sscanf(getparam("dtout"), "%lf/%lf", &dt1, &dt2) == 2 ?
186                 dt1 / dt2 : getdparam("dtout"));
187#endif
188        options = getparam("options");
189        if (! strnull(infile))                  /* if data file was given   */
190            inputdata_2();                        /* then read inital data    */
191        else {                                  /* else make initial data   */
192            nbody = getiparam("nbody");         /* get number of bodies     */
193            if (nbody < 1)                      /* check for silly values   */
194                error("startrun: absurd value for nbody\n");
195            srandom(getiparam("seed"));         /* set random number gen.   */
196            testdata();                         /* and make plummer model   */
197            tnow = 0.0;                         /* reset elapsed model time */
198        }
199        rsize = 1.0;                            /* start root w/ unit cube  */
200        nstep = 0;                              /* begin counting steps     */
201        tout = tnow;                            /* schedule first output    */
202    } else {                                    /* else restart old run     */
203        restorestate(getparam("restore"));      /* read in state file       */
204        if (getparamstat("eps") & ARGPARAM)     /* if given, set new params */
205            eps = getdparam("eps");
206#if !defined(QUICKSCAN)
207        if (getparamstat("theta") & ARGPARAM)
208            theta = getdparam("theta");
209#endif
210        if (getparamstat("usequad") & ARGPARAM)
211            usequad = getbparam("usequad");
212        if (getparamstat("options") & ARGPARAM)
213            options = getparam("options");
214        if (getparamstat("tstop") & ARGPARAM)
215            tstop = getdparam("tstop");
216#if defined(USEFREQ)
217        if (getparamstat("freqout") & ARGPARAM)
218            freqout = getdparam("freqout");
219        if (scanopt(options, "new-tout"))       /* if output time reset     */
220            tout = tnow + 1 / freqout;          /* then offset from now     */
221#else
222            dtout = (sscanf(getparam("dtout"), "%lf/%lf", &dt1, &dt2) == 2 ?
223                      dt1 / dt2 : getdparam("dtout"));
224        if (scanopt(options, "new-tout"))       /* if output time reset     */
225            tout = tnow + dtout;                /* then offset from now     */
226#endif
227    }
228}
229
230/*
231 * TESTDATA: generate Plummer model initial conditions for test runs,
232 * scaled to units such that M = -4E = G = 1 (Henon, Hegge, etc).
233 * See Aarseth, SJ, Henon, M, & Wielen, R (1974) Astr & Ap, 37, 183.
234 */
235
236#define MFRAC  0.999                            /* cut off 1-MFRAC of mass  */
237
238local void testdata(void)
239{
240    real rsc, vsc, r, v, x, y;
241    vector rcm, vcm;
242    bodyptr p;
243
244    bodytab = (bodyptr) allocate(nbody * sizeof(body));
245                                                /* alloc space for bodies   */
246    rsc = (3 * PI) / 16;                        /* and length scale factor  */
247    vsc = rsqrt(1.0 / rsc);                     /* find speed scale factor  */
248    CLRV(rcm);                                  /* zero out cm position     */
249    CLRV(vcm);                                  /* zero out cm velocity     */
250    for (p = bodytab; p < bodytab+nbody; p++) { /* loop over bodies         */
251        Type(p) = BODY;                         /* tag as a body            */
252        Mass(p) = 1.0 / nbody;                  /* set masses equal         */
253        x = xrandom(0.0, MFRAC);                /* pick enclosed mass       */
254        r = 1.0 / rsqrt(rpow(x, -2.0/3.0) - 1); /* find enclosing radius    */
255        pickshell(Pos(p), NDIM, rsc * r);       /* pick position vector     */
256        do {                                    /* select from fn g(x)      */
257            x = xrandom(0.0, 1.0);              /* for x in range 0:1       */
258            y = xrandom(0.0, 0.1);              /* max of g(x) is 0.092     */
259        } while (y > x*x * rpow(1 - x*x, 3.5)); /* using von Neumann tech   */
260        v = x * rsqrt(2.0 / rsqrt(1 + r*r));    /* find resulting speed     */
261        pickshell(Vel(p), NDIM, vsc * v);       /* pick velocity vector     */
262        ADDMULVS(rcm, Pos(p), 1.0 / nbody);     /* accumulate cm position   */
263        ADDMULVS(vcm, Vel(p), 1.0 / nbody);     /* accumulate cm velocity   */
264    }
265    for (p = bodytab; p < bodytab+nbody; p++) { /* loop over bodies again   */
266        SUBV(Pos(p), Pos(p), rcm);              /* subtract cm position     */
267        SUBV(Vel(p), Vel(p), vcm);              /* subtract cm velocity     */
268    }
269}
Note: See TracBrowser for help on using the repository browser.