real r(100),v(100),ev(100) real a(2),covar(2,2),alpha(2,2),dyda(2) integer lista(2) real h0 common/hubble/h0 print *, 'Okay, I want to read a file called rotfile.rot' print *, 'which has the following format:' print *, ' r(kpc) v(km/s) [sigv(km/s)]' print *, 'If your file aint in this format, stop now.' print *, ' ' print *, 'Velocity Errorbars?' print *, '(enter 0 to read from file col 3)' read *, evel print *, ' ' C print *, 'What is H0? [km/s/Mpc]' C read *, h0 h0=0.075 print *, ' ' print *, 'Initial Guess at c, r200?' read *, cguess, r200guess nrot=0 open (unit=10,file='rotfile.rot') 3 continue if (evel.ne.0) then read (10,*,end=100) r(nrot+1),v(nrot+1) ev(nrot+1)=evel else read (10,*,end=100) r(nrot+1),v(nrot+1),ev(nrot+1) endif nrot=nrot+1 go to 3 100 close (10) ma=2 lista(1)=1 lista(2)=2 mfit=2 nca=2 a(1)=cguess a(2)=r200guess alamda=-1. call mrqmin(r,v,ev,nrot,a,ma,lista,mfit, & covar,alpha,nca,chisq,alamda) oldchisq=chisq it=0 20 call mrqmin(r,v,ev,nrot,a,ma,lista,mfit, & covar,alpha,nca,chisq,alamda) it=it+1 del=abs(oldchisq-chisq)/oldchisq oldchisq=chisq if (it.gt.50) go to 50 if (abs(del).gt.0.001) go to 20 50 alamda=0. call mrqmin(r,v,ev,nrot,a,ma,lista,mfit, & covar,alpha,nca,chisq,alamda) write (*,999) write (*,*) 'Number of data points: ',nrot write (*,*) 'Number of iterations: ',it write (*,*) 'Chisq : ',chisq write (*,999) write (*,200) ' c=',a(1),' +/-',sqrt(covar(1,1)) write (*,200) ' r200=',a(2),' +/-',sqrt(covar(2,2)) write (*,999) 999 format (40('=')) 200 format (a6,f10.4,a5,f10.4) open (unit=10,file='rotfit.dat') do i=1,nrot rin=r(i) call navarro(rin,a,vout,dyda,2) write (10,*) rin,v(i),ev(i),vout enddo close (10) end subroutine navarro(x,a,y,dyda,na) dimension a(2),dyda(2) real l1pcronr200,lcstuff real h0 common/hubble/h0 C alpha=10*H where H is in km/s/kpc (for this task) alpha=10.*h0 C set up vars c=a(1) r200=a(2) r=x cronr200=c*r/r200 l1pcronr200=log(1+cronr200) lcstuff=log(1+c) - c/(1+c) C calculate v v=alpha*r200 * sqrt( (r200/r) * & (l1pcronr200 - (cronr200/(1+cronr200))) / & lcstuff ) C calculate dvdc (painful) dvdc1 = 1./(2*sqrt(r200)) dvdc1 = dvdc1 * r**1.5/ & (sqrt(l1pcronr200 - c*r/(r200*(1+cronr200)) ) * & sqrt(lcstuff) ) dvdc1 = dvdc1*alpha*c/(1+cronr200)**2 dvdc2 = 0.5*(r200**1.5)/sqrt(r) dvdc2 = dvdc2*sqrt(l1pcronr200-c*r/(r200*(1+cronr200))) dvdc2 = dvdc2/(lcstuff**1.5) dvdc2 = dvdc2*alpha*c/(1+c)**2 dvdc = dvdc1-dvdc2 C calculate dvdr200 (also painful) dvdr2001 = (1.5*alpha*sqrt(r200))/sqrt(r*lcstuff) dvdr2001 = dvdr2001*sqrt(l1pcronr200 - c*r/(r200*(1+cronr200))) dvdr2002 = ((r**1.5)*alpha*c*c)/(2*(r200**1.5)*(1+cronr200)**2) dvdr2002 = dvdr2002 / sqrt(l1pcronr200-c*r/(r200*(1+cronr200))) dvdr2002 = dvdr2002 / sqrt(lcstuff) dvdr200 = dvdr2001 - dvdr2002 C clean up y=v dyda(1)=dvdc dyda(2)=dvdr200 return end SUBROUTINE COVSRT(COVAR,NCVM,MA,LISTA,MFIT) DIMENSION COVAR(NCVM,NCVM),LISTA(MFIT) DO 12 J=1,MA-1 DO 11 I=J+1,MA COVAR(I,J)=0. 11 CONTINUE 12 CONTINUE DO 14 I=1,MFIT-1 DO 13 J=I+1,MFIT IF(LISTA(J).GT.LISTA(I)) THEN COVAR(LISTA(J),LISTA(I))=COVAR(I,J) ELSE COVAR(LISTA(I),LISTA(J))=COVAR(I,J) ENDIF 13 CONTINUE 14 CONTINUE SWAP=COVAR(1,1) DO 15 J=1,MA COVAR(1,J)=COVAR(J,J) COVAR(J,J)=0. 15 CONTINUE COVAR(LISTA(1),LISTA(1))=SWAP DO 16 J=2,MFIT COVAR(LISTA(J),LISTA(J))=COVAR(1,J) 16 CONTINUE DO 18 J=2,MA DO 17 I=1,J-1 COVAR(I,J)=COVAR(J,I) 17 CONTINUE 18 CONTINUE RETURN END SUBROUTINE GAUSSJ(A,N,NP,B,M,MP) PARAMETER (NMAX=50) DIMENSION A(NP,NP),B(NP,MP),IPIV(NMAX),INDXR(NMAX),INDXC(NMAX) DO 11 J=1,N IPIV(J)=0 11 CONTINUE DO 22 I=1,N BIG=0. DO 13 J=1,N IF(IPIV(J).NE.1)THEN DO 12 K=1,N IF (IPIV(K).EQ.0) THEN IF (ABS(A(J,K)).GE.BIG)THEN BIG=ABS(A(J,K)) IROW=J ICOL=K ENDIF ELSE IF (IPIV(K).GT.1) THEN RETURN ENDIF 12 CONTINUE ENDIF 13 CONTINUE IPIV(ICOL)=IPIV(ICOL)+1 IF (IROW.NE.ICOL) THEN DO 14 L=1,N DUM=A(IROW,L) A(IROW,L)=A(ICOL,L) A(ICOL,L)=DUM 14 CONTINUE DO 15 L=1,M DUM=B(IROW,L) B(IROW,L)=B(ICOL,L) B(ICOL,L)=DUM 15 CONTINUE ENDIF INDXR(I)=IROW INDXC(I)=ICOL IF (A(ICOL,ICOL).EQ.0.) RETURN PIVINV=1./A(ICOL,ICOL) A(ICOL,ICOL)=1. DO 16 L=1,N A(ICOL,L)=A(ICOL,L)*PIVINV 16 CONTINUE DO 17 L=1,M B(ICOL,L)=B(ICOL,L)*PIVINV 17 CONTINUE DO 21 LL=1,N IF(LL.NE.ICOL)THEN DUM=A(LL,ICOL) A(LL,ICOL)=0. DO 18 L=1,N A(LL,L)=A(LL,L)-A(ICOL,L)*DUM 18 CONTINUE DO 19 L=1,M B(LL,L)=B(LL,L)-B(ICOL,L)*DUM 19 CONTINUE ENDIF 21 CONTINUE 22 CONTINUE DO 24 L=N,1,-1 IF(INDXR(L).NE.INDXC(L))THEN DO 23 K=1,N DUM=A(K,INDXR(L)) A(K,INDXR(L))=A(K,INDXC(L)) A(K,INDXC(L))=DUM 23 CONTINUE ENDIF 24 CONTINUE RETURN END SUBROUTINE MRQCOF(X,Y,SIG,NDATA,A,MA,LISTA,MFIT,ALPHA,BETA,NALP, *CHISQ) PARAMETER (MMAX=20) DIMENSION X(NDATA),Y(NDATA),SIG(NDATA),ALPHA(NALP,NALP),BETA(MA), * DYDA(MMAX),LISTA(MFIT),A(MA) DO 12 J=1,MFIT DO 11 K=1,J ALPHA(J,K)=0. 11 CONTINUE BETA(J)=0. 12 CONTINUE CHISQ=0. DO 15 I=1,NDATA CALL navarro(X(I),A,YMOD,DYDA,MA) SIG2I=1./(SIG(I)*SIG(I)) DY=Y(I)-YMOD DO 14 J=1,MFIT WT=DYDA(LISTA(J))*SIG2I DO 13 K=1,J ALPHA(J,K)=ALPHA(J,K)+WT*DYDA(LISTA(K)) 13 CONTINUE BETA(J)=BETA(J)+DY*WT 14 CONTINUE CHISQ=CHISQ+DY*DY*SIG2I 15 CONTINUE DO 17 J=2,MFIT DO 16 K=1,J-1 ALPHA(K,J)=ALPHA(J,K) 16 CONTINUE 17 CONTINUE RETURN END SUBROUTINE MRQMIN(X,Y,SIG,NDATA,A,MA,LISTA,MFIT, * COVAR,ALPHA,NCA,CHISQ,ALAMDA) PARAMETER (MMAX=20) DIMENSION X(NDATA),Y(NDATA),SIG(NDATA),A(MA),LISTA(MA), * COVAR(NCA,NCA),ALPHA(NCA,NCA),ATRY(MMAX),BETA(MMAX),DA(MMAX) save ochisq IF(ALAMDA.LT.0.)THEN KK=MFIT+1 DO 12 J=1,MA IHIT=0 DO 11 K=1,MFIT IF(LISTA(K).EQ.J)IHIT=IHIT+1 11 CONTINUE IF (IHIT.EQ.0) THEN LISTA(KK)=J KK=KK+1 ELSE IF (IHIT.GT.1) THEN PAUSE 'Improper permutation in LISTA' ENDIF 12 CONTINUE IF (KK.NE.(MA+1)) PAUSE 'Improper permutation in LISTA' ALAMDA=0.001 CALL MRQCOF(X,Y,SIG,NDATA,A,MA,LISTA,MFIT,ALPHA,BETA,NCA,CHISQ) OCHISQ=CHISQ DO 13 J=1,MA ATRY(J)=A(J) 13 CONTINUE ENDIF DO 15 J=1,MFIT DO 14 K=1,MFIT COVAR(J,K)=ALPHA(J,K) 14 CONTINUE COVAR(J,J)=ALPHA(J,J)*(1.+ALAMDA) DA(J)=BETA(J) 15 CONTINUE CALL GAUSSJ(COVAR,MFIT,NCA,DA,1,1) IF(ALAMDA.EQ.0.)THEN CALL COVSRT(COVAR,NCA,MA,LISTA,MFIT) RETURN ENDIF DO 16 J=1,MFIT ATRY(LISTA(J))=A(LISTA(J))+DA(J) 16 CONTINUE CALL MRQCOF(X,Y,SIG,NDATA,ATRY,MA,LISTA,MFIT,COVAR,DA,NCA,CHISQ) IF(CHISQ.LT.OCHISQ)THEN ALAMDA=0.1*ALAMDA OCHISQ=CHISQ DO 18 J=1,MFIT DO 17 K=1,MFIT ALPHA(J,K)=COVAR(J,K) 17 CONTINUE BETA(J)=DA(J) A(LISTA(J))=ATRY(LISTA(J)) 18 CONTINUE ELSE ALAMDA=10.*ALAMDA CHISQ=OCHISQ ENDIF RETURN END SUBROUTINE SORT(N,RA) DIMENSION RA(N) L=N/2+1 IR=N 10 CONTINUE IF(L.GT.1)THEN L=L-1 RRA=RA(L) ELSE RRA=RA(IR) RA(IR)=RA(1) IR=IR-1 IF(IR.EQ.1)THEN RA(1)=RRA RETURN ENDIF ENDIF I=L J=L+L 20 IF(J.LE.IR)THEN IF(J.LT.IR)THEN IF(RA(J).LT.RA(J+1))J=J+1 ENDIF IF(RRA.LT.RA(J))THEN RA(I)=RA(J) I=J J=J+J ELSE J=IR+1 ENDIF GO TO 20 ENDIF RA(I)=RRA GO TO 10 END SUBROUTINE INDEXX(N,ARRIN,INDX) DIMENSION ARRIN(N),INDX(N) DO 11 J=1,N INDX(J)=J 11 CONTINUE L=N/2+1 IR=N 10 CONTINUE IF(L.GT.1)THEN L=L-1 INDXT=INDX(L) Q=ARRIN(INDXT) ELSE INDXT=INDX(IR) Q=ARRIN(INDXT) INDX(IR)=INDX(1) IR=IR-1 IF(IR.EQ.1)THEN INDX(1)=INDXT RETURN ENDIF ENDIF I=L J=L+L 20 IF(J.LE.IR)THEN IF(J.LT.IR)THEN IF(ARRIN(INDX(J)).LT.ARRIN(INDX(J+1)))J=J+1 ENDIF IF(Q.LT.ARRIN(INDX(J)))THEN INDX(I)=INDX(J) I=J J=J+J ELSE J=IR+1 ENDIF GO TO 20 ENDIF INDX(I)=INDXT GO TO 10 END SUBROUTINE FIT(X,Y,NDATA,SIG,MWT,A,B,SIGA,SIGB,CHI2,Q) DIMENSION X(NDATA),Y(NDATA),SIG(NDATA) SX=0. SY=0. ST2=0. B=0. IF(MWT.NE.0) THEN SS=0. DO 11 I=1,NDATA WT=1./(SIG(I)**2) SS=SS+WT SX=SX+X(I)*WT SY=SY+Y(I)*WT 11 CONTINUE ELSE DO 12 I=1,NDATA SX=SX+X(I) SY=SY+Y(I) 12 CONTINUE SS=FLOAT(NDATA) ENDIF SXOSS=SX/SS IF(MWT.NE.0) THEN DO 13 I=1,NDATA T=(X(I)-SXOSS)/SIG(I) ST2=ST2+T*T B=B+T*Y(I)/SIG(I) 13 CONTINUE ELSE DO 14 I=1,NDATA T=X(I)-SXOSS ST2=ST2+T*T B=B+T*Y(I) 14 CONTINUE ENDIF B=B/ST2 A=(SY-SX*B)/SS SIGA=SQRT((1.+SX*SX/(SS*ST2))/SS) SIGB=SQRT(1./ST2) CHI2=0. IF(MWT.EQ.0) THEN DO 15 I=1,NDATA CHI2=CHI2+(Y(I)-A-B*X(I))**2 15 CONTINUE Q=1. SIGDAT=SQRT(CHI2/(NDATA-2)) SIGA=SIGA*SIGDAT SIGB=SIGB*SIGDAT ELSE DO 16 I=1,NDATA CHI2=CHI2+((Y(I)-A-B*X(I))/SIG(I))**2 16 CONTINUE Q=GAMMQ(0.5*(NDATA-2),0.5*CHI2) ENDIF RETURN END FUNCTION GAMMQ(A,X) IF(X.LT.0..OR.A.LE.0.)PAUSE IF(X.LT.A+1.)THEN CALL GSER(GAMSER,A,X,GLN) GAMMQ=1.-GAMSER ELSE CALL GCF(GAMMCF,A,X,GLN) GAMMQ=GAMMCF ENDIF RETURN END FUNCTION GAMMLN(XX) REAL*8 COF(6),STP,HALF,ONE,FPF,X,TMP,SER SAVE COF,STP DATA COF,STP/76.18009173D0,-86.50532033D0,24.01409822D0, * -1.231739516D0,.120858003D-2,-.536382D-5,2.50662827465D0/ DATA HALF,ONE,FPF/0.5D0,1.0D0,5.5D0/ X=XX-ONE TMP=X+FPF TMP=(X+HALF)*LOG(TMP)-TMP SER=ONE DO 11 J=1,6 X=X+ONE SER=SER+COF(J)/X 11 CONTINUE GAMMLN=TMP+LOG(STP*SER) RETURN END SUBROUTINE GCF(GAMMCF,A,X,GLN) PARAMETER (ITMAX=100,EPS=3.E-16) GLN=GAMMLN(A) GOLD=0. A0=1. A1=X B0=0. B1=1. FAC=1. DO 11 N=1,ITMAX AN=FLOAT(N) ANA=AN-A A0=(A1+A0*ANA)*FAC B0=(B1+B0*ANA)*FAC ANF=AN*FAC A1=X*A0+ANF*A1 B1=X*B0+ANF*B1 IF(A1.NE.0.)THEN FAC=1./A1 G=B1*FAC IF(ABS((G-GOLD)/G).LT.EPS)GO TO 1 GOLD=G ENDIF 11 CONTINUE PAUSE 'A too large, ITMAX too small' 1 GAMMCF=EXP(-X+A*LOG(X)-GLN)*G RETURN END SUBROUTINE GSER(GAMSER,A,X,GLN) PARAMETER (ITMAX=100,EPS=3.E-16) GLN=GAMMLN(A) IF(X.LE.0.)THEN IF(X.LT.0.)PAUSE GAMSER=0. RETURN ENDIF AP=A SUM=1./A DEL=SUM DO 11 N=1,ITMAX AP=AP+1. DEL=DEL*X/AP SUM=SUM+DEL IF(ABS(DEL).LT.ABS(SUM)*EPS)GO TO 1 11 CONTINUE PAUSE 'A too large, ITMAX too small' 1 GAMSER=SUM*EXP(-X+A*LOG(X)-GLN) RETURN END