https://github.com/florentrenaud/nbody6tt
Tip revision: 8a4716382ead3ece116c48a4ae5c65f8c9534437 authored by Florent on 29 January 2015, 12:19:28 UTC
Nbody6 - 29 January 2015 (added GPU2/Build/.gitkeep)
Nbody6 - 29 January 2015 (added GPU2/Build/.gitkeep)
Tip revision: 8a47163
triple.f
SUBROUTINE TRIPLE(ISUB)
*
*
* Three-body regularization.
* --------------------------
*
* Method of Aarseth & Zare, Celestial Mechanics 10, 185.
* ......................................................
*
*
IMPLICIT REAL*8 (A-H,M,O-Z)
PARAMETER (NCMAX=10)
COMMON/AZREG/ TIME3,TMAX,Q(8),P(8),R1,R2,R3,ENERGY,M(3),X3(3,3),
& XDOT3(3,3),CM(10),C11,C12,C19,C20,C24,C25,
& NSTEP3,NAME3(3),KZ15,KZ27
COMMON/CLOSE/ RIJ(4,4),RCOLL,QPERI,SIZE(4),ECOLL3,IP(4)
COMMON/AZCOLL/ RK(3),QK(8),PK(8),ICALL,ICOLL,NDISS3
COMMON/BSSAVE/ EP(4),DSC,FACM,TFAC,ITFAC,JC
COMMON/EBSAVE/ EBS
COMMON/AZCONF/ ICONF(3)
COMMON/CLUMP/ BODYS(NCMAX,5),T0S(5),TS(5),STEPS(5),RMAXS(5),
& NAMES(NCMAX,5),ISYS(5)
REAL*8 Y(17)
SAVE
*
*
* Main variables for AZ regularization
* ************************************
*
* ---------------------------------------------------------------------
* CM(1-7) Coordinates, velocities & total mass of triple system.
* CM(8) Total energy of N-body system (copied in routine START3).
* CM(9) Binary energy change (copied to SBCOLL in START3).
* CM(10) Relative energy error (not used).
* C11 Inverse mass factor for DERQP3 (also C12,C19,C20,C24,C25).
* ENERGY Twice the initial total energy.
* ICALL Pericentre indicator (activated if MIN(R1,R2) < RSTAR).
* ICOLL Collision or capture indicator (activated in routine DERQP3).
* IP Polytropic index (=1: n = 3/2; =2: n = 2; =3: n = 3).
* KZ15 Triple option copied in START3 (full output if > 1).
* KZ27 Tidal capture & collision option (copied in START3).
* M Particle mass (CM(7) = M(1) + M(2) + M(3)).
* NAME3 Particle identity (initialized to global name).
* NREG Number of regularization switches.
* NSTEP3 Number of DIFSY3 calls.
* ICONF Three-body configuration array (initialized to 1, 2, 3).
* P Regularized momenta.
* Q Regularized coordinates.
* QPERI Pericentre distance of closest two-body motion.
* R1 Distance between M(1) and M(3).
* R2 Distance between M(2) and M(3).
* R3 Distance between M(1) and M(2) (not regularized).
* RCOLL Minimum two-body separation.
* RCRIT Escape test criterion (RGRAV or harmonic mean with RMAXS).
* RGRAV Gravitational radius (sum (M(I)*M(J))/ABS(0.5*ENERGY)).
* RIJ Minimum pairwise separations.
* RMAXS Maximum of unperturbed & initial size (R1 + R2).
* RSTAR Pericentre check distance (= 0.2*RGRAV).
* SIZE Individual stellar radius (collisions or tidal capture).
* TIME3 Local physical time in scaled units.
* TCR Local crossing time ((sum M(I))**2.5/ABS(ENERGY)**1.5).
* TOL Tolerance for DIFSY3 (1.0E-10 is recommended).
* TMAX Maximum integration time (based on c.m. step).
* X3 Particle coordinates (X3(3,I) is Z-component).
* XDOT3 Velocity components (XDOT3(3,I) is Z-component).
* ---------------------------------------------------------------------
*
*
* Save termination indicator and check for restart.
ITERM = ISUB
IF (ISUB.GT.0) THEN
* Synchronize next time interval with c.m. step unless termination.
TMAX = TIME3 + STEPS(ISUB)
IF (STEPS(ISUB).LE.0.0D0) DTAU3 = 0.01*DTAU3
* Copy input array for DIFSY3 (just in case).
GO TO 15
END IF
*
* Obtain initial conditions from N-body COMMON.
CALL START3(ISUB)
*
* Specify tolerance & DSC for DIFSY3 (relative energy error < TOL).
TOL = 1.0D-10
DSC = 1.0
*
* Initialize diagnostic & COMMON variables.
R12MIN = 100.0
R3MIN = 100.0
RCOLL = 100.0
ZMI1 = 100.0
ZMI2 = 100.0
ZMI3 = 100.0
DO 10 J = 1,3
ICONF(J) = J
DO 5 K = 1,3
RIJ(J,K) = 100.0
5 CONTINUE
10 CONTINUE
ICALL = 0
ICOLL = 0
NEXT = 0
NDISS3 = 0
ECOLL3 = 0.0D0
JC = 0
ITFAC = 0
NSTEP3 = 0
ITRY = 0
NREG = 0
*
* Initialize local time & regularized time.
TIME3 = 0.0D0
TAU3 = 0.0D0
Y(17) = 0.0D0
* Specify the number of first-order equations for the integrator.
NEQ = 17
*
* Evaluate the initial total energy (superseded; done in START3).
* CALL TRANS3(0)
*
* Transform to regularized variables.
CALL TRANS3(1)
*
* Define gravitational radius and pericentre check distance.
RGRAV = (M(1)*M(2) + M(1)*M(3) + M(2)*M(3))/(0.5D0*ABS(ENERGY))
RSTAR = 0.2*RGRAV
* Introduce average mass factor for Bulirsch-Stoer integrator.
FACM = (M(1)*M(2) + M(1)*M(3) + M(2)*M(3))/3.0
*
* Ensure that unperturbed boundary exceeds system size.
R1 = Q(1)**2 + Q(2)**2 + Q(3)**2 + Q(4)**2
R2 = Q(5)**2 + Q(6)**2 + Q(7)**2 + Q(8)**2
IF (RMAXS(ISUB).LT.R1 + R2) RMAXS(ISUB) = R1 + R2
*
* Modify escape distance criterion in case of hierarchical system.
RCRIT = MAX(RGRAV,SQRT(RGRAV*RMAXS(ISUB)))
*
* Specify local crossing time (also meaningful if ENERGY > 0).
TCR = (M(1) + M(2) + M(3))**2.5/ABS(ENERGY)**1.5
*
* Define a nominal crossing time in near-parabolic cases.
RMAX = MAX(R1,R2)
TSTAR = RMAX*SQRT(RMAX/CM(7))
*
* Determine the smallest two-body time-scale from parabolic orbit.
IM = 1
RM = R1
IF (R2.LT.R1) THEN
IM = 2
RM = R2
END IF
VP2 = 2.0*(M(IM) + M(3))/RM
TP = RM/SQRT(VP2)
TSTAR = MIN(TP,TSTAR)
*
* Set step for time transformation DT/DTAU = R1*R2/(R1 + R2)**0.5.
TPR = R1*R2/SQRT(R1 + R2)
DTAU3 = MIN(TCR,TSTAR)*TOL**0.1/TPR
*
* Form initial binding energy of the binary.
VREL2 = (XDOT3(1,2) - XDOT3(1,3))**2 +
& (XDOT3(2,2) - XDOT3(2,3))**2 +
& (XDOT3(3,2) - XDOT3(3,3))**2
EB0 = (0.5D0*VREL2/(M(2) + M(3)) - 1.0/R2)*M(2)*M(3)
*
* Initialize input array for the integrator.
15 DO 20 K = 1,8
Y(K) = Q(K)
Y(K+8) = P(K)
20 CONTINUE
Y(17) = TIME3
*
* Advance the equations of motion by Bulirsch-Stoer integrator.
30 CALL DIFSY3(NEQ,TOL,DTAU3,TAU3,Y)
*
* Copy regularized coordinates, momenta & time to COMMON variables.
DO 40 K = 1,8
Q(K) = Y(K)
P(K) = Y(K+8)
40 CONTINUE
TIME0 = TIME3
TIME3 = Y(17)
*
* Update relative distances (NB! Not quite latest value).
R1 = Q(1)**2 + Q(2)**2 + Q(3)**2 + Q(4)**2
R2 = Q(5)**2 + Q(6)**2 + Q(7)**2 + Q(8)**2
*
* Check minimum two-body separations and increase step counter.
R3MIN = MIN(R3MIN,R3)
RM = MIN(R1,R2)
R12MIN = MIN(R12MIN,RM)
NSTEP3 = NSTEP3 + 1
*
* Check minimum pairwise separations (also in DERQP3).
RK(1) = R1
RK(2) = R2
RK(3) = R3
*
* Consider pairs 1-2, 1-3 & 2-3 (initial names = 1, 2, 3).
DO 44 K = 1,3
DO 42 L = K+1,3
I = ICONF(K)
J = ICONF(L)
* Use cyclic loop index (3,1,2) for distances R3, R1 & R2.
KK = K - 1
IF (KK.EQ.0) KK = 3
RIJ(I,J) = MIN(RIJ(I,J),RK(KK))
RIJ(J,I) = MIN(RIJ(J,I),RK(KK))
42 CONTINUE
44 CONTINUE
*
* Update smallest moment of inertia during normal forward integration.
IF (TIME3.GT.TIME0.AND.JC.EQ.0) THEN
ZMI = RM**2
ZMI1 = ZMI2
ZMI2 = ZMI3
ZMI3 = ZMI
DTAU0 = DTAU3
END IF
*
* Switch on search indicator during iteration or just after pericentre.
IF (ICOLL.LT.0) ICALL = 1
IF (RM.LT.RSTAR.AND.NSTEP3.GT.NEXT) THEN
IF (ZMI3.GT.ZMI2.AND.ZMI2.LT.ZMI1) THEN
ICALL = 1
END IF
END IF
*
* Check for tidal dissipation or collision during last step.
IF (ICOLL.LE.0) GO TO 48
*
* Restore the minimum configuration.
DO 45 K = 1,8
Q(K) = QK(K)
P(K) = PK(K)
45 CONTINUE
*
* Set two-body separations.
R1 = Q(1)**2 + Q(2)**2 + Q(3)**2 + Q(4)**2
R2 = Q(5)**2 + Q(6)**2 + Q(7)**2 + Q(8)**2
*
* Delay next search a few steps to avoid the same pericentre.
NEXT = NSTEP3 + 2
*
* Distinguish between tidal energy loss and collision (ICOLL holds IM).
IM = ICOLL
ICOLL = 0
IF (QPERI.LT.4.0*MAX(SIZE(IM),SIZE(3))) THEN
J1 = 3
J2 = IM
IF (SIZE(J2).GT.SIZE(J1)) J1 = J2
FAC = 0.5*(M(IM) + M(3))/M(J1)
* Adopt collision criterion of Kochanek (Ap.J. 385, 604, 1992).
RCOLL = 1.7*FAC**0.3333*SIZE(J1)
IF (QPERI.LT.RCOLL) THEN
*
* Transform to physical variables.
CALL TRANS3(2)
*
* Obtain global coordinates & velocities (ITERM < 0: termination).
ITERM = -1
ISUB = -ISUB
CALL START3(ISUB)
*
* Combine internal energy and external c.m. kinetic energy.
H3 = 0.5D0*ENERGY + 0.5D0*CM(7)*(CM(4)**2 + CM(5)**2 +
& CM(6)**2)
*
* Evaluate the two-body energy for diagnostic purposes.
CALL EREL3(IM,EBS,SEMI)
DMINC = MIN(RCOLL,DMINC) ! note DMINC not in common6.
*
* Form composite body and begin KS regularization of new pair.
CALL CMBODY(H3,3)
GO TO 100
ELSE
*
* Modify variables due to tidal effects and check stability parameter.
CALL QPMOD3(IM,ITERM)
* Ensure positive step from pericentre and switch off search indicator.
DTAU3 = ABS(DTAU0)
ICALL = 0
* Update relative distances (NB! Not quite latest value).
R1 = Q(1)**2 + Q(2)**2 + Q(3)**2 + Q(4)**2
R2 = Q(5)**2 + Q(6)**2 + Q(7)**2 + Q(8)**2
IF (ITERM.LT.0) GO TO 90
* Initialize input array and continue integration.
GO TO 15
END IF
END IF
*
* See whether switching of reference body is desirable.
48 IF (R3.GT.RM) GO TO 70
*
* Use a simple distance test to determine new reference body IMIN.
IMIN = 1
IF (R2.LT.R1) IMIN = 2
*
* Transform to physical variables and rename the exchanged particles.
CALL TRANS3(2)
*
DO 50 K = 1,3
TEMP1 = X3(K,3)
TEMP2 = XDOT3(K,3)
X3(K,3) = X3(K,IMIN)
XDOT3(K,3) = XDOT3(K,IMIN)
X3(K,IMIN) = TEMP1
XDOT3(K,IMIN) = TEMP2
50 CONTINUE
*
TEMP1 = M(3)
M(3) = M(IMIN)
M(IMIN) = TEMP1
TEMP2 = SIZE(3)
SIZE(3) = SIZE(IMIN)
SIZE(IMIN) = TEMP2
NAME33 = NAME3(3)
NAME3(3) = NAME3(IMIN)
NAME3(IMIN) = NAME33
I3 = ICONF(3)
ICONF(3) = ICONF(IMIN)
ICONF(IMIN) = I3
I3 = IP(3)
IP(3) = IP(IMIN)
IP(IMIN) = I3
*
* Transform back to regularized variables and initialize input array.
CALL TRANS3(4)
DO 60 K = 1,8
Y(K) = Q(K)
Y(K+8) = P(K)
60 CONTINUE
*
* Update regularization counter at the end of switching procedure.
NREG = NREG + 1
*
* Set consistent relative distances and minimum separation.
R1 = Q(1)**2 + Q(2)**2 + Q(3)**2 + Q(4)**2
R2 = Q(5)**2 + Q(6)**2 + Q(7)**2 + Q(8)**2
RM = MIN(R1,R2)
*
* Terminate triple integration if R3 > specified perturber limit.
70 IF (R3.GT.RMAXS(ISUB)) GO TO 90
IF (ITERM.LT.0) GO TO 74
*
* Check for hierarchical stability in case of tidal capture.
IF (NDISS3.GT.0) THEN
ISKIP = 10
AN = INT(NSTEP3/FLOAT(ISKIP)) - FLOAT(NSTEP3)/FLOAT(ISKIP)
* Evaluate stability parameter every ISKIP step.
IF (ABS(AN).LT.0.01) THEN
CALL STABL3(ITERM)
IF (ITERM.LT.0) GO TO 90
END IF
END IF
*
* Check temporary termination time for return to routine INTGRT.
IF (TIME3.GT.TMAX) THEN
IF (STEPS(ISUB).LE.0.0D0) GO TO 90
GO TO 100
END IF
*
* See if the configuration permits testing of escape condition.
IF (R1 + R2 + R3.LT.3.0*RCRIT) GO TO 30
*
* Obtain current physical variables.
CALL TRANS3(2)
*
* Identify index of second binary component & escaper.
IMIN = 1
IF (R2.LT.R1) IMIN = 2
I = 3 - IMIN
*
* Skip escape test if distant body is approaching the system c.m.
RIDOT = X3(1,I)*XDOT3(1,I) + X3(2,I)*XDOT3(2,I) +
& X3(3,I)*XDOT3(3,I)
IF (RIDOT.LT.0.0) GO TO 30
*
* Set distance & radial velocity of body #I with respect to binary.
MB = M(IMIN) + M(3)
FAC = CM(7)/MB
RI = SQRT(X3(1,I)**2 + X3(2,I)**2 + X3(3,I)**2)
RIDOT = FAC*RIDOT/RI
RI = FAC*RI
*
* Check the escape criterion due to Standish (Celes. Mech. 4, 44).
RATIO = RGRAV/(MB*RI)
VCRIT2 = 2.0*CM(7)*(1.0/RI + M(3)*M(IMIN)*RATIO**2/(RI - RGRAV))
IF (RIDOT**2.LT.VCRIT2.OR.RI.LT.RGRAV) GO TO 30
*
* Define basic variables for termination of tidal capture event.
74 IF (ITERM.LT.0.AND.NDISS3.GT.0) THEN
CALL TRANS3(2)
IM = 1
IF (R2.LT.R1) IM = 2
I = 3 - IM
RI = R3
RM = MIN(R1,R2)
CALL EREL3(IM,EBS,SEMI)
MB = M(IMIN) + M(3)
FAC = CM(7)/MB
END IF
*
* Evaluate orbital elements.
VREL2 = 0.0D0
RDOT = 0.0D0
VI2 = 0.0D0
DO 75 K = 1,3
RDOT = RDOT +
& (X3(K,3) - X3(K,IMIN))*(XDOT3(K,3) - XDOT3(K,IMIN))
VREL2 = VREL2 + (XDOT3(K,3) - XDOT3(K,IMIN))**2
VI2 = VI2 + XDOT3(K,I)**2
75 CONTINUE
*
* Form outer semi-major axis (not used).
VI2 = VI2*FAC**2
SEMI1 = 2.0D0/RI - VI2/CM(7)
SEMI1 = 1.0/SEMI1
*
* Determine semi-major axis & eccentricity of inner binary.
RB = RM
SEMI = 2.0D0/RB - VREL2/MB
SEMI = 1.0/SEMI
E = SQRT((1.0D0 - RB/SEMI)**2 + RDOT**2/(SEMI*MB))
*
* Delay new regularization if binary is near small pericentre.
ITRY = ITRY + 1
IF (RB.LT.SEMI.AND.ITRY.LE.10) GO TO 30
*
* Set binary energy ratio for triple system and whole N-body system.
EB = -M(IMIN)*M(3)/(SEMI*ENERGY)
ET = -M(IMIN)*M(3)/(2.0*SEMI*CM(8))
* Form relative perturbation on inner binary due to body #I.
GB = 2.0*M(I)/MB*(RB/RI)**3
DB = (EB*ENERGY - EB0)/EB0
*
* Print final configuration for significant energy increase.
IF (DB.GT.0.1) THEN
WRITE (6,80) NAME3(IMIN), NAME3(3), MB, SEMI, E, EB, GB, RB,
& M(I), RI, ET
80 FORMAT (/,' TRIPLE BINARY ',2I5,' MB =',F7.4,' A =',1P,E8.1,
& ' E =',0P,F5.2,' EB =',F5.2,' GB =',1P,E8.1,' RB =',E8.1,
& ' MI =',E8.1,' RI =',E8.1,' ET =',0P,F6.3)
END IF
*
* Postpone termination by one small step unless restart case.
IF (STEPS(ISUB).GT.0.0D0) THEN
STEPS(ISUB) = 0.0D0
GO TO 100
END IF
*
* Transform to physical variables for termination.
90 CALL TRANS3(3)
*
* Identify second component and obtain osculating elements.
IMIN = 1
IF (R2.LT.R1) IMIN = 2
RB = MIN(R1,R2)
VREL2 = (XDOT3(1,IMIN) - XDOT3(1,3))**2 +
& (XDOT3(2,IMIN) - XDOT3(2,3))**2 +
& (XDOT3(3,IMIN) - XDOT3(3,3))**2
*
* Form the semi-major axis & energy of closest pair.
SEMI = 2.0D0/RB - VREL2/(M(IMIN) + M(3))
SEMI = 1.0/SEMI
EB = -0.5D0*M(IMIN)*M(3)/SEMI
*
* Avoid new KS regularization inside half semi-major axis.
ITRY = ITRY + 1
IF (RB.LT.ABS(SEMI).AND.ITRY.LE.10) THEN
NEXT = NSTEP3 + 10
GO TO 15
END IF
*
IF (STEPS(ISUB).GT.0.0D0) THEN
STEPS(ISUB) = 0.0D0
GO TO 100
END IF
*
* Check optional print diagnostics of triple integration.
IF (KZ15.GT.1.OR.DB.GT.0.1) THEN
TC = TIME3/TCR
* Print relative energy change of binary (including exchange).
DB = (EB - EB0)/EB0
WRITE (6,95) NREG, R12MIN, R3MIN, R3, RGRAV, TC, NSTEP3, DB,
& NAME3(3-IMIN)
95 FORMAT (/,' END TRIPLE NREG =',I3,' MIN(RB&R3) =',1P,E8.1,
& E9.1,' R3 =',E8.1,' RG =',E8.1,' TC =',0P,F5.1,
& ' STEPS =',I4,' DB =',F6.2,' NMESC =',I5)
END IF
*
* Form binary energy change (set in SBCOLL; routine START3).
CM(9) = EB - EB0
*
* Transform to global variables and begin new KS & single body #I.
CALL START3(ISUB)
*
* Activate termination index for routine INTGRT.
ITERM = -1
*
* Update current time unless termination and set subsystem index.
100 IF (ITERM.GE.0) TS(ISUB) = T0S(ISUB) + TIME3
ISUB = ITERM
*
RETURN
*
END