package tfa; import mmc.*; import java.io.Reader; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.Vector; import java.util.StringTokenizer; /** * Implements muon/tau propagation through multiple media to/through the detector. * Current possibilities for detector geometry are cylinder, cuboid, and sphere. * The origin is at the center of the detector. */ public class Amanda{ private final static boolean lfix=true; private final static double LENGTH=800; private final static double RADIUS=400; private final static double WIDTH=800; private final static double HEIGHT=800; private final static double BIG=6.40e7; private boolean SURF=false; private boolean FACE=false; private boolean USER=false; private boolean USFI=false; private boolean SDEC=false; private boolean RECC=false; private double zset=0; private String type; private int mediamax=100; private String mediadef=null; private double vcut[] = { -1.0, -1.0 }; private double ecut[] = { -1.0, -1.0 }; private String med="Ice"; private String muta="mu"; private String usna="mmc_en"; private double elow=PhysicsModel.elow; private double ebig=PhysicsModel.ebig; private boolean conti[] = { false, false }; private boolean timef=false; private boolean lpmef=false; private boolean scatt=false; private boolean frho=false; private boolean rfix=false; private boolean amasim=false; private int bspar=1; private int pncrs=1; private int pncbb=1; private int pncsh=1; private double crsci=1; private double crscb=1; private double crscp=1; private double crsce=1; private double crscd=1; private double drho=1; private int romb=5; private long seed=0; private boolean SEED=false; private boolean raw=false; private String tdir=""; public String dtct=""; public int gdet=0; public double length=LENGTH, radius=RADIUS, width=WIDTH, height=HEIGHT; public double rho[], srho[]; private Propagate p1[], p2[], p3[]; private double surf=0; private double emax=0; private StringBuffer hist; private Vector userbf; private Vector I3hist; private Particle pI; private int igen, gens=0, imax=0; private String prnt; public long events=0, tracks=0, vertices=0, missed=0; private String param="Amanda", options; private int fnu; private int fnm[]; private double fnx[]; public int medt[]; public double sphz[]; public double sphr[]; public double boxx[]; public double boxy[]; public double boxz[]; public double boxl[]; public double boxw[]; public double boxh[]; public double cylz[]; public double cylr[]; public double cyll[]; public int medianum=1; public boolean DEBUG=false; //----------------------------------------------------------------------------------------------------// /** * Front-end for AMANDA, reads from and outputs to standard input/output in F2000 format. */ public static void main(String[] args){ Amanda A = new Amanda(); A.mmcf2k(args); } //----------------------------------------------------------------------------------------------------// /** * Initializes propagation for external applications, e.g. mmc-icetray (through jni). */ public void setup(String args){ dtct=".icecube"; setup(Output.splitString(args)); } //----------------------------------------------------------------------------------------------------// /** * Initializes propagation for external applications, e.g. mmc-icetray (through jni). */ public void setup(String args[]){ Output.I3flag=true; setp(args); I3hist = new Vector(Output.HISTSIZE); } //----------------------------------------------------------------------------------------------------// /** * Propagates particles for the external applications. Returns an array of secondaries. * If "-user" option is used, fills user-block variables. */ public Particle[] propagate(Particle p){ if(!Output.I3flag) return null; Particle[] I3p; pI=p; type=p.name; if(muta.equals(type) || (muta+"-").equals(type) || (muta+"+").equals(type)){ p.r=prop(p.igen, p.gens, p.x*1.e-2, p.y*1.e-2, p.z*1.e-2, 180-p.theta, p.phi<180?p.phi+180:p.phi-180, p.r*1.e-2, p.e*1.e-3, p.t*1.e9); I3p = new Particle[I3hist.size()]; for(int i=0; i1?",":"")+" \""+args[n]+"\""; pflag=false; } if(pflag) param+=" "+args[n]; } Output.err.println(Output.version); Output.err.println("Running \""+param+"\""); if(bnum>0){ param+=" (not used:"+pbad+")"; pbad=bnum==1?pbad+" is":"s"+pbad+" are"; Output.err.println("Warning: Parameter"+pbad+" not recognized"); } if(gdet!=0 && gdet!=1 && gdet!=2){ Output.err.println("Warning: gdet is not a valid number"); gdet=0; } if(length<=0){ Output.err.println("Warning: length is not a valid number"); length=LENGTH; } if(radius<=0){ Output.err.println("Warning: radius is not a valid number"); radius=RADIUS; } if(width<=0){ Output.err.println("Warning: width is not a valid number"); width=WIDTH; } if(height<=0){ Output.err.println("Warning: height is not a valid number"); height=HEIGHT; } if(!SURF || surf==0) FACE=false; if(bspar<1 || bspar>4){ Output.err.println("Warning: bs is not a valid number"); bspar=1; } if(pncrs<1 || pncrs>4 || (pncrs==2 && !(muta.equals("mu") || muta.equals("tau")))){ Output.err.println("Warning: ph is not a valid number"); pncrs=1; } if(((pncrs==1 || pncrs==2) && (pncbb<1 || pncbb>4)) || (pncrs==3 && (pncbb<1 || pncbb>2)) || (pncrs==4 && pncbb!=1)){ Output.err.println("Warning: bb is not a valid number"); pncbb=1; } if(((pncrs==1 || pncrs==2) && (pncsh!=1)) || ((pncrs>2) && (pncsh<1 || pncsh>2))){ Output.err.println("Warning: sh is not a valid number"); pncsh=1; } if(romb<2 || romb>6){ Output.err.println("Warning: romb is not a valid number"); romb=5; } if(mediadef!=null){ try{ if(Output.exists(mediadef)){ Reader ifile = Output.reader(mediadef); LineNumberReader inf = new LineNumberReader(ifile); int mediacur; String buf; mediaopts="HI Attaching the media definition file:\n"; while((buf=inf.readLine())!=null){ mediaopts+="HI ! "+buf+"\n"; StringTokenizer st = new StringTokenizer(buf); if(!st.hasMoreTokens()) continue; String taux=st.nextToken(); if(taux.charAt(0)=='#') continue; if(medianum==mediamax){ Output.err.println("Warning: Number of defined media will not exceed "+mediamax); break; } boolean sflag=false; if("all".equals(taux.toLowerCase())){ mediacur=0; medt[mediacur]=0; } else if("sphere".equals(taux.toLowerCase())){ mediacur=medianum; medt[mediacur]=1; sphz[mediacur]=Double.parseDouble(st.nextToken()); sphr[mediacur]=Double.parseDouble(st.nextToken()); if(sphr[mediacur]<0){ sphr[mediacur]*=-1; sflag=true; } if(sflag) medt[mediacur]*=-1; for(i=0; i0?true:false; vcut[0][mediacur]=Double.parseDouble(st.nextToken()); ecut[0][mediacur]=Double.parseDouble(st.nextToken()); conti[0][mediacur]=Integer.parseInt(st.nextToken())>0?true:false; vcut[1][mediacur]=Double.parseDouble(st.nextToken()); ecut[1][mediacur]=Double.parseDouble(st.nextToken()); conti[1][mediacur]=Integer.parseInt(st.nextToken())>0?true:false; rho[mediacur]=Double.parseDouble(st.nextToken()); taux=st.nextToken(); while(st.hasMoreTokens()) taux=taux+" "+st.nextToken(); med[mediacur]=taux; } ifile.close(); } else Output.err.println("Error: File "+mediadef+" cannot be found"); }catch(Exception error){ Output.err.println("Error: File "+mediadef+" is corrupt: "+error.toString()); medianum=1; mediaseg=1; medn[0]=true; } mediaopts+="HI total number of defined media is "+medianum+"\n"; } fnm = new int[mediaseg]; fnx = new double[mediaseg]; options=(gdet==2?"HI radius = "+Output.f(radius):"HI length = "+Output.f(length)+(gdet==1?" m width = "+Output.f(width)+" m height = "+Output.f(height):" m radius = "+Output.f(radius)))+" m medium = \""+med[0]+"\"\n"; if(SURF){ options+="HI propagating to surface z = "+Output.f(surf)+" m"; if(FACE){ if(surf<0) options+=" (up only)"; else if(surf>0) options+=" (down only)"; } options+="\n"; } for(i=0; i0?Output.f(ec):"?")+" "+ (e1!=0?Output.f(e1):"?")+" "+(e2!=0?Output.f(e2):"?")+" "+ Output.f(nx)+" "+Output.f(ny)+" "+Output.f(nz)+" "+ (h1>0?Output.f(z1):"?")+" "+(h2>0?Output.f(z2):"?")); if(rfix) if(e>emax){ imax=userbf.size()-1; emax=e; } } //----------------------------------------------------------------------------------------------------// /** * Output user line block for the f2k file streams. */ public void outUSER(){ if(USER){ if(rfix){ if(userbf.size()==0) Output.out.println("US "+usna+" ? ? ? ? ? ? ? ? ? ?"); else Output.out.println("US "+usna+" "+userbf.elementAt(imax)); } else for(int i=0; igens) gens=igen; prnt=st.nextToken(); try{ ipar=Integer.parseInt(prnt); if(ipar>gens) gens=ipar; }catch(NumberFormatException error){ ipar=-1; } } else if("EE".equals(taux) || "END".equals(taux)){ iniUSER(); if(rw!=0) dw=true; for(i=0; iaux) h1=aux; if(h2>aux) h2=aux; if(h3>aux) h3=aux; } if(USER){ if(USFI){ if(costh!=0) n2=(z-zset)/costh; else n2=0; } else n2=x*sinth*cosph+y*sinth*sinph+z*costh; if(n20?1:2); ij++){ if(medt[m]>0){ r1=hx1; r2=hx2; } else{ if(ij==0){ r1=0; r2=hx1; } else{ r1=hx2; r2=BIG; } } if(r2>r1){ md=0; mi=0; if(r1>0){ md++; for(mi=0; mir1) break; } mf=0; if(r2>0){ md++; for(mf=mi; mfr2) break; } md+=mi-mf; if(md>0) for(mj=fnu-1; mj>=mf; mj--){ fnx[mj+md]=fnx[mj]; fnm[mj+md]=fnm[mj]; } else if(md<0) for(mj=mf; mj0){ fnx[mi]=r1; mi++; } if(r2>0){ fnx[mi]=r2; fnm[mi]=m; } } } } if(DEBUG){ for(j=0; j=rr && r1==h1){ e1=result; if(Output.I3flag) pI.ti=pp.p.t; } if(Output.RecDec){ if(Output.I3flag) I3hist.addAll(pp.o.I3hist); else hist.append(pp.o.history); gens=pp.o.gens; } if(result>0){ if(r1>rr) rr=r1; if(USER) elost+=result; if(dw){ p2[m].dw=true; p2[m].rw=rw; p2[m].hw=(hw-rr)*1.e2; } result=propagateTo(r2-rr, result, n2-rr, 2, p2[m], igen, gens, pp.p.t, pp.p.x, pp.p.y, pp.p.z, pp.p.theta, pp.p.phi); pp=p2[m]; l+=pp.p.r; if(USER) if(r2>=rr && r2==h2){ e2=result; if(Output.I3flag) pI.tf=pp.p.t; } if(dw){ if(!p2[m].dw){ dw=false; fw=p2[m].rw; hw=p2[m].hw*1.e-2+rr; } else p2[m].dw=false; p2[m].rw=0; p2[m].hw=0; } if(Output.I3flag) I3hist.addAll(pp.o.I3hist); else hist.append(pp.o.history); vertices+=pp.o.gens-gens; gens=pp.o.gens; if(result>0){ if(r2>rr) rr=r2; if(USER){ elost-=result; if(elost<0) elost=0; } result=propagateTo(r3-rr, result, n2-rr, 3, p3[m], igen, gens, pp.p.t, pp.p.x, pp.p.y, pp.p.z, pp.p.theta, pp.p.phi); pp=p3[m]; l+=pp.p.r; if(Output.RecDec){ if(Output.I3flag) I3hist.addAll(pp.o.I3hist); else hist.append(pp.o.history); gens=pp.o.gens; } if(result>0) if(r3>rr) rr=r3; } } if(result<=0) break; } if(USER){ if(h1==0) e1=0; if(h2==0) e2=0; if(e1<0) e1-=rr; if(e2<0) e2-=rr; z1=z-costh*h1; z2=z-costh*h2; nx=x-sinth*cosph*n2; ny=y-sinth*sinph*n2; nz=z-costh*n2; if(!Output.I3flag) recUSER(); else{ pI.xi=x-sinth*cosph*h1; pI.yi=y-sinth*sinph*h1; pI.zi=z-costh*h1; pI.xf=x-sinth*cosph*h2; pI.yf=y-sinth*sinph*h2; pI.zf=z-costh*h2; pI.xc=nx; pI.yc=ny; pI.zc=nz; pI.Ei=e1; pI.Ef=e2; pI.Ec=ec>0?ec:0; pI.Elost=elost; } } if(SURF){ x=pp.p.x*1.e-2; y=pp.p.y*1.e-2; z=pp.p.z*1.e-2; th=180-pp.p.theta; phi=pp.p.phi; phi=phi<180?phi+180:phi-180; if(result>0){ e=result; l=-BIG; } else{ e=0; l=0; } t=pp.p.t*1.e9; } if(!Output.I3flag){ Output.out.println("TR "+igen+" "+prnt+" "+type+" "+Output.f(x)+" "+Output.f(y)+" "+Output.f(z)+" "+ Output.f(th)+" "+Output.f(phi)+" "+(l>=0?Output.f(l*1.e-2):"?")+" "+ Output.f(e)+" "+Output.f(t)); Output.out.print(hist); } return l; } //----------------------------------------------------------------------------------------------------// private double hx1, hx2; /** * Calculate points of intersection with the cylinder. */ private void setcyl(double x, double y, double z, double cosph, double sinph, double costh,double sinth, double length, double radius){ double aux, r1, r2; double b=x*cosph+y*sinph; double d=b*b+radius*radius-x*x-y*y; if(d>0){ d=Math.sqrt(d); if(costh!=0){ hx1=(z-length/2)/costh; hx2=(z+length/2)/costh; if(hx1>hx2){ aux=hx1; hx1=hx2; hx2=aux; } } if(sinth!=0){ r1=(b-d)/sinth; r2=(b+d)/sinth; if(r1>r2){ aux=r1; r1=r2; r2=aux; } if(costh==0){ if(z>-length/2 && z=r2 || hx2<=r1){ hx1=0; hx2=0; } else{ hx1=Math.max(r1, hx1); hx2=Math.min(r2, hx2); } } } } else{ hx1=0; hx2=0; } } //----------------------------------------------------------------------------------------------------// /** * Calculate points of intersection with the box. */ private void setbox(double x, double y, double z, double dx, double dy, double dz, double length, double width, double height){ boolean top=false, bottom=false, tbflag=false; double hx; if(dx!=0){ if(!tbflag){ hx=-(x-length/2)/dx; if(Math.abs(y+hx*dy)<=width/2 && Math.abs(z+hx*dz)<=height/2){ if(!top){ hx1=hx; top=true; } else if(hx!=hx1 && !bottom){ hx2=hx; bottom=true; } else tbflag=true; } } if(!tbflag){ hx=-(x+length/2)/dx; if(Math.abs(y+hx*dy)<=width/2 && Math.abs(z+hx*dz)<=height/2){ if(!top){ hx1=hx; top=true; } else if(hx!=hx1 && !bottom){ hx2=hx; bottom=true; } else tbflag=true; } } } if(dy!=0){ if(!tbflag){ hx=-(y-width/2)/dy; if(Math.abs(x+hx*dx)<=length/2 && Math.abs(z+hx*dz)<=height/2){ if(!top){ hx1=hx; top=true; } else if(hx!=hx1 && !bottom){ hx2=hx; bottom=true; } else tbflag=true; } } if(!tbflag){ hx=-(y+width/2)/dy; if(Math.abs(x+hx*dx)<=length/2 && Math.abs(z+hx*dz)<=height/2){ if(!top){ hx1=hx; top=true; } else if(hx!=hx1 && !bottom){ hx2=hx; bottom=true; } else tbflag=true; } } } if(dz!=0){ if(!tbflag){ hx=-(z-height/2)/dz; if(Math.abs(x+hx*dx)<=length/2 && Math.abs(y+hx*dy)<=width/2){ if(!top){ hx1=hx; top=true; } else if(hx!=hx1 && !bottom){ hx2=hx; bottom=true; } else tbflag=true; } } if(!tbflag){ hx=-(z+height/2)/dz; if(Math.abs(x+hx*dx)<=length/2 && Math.abs(y+hx*dy)<=width/2){ if(!top){ hx1=hx; top=true; } else if(hx!=hx1 && !bottom){ hx2=hx; bottom=true; } else tbflag=true; } } } if(!top) hx1=0; if(!bottom) hx2=0; if(hx1>hx2){ hx=hx1; hx1=hx2; hx2=hx; } } //----------------------------------------------------------------------------------------------------// /** * Calculate points of intersection with the sphere. */ private void setsph(double x, double y, double z, double cosph, double sinph, double costh, double sinth, double radius){ double b=(x*cosph+y*sinph)*sinth+(z+radius)*costh; double d=b*b-(x*x+y*y+z*(z+2*radius)); if(d>0){ d=Math.sqrt(d); hx1=b-d; hx2=b+d; } else{ hx1=0; hx2=0; } } //----------------------------------------------------------------------------------------------------// /** * Calculate points of intersection with the box. */ private void setpln(double x, double y, double z, double dx, double dy, double dz, double nx, double ny, double nz){ double b=-(x*nx+y*ny+z*nz); double d=dx*nx+dy*ny+dz*nz; if(b>=0 || b*d>0){ if(b>=0){ hx1=0; hx2=d!=0?b/d:BIG; } else{ hx1=d!=0?b/d:0; hx2=BIG; } } else{ hx1=0; hx2=0; } } //----------------------------------------------------------------------------------------------------// public boolean dw=false; public double rw=0, hw=0, fw=1; private int flag=0; private double e; /** * user-block variable: z-coordinate of entry point into the detector cylinder (Z_IN) */ public double z1=0; /** * user-block variable: z-coordinate of exit point from the detector cylinder (Z_OUT) */ public double z2=0; /** * user-block variable: distance to the point of entry into the detector cylinder (R_IN) */ public double h1=0; /** * user-block variable: distance to the point of exit from the detector cylinder (R_OUT) */ public double h2=0; /** * user-block variable: x-coordinate of closest approach point (CPD_X) or -user=z point */ public double nx=0; /** * user-block variable: y-coordinate of closest approach point (CPD_Y) or -user=z point */ public double ny=0; /** * user-block variable: z-coordinate of closest approach point (CPD_Z) or -user=z point */ public double nz=0; /** * user-block variable: Energy at the entry point into the detector cylinder if positive (E_IN) */ public double e1=0; /** * user-block variable: Energy at the exit point from the detector cylinder if positive (E_OUT) */ public double e2=0; /** * user-block variable: Energy at the CPD point if positive (E_CPD) */ public double ec=0; /** * Energy lost inside the detector cylinder */ public double elost=0; //----------------------------------------------------------------------------------------------------// /** * checks the flag, corrects the units, initializes the particle and calls the propagator */ private double propagateTo(double h, double e, double n, int i, Propagate p, int igen, int gens, double time, double x, double y, double z, double theta, double phi){ double result; switch(i){ case 1: p.o.initDefault(igen, gens, type, time, x, y, z, theta, phi); break; case 2: p.o.initF2000(igen, gens, type, time, x, y, z, theta, phi); break; case 3: p.o.initDefault(igen, gens, type, time, x, y, z, theta, phi); break; } if(flag==i && n>=0 && n0?ec*1.e-3:ec*1.e-2; if(Output.I3flag) pI.tc=p.getPropTc(); } else result=p.propagateTo(h*1.e2, e*1.e3); return result>0?result*1.e-3:result*1.e-2; } }