!------------------------------------------------- ! ! MODULE setHaloParticles PUBLIC Integer, PARAMETER :: NROW =2048, & NGRID =256, & nbyteword = 4, & NPAGE = NROW**2, & ! # particles in a record NRECL = NPAGE*6, & Nrad = 40, & ! # of radial bins Nbf = 10, & ! width of buffer for linker list Nmaxpart = 1024**3+200e6, & ! max # of particles Nlinker = 200, & ! linker-list dimension FracSearch = 5., & ! Nhmax = 150, & ! max # of selected particles in a halo Srms = 0.2, & ! fraction of rms velocity for bound particles nwant = 20000, & ! pool of preselected particles Kdynamic= 100 ! OMP chunk Real :: INPUT,Mhalo,Ovlim,Ovcnt Real, DIMENSION(Nrad) :: Rad(Nrad)=0. Real, DIMENSION(Nmaxpart) :: Xp,Yp,Zp,VXp,VYp,Vzp,iWeight Integer, DIMENSION(Nmaxpart) ::Lagrang Real :: Box=0.,Xscale=0.,Vscale=0.,Dscale=0.,Cell=0., weightSmall Integer :: Np=0,Ncp=0,Ncenter=0, & Nmx,Nbx,Nmy,Nby,Nmz,Nbz Real, ALLOCATABLE, DIMENSION (:) :: Xpp,Ypp,Zpp,VXpp,VYpp,Vzpp,Wpp Integer, ALLOCATABLE, DIMENSION (:) :: LagrangP COMMON / ROW / XPAR(NPAGE),YPAR(NPAGE),ZPAR(NPAGE), & VX(NPAGE),VY(NPAGE),VZ(NPAGE) COMMON / CONTROL/ AEXPN,AEXP0,AMPLT,ASTEP,ISTEP,PARTW, & TINTG,EKIN,EKIN1,EKIN2,AU0,AEU0, & NROWC,NGRIDC,Nspecies,Nseed,Om0,Oml0,hubble,Wp5, & Ocurv,extras(100) COMMON / HEADDR/ HEADER CHARACTER*45 HEADER Real :: RECDAT(NRECL),wspecies(10) Integer :: lspecies(10) Integer, ALLOCATABLE, DIMENSION (:,:,:) :: Label Integer, ALLOCATABLE, DIMENSION (:) :: Lst,nBins,nSelect Real, ALLOCATABLE, DIMENSION (:) :: Xc,Yc,Zc, & VXc,VYc,Vzc, & Amc,Rmc,Vrms,Vcirc Real, ALLOCATABLE, DIMENSION (:,:) :: aMr,Vvrms,GravPot Integer, ALLOCATABLE, DIMENSION (:,:) :: nPr,nBound EQUIVALENCE (wspecies(1),extras(1)), & (lspecies(1),extras(11)) !$OMP THREADPRIVATE(/ROW/) Contains !-------------------------------------------------------------- ! Make linker lists of particles in each cell SUBROUTINE List !-------------------------------------------------------------- !$OMP PARALLEL DO DEFAULT(SHARED) & !$OMP PRIVATE (i) Do i=1,Ncp Lst(i)=-1 EndDo !$OMP PARALLEL DO DEFAULT(SHARED) & !$OMP PRIVATE (i,j,k) Do k=Nmz,Nbz Do j=Nmy,Nby Do i=Nmx,Nbx Label(i,j,k)=0 EndDo EndDo EndDo Do jp=1,Ncp i=INT(Xp(jp)/Cell) j=INT(Yp(jp)/Cell) k=INT(Zp(jp)/Cell) i=MIN(MAX(Nmx,i),Nbx) j=MIN(MAX(Nmy,j),Nby) k=MIN(MAX(Nmz,k),Nbz) Lst(jp) =Label(i,j,k) Label(i,j,k) =jp EndDo write(*,*) ' Made first list' ALLOCATE(Xpp(Ncp),Ypp(Ncp),Zpp(Ncp),Stat=iStat) If(iStat.ne.0)Then write(*,*)'Not enough memory for Xpp in List. No Rearrangment' return EndIf ALLOCATE(VXpp(Ncp),VYpp(Ncp),VZpp(Ncp),Stat=iStat) If(iStat.ne.0)Then write(*,*)'Not enough memory for Vpp in List. No Rearrangment' DEALLOCATE (Xpp,Ypp,Zpp) return EndIf ALLOCATE(LagrangP(Ncp),Wpp(Ncp),Stat=iStat) If(iStat.ne.0)Then write(*,*)'Not enough memory for LagrangP in List. No Rearrangment' DEALLOCATE (Xpp,Ypp,Zpp,VXpp,VYpp,VZpp) return EndIf write(*,*) ' --- working on rearranging ' nn = 0 ! main particles should be first Do k=Nmz,Nbz !write (*,*) ' re-arrange k=',k Do j=Nmy,Nby Do i=Nmx,Nbx jp =Label(i,j,k) Do while(jp.ne.0) If(jp.le.Np)Then nn =nn +1 LagrangP(nn) =Lagrang(jp) Wpp(nn) =iWeight(jp) Xpp(nn) =Xp(jp) Ypp(nn) =Yp(jp) Zpp(nn) =Zp(jp) VXpp(nn) =VXp(jp) VYpp(nn) =VYp(jp) VZpp(nn) =VZp(jp) EndIf jp =Lst(jp) End DO EndDo EndDo EndDo If(nn.ne.Np)Then write(*,*) ' error in rearranging particles in List' write(*,*) ' New number of particles is=',nn write(*,*) ' It must be equal to old =',Np Stop EndIf write(*,*) ' --- restore particles ' ! Restore particles !$OMP PARALLEL DO DEFAULT(SHARED) & !$OMP PRIVATE (i) Do i=1,Np ! (1,Ncp) changed ! to Np for parallelization Lagrang(i) =LagrangP(i) iWeight(i) =Wpp(i) Xp(i) =Xpp(i) Yp(i) =Ypp(i) Zp(i) =Zpp(i) VXp(i) =VXpp(i) VYp(i) =VYpp(i) VZp(i) =VZpp(i) EndDo DEALLOCATE (Xpp,Ypp,Zpp,VXpp,VYpp,VZpp,LagrangP,Wpp) write(*,*) ' re-arranged particles' !$OMP PARALLEL DO DEFAULT(SHARED) & !$OMP PRIVATE (i) Do i=1,Ncp Lst(i)=-1 EndDo !$OMP PARALLEL DO DEFAULT(SHARED) & !$OMP PRIVATE (i,j,k) Do k=Nmz,Nbz Do j=Nmy,Nby Do i=Nmx,Nbx Label(i,j,k)=0 EndDo EndDo EndDo Do jp=1,Ncp i=INT(Xp(jp)/Cell) j=INT(Yp(jp)/Cell) k=INT(Zp(jp)/Cell) i=MIN(MAX(Nmx,i),Nbx) j=MIN(MAX(Nmy,j),Nby) k=MIN(MAX(Nmz,k),Nbz) Lst(jp) =Label(i,j,k) Label(i,j,k) =jp EndDo write(*,*) ' Made second list' Return End SUBROUTINE List !-------------------------------------------------------------- ! Find all neibhours for a center ! Xc,Yc,Zc - center; ! SUBROUTINE SNeib(iHalo) !-------------------------------------------------------------- Real, DIMENSION(nwant) :: Rpart,Ek,Et,Ec Integer, DIMENSION(nwant) :: Lpart,ind Integer :: Labpart(1) x = Xc(iHalo) ; y = Yc(iHalo); z = Zc(iHalo) Vx1=VXc(iHalo) ; Vy1= VYc(iHalo); Vz1= VZc(iHalo) Lpart = 0 Labpart = 0 Ek = 1.e10 Et = 1.e10 nn =0 mm =0 kbin =Nbins(iHalo) RhaloMax =Rad(kbin) Do i=1,kbin nn = nPr(i,iHalo) mm = i If(Rad(i).gt.Rmc(iHalo)/2.)exit EndDo If(nn.eq.0)Then Nbound(1,iHalo) =0 ! no particles selected return EndIf Frac = min(nwant/float(nn),1.) ! fraction of particles, ! selected as candidates vthresh2 = (max(fSigma(Frac),0.2)*Vrms(iHalo))**2 ! take particles ! with small velocity Radmax = Rad(mm) dmax = Radmax**2 d0 = Rad(1) ! write(*,'(3i6,3g12.3)')iHalo,nn,mm,Radmax,Cell ! write(*,'(10x,2(3x,3f8.2))') x,y,z,Vx1,Vy1,Vz1 nn = 0 ! counter for pre-selected particles ! limits for Label i1=INT((x-Radmax)/Cell) j1=INT((y-Radmax)/Cell) k1=INT((z-Radmax)/Cell) i1=MIN(MAX(Nmx,i1),Nbx) j1=MIN(MAX(Nmy,j1),Nby) k1=MIN(MAX(Nmz,k1),Nbz) i2=INT((x+Radmax)/Cell) j2=INT((y+Radmax)/Cell) k2=INT((z+Radmax)/Cell) i2=MIN(MAX(Nmx,i2),Nbx) j2=MIN(MAX(Nmy,j2),Nby) k2=MIN(MAX(Nmz,k2),Nbz) ! Look for neibhours Do k=k1,k2 Do j=j1,j2 Do i=i1,i2 jp =Label(i,j,k) ! Dark matter 10 If(jp.ne.0.and.nn10)STOP Return End SUBROUTINE SNeib !-------------------------------------------------------------- ! Add points around the Box to take into account periodical conditions ! It replicates points periodically and keeps those which are at distance ! less than Radius from the Box. ! N = number of points inside the Box ! Ncp = total number of points SUBROUTINE Points(Radius) !-------------------------------------------------------------- Logical Inside B1 =-Radius B2 =Box+Radius B3 =Box-Radius Ncp =Np Do i=1,Np ! Add dark matter particles x0 =xp(i) y0 =yp(i) z0 =zp(i) Inside = (x0.gt.Radius).and.(x0.lt.B3) Inside =Inside.and.((y0.gt.Radius).and.(y0.lt.B3)) Inside =Inside.and.((z0.gt.Radius).and.(z0.lt.B3)) If(.not.Inside)THEN ux =VXp(i) uy =VYp(i) uz =VZp(i) ww=iWeight(i) Do k1 = -1,1 zr =z0+k1*Box If(zr.GT.B1.AND.zr.LT.B2)Then kk =k1**2 Do j1 = -1,1 yr =y0+j1*Box If(yr.GT.B1.AND.yr.LT.B2)Then jj = kk +j1**2 Do i1 = -1,1 xr =x0+i1*Box ii =jj +i1**2 If((xr.GT.B1.AND.xr.LT.B2).AND.ii.ne.0)Then Ncp =Ncp +1 If(Ncp.le.Np)Then xp(Ncp) =xr yp(Ncp) =yr zp(Ncp) =zr VXp(Ncp) =ux VYp(Ncp) =uy VZp(Ncp) =uz iWeight(Ncp) =ww Lagrang(Ncp) =i EndIf EndIf EndDo EndIf EndDo EndIf EndDo EndIf EndDo If(Ncp.Gt.Nmaxpart)Then write(*,*)' Too many points:',Ncp,' Increase Nmaxpart =', Nmaxpart STOP EndIf Return End SUBROUTINE Points !-------------------------------- Update Statistics of pairs ! SUBROUTINE SPairs !--------------------------------------------------- !$OMP PARALLEL DO DEFAULT(SHARED) & !$OMP PRIVATE (i) & !$OMP SCHEDULE (DYNAMIC,kDynamic) Do i=1,Ncenter Call Sneib(i) EndDo Return End SUBROUTINE SPairs !----------------------------------------------------------------- ! Inverse cumulative chi-2 distribution with ! 3 degrees of freedom: chi_3(x)=frac. Need it for finding ! velocity, which has given fraction of particles. ! Finds x, ! which has given fraction of particles frac. ! fSigma = v/rms_v = [0-infty] ! frac = [0-1] ! error of approximation is less than ! 7.5 percent for v<4.5sigma ! 15 percent at 6 sigma, ! 30 percent at 10sigma FUNCTION fSigma(frac) real, parameter :: beta =1.,thresh=0.9 real, parameter :: C =log(1.-thresh) If(frac