Nbody6
 All Files Functions Variables
reduce.f
Go to the documentation of this file.
1  SUBROUTINE reduce(IESC,JESC,ISUB)
2 *
3 *
4 * Reduction of chain.
5 * -------------------
6 *
7  include 'common6.h'
8  parameter(nmx=10,nmx2=2*nmx,nmx3=3*nmx,nmx4=4*nmx,
9  & nmx8=8*nmx,nmxm=nmx*(nmx-1)/2)
10  REAL*8 m,mass,mc,mij,mkk,xcm(3),vcm(3),dxc(3),dvc(3),cg(6)
11  common/chain1/ xch(nmx3),vch(nmx3),m(nmx),
12  & zz(nmx3),wc(nmx3),mc(nmx),
13  & xi(nmx3),pi(nmx3),mass,rinv(nmxm),rsum,mkk(nmx),
14  & mij(nmx,nmx),tkk(nmx),tk1(nmx),iname(nmx),nn
15  common/chainc/ xc(3,ncmax),uc(3,ncmax),bodyc(ncmax),ich,
16  & listc(lmax)
17  common/chreg/ timec,tmax,rmaxc,cm(10),namec(6),nstep1,kz27,kz30
18  common/clump/ bodys(ncmax,5),t0s(5),ts(5),steps(5),rmaxs(5),
19  & names(ncmax,5),isys(5)
20  common/ccoll2/ qk(nmx4),pk(nmx4),rik(nmx,nmx),SIZE(nmx),vstar1,
21  & ecoll1,rcoll,qperi,istar(nmx),icoll,isync,ndiss1
22  common/incond/ x4(3,nmx),xdot4(3,nmx)
23  REAL*8 firr(3),fd(3)
24 *
25 *
26 * Define discrete time for new polynomials (DT2 < 0 is OK).
27  time0 = time
28  dt2 = t0s(isub) + timec - tprev
29  dt8 = (tblock - tprev)/8.0d0
30  time = tprev + nint(dt2/dt8)*dt8
31  time = min(tblock,time)
32 * Re-define initial epoch for consistency (ignore phase error).
33  t0s(isub) = time - timec
34 *
35  IF (kz(30).GT.2) THEN
36  WRITE (6,1) time0+toff, time+toff, dt2, dt8
37  1 FORMAT (' REDUCE: TIME0 TIME DT2 DT8 ',2f12.6,1p,2e10.2)
38  END IF
39 *
40 * Make new chain from remaining members.
41  2 lk = 0
42  DO 10 l = 1,nch
43  IF (l.EQ.iesc) go to 10
44  DO 5 k = 1,3
45  lk = lk + 1
46  xch(lk) = x4(k,l)
47  vch(lk) = xdot4(k,l)
48  5 CONTINUE
49  10 CONTINUE
50 *
51 * Reduce chain membership and mass (global & local COMMON).
52  nch = nch - 1
53  nn = nch
54  mass = mass - m(iesc)
55 *
56 * Improve coordinates & velocities of c.m. body to order F3DOT.
57  CALL xvpred(ich,-1)
58 *
59 * Predict X & XDOT of pertubers to order FDOT.
60  nb1 = listc(1) + 1
61  DO 15 l = 2,nb1
62  j = listc(l)
63  CALL xvpred(j,-2)
64  15 CONTINUE
65 *
66 * Set new c.m. for reduced system and save old c.m. variables.
67  DO 20 k = 1,3
68  dxc(k) = -bodyc(iesc)*x4(k,iesc)/(body(ich) - bodyc(iesc))
69  dvc(k) = -bodyc(iesc)*xdot4(k,iesc)/(body(ich) - bodyc(iesc))
70  xcm(k) = x(k,ich) + dxc(k)
71  vcm(k) = xdot(k,ich) + dvc(k)
72  cm(k) = x(k,ich)
73  cm(k+3) = xdot(k,ich)
74  20 CONTINUE
75 *
76 * Re-define new chain variables w.r. to modified c.m. (NB! retain X4).
77  lk = 0
78  DO 30 l = 1,nch
79  DO 25 k = 1,3
80  lk = lk + 1
81  xch(lk) = xch(lk) - dxc(k)
82  vch(lk) = vch(lk) - dvc(k)
83  25 CONTINUE
84  30 CONTINUE
85 *
86 * Save original mass & neighbour radius of c.m. body.
87  bodych = body(ich)
88  rs0 = rs(ich)
89 *
90 * Search for global index of escaper.
91  DO 40 j = ifirst,ntot
92  IF (name(j).EQ.namec(iesc)) THEN
93  i = j
94  IF (body(j).GT.0.0d0) WRITE (6,35) i, iesc, namec(iesc)
95  35 FORMAT (' WARNING! NON-ZERO GHOST I IESC NAMEC ',3i5)
96  go to 55
97  END IF
98  40 CONTINUE
99 *
100 * Switch to another reference body since #ICH is escaping (NAME = 0).
101  i = ich
102  IF (iesc.GT.1) THEN
103  new = 1
104  ELSE
105  new = 2
106  END IF
107 *
108 * Identify global index of new reference body (including binary c.m.).
109  DO 45 j = ifirst,ntot
110  IF (name(j).EQ.namec(new)) THEN
111  ich = j
112  go to 50
113  END IF
114  45 CONTINUE
115 *
116 * Include warning if no reference body (this should not occur).
117  WRITE (6,48) iesc, namec(new)
118  48 FORMAT (' REDUCE: DANGER! NO REFERENCE BODY IESC NAME',2i5)
119  nch = nch + 1
120  nn = nch
121  mass = mass + m(iesc)
122  go to 100
123 *
124 * Copy neighbour list of old c.m. body for routine NBREST.
125  50 nnb = list(1,i)
126  DO 52 l = 2,nnb+1
127  jpert(l-1) = list(l,i)
128  52 CONTINUE
129 *
130 * Restore ghost to lists of neighbours (body #I will be skipped).
131  jlist(1) = ich
132  CALL nbrest(i,1,nnb)
133 *
134  IF (kz(30).GT.1) THEN
135  WRITE (6,53) name0, name(ich), ich
136  53 FORMAT (' REDUCE: SWITCH C.M. NAME0 NAMECH ICH ',3i5)
137  END IF
138 *
139 * Exchange name of reference body and initialize new c.m. name.
140  name(i) = name0
141  name0 = name(ich)
142  name(ich) = 0
143 *
144 * Update total mass and initialize new c.m. body variables.
145  55 body(ich) = bodych - bodyc(iesc)
146  cm(7) = body(ich)
147  t0(ich) = time
148  DO 60 k = 1,3
149  x(k,ich) = xcm(k)
150  x0(k,ich) = xcm(k)
151  xdot(k,ich) = vcm(k)
152  x0dot(k,ich) = vcm(k)
153  60 CONTINUE
154 *
155 * Restore the mass and transform to global coordinates & velocities.
156  body(i) = bodyc(iesc)
157  t0(i) = time
158  DO 65 k = 1,3
159  x(k,i) = x4(k,iesc) + cm(k)
160  xdot(k,i) = xdot4(k,iesc) + cm(k+3)
161  x0(k,i) = x(k,i)
162  x0dot(k,i) = xdot(k,i)
163  65 CONTINUE
164 *
165 * Remove chain (and clump) mass & reference name of escaper.
166  DO 70 l = iesc,nch
167  m(l) = m(l+1)
168  bodyc(l) = bodyc(l+1)
169  namec(l) = namec(l+1)
170  SIZE(l) = SIZE(l+1)
171  istar(l) = istar(l+1)
172  bodys(l,isub) = bodys(l+1,isub)
173  names(l,isub) = names(l+1,isub)
174  70 CONTINUE
175 *
176 * Ensure current coordinates & velocities for chain components.
177  CALL xcpred(1)
178 *
179 * Initialize neighbour list using current radius of (old) #ICH.
180  CALL nblist(ich,rs0)
181 *
182 * Set dominant F & FDOT on body #I for #ICH in FPOLY2.
183  jlist(1) = ich
184  jlist(2) = jclose
185  np = 2
186  IF (jclose.EQ.0) np = 1
187  CALL fclose(i,np)
188 *
189 * Perform re-initialization of c.m. polynomials & perturber list.
190  CALL reinit(isub)
191 *
192 * Copy new chain coordinates & velocities to standard variables.
193  lk = 0
194  DO 80 l = 1,nch
195  DO 75 k = 1,3
196  lk = lk + 1
197  x4(k,l) = xch(lk)
198  xdot4(k,l) = vch(lk)
199  75 CONTINUE
200  80 CONTINUE
201 *
202 * Copy neighbour list of cm. body for routine NBREST.
203  nnb = list(1,ich)
204  DO 82 l = 2,nnb+1
205  jpert(l-1) = list(l,ich)
206  82 CONTINUE
207 *
208 * Restore ghost to lists of neighbours (body #ICH will be skipped).
209  jlist(1) = i
210  CALL nbrest(ich,1,nnb)
211 *
212 * Make new neighbour list.
213  CALL nblist(i,rs0)
214 *
215 * Distinguish between single particle and binary (JESC = 0 & > 0).
216  IF (jesc.EQ.0) THEN
217 * Initialize force polynomials & time-steps (add differential F & FD).
218  iphase = 8
219  CALL fpoly1(i,i,0)
220  DO 85 k = 1,3
221  firr(k) = 0.0
222  fd(k) = 0.0
223  85 CONTINUE
224  CALL fchain(i,0,x(1,i),xdot(1,i),firr,fd)
225  rij2 = 0.0
226  vij2 = 0.0
227  rdot = 0.0
228  DO 86 k = 1,3
229  f(k,i) = f(k,i) + firr(k)
230  fdot(k,i) = fdot(k,i) + fd(k)
231  rij2 = rij2 + (x(k,i) - x(k,ich))**2
232  vij2 = vij2 + (xdot(k,i) - xdot(k,ich))**2
233  rdot = rdot + (x(k,i) - x(k,ich))*(xdot(k,i)-xdot(k,ich))
234  86 CONTINUE
235  CALL fpoly2(i,i,0)
236 * Reduce regular steps for large velocities to minimize NNB change.
237  j = ich
238  DO 87 l = 1,2
239  vi2 = xdot(1,j)**2 + xdot(2,j)**2 + xdot(3,j)**2
240  IF (vi2.GT.2.0.AND.stepr(j).GE.8.0*step(j)) THEN
241  stepr(j) = stepr(j)/8.0d0
242  END IF
243  j = i
244  87 CONTINUE
245 * Check high-velocity ejection for outwards hyperbolic motion.
246  hi = 0.5*vij2 - (body(i) + body(ich))/sqrt(rij2)
247  IF (hi.GT.0.0.AND.rdot.GT.0.0) THEN
248  CALL hivel(i)
249  END IF
250  iphase = -1
251 * Include case of escaping binary (set JESC < 0 for new KS).
252  ELSE IF (jesc.GT.0) THEN
253  iclose = i
254  IF (jesc.GT.iesc) jesc = jesc - 1
255  iesc = jesc
256  jesc = -1
257  go to 2
258  ELSE
259 * Initialize KS regularization after second reduction.
260  icomp = min(iclose,i)
261  jcomp = max(iclose,i)
262  CALL ksreg
263  END IF
264 *
265 * Re-activate any dormant binary.
266  IF (i.GT.n.AND.jesc.EQ.0) THEN
267  CALL renew(i)
268  END IF
269 *
270 * Prepare c.m. check.
271  DO 88 k = 1,6
272  cg(k) = 0.0
273  88 CONTINUE
274 *
275  lk = 0
276  DO 95 l = 1,nch
277  DO 90 k = 1,3
278  lk = lk + 1
279  cg(k) = cg(k) + bodyc(l)*xch(lk)
280  cg(k+3) = cg(k+3) + bodyc(l)*vch(lk)
281  90 CONTINUE
282  95 CONTINUE
283 *
284  DO 96 k = 1,6
285  cg(k) = cg(k)/body(ich)
286  96 CONTINUE
287 *
288  IF (kz(30).GT.2) THEN
289  WRITE (6,97) time+toff, (cg(k),k=1,6)
290  97 FORMAT (' REDUCE: T CG ',f12.5,1p,6e9.1)
291  END IF
292 *
293  100 RETURN
294 *
295  END