Raw File
cmfreg.f
      SUBROUTINE CMFREG(I,RS2,RCRIT2,VRFAC,NNB,XI,XID,FIRR,FREG,FD,FDR)
*
*
*       Regular & irregular c.m. force & first derivative.
*       --------------------------------------------------
*
      INCLUDE 'common6.h'
      REAL*8  XI(3),XID(3),FIRR(3),FREG(3),DV(3),FD(3),FDR(3)
*
*
*       Set non-zero indicator for perturbed c.m.
      NP = 0
      IF (I.GT.N) THEN
          IPAIR = I - N
          IF (LIST(1,2*IPAIR-1).GT.0) NP = 1
      END IF
*
*       Prepare case of single particle or unperturbed c.m. (second call).
      IF (I.LE.N.OR.NP.EQ.0) THEN
*       Copy all KS pairs to JLIST and find MAX(R) for joint treatment.
          NNB1 = NPAIRS
          RMAX1 = 0.0
          DO 10 LJ = 1,NNB1
              JLIST(LJ) = N + LJ
              RMAX1 = MAX(RMAX1,R(LJ))
   10     CONTINUE
*
*       Adopt adequate square distance for c.m. approximation.
          RCM2 = MAX(RCRIT2,CMSEP2*RMAX1**2)
*       Define dummy indices for skipping perturber test.
          JP = 0
          LP = 1
          GO TO 25
      END IF
*
*       Specify variables for treatment of perturbed c.m. particle.
      I2 = 2*IPAIR
      I1 = I2 - 1
      RPERT2 = CMSEP2*R(IPAIR)**2
      BODYIN = 1.0/BODY(I)
*       Initialize perturber list for decision-making.
      NP = LIST(1,I1)
      LP = 2
      JP = LIST(2,I1)
*
*       Use fast force loop for particles satisfying c.m. approximation.
      RCM2 = MAX(RCRIT2,RPERT2)
      NNB1 = 0
      DO 20 J = IFIRST,NTOT
          A1 = X(1,J) - XI(1)
          A2 = X(2,J) - XI(2)
          A3 = X(3,J) - XI(3)
          DV(1) = XDOT(1,J) - XID(1)
          DV(2) = XDOT(2,J) - XID(2)
          DV(3) = XDOT(3,J) - XID(3)
          RIJ2 = A1*A1 + A2*A2 + A3*A3
*
*       Form a list of particles for more careful consideration.
          IF (RIJ2.LT.RCM2) THEN
              NNB1 = NNB1 + 1
              JLIST(NNB1) = J
              GO TO 20
          END IF
*
          DR2I = 1.0/RIJ2
          DR3I = BODY(J)*DR2I*SQRT(DR2I)
          DRDV = 3.0*(A1*DV(1) + A2*DV(2) + A3*DV(3))*DR2I
*
          FREG(1) = FREG(1) + A1*DR3I
          FREG(2) = FREG(2) + A2*DR3I
          FREG(3) = FREG(3) + A3*DR3I
          FDR(1) = FDR(1) + (DV(1) - A1*DRDV)*DR3I
          FDR(2) = FDR(2) + (DV(2) - A2*DRDV)*DR3I
          FDR(3) = FDR(3) + (DV(3) - A3*DRDV)*DR3I
   20 CONTINUE
*
*       Begin dual purpose force loop (all RIJ2 < RCM2, J > N or I <= N).
   25 DO 60 LJ = 1,NNB1
          JDUM = JLIST(LJ)
          A1 = X(1,JDUM) - XI(1)
          A2 = X(2,JDUM) - XI(2)
          A3 = X(3,JDUM) - XI(3)
          DV(1) = XDOT(1,JDUM) - XID(1)
          DV(2) = XDOT(2,JDUM) - XID(2)
          DV(3) = XDOT(3,JDUM) - XID(3)
          RIJ2 = A1*A1 + A2*A2 + A3*A3
*       First see if the distance exceeds c.m. approximation limit.
          IF (RIJ2.GT.RCM2) GO TO 56
*
          J = JDUM
*       Check whether particle #J satisfies neighbour criteria.
          IF (RIJ2.GT.RCRIT2) GO TO 54
*
*       Consider small step particle (may give large correction terms).
          IF (RIJ2.GT.RS2.AND.STEP(J).GT.SMIN) THEN
              A7 = A1*DV(1) + A2*DV(2) + A3*DV(3)
*       Accept member if maximum penetration factor exceeds 8 per cent.
              IF (A7.GT.VRFAC) GO TO 54
          END IF
          IF (JDUM.EQ.I) GO TO 60
*
*       Obtain force due to current neighbours.
          NNB = NNB + 1
          ILIST(NNB) = J
          KCM = 1
*
*       Advance lower perturber index (includes possible old neighbour).
   26     IF (LP.LE.NP.AND.J.GT.JP) THEN
              LP = LP + 1
              JP = LIST(LP,I1)
*       Include rare case of two consecutive previous neighbours.
              GO TO 26
          END IF
*
*       Decide appropriate expressions from perturber comparison.
          IF (J.NE.JP) THEN
              IF (J.LE.N) GO TO 30
              IF (RIJ2.GT.CMSEP2*R(J-N)**2) GO TO 30
              KDUM = 2*(J - N) - 1
              IF (LIST(1,KDUM).GT.0) THEN
                  K = KDUM
                  J2 = K + 1
                  GO TO 50
              END IF
          ELSE
*       Treat perturbers more carefully.
              IF (LP.LE.NP) THEN
                  LP = LP + 1
                  JP = LIST(LP,I1)
              END IF
              J2 = 0
              IF (J.GT.N) THEN
                  KDUM = 2*(J - N) - 1
                  IF (LIST(1,KDUM).GT.0) THEN
                      J = KDUM
                      J2 = J + 1
                  END IF
              END IF
              GO TO 40
          END IF
*
   30     DR2I = 1.0/RIJ2
          DR3I = BODY(J)*DR2I*SQRT(DR2I)
          DRDV = 3.0*(A1*DV(1) + A2*DV(2) + A3*DV(3))*DR2I
*
          FIRR(1) = FIRR(1) + A1*DR3I
          FIRR(2) = FIRR(2) + A2*DR3I
          FIRR(3) = FIRR(3) + A3*DR3I
          FD(1) = FD(1) + (DV(1) - A1*DRDV)*DR3I
          FD(2) = FD(2) + (DV(2) - A2*DRDV)*DR3I
          FD(3) = FD(3) + (DV(3) - A3*DRDV)*DR3I
          GO TO 60
*
*       Obtain relevant force on c.m (KCM = 0 denotes regular force).
   40     K = J
   42     L = I1
*       Individual components I1 & I2 are resolved in routine INTGRT.
   45     A1 = X(1,K) - X(1,L)
          A2 = X(2,K) - X(2,L)
          A3 = X(3,K) - X(3,L)
          RIJ2 = A1*A1 + A2*A2 + A3*A3
          DV(1) = XDOT(1,K) - XDOT(1,L)
          DV(2) = XDOT(2,K) - XDOT(2,L)
          DV(3) = XDOT(3,K) - XDOT(3,L)
*
          DR2I = 1.0/RIJ2
          DR3I = BODY(K)*BODY(L)*DR2I*SQRT(DR2I)*BODYIN
          DRDV = 3.0*(A1*DV(1) + A2*DV(2) + A3*DV(3))*DR2I
*
          IF (KCM.NE.0) THEN
              FIRR(1) = FIRR(1) + A1*DR3I
              FIRR(2) = FIRR(2) + A2*DR3I
              FIRR(3) = FIRR(3) + A3*DR3I
              FD(1) = FD(1) + (DV(1) - A1*DRDV)*DR3I
              FD(2) = FD(2) + (DV(2) - A2*DRDV)*DR3I
              FD(3) = FD(3) + (DV(3) - A3*DRDV)*DR3I
          ELSE
              FREG(1) = FREG(1) + A1*DR3I
              FREG(2) = FREG(2) + A2*DR3I
              FREG(3) = FREG(3) + A3*DR3I
              FDR(1) = FDR(1) + (DV(1) - A1*DRDV)*DR3I
              FDR(2) = FDR(2) + (DV(2) - A2*DRDV)*DR3I
              FDR(3) = FDR(3) + (DV(3) - A3*DRDV)*DR3I
          END IF
*
          L = L + 1
          IF (L.EQ.I2) GO TO 45
          K = K + 1
          IF (K.EQ.J2) GO TO 42
          GO TO 60
*
*       Treat c.m. approximation for #I and #K as single or composite.
   50     A1 = X(1,K) - XI(1)
          A2 = X(2,K) - XI(2)
          A3 = X(3,K) - XI(3)
          DV(1) = XDOT(1,K) - XID(1)
          DV(2) = XDOT(2,K) - XID(2)
          DV(3) = XDOT(3,K) - XID(3)
          RIJ2 = A1*A1 + A2*A2 + A3*A3
*
          DR2I = 1.0/RIJ2
          DR3I = BODY(K)*DR2I*SQRT(DR2I)
          DRDV = 3.0*(A1*DV(1) + A2*DV(2) + A3*DV(3))*DR2I
*
          IF (KCM.NE.0) THEN
              FIRR(1) = FIRR(1) + A1*DR3I
              FIRR(2) = FIRR(2) + A2*DR3I
              FIRR(3) = FIRR(3) + A3*DR3I
              FD(1) = FD(1) + (DV(1) - A1*DRDV)*DR3I
              FD(2) = FD(2) + (DV(2) - A2*DRDV)*DR3I
              FD(3) = FD(3) + (DV(3) - A3*DRDV)*DR3I
          ELSE
              FREG(1) = FREG(1) + A1*DR3I
              FREG(2) = FREG(2) + A2*DR3I
              FREG(3) = FREG(3) + A3*DR3I
              FDR(1) = FDR(1) + (DV(1) - A1*DRDV)*DR3I
              FDR(2) = FDR(2) + (DV(2) - A2*DRDV)*DR3I
              FDR(3) = FDR(3) + (DV(3) - A3*DRDV)*DR3I
          END IF
*
          K = K + 1
          IF (K.EQ.J2) GO TO 50
          GO TO 60
*
*       Define regular force indicator.
   54 KCM = 0
*       Distinguish between second and first call (I > N & I <= N, J > N)
      IF (JP.EQ.0) THEN
*       Note that first case is for J > N and #I single or unperturbed c.m.
          IF (RIJ2.LT.CMSEP2*R(J-N)**2) THEN
              J2 = 2*(J - N)
              K = J2 - 1
              GO TO 50
          END IF
      ELSE IF (J.LE.N) THEN
*       Consider case of single #J and perturbed c.m.
          IF (RIJ2.LT.RPERT2) THEN
              J2 = 0
              GO TO 40
          END IF
      ELSE
*       Split final case I > N & J > N into two parts according to RPERT2.
          IF (RIJ2.GT.RPERT2) THEN
              IF (RIJ2.GT.CMSEP2*R(J-N)**2) THEN
                  K = J
                  J2 = 0
              ELSE
                  J2 = 2*(J - N)
                  K = J2 - 1
              END IF
*       Adopt c.m. approximation for #I.
              GO TO 50
          ELSE
*       See whether both c.m. bodies should be resolved.
              IF (RIJ2.GT.CMSEP2*R(J-N)**2) THEN
                  J2 = 0
                  GO TO 40
              ELSE
                  J2 = 2*(J - N)
                  K = J2 - 1
                  GO TO 42
              END IF
          END IF
      END IF
*
*       Obtain the regular force due to single body or c.m. particle.
   56     DR2I = 1.0/RIJ2
          DR3I = BODY(JDUM)*DR2I*SQRT(DR2I)
          DRDV = 3.0*(A1*DV(1) + A2*DV(2) + A3*DV(3))*DR2I
*
          FREG(1) = FREG(1) + A1*DR3I
          FREG(2) = FREG(2) + A2*DR3I
          FREG(3) = FREG(3) + A3*DR3I
          FDR(1) = FDR(1) + (DV(1) - A1*DRDV)*DR3I
          FDR(2) = FDR(2) + (DV(2) - A2*DRDV)*DR3I
          FDR(3) = FDR(3) + (DV(3) - A3*DRDV)*DR3I
   60 CONTINUE
*
*       Check force correction due to regularized chain (same as CMFIRR).
      IF (I.GT.N.AND.NCH.GT.0) THEN
          IF (JP.GT.0) THEN
              CALL KCPERT(I,I1,FIRR,FD)
          END IF
      END IF 
*
      RETURN
*
      END
back to top