Nbody6
 All Files Functions Variables
triple.f
Go to the documentation of this file.
1  SUBROUTINE triple(ISUB)
2 *
3 *
4 * Three-body regularization.
5 * --------------------------
6 *
7 * Method of Aarseth & Zare, Celestial Mechanics 10, 185.
8 * ......................................................
9 *
10 *
11  IMPLICIT REAL*8 (a-h,m,o-z)
12  parameter(ncmax=10)
13  common/azreg/ time3,tmax,q(8),p(8),r1,r2,r3,energy,m(3),x3(3,3),
14  & xdot3(3,3),cm(10),c11,c12,c19,c20,c24,c25,
15  & nstep3,name3(3),kz15,kz27
16  common/close/ rij(4,4),rcoll,qperi,SIZE(4),ecoll3,ip(4)
17  common/azcoll/ rk(3),qk(8),pk(8),icall,icoll,ndiss3
18  common/bssave/ ep(4),dsc,facm,tfac,itfac,jc
19  common/ebsave/ ebs
20  common/azconf/ iconf(3)
21  common/clump/ bodys(ncmax,5),t0s(5),ts(5),steps(5),rmaxs(5),
22  & names(ncmax,5),isys(5)
23  REAL*8 y(17)
24  SAVE
25 *
26 *
27 * Main variables for AZ regularization
28 * ************************************
29 *
30 * ---------------------------------------------------------------------
31 * CM(1-7) Coordinates, velocities & total mass of triple system.
32 * CM(8) Total energy of N-body system (copied in routine START3).
33 * CM(9) Binary energy change (copied to SBCOLL in START3).
34 * CM(10) Relative energy error (not used).
35 * C11 Inverse mass factor for DERQP3 (also C12,C19,C20,C24,C25).
36 * ENERGY Twice the initial total energy.
37 * ICALL Pericentre indicator (activated if MIN(R1,R2) < RSTAR).
38 * ICOLL Collision or capture indicator (activated in routine DERQP3).
39 * IP Polytropic index (=1: n = 3/2; =2: n = 2; =3: n = 3).
40 * KZ15 Triple option copied in START3 (full output if > 1).
41 * KZ27 Tidal capture & collision option (copied in START3).
42 * M Particle mass (CM(7) = M(1) + M(2) + M(3)).
43 * NAME3 Particle identity (initialized to global name).
44 * NREG Number of regularization switches.
45 * NSTEP3 Number of DIFSY3 calls.
46 * ICONF Three-body configuration array (initialized to 1, 2, 3).
47 * P Regularized momenta.
48 * Q Regularized coordinates.
49 * QPERI Pericentre distance of closest two-body motion.
50 * R1 Distance between M(1) and M(3).
51 * R2 Distance between M(2) and M(3).
52 * R3 Distance between M(1) and M(2) (not regularized).
53 * RCOLL Minimum two-body separation.
54 * RCRIT Escape test criterion (RGRAV or harmonic mean with RMAXS).
55 * RGRAV Gravitational radius (sum (M(I)*M(J))/ABS(0.5*ENERGY)).
56 * RIJ Minimum pairwise separations.
57 * RMAXS Maximum of unperturbed & initial size (R1 + R2).
58 * RSTAR Pericentre check distance (= 0.2*RGRAV).
59 * SIZE Individual stellar radius (collisions or tidal capture).
60 * TIME3 Local physical time in scaled units.
61 * TCR Local crossing time ((sum M(I))**2.5/ABS(ENERGY)**1.5).
62 * TOL Tolerance for DIFSY3 (1.0E-10 is recommended).
63 * TMAX Maximum integration time (based on c.m. step).
64 * X3 Particle coordinates (X3(3,I) is Z-component).
65 * XDOT3 Velocity components (XDOT3(3,I) is Z-component).
66 * ---------------------------------------------------------------------
67 *
68 *
69 * Save termination indicator and check for restart.
70  iterm = isub
71  IF (isub.GT.0) THEN
72 * Synchronize next time interval with c.m. step unless termination.
73  tmax = time3 + steps(isub)
74  IF (steps(isub).LE.0.0d0) dtau3 = 0.01*dtau3
75 * Copy input array for DIFSY3 (just in case).
76  go to 15
77  END IF
78 *
79 * Obtain initial conditions from N-body COMMON.
80  CALL start3(isub)
81 *
82 * Specify tolerance & DSC for DIFSY3 (relative energy error < TOL).
83  tol = 1.0d-10
84  dsc = 1.0
85 *
86 * Initialize diagnostic & COMMON variables.
87  r12min = 100.0
88  r3min = 100.0
89  rcoll = 100.0
90  zmi1 = 100.0
91  zmi2 = 100.0
92  zmi3 = 100.0
93  DO 10 j = 1,3
94  iconf(j) = j
95  DO 5 k = 1,3
96  rij(j,k) = 100.0
97  5 CONTINUE
98  10 CONTINUE
99  icall = 0
100  icoll = 0
101  next = 0
102  ndiss3 = 0
103  ecoll3 = 0.0d0
104  jc = 0
105  itfac = 0
106  nstep3 = 0
107  itry = 0
108  nreg = 0
109 *
110 * Initialize local time & regularized time.
111  time3 = 0.0d0
112  tau3 = 0.0d0
113  y(17) = 0.0d0
114 * Specify the number of first-order equations for the integrator.
115  neq = 17
116 *
117 * Evaluate the initial total energy (superseded; done in START3).
118 * CALL TRANS3(0)
119 *
120 * Transform to regularized variables.
121  CALL trans3(1)
122 *
123 * Define gravitational radius and pericentre check distance.
124  rgrav = (m(1)*m(2) + m(1)*m(3) + m(2)*m(3))/(0.5d0*abs(energy))
125  rstar = 0.2*rgrav
126 * Introduce average mass factor for Bulirsch-Stoer integrator.
127  facm = (m(1)*m(2) + m(1)*m(3) + m(2)*m(3))/3.0
128 *
129 * Ensure that unperturbed boundary exceeds system size.
130  r1 = q(1)**2 + q(2)**2 + q(3)**2 + q(4)**2
131  r2 = q(5)**2 + q(6)**2 + q(7)**2 + q(8)**2
132  IF (rmaxs(isub).LT.r1 + r2) rmaxs(isub) = r1 + r2
133 *
134 * Modify escape distance criterion in case of hierarchical system.
135  rcrit = max(rgrav,sqrt(rgrav*rmaxs(isub)))
136 *
137 * Specify local crossing time (also meaningful if ENERGY > 0).
138  tcr = (m(1) + m(2) + m(3))**2.5/abs(energy)**1.5
139 *
140 * Define a nominal crossing time in near-parabolic cases.
141  rmax = max(r1,r2)
142  tstar = rmax*sqrt(rmax/cm(7))
143 *
144 * Determine the smallest two-body time-scale from parabolic orbit.
145  im = 1
146  rm = r1
147  IF (r2.LT.r1) THEN
148  im = 2
149  rm = r2
150  END IF
151  vp2 = 2.0*(m(im) + m(3))/rm
152  tp = rm/sqrt(vp2)
153  tstar = min(tp,tstar)
154 *
155 * Set step for time transformation DT/DTAU = R1*R2/(R1 + R2)**0.5.
156  tpr = r1*r2/sqrt(r1 + r2)
157  dtau3 = min(tcr,tstar)*tol**0.1/tpr
158 *
159 * Form initial binding energy of the binary.
160  vrel2 = (xdot3(1,2) - xdot3(1,3))**2 +
161  & (xdot3(2,2) - xdot3(2,3))**2 +
162  & (xdot3(3,2) - xdot3(3,3))**2
163  eb0 = (0.5d0*vrel2/(m(2) + m(3)) - 1.0/r2)*m(2)*m(3)
164 *
165 * Initialize input array for the integrator.
166  15 DO 20 k = 1,8
167  y(k) = q(k)
168  y(k+8) = p(k)
169  20 CONTINUE
170  y(17) = time3
171 *
172 * Advance the equations of motion by Bulirsch-Stoer integrator.
173  30 CALL difsy3(neq,tol,dtau3,tau3,y)
174 *
175 * Copy regularized coordinates, momenta & time to COMMON variables.
176  DO 40 k = 1,8
177  q(k) = y(k)
178  p(k) = y(k+8)
179  40 CONTINUE
180  time0 = time3
181  time3 = y(17)
182 *
183 * Update relative distances (NB! Not quite latest value).
184  r1 = q(1)**2 + q(2)**2 + q(3)**2 + q(4)**2
185  r2 = q(5)**2 + q(6)**2 + q(7)**2 + q(8)**2
186 *
187 * Check minimum two-body separations and increase step counter.
188  r3min = min(r3min,r3)
189  rm = min(r1,r2)
190  r12min = min(r12min,rm)
191  nstep3 = nstep3 + 1
192 *
193 * Check minimum pairwise separations (also in DERQP3).
194  rk(1) = r1
195  rk(2) = r2
196  rk(3) = r3
197 *
198 * Consider pairs 1-2, 1-3 & 2-3 (initial names = 1, 2, 3).
199  DO 44 k = 1,3
200  DO 42 l = k+1,3
201  i = iconf(k)
202  j = iconf(l)
203 * Use cyclic loop index (3,1,2) for distances R3, R1 & R2.
204  kk = k - 1
205  IF (kk.EQ.0) kk = 3
206  rij(i,j) = min(rij(i,j),rk(kk))
207  rij(j,i) = min(rij(j,i),rk(kk))
208  42 CONTINUE
209  44 CONTINUE
210 *
211 * Update smallest moment of inertia during normal forward integration.
212  IF (time3.GT.time0.AND.jc.EQ.0) THEN
213  zmi = rm**2
214  zmi1 = zmi2
215  zmi2 = zmi3
216  zmi3 = zmi
217  dtau0 = dtau3
218  END IF
219 *
220 * Switch on search indicator during iteration or just after pericentre.
221  IF (icoll.LT.0) icall = 1
222  IF (rm.LT.rstar.AND.nstep3.GT.next) THEN
223  IF (zmi3.GT.zmi2.AND.zmi2.LT.zmi1) THEN
224  icall = 1
225  END IF
226  END IF
227 *
228 * Check for tidal dissipation or collision during last step.
229  IF (icoll.LE.0) go to 48
230 *
231 * Restore the minimum configuration.
232  DO 45 k = 1,8
233  q(k) = qk(k)
234  p(k) = pk(k)
235  45 CONTINUE
236 *
237 * Set two-body separations.
238  r1 = q(1)**2 + q(2)**2 + q(3)**2 + q(4)**2
239  r2 = q(5)**2 + q(6)**2 + q(7)**2 + q(8)**2
240 *
241 * Delay next search a few steps to avoid the same pericentre.
242  next = nstep3 + 2
243 *
244 * Distinguish between tidal energy loss and collision (ICOLL holds IM).
245  im = icoll
246  icoll = 0
247  IF (qperi.LT.4.0*max(SIZE(im),SIZE(3))) THEN
248  IF (qperi.LT.0.75*(SIZE(im) + SIZE(3))) THEN
249 *
250 * Transform to physical variables.
251  CALL trans3(2)
252 *
253 * Obtain global coordinates & velocities (ITERM < 0: termination).
254  iterm = -1
255  isub = -isub
256  CALL start3(isub)
257 *
258 * Combine internal energy and external c.m. kinetic energy.
259  h3 = 0.5d0*energy + 0.5d0*cm(7)*(cm(4)**2 + cm(5)**2 +
260  & cm(6)**2)
261 *
262 * Evaluate the two-body energy for diagnostic purposes.
263  CALL erel3(im,ebs,semi)
264  dminc = min(rcoll,dminc)
265 *
266 * Form composite body and begin KS regularization of new pair.
267  CALL cmbody(h3,3)
268  go to 100
269  ELSE
270 *
271 * Modify variables due to tidal effects and check stability parameter.
272  CALL qpmod3(im,iterm)
273 * Ensure positive step from pericentre and switch off search indicator.
274  dtau3 = abs(dtau0)
275  icall = 0
276 * Update relative distances (NB! Not quite latest value).
277  r1 = q(1)**2 + q(2)**2 + q(3)**2 + q(4)**2
278  r2 = q(5)**2 + q(6)**2 + q(7)**2 + q(8)**2
279  IF (iterm.LT.0) go to 90
280 * Initialize input array and continue integration.
281  go to 15
282  END IF
283  END IF
284 *
285 * See whether switching of reference body is desirable.
286  48 IF (r3.GT.rm) go to 70
287 *
288 * Use a simple distance test to determine new reference body IMIN.
289  imin = 1
290  IF (r2.LT.r1) imin = 2
291 *
292 * Transform to physical variables and rename the exchanged particles.
293  CALL trans3(2)
294 *
295  DO 50 k = 1,3
296  temp1 = x3(k,3)
297  temp2 = xdot3(k,3)
298  x3(k,3) = x3(k,imin)
299  xdot3(k,3) = xdot3(k,imin)
300  x3(k,imin) = temp1
301  xdot3(k,imin) = temp2
302  50 CONTINUE
303 *
304  temp1 = m(3)
305  m(3) = m(imin)
306  m(imin) = temp1
307  temp2 = SIZE(3)
308  SIZE(3) = SIZE(imin)
309  SIZE(imin) = temp2
310  name33 = name3(3)
311  name3(3) = name3(imin)
312  name3(imin) = name33
313  i3 = iconf(3)
314  iconf(3) = iconf(imin)
315  iconf(imin) = i3
316  i3 = ip(3)
317  ip(3) = ip(imin)
318  ip(imin) = i3
319 *
320 * Transform back to regularized variables and initialize input array.
321  CALL trans3(4)
322  DO 60 k = 1,8
323  y(k) = q(k)
324  y(k+8) = p(k)
325  60 CONTINUE
326 *
327 * Update regularization counter at the end of switching procedure.
328  nreg = nreg + 1
329 *
330 * Set consistent relative distances and minimum separation.
331  r1 = q(1)**2 + q(2)**2 + q(3)**2 + q(4)**2
332  r2 = q(5)**2 + q(6)**2 + q(7)**2 + q(8)**2
333  rm = min(r1,r2)
334 *
335 * Terminate triple integration if R3 > specified perturber limit.
336  70 IF (r3.GT.rmaxs(isub)) go to 90
337  IF (iterm.LT.0) go to 74
338 *
339 * Check for hierarchical stability in case of tidal capture.
340  IF (ndiss3.GT.0) THEN
341  iskip = 10
342  an = int(nstep3/float(iskip)) - float(nstep3)/float(iskip)
343 * Evaluate stability parameter every ISKIP step.
344  IF (abs(an).LT.0.01) THEN
345  CALL stabl3(iterm)
346  IF (iterm.LT.0) go to 90
347  END IF
348  END IF
349 *
350 * Check temporary termination time for return to routine INTGRT.
351  IF (time3.GT.tmax) THEN
352  IF (steps(isub).LE.0.0d0) go to 90
353  go to 100
354  END IF
355 *
356 * See if the configuration permits testing of escape condition.
357  IF (r1 + r2 + r3.LT.3.0*rcrit) go to 30
358 *
359 * Obtain current physical variables.
360  CALL trans3(2)
361 *
362 * Identify index of second binary component & escaper.
363  imin = 1
364  IF (r2.LT.r1) imin = 2
365  i = 3 - imin
366 *
367 * Skip escape test if distant body is approaching the system c.m.
368  ridot = x3(1,i)*xdot3(1,i) + x3(2,i)*xdot3(2,i) +
369  & x3(3,i)*xdot3(3,i)
370  IF (ridot.LT.0.0) go to 30
371 *
372 * Set distance & radial velocity of body #I with respect to binary.
373  mb = m(imin) + m(3)
374  fac = cm(7)/mb
375  ri = sqrt(x3(1,i)**2 + x3(2,i)**2 + x3(3,i)**2)
376  ridot = fac*ridot/ri
377  ri = fac*ri
378 *
379 * Check the escape criterion due to Standish (Celes. Mech. 4, 44).
380  ratio = rgrav/(mb*ri)
381  vcrit2 = 2.0*cm(7)*(1.0/ri + m(3)*m(imin)*ratio**2/(ri - rgrav))
382  IF (ridot**2.LT.vcrit2.OR.ri.LT.rgrav) go to 30
383 *
384 * Define basic variables for termination of tidal capture event.
385  74 IF (iterm.LT.0.AND.ndiss3.GT.0) THEN
386  CALL trans3(2)
387  im = 1
388  IF (r2.LT.r1) im = 2
389  i = 3 - im
390  ri = r3
391  rm = min(r1,r2)
392  CALL erel3(im,ebs,semi)
393  mb = m(imin) + m(3)
394  fac = cm(7)/mb
395  END IF
396 *
397 * Evaluate orbital elements.
398  vrel2 = 0.0d0
399  rdot = 0.0d0
400  vi2 = 0.0d0
401  DO 75 k = 1,3
402  rdot = rdot +
403  & (x3(k,3) - x3(k,imin))*(xdot3(k,3) - xdot3(k,imin))
404  vrel2 = vrel2 + (xdot3(k,3) - xdot3(k,imin))**2
405  vi2 = vi2 + xdot3(k,i)**2
406  75 CONTINUE
407 *
408 * Form outer semi-major axis (not used).
409  vi2 = vi2*fac**2
410  semi1 = 2.0d0/ri - vi2/cm(7)
411  semi1 = 1.0/semi1
412 *
413 * Determine semi-major axis & eccentricity of inner binary.
414  rb = rm
415  semi = 2.0d0/rb - vrel2/mb
416  semi = 1.0/semi
417  e = sqrt((1.0d0 - rb/semi)**2 + rdot**2/(semi*mb))
418 *
419 * Delay new regularization if binary is near small pericentre.
420  itry = itry + 1
421  IF (rb.LT.semi.AND.itry.LE.10) go to 30
422 *
423 * Set binary energy ratio for triple system and whole N-body system.
424  eb = -m(imin)*m(3)/(semi*energy)
425  et = -m(imin)*m(3)/(2.0*semi*cm(8))
426 * Form relative perturbation on inner binary due to body #I.
427  gb = 2.0*m(i)/mb*(rb/ri)**3
428  db = (eb*energy - eb0)/eb0
429 *
430 * Print final configuration for significant energy increase.
431  IF (db.GT.0.1) THEN
432  WRITE (6,80) name3(imin), name3(3), mb, semi, e, eb, gb, rb,
433  & m(i), ri, et
434  80 FORMAT (/,' TRIPLE BINARY ',2i5,' MB =',f7.4,' A =',1p,e8.1,
435  & ' E =',0p,f5.2,' EB =',f5.2,' GB =',1p,e8.1,' RB =',e8.1,
436  & ' MI =',0p,f7.4,' RI =',1p,e8.1,' ET =',0p,f6.3)
437  END IF
438 *
439 * Postpone termination by one small step unless restart case.
440  IF (steps(isub).GT.0.0d0) THEN
441  steps(isub) = 0.0d0
442  go to 100
443  END IF
444 *
445 * Transform to physical variables for termination.
446  90 CALL trans3(3)
447 *
448 * Identify second component and obtain osculating elements.
449  imin = 1
450  IF (r2.LT.r1) imin = 2
451  rb = min(r1,r2)
452  vrel2 = (xdot3(1,imin) - xdot3(1,3))**2 +
453  & (xdot3(2,imin) - xdot3(2,3))**2 +
454  & (xdot3(3,imin) - xdot3(3,3))**2
455 *
456 * Form the semi-major axis & energy of closest pair.
457  semi = 2.0d0/rb - vrel2/(m(imin) + m(3))
458  semi = 1.0/semi
459  eb = -0.5d0*m(imin)*m(3)/semi
460 *
461 * Avoid new KS regularization inside half semi-major axis.
462  itry = itry + 1
463  IF (rb.LT.abs(semi).AND.itry.LE.10) THEN
464  next = nstep3 + 10
465  go to 15
466  END IF
467 *
468  IF (steps(isub).GT.0.0d0) THEN
469  steps(isub) = 0.0d0
470  go to 100
471  END IF
472 *
473 * Check optional print diagnostics of triple integration.
474  IF (kz15.GT.1.OR.db.GT.0.1) THEN
475  tc = time3/tcr
476 * Print relative energy change of binary (including exchange).
477  db = (eb - eb0)/eb0
478  WRITE (6,95) nreg, r12min, r3min, r3, rgrav, tc, nstep3, db,
479  & name3(3-imin)
480  95 FORMAT (/,' END TRIPLE NREG =',i3,' MIN(RB&R3) =',1p,e8.1,
481  & e9.1,' R3 =',e8.1,' RG =',e8.1,' TC =',0p,f5.1,
482  & ' STEPS =',i4,' DB =',f6.2,' NMESC =',i5)
483  END IF
484 *
485 * Form binary energy change (set in SBCOLL; routine START3).
486  cm(9) = eb - eb0
487 *
488 * Transform to global variables and begin new KS & single body #I.
489  CALL start3(isub)
490 *
491 * Activate termination index for routine INTGRT.
492  iterm = -1
493 *
494 * Update current time unless termination and set subsystem index.
495  100 IF (iterm.GE.0) ts(isub) = t0s(isub) + time3
496  isub = iterm
497 *
498  RETURN
499 *
500  END