IAP GITLAB

Skip to content
Snippets Groups Projects
coload.f 28.6 KiB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
c $Id: coload.f,v 1.11 2001/04/06 21:48:16 weber Exp $
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      real*8 function sigtot(ind1,ind2,sqrts)
c
c     Revision : 1.0
C
cinput ind1 : index of particle 1
cinput ind2 : index of particle 2
cinput sqrts: $\sqrt{s}$ of collision between part. 1 and 2
c
c     {\tt sigtot} returns the total cross section (in mbarn) for the collision
c     between the particles with the indices {\tt ind1} and {\tt ind2}.
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
       implicit none
       include 'coms.f'
       include 'comres.f'
       include 'newpart.f'
c
       integer isigline
       integer ind1,ind2,collclass
       integer ityp1,ityp2,iso31,iso32
       real*8 sqrts,mminit
c for detailed-balance
       integer nCh,ii
       real*8 e1,e2,sigma


c     reset sigtot, store often needed values in scalars
       sigtot=0.d0
       ityp1=ityp(ind1)
       ityp2=ityp(ind2)
       iso31=iso3(ind1)
       iso32=iso3(ind2)

c     now get collision class (line-number for sigmaLN array in blockres.f)
c     isigline classifies the collision (pp,pn,Delta N, Meson-Baryon etc)
       isigline=collclass(ityp1,iso31,ityp2,iso32)

       if(isigline.eq.0) return ! zero cross section for collclass=0

c     get pointer for total cross section (column #2 in SigmaLN array)
       iline=SigmaLn(2,1,isigline) ! flag of total cross section

c     if zero, cross section is zero, return
       if(iline.eq.0) return

       if(iline.gt.0) then
c
c     if gt zero we have a tabulated or parameterized total cross section,
c     all table-lookups and parametrizations are accessed via crossx
c
             call crossx(iline,sqrts,ityp1,iso31,
     &                         max(fmass(ind1),mminit(ityp1)),
     &                         ityp2,iso32,
     &                         max(fmass(ind2),mminit(ityp2)),
     &                         sigtot)

       else
c
c     total cross section via sum of partial cross sections
c
c     get number of exit-channels:
          if (isigline.gt.maxreac) then
             write (6,*) '4isigline: ',isigline
          endif
          nCh=SigmaLn(1,1,isigline)
c
c transformation quantities  into NN system for proper kinematics
c (necessary for detailed balance cross sections)
c     first compute transformation betas
          e1=sqrt(fmass(ind1)**2+px(ind1)**2
     &         +py(ind1)**2+pz(ind1)**2)
          e2=sqrt(fmass(ind2)**2+px(ind2)**2
     &         +py(ind2)**2+pz(ind2)**2)
          betax=(px(ind1)+px(ind2))/(e1+e2)
          betay=(py(ind1)+py(ind2))/(e1+e2)
          betaz=(pz(ind1)+pz(ind2))/(e1+e2)
c     now transform momenta
          pxnn=px(ind1)
          pynn=py(ind1)
          pznn=pz(ind1)
          p0nn=e1
c     call to Lorentz transformation
          call rotbos(0d0,0d0,-betax,-betay,-betaz,
     &         pxnn,pynn,pznn,p0nn)
          pnn=sqrt(pxnn*pxnn+pynn*pynn+pznn*pznn)
c     end of transform part
c
c     loop over exit channels for sum of partial cross sections
c     partial cross sections start in column #3 of SigmaLN in blockres.f
          do 10 ii=3,nCh+2
c     get pointer for partial cross section
             iline=SigmaLn(ii,1,isigline)
c     normal partial cross sections
             if(iline.gt.0) then
                   call crossx(iline,sqrts,ityp1,iso31,fmass(ind1),
     &                         ityp2,iso32,fmass(ind2),sigma)
             else
c     detailed balance partial cross section (must be computed now)
c     (crossz delivers inelastic channel for SINGLE resonance)
                call crossz(iline,sqrts,ityp1,iso31,fmass(ind1),
     &                      ityp2,iso32,fmass(ind2),sigma)
             endif
c     perform summation of partial cross sections
             sigtot=sigtot+sigma
c     end of loop for partial cross sections
 10       continue
c     end of total / sum of partial cross sections if
       endif

c     return to caller
       return

       end


ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine getnext(k)
c
c     Revision : 1.0
C
coutput k : index of next collison
c
c {\tt getnext} returns the index of the next collision or decay
c to be performed.
c If no further collisons occur in the timestep, {\tt getnext} returns
c {\tt k}=0 .
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
      implicit none
      integer k
      include 'coms.f'
      include 'options.f'
      include 'colltab.f'

c     shrink collision tables in case 80% load to counter possible overflow
       if(dble(nct)/ncollmax.ge.0.8) call collshrink

c
c     set k to current collision/decay (which has already been performed and
c     and is outdated by the time of this call)
      k = actcol

 1    continue
c     increment counter, next entry in table is now the current one
      k = k+1
c     if the end of the collision table has been reached, return with k=0
      if (k.gt.nct) then
         k = 0
         actcol = k
         return
      endif

c     if the current entry in the collision table is marked "F" - false -
c     (due to previous interaction of one of the collision partners)
c     then find new collision partners for the particle(s) via calls
c     to collupd
      if (.not.ctvalid(k)) then
         call collupd(cti1(k),1)
c     second call only if not a decay entry
         if(cti2(k).gt.0) call collupd(cti2(k),1)
c     if the current collision is now marked "T" - true - return
         if(ctvalid(k)) then
            actcol = k
            return
         endif
c     the current collision is still marked false, go to top of loop
c     (and increment counter)
         goto 1
      endif
c
c     the current entry is marked "T" - true - this is the next
c     collision to be perfomed
      actcol = k
      return
      end

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine collshrink
c
c     Revision : 1.0
c
c     This subroutine deletes all entries in the collision tables between
c     1 and {\tt actcol}-1. It's purpose is to counter a possible overflow
c     of the collision tables.
c
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      implicit none
      integer i
      include 'colltab.f'

      do 104 i=actcol,nct
         cttime(1+i-actcol) = cttime(i)
         ctsqrts(1+i-actcol) = ctsqrts(i)
         ctsigtot(1+i-actcol) = ctsigtot(i)
         cti1(1+i-actcol) = cti1(i)
         cti2(1+i-actcol) = cti2(i)
         ctvalid(1+i-actcol) = ctvalid(i)
         ctcolfluc(1+i-actcol) = ctcolfluc(i)
 104  continue
c     recalculate number of collisions in tables
      nct=1+nct-actcol
c     reset pointer to current collision
      actcol=1

      return
      end

ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine colload
c
c     Revision : 1.0
c
c
c This routine fills the collision tables with all collisions and decays
c to be performed in the current timestep. Within the timestep,
c particle propagation is assumed on straight lines. This routine
c actually only performs the outer of the double particle loop and
c calls {\tt collupd} for the inner loop.
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      implicit none
      integer i

      include 'coms.f'
      include 'colltab.f'

c     reset number of collisions in table and current collision pointer
      nct = 0
      actcol = 0

c reset all collision arrays
      do 10 i=1,ncollmax
         cttime(i)=0.d0
         ctsqrts(i)=0.d0
         ctsigtot(i)=0.d0
         cti1(i)=0
         cti2(i)=0
         ctvalid(i)=.false.
         ctcolfluc(i)=1.d0
 10   continue

c     outer loop over all particles
      do 20 i=1,npart
c     call collupd for inner loop, -1: inner loop only from i+1 to npart
         call collupd(i,-1)
 20   continue
      return
      end

ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine collupd(i,all)
c
c     Revision : 1.0
C
cinput i   : particle to be checked for collison or decay
cinput all : flag for update mode
c
c {\tt collupd} checks whether particle {\tt i} will collide or decay
c in the time interval between the current time {\tt acttime}
c and the end of the time step.
c {\tt collupd} uses the variable {\tt tmin} to find the {\bf earliest}
c interaction/decay of particle {\tt i} and store it in the
c collision arrays via a call to {\tt ctupdate}.
c For {\tt all}$>0$ all other particles from 1 to {\tt npart} are checked
c (necessary for update after a collision/decay), whereas for
c {\tt all}$<0$ only the particles with the indices from {\tt i+1} to
c {\tt npart} are checked (for calls via {\tt colload}).
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      implicit none

      include 'coms.f'
      include 'options.f'
      include 'colltab.f'
      include 'boxinc.f'

      real*8 dst2
      integer i,all
      integer j,imin,jmin,j0,A
      integer wall
      integer stidx
      logical isstable
      real*8  tn, wallcoll
cc
      real*8 tcoll,sqrs,sigt,sqrts,sigtot
      real*8 smin,sigmin,sigfac

      real*8 colfaci,colfacj,colfac,colfacmin

c     number of "initial" particles in event
      A = At+Ap
c     initially tmin is set to the time-interval until the end of the timestep
c     tmin is then minimized to the time of the first interaction of
c     particle i
c
c     acttime: current time
c     time: time at beginning of timestep
c     dtimestep: length of timestep
      tmin=dtimestep-acttime+time
c
c     other information to be stored together with tmin
      smin = 0 ! sqrt(s) of interaction
      sigmin = 0 ! total cross section of interaction
      imin = 0 ! index of first particle
      jmin = 0 ! index of second particle
c
c  check, if particle i is a resonance, that might decay within the remaining
c  part of the timestep.
c  If so, than treat decay as collision (with particle 2= 0)
      if (dectime(i)-acttime.lt.tmin) then
         isstable = .false.
         do 132 stidx=1,nstable
            if (ityp(i).eq.stabvec(stidx)) then
c               write (6,*) 'no decay of particle ',ityp(i)
               isstable = .true.
            endif
 132     enddo
         if (.not.isstable) then
            tmin = dectime(i) - acttime
            smin=fmass(i)
            imin = i
            jmin = 0
         endif
      endif


ccccccccccccccccccccccccccccccccc
c new walls selected if mbflag equals 2
      if ((mbox.gt.0).and.(mbflag.eq.2)) then

c acttime is the ACTUAL time
c time is the time at the BEGINNING of the timestep
c tmin is being minimized RELATIVE to the beginning of the timestep

c tn is the relativ time to the next wall colision
        tn=wallcoll(i,wall)

c comparison wheather a particle decays before a wall colision
            if (tn.lt.tmin) then
c set the time
                    tmin=tn
c set the particle number
                    imin=i
c set the wall
                    jmin=wall
            endif
        endif
cc


c default setting: loop does only go from i+1 to npart
         j0 = i+1
c in case of "update mode" let loop run starting from 1
         if (all.gt.0) j0 = 1
c
c  Now check, which is the earliest collision of particle i
c
         do 101 j=j0,npart

c check for some exclusion cases
            if (
c 1. avoid "self-interaction"
     &           i.ne.j
c 2. particles which have interacted with each other in the past
c    are only allowed to interact with each other if at least one
c    of them has had an interaction in between.
c    (due to string-decays the structure is a little complicated, since
c    one particle can have multiple partners of it's last interaction)
     &          .AND.
     &          ((lstcoll(i).ne.j.and.lstcoll(i).ne.(nmax+strid(j)+1))
     &           .or.
     &           (lstcoll(j).ne.i.and.lstcoll(j).ne.(nmax+strid(i)+1))
     &           .or.
     &           (lstcoll(i).eq.0.and.lstcoll(j).eq.0))
c 3. Particles within the projectile or target respectively are per
c    default only allowed to interact with each other in case they
c    have already had an interaction with a particle of the target
c    or projectile respectively. This can be turned off by setting
c    CTOption(6) to a nonzero value.
c    This rule of course must not not apply to produced particles.
c    In the case of a meson nucleus collision, projectile and
c    target may be swapped in the particle vectors (therefore the
c    use of Apt instead of Ap, because Apt has been then swapped
c    accordingly)
     &          .AND.
     &          (CToption(6).ne.0.or.i.gt.A.or.j.gt.A.or.
     &           ncoll(i)+ncoll(j).gt.0.or.
     &          (i.le.Apt.and.j.gt.Apt).or.(j.le.Apt.and.i.gt.Apt))
     &         ) then

c
c  determine time of minimal approach of particles i and j
c  relative to current time
                  call nxtcoll(i,j,dst2,tcoll)
c
c  are the particles close enough - check cut off
c (default: 250 mbarn, defined in coms.f)
               if (dst2.lt.hit_sphere) then
c does the collision occur in the current time step?
                  if (tcoll.gt.0.d0.and.tcoll.lt.tmin) then
c     get sqrt(s) and total cross section
                     sqrs = sqrts(i,j)
c
c reduced cross section for leading hadrons of string fragmentation
c within their formation time
c the scaling factor is sigfac which is determined by the
c individual particles scaling factors xtotfac
                     if(tform(i).le.acttime+tcoll
     &                       .and.tform(j).le.acttime+tcoll) then
                       sigfac=1.d0
                     else if(tform(i).le.acttime+tcoll
     &                       .and.tform(j).gt.acttime+tcoll) then
                       sigfac=xtotfac(j)
                     else if(tform(j).le.acttime+tcoll
     &                       .and.tform(i).gt.acttime+tcoll) then
                       sigfac=xtotfac(i)
                     else
                       sigfac=xtotfac(i)*xtotfac(j)
                     endif
c     get total cross section via call to sigtot and rescale
                     sigt = sigfac*sigtot(i,j,sqrs)
c     rescale sigtot due to color fluctuations
ctp060202                     call colorfluc(ityp(i),ityp(j),sqrs,
                     call colorfluc(ityp(i),ityp(j),
     &                              colfaci,colfacj)
                     colfac=colfaci*colfacj
                     sigt = sigt*colfac
c     are we within the geometrical cross section
                     if (sigt.gt.max(1.d-8,(10.d0*pi*dst2))) then
c     this collision is to beat, now
                        tmin = tcoll
                        smin = sqrs
                        sigmin = sigt
                        imin = i
                        jmin = j
                        colfacmin=colfac
                     endif
                  endif
               endif
            endif
 101     continue
         if (imin.gt.0) then
c  if we found something, then update table via call to ctupdate
c  (keep in mind: tmin is relative to actual time!)
            call ctupdate(imin,jmin,acttime+tmin,smin,sigmin,colfacmin)
c     in case of "full load mode" after every collision
c     only the first entry in the collision table is relevant
            if(CTOption(17).ne.0) nct=1
         endif

       return
       end

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       subroutine ctupdate(i,j,t,s,sig,cfac)
c
cinput i : index of 1st colliding particle
cinput j : index of 2nd colliding particle (0 for decay)
cinput t : (absolut) time  of collision/decay
cinput s : $sqrt{s}$ (GeV) of collison
cinput sig : total cross section (mbarn) of collision
cinput cfac :  scaling factor for color fluctuation
c
c This subroutine updates the collision arrays.
c It determines the (chonologically) correct position for the new
c entry in the collision arrays, creates the respective slot and
c inserts the new entry (via a call to {\tt ctset}.
c Then the arrays are scanned to tag the chonologically first collision
c of particle {\tt i} or {\tt j} {\em true} and all subsequent ones
c as {\em false}.
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

       implicit none

       integer i,j
       real*8 t,s,sig,cfac
       include 'colltab.f'
       integer k,tfound,ncoll1

       ncoll1 = nct + 1
       tfound = ncoll1
c loop over all collisions in table
       do 101 k=actcol+1,nct
c     get the correct position for the new entry (chronologically sorted)
          if (tfound.eq.ncoll1.and.t.le.cttime(k)) tfound = k
c     the above construct works as follows:
c     as long as t > cttime(k), the first term is true and teh
c     the second is false. At the correct position for the new
c     entry BOTH terms are true, for all later times the first
c     term is false in order not to overwrite the value of tfound
 101   continue

c make sure that collision is not already listed in the table
       if (.not.(t.eq.cttime(tfound).and.(i.eq.cti1(tfound).and.
     &      j.eq.cti2(tfound).or.i.eq.cti2(tfound).and.
     &      j.eq.cti1(tfound)))) then
c then create slot for  new entry
             do 102 k=nct,tfound,-1
                cttime(k+1) = cttime(k)
                ctsqrts(k+1) = ctsqrts(k)
                ctsigtot(k+1) = ctsigtot(k)
                cti1(k+1) = cti1(k)
                cti2(k+1) = cti2(k)
                ctvalid(k+1) = ctvalid(k)
                ctcolfluc(k+1) = ctcolfluc(k)
 102         continue
c     increment number of collisions/decays in table
          nct = ncoll1
       endif
c insert new entry into the created slot via call to ctset
       call ctset(tfound,i,j,t,s,sig,cfac)
c
c     only the chonologically FIRST collision of particle i is set to true
c
       do 103 k=actcol+1,nct,1
c     the newly found collision must be omitted in the following sequence
          if (k.eq.tfound) goto 103
c  is there already a collision with i or j ?
          if (cti1(k).eq.i.or.cti2(k).eq.i) then
c     if the other collision is at an earlier time (the table is time-ordered,
c     therefore k < tfound corresponds to an earlier time)
c     then set the new one to false or vice versa
             if (k.lt.tfound.and.ctvalid(k)) then
                ctvalid(tfound) = .false.
             else
                ctvalid(k) = .false.
             endif
          endif
c     do likewise for the second particle
          if (j.gt.0.and.(cti1(k).eq.j.or.cti2(k).eq.j)) then
             if (k.lt.tfound.and.ctvalid(k)) then
                ctvalid(tfound) = .false.
             else
                ctvalid(k) = .false.
             endif
          endif
 103   continue

       return
       end



cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
      subroutine ctset(tfound,i,j,t,s,sig,cfac)
c
c     Revision : 1.0
C
cinput tfound : index in coll. array for coll. to be inserted
cinput i : index of first colliding particle
cinput j : index of second colliing particle (0 for decay, negative: wall)
cinput t : (absolute) time of collision
cinput s : $sqrt{s}$ (GeV) of collison
cinput sig : total cross section (mbarn) of collsion
cinput cfac :  scaling factor for color fluctuation
c
c {\tt ctset} enters the collision of particles {\tt i} and {\tt j}
c into the collision arrays at index {\tt tfound}.
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

      implicit none

      integer tfound,i,j

      real*8 t,s,sig,cfac
      include 'colltab.f'
c
      cttime(tfound) = t
      ctsqrts(tfound) = s
      ctsigtot(tfound) = sig
      cti1(tfound) = i
      cti2(tfound) = j
      ctvalid(tfound) = .true.
      ctcolfluc(tfound) = cfac
      return
      end

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
       real*8 function sqrts(i,j)
c
c     Revision : 1.0
c
c     input: i,j : numbers of colliding particles
c     output: $\sqrt{s}$ of collision as return value
c
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

       implicit none

       include 'coms.f'
       integer i,j
       real*8 p10,p20
       p10 = sqrt((px(i)+ffermpx(i))**2
     +           +(py(i)+ffermpy(i))**2
     +           +(pz(i)+ffermpz(i))**2+fmass(i)**2)
       p20 = sqrt((px(j)+ffermpx(j))**2
     +           +(py(j)+ffermpy(j))**2
     +           +(pz(j)+ffermpz(j))**2+fmass(j)**2)
       sqrts = sqrt((p10+p20)**2
     +               -(px(i)+ffermpx(i)+px(j)+ffermpx(j))**2
     +               -(py(i)+ffermpy(i)+py(j)+ffermpy(j))**2
     +               -(pz(i)+ffermpz(i)+pz(j)+ffermpz(j))**2)
       return
       end


cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine nxtcoll(j,k,dst,dtauc)
c
c     Revision : 1.0
c
c input:  j,k   : indices of colliding particles
coutput dst   : impact parameter squared
coutput dtauc : collisiontime in the computational system
c
c     {\tt nxtcoll}  is the heart  of the collision term. It determines
c     the time  in the  computional system, when the  collision between
c     j and k took or will take place ({\tt dtauc}). The squared impact
c     parameter of the collision is returned in {\tt dst}. {\tt dst} is
c     independent of the computational system  in which the coordinates
c     of j and k are given.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

      implicit none
      integer j,k, i
      include 'coms.f'
      real*8 u1(0:3), u2(0:3), p1(0:3), p2(0:3)
      real*8 dp(0:3), du(0:3), bt_com(3), bt(3)
      real*8 du2, dp2, dudp, bt_du, bt_dp, btdr, bt2
      real*8 dst, gam_com, gam_com2, bt_com2, dtauc

c
c do some assignments first
c
      u1(0) = r0(j)
      u1(1) = rx(j)
      u1(2) = ry(j)
      u1(3) = rz(j)
      u2(0) = r0(k)
      u2(1) = rx(k)
      u2(2) = ry(k)
      u2(3) = rz(k)

      p1(0) = sqrt(px(j)**2+py(j)**2+pz(j)**2+fmass(j)**2)
      p1(1) = px(j)
      p1(2) = py(j)
      p1(3) = pz(j)
      p2(0) = sqrt(px(k)**2+py(k)**2+pz(k)**2+fmass(k)**2)
      p2(1) = px(k)
      p2(2) = py(k)
      p2(3) = pz(k)
c
c -velocity and gamma-factor of the two particle center of momentum
c frame (com) measured in the computational system
c
      bt_com2 = 0.0d0
      do 1 i=1,3
        bt_com(i) = -((p1(i)+p2(i))/(p1(0)+p2(0)))
        bt_com2 = bt_com2 + bt_com(i)**2
    1 continue
      gam_com = 1.0d0/sqrt(1.0d0-bt_com2)
      gam_com2 = gam_com**2/(1.0d0+gam_com)
c
c calculate some numbers which are needed for the Lorentz-transformation
c
      bt_du = 0.0d0
      bt_dp = 0.0d0
      do 2 i=1,3
        bt_du = bt_du + bt_com(i)*(u1(i) - u2(i))
        bt_dp = bt_dp + bt_com(i)*(p1(i) - p2(i))
    2 continue
c
c calculate bt_com square and the dotproduct bt_com*(r(j)-r(k)),
c where the r's are given in the computational frame
c
c perform Lorentz-transformation of relative distance and relative
c momentum vectors of particles j and k into com-frame
c
c use the resulting 3-vectors du and dp to obtain du and dp squared
c and the dotproduct du*dp
c
      du2  = 0.0d0
      dp2  = 0.0d0
      dudp = 0.0d0
      bt2  = 0.0d0
      btdr = 0.0d0
      do 3 i=1,3
        bt(i) = p1(i)/p1(0) - p2(i)/p2(0) ! Rechensystem rel. vel.
        bt2 = bt2 + bt(i)**2
        btdr = btdr + bt(i)*(u1(i)-u2(i)) ! Rechensystem
        du(i) = u1(i)-u2(i) + bt_com(i)*
     *      (gam_com2*bt_du+gam_com*(u1(0)-u2(0)))
        dp(i) = p1(i)-p2(i) + bt_com(i)*
     *      (gam_com2*bt_dp+gam_com*(p1(0)-p2(0)))
        du2  = du2  + du(i)*du(i)
        dp2  = dp2  + dp(i)*dp(i)
        dudp = dudp + du(i)*dp(i)
    3 continue
c
c  obtain collision time and impact parameter squared
c
      dtauc = -(btdr/bt2)
      dst   = du2 - dudp*dudp/dp2

      end


ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine scantab(ind,offs)
c
c     Revision : 1.0
c
cinput ind : index of particle
cinput offs: offset
c
c     {\tt scantab} adjusts the collision table to changed particle
c     indices due to calls to {\tt addpart} or {\tt delpart}.
c
c     In case of an annihilation a list is created of those particles
c     which have lost their collision partner and have to be rechecked
c     for possible collisions/decays.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

      implicit none
      include 'colltab.f'
      include 'coms.f'
      integer ind,offs,i,k
      logical rescan

c     reset counters for the rechecking of particles due to lost collision
c     partners
      nsav=0
      rescan=.false.

c     call from addpart
      if (offs.gt.0) then
c     shift upwards, if necessary
         do 1 i=1,nct
            if (cti1(i).ge.ind) cti1(i) = cti1(i) + offs
            if (cti2(i).ge.ind) cti2(i) = cti2(i) + offs
 1       continue
c
c     call from delpart
      else

c     omit scan, if last collision in table
         if(actcol.eq.nct) return
c     start loop with next collision in table
         i=actcol+1
 2       continue
         if((cti1(i).eq.ind).or.(cti2(i).eq.ind)) then
c     a dubious entry has been found, now
c     look for particles with 'lost' collision partners
            if(cti1(i).eq.ind.and.cti2(i).gt.0) then
c     save particles with 'lost' partners in the ctsav array
               nsav=nsav+1
               ctsav(nsav)=cti2(i)
               if(ctsav(nsav).gt.ind) ctsav(nsav)=ctsav(nsav) + offs
            elseif(cti2(i).eq.ind.and.cti1(i).gt.0) then
               nsav=nsav+1
               ctsav(nsav)=cti1(i)
               if(ctsav(nsav).gt.ind) ctsav(nsav)=ctsav(nsav) + offs
            endif
c     delete obsolete collision
            do 4 k=i+1,nct
               cttime(k-1) = cttime(k)
               ctsqrts(k-1) = ctsqrts(k)
               ctsigtot(k-1) = ctsigtot(k)
               cti1(k-1) = cti1(k)
               cti2(k-1) = cti2(k)
               ctvalid(k-1) = ctvalid(k)
               ctcolfluc(k-1) = ctcolfluc(k)
 4          continue
c     decrement collision counter
            nct = nct-1
            rescan=.true.
         else
c     else entry is OK
            rescan=.false.
         endif
c     shift rest of table, in case entry has not been deleted
         if(.not.rescan) then
            if (cti1(i).gt.ind) cti1(i) = cti1(i) + offs
            if (cti2(i).gt.ind) cti2(i) = cti2(i) + offs
            i=i+1
         endif
c     condinue procedure until all collisions have been scanned
         if(i.le.nct) goto 2
      endif

      return
      end

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
        subroutine printtab
c
c     Revision: 1.0
c
c     {\tt printtab} prints the contents of the collision arrays on
c     unit 6 and marks the current collision with an *. This subroutine
c     is used for debugging purposes only.
c
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

        implicit none

        include 'colltab.f'
        integer i
        character*1 c
c
        write(6,*) 'colltab:'
        do 101 i=1,nct
           c = ' '
           if (i.eq.actcol) c = '*'
           write(6,'(i4,1x,L1,A1,2(i4,1x),4(f6.3,1x))')
     &            i,ctvalid(i),c,cti1(i),cti2(i),cttime(i),ctsqrts(i)
 101    continue
        return
        end


ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ctp060202      subroutine colorfluc(it1,it2,ws,fac1,fac2)
      subroutine colorfluc(it1,it2,fac1,fac2)
c
c     Revision : 1.0
c
cinput it1 : ityp particle 1
cinput it2 : ityp particle 2
cinput ws  : $\sqrt{s}$ of collision
coutput fac1 : x-section scaling factor of particle 1
coutput fac2 : x-section scaling factor of particle 2
c
c     Modifies the hadron cross section due to color fluctuations,
c     ref. L. Frankfurt et al.: Ann. Rev. Nucl. Part. Sc. 44 (1994)501
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

      implicit none
      include 'options.f'

ctp060202      real*8 ws,fac1,fac2
      real*8 fac1,fac2
      real*8 x,y,Pmes,Pbar,ranf
      integer it1,it2


      fac1=1d0
      fac2=1d0

c switched on ?
      if (ctoption(42).eq.0) return


c particle 1 is baryon
      if (abs(it1).lt.100) then
 1     x=ranf(0)*3d0
       y=ranf(0)

c probability disrtibution for x-section factor
       Pbar=(1.19+32.11*x-15.65*x**2-1.24*x**3+0.94*x**4)/18.d0
       Pbar=max(0d0,Pbar)
       if(y.gt.Pbar) goto 1
       fac1=x
c particle 1 is meson
      else
 2     x=ranf(0)*5d0
       y=ranf(0)

c probability disrtibution for x-section factor
       Pmes=(21.76+4.41*x-3-79*x**2+0.40*x**3)/25.d0
       Pmes=max(0d0,Pmes)
       if(y.gt.Pmes) goto 2
       fac1=x
      endif

c particle 2 is baryon
      if (abs(it2).lt.100) then
 3     x=ranf(0)*3d0
       y=ranf(0)

c probability disrtibution for x-section factor
       Pbar=(1.19+32.11*x-15.65*x**2-1.24*x**3+0.94*x**4)/18.d0
       Pbar=max(0d0,Pbar)
       if(y.gt.Pbar) goto 3
       fac2=x
c particle 2 is meson
      else
 4     x=ranf(0)*5d0
       y=ranf(0)

c probability disrtibution for x-section factor
       Pmes=(21.76+4.41*x-3-79*x**2+0.40*x**3)/25.d0
       Pmes=max(0d0,Pmes)
       if(y.gt.Pmes) goto 4
       fac2=x
      endif

      return
      end