#include #include #include #include using namespace RAT; SNOAVBellyPlate::SNOAVBellyPlate(DBLinkPtr geoDimensionsTable, const G4double rmin, const G4double rmax, const G4ThreeVector &xAxis, const G4ThreeVector &yAxis, const G4ThreeVector &zAxis, const G4double zInner, const G4double zOuter): fXaxis(xAxis), fYaxis(yAxis),fZaxis(zAxis){ //y axis goes through the center of the belly plate; x axis perpendicular and z vertical fThreshold = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); fRmin = rmin; fRmax = rmax; fZInner = zInner; fZOuter = zOuter; fRhomin = sqrt(fRmin*fRmin - fZOuter*fZOuter); fRhomax = sqrt(fRmax*fRmax - fZInner*fZInner); fRhoSlope = (fRhomax - fRhomin) / (fZInner - fZOuter); //so Rho=(fRhoSlope * (z-fZOffset)); Rhoslope is negative for the outside of the belly plates fZOffset = fZInner - fRhomax / fRhoSlope; //fZOffset is positive G4double fInnerAVradius = geoDimensionsTable->GetD( "inner_av_radius" ); G4double fAVthickness = geoDimensionsTable->GetD( "av_thickness" ); G4double fGrooveInnerRadius = geoDimensionsTable->GetD("ropegroove_inner_radius"); fGrooveRadius = geoDimensionsTable->GetD("ropegroove_radius"); fGrooveHalfWidth = fGrooveRadius - fGrooveInnerRadius; fSlotHalfWidth = geoDimensionsTable->GetD("ropeslot_half_width"); fSlotRadius = fGrooveRadius - geoDimensionsTable->GetD("groove_tolerance"); fGrooveY1 = sqrt(pow(fInnerAVradius+fAVthickness/2.,2)-pow(fGrooveRadius,2)); fGrooveY2 = fGrooveY1+geoDimensionsTable->GetD("ropegroove_depth"); } G4double SNOAVBellyPlate::Rho(G4double z){ //returns cylindrical radius for a given z G4double rho; if (z<0)z = -z; if (zfZOuter)rho = sqrt(fRmin*fRmin - z*z); else rho = (z - fZOffset)*fRhoSlope; return rho; } G4double SNOAVBellyPlate::Radius(G4double z)const { //returns spherical radius for a given z G4double radius; double rho; if (z<0)z = -z; if (zfZOuter)radius = fRmin; else { rho = (z - fZOffset)*fRhoSlope; radius = sqrt(rho*rho + z*z); } return radius; } EInside SNOAVBellyPlate::Inside(const G4ThreeVector &p)const { EInside in; double x = fabs(p*fXaxis); //The panel is symmetric about x; the fabs allows easier testing of the rope groove double z = p*fZaxis; double y=p*fYaxis; double r = Radius(x); double r2 = Radius(z); if (r2fThreshold)in = kOutside; else in = kSurface; if(in!=kOutside){ // for points on surface or inside, check to see if the point is in the rope groove. double rl; //distance from "center" of panel- so the rope groove itself is defined by rl=constant. if(z<0)rl=sqrt(x*x+z*z);else rl=x; // Since the rope is vertical above the equator, we can treat points above the equator as if they were on the equator if(fabs(rl-fGrooveRadius)<(fGrooveHalfWidth+fThreshold)){ //point is within the "U" defined by the outer surface of wider rope groove if(in==kSurface && yfGrooveY1)in=kOutside; //in the cutaway region where the rope groove comes through the top of the panel else if(fabs(rl-fGrooveRadius)>(fGrooveHalfWidth-fThreshold)){ //point is in the surface layer of the "U" defined by the outer surface of wider rope groove if(y>fGrooveY1-fThreshold && yfGrooveY1+fThreshold)in=kOutside; //water volume else if(y>fGrooveY1-fThreshold) in=kSurface; }else if(fabs(rl-fSlotRadius)<(fSlotHalfWidth+fThreshold)){ //point is within the surface layer defined by the slot if(y>fGrooveY1+fThreshold &&yfGrooveY1-fThreshold) in=kSurface; //surface includes tiny ribbon at bottom of groove, and edges of the slot }else{ if(y>fGrooveY2+fThreshold)in=kInside; //inside the bulk of the panel else if(y>fGrooveY1+fThreshold &&yfGrooveY1-fThreshold)in=kSurface; } } } return in; } G4ThreeVector SNOAVBellyPlate::SurfaceNormal(const G4ThreeVector &p, G4bool &isValid)const{ G4ThreeVector normal=p.unit(); isValid = true; // we set true , to allow us to return at any point. However, if we find that the point is not "within" the belly plate, we need to set it false. double x = p*fXaxis; double y=p*fYaxis; double z = p*fZaxis; double rx = Radius(x); double rz = Radius(z); double r = rxfThreshold){ isValid=false; //outside the bellyplate }else{ if(rfThreshold){ //on a conical surface if (rx0){ normal = (fXaxis-1/ fRhoSlope*cos(phi)*fYaxis-1 / fRhoSlope*sin(phi)*fZaxis).unit(); } else{ normal = (fXaxis-1/ fRhoSlope*cos(phi)*fYaxis-1 / fRhoSlope*sin(phi)*fZaxis).unit(); } } else{ //on one of the z-cones/ We implicitly assume zaxis is vertical here. double phi = p.phi(); if (z>0){ normal = G4ThreeVector(-1.0 / fRhoSlope*cos(phi), -1.0 / fRhoSlope*sin(phi), 1).unit(); } else{ normal = G4ThreeVector(-1.0 / fRhoSlope*cos(phi), -1.0 / fRhoSlope*sin(phi), -1).unit(); } } } // check for the rope groove double rl; if(z<0)rl=sqrt(x*x+z*z);else rl=fabs(x); if(fabs(rl-fGrooveRadius)<(fGrooveHalfWidth+fThreshold)){ //point is within the "U" defined by the outer surface of wider rope groove if((rl-fGrooveRadius)>(fGrooveHalfWidth-fThreshold)){ //point is in the bottom surface layer of the "U" defined by the outer surface of wider rope groove if(y>fGrooveY1+fThreshold && y0)normal=-x/fabs(x)*fXaxis; else if (x!=0) normal=-(fZaxis-z/x*fXaxis).unit();else normal=-fZaxis; }else isValid=false; }else if(-(rl-fGrooveRadius)>(fGrooveHalfWidth-fThreshold)){ //point is in the top surface layer of the "U" defined by the outer surface of wider rope groove if(y>fGrooveY1+fThreshold && y0)normal=-x/fabs(x)*fXaxis; else if (x!=0) normal=(fZaxis-z/x*fXaxis).unit();else normal=fZaxis; }else isValid=false; }else if(fabs(rl-fSlotRadius)<(fSlotHalfWidth-fThreshold)){ //point is within the "U" defined by the slot if(y>fGrooveY1+fThreshold)isValid=false; //water volume else if(y>fGrooveY1-fThreshold)normal=fYaxis; }else if(fabs(rl-fSlotRadius)<(fSlotHalfWidth+fThreshold)){ //point is within the surface layer defined by the slot if(y>fGrooveY1+fThreshold &&yfGrooveY2-fThreshold){ if(z>0)normal=-x/fabs(x)*fXaxis; else if (x!=0) normal=(fZaxis-z/x*fXaxis).unit();else normal=fZaxis; }else{ normal=fYaxis; } }else{ if(fabs(y-fGrooveY1)fThreshold)dtest=dInner[0]; else dtest=dInner[1]; double dist=kInfinity; if (dtest>fThreshold){ //check intersections with inner radius test = p + dtest * n; x = fabs(test*fXaxis); z = (test*fZaxis); if (z<0) rloop=sqrt(x*x+z*z); else rloop=x; double rr = test.mag(); if (fabs(rr-fRmin)fZOuter ||fabs(z)>fZOuter))dist=dtest; } if(dOuter[0]>fThreshold)dtest=dOuter[0]; else dtest=dOuter[1]; if(dtest>fThreshold && dtestfSlotHalfWidth)|| ((fabs(rloop-fGrooveRadius)= 0){ q = sqrt(q); d = (-b + q) / (2 * a); if (d>fThreshold && dfThreshold && d= 0){ q = sqrt(q); d = (-b + q) / (2 * a); if (d>fThreshold && dfThreshold && dfThreshold&&dfThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } } if(nx.x()!=0){ d=(fGrooveRadius+fGrooveHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(fGrooveRadius-fGrooveHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(-fGrooveRadius+fGrooveHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(-fGrooveRadius-fGrooveHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(fSlotRadius+fSlotHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(fSlotRadius-fSlotHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(-fSlotRadius+fSlotHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } d=(-fSlotRadius-fSlotHalfWidth-px.x())/nx.x(); if(d>fThreshold&&dfThreshold&&Inside(test)==kSurface)dist=d; } } //now do cylindrical surfaces b = 2 * (px.x()*nx.x() + px.z()*nx.z()); double c0 = px.x()*px.x() + px.z()*px.z(); a = nx.x()*nx.x()+nx.z()*nx.z(); double cc[4]; cc[0]=c0-pow(fGrooveRadius+fGrooveHalfWidth,2); cc[1]=c0-pow(fGrooveRadius-fGrooveHalfWidth,2); cc[2]=c0-pow(fSlotRadius+fSlotHalfWidth,2); cc[3]=c0-pow(fSlotRadius-fSlotHalfWidth,2); for(i=0;i<4;i++){ q = b*b - 4 * a*cc[i]; if (q >= 0){ q = sqrt(q); d = (-b + q) / (2 * a); if (d>fThreshold && dfThreshold && dctheta); } return retval; }