//////////////////////////////////////////////////////////////////////////////// /// /// SNOSpreaderRope.cc /// Created on: Oct 17, 2014 /// Author: Aksel Hallin /////////////////////////////////////////////////////////////////////////////// #include #include #include namespace RAT { SNOSpreaderRope::SNOSpreaderRope(DBLinkPtr geoDimensionsTable,G4double aPhi) { G4double fDownRopeRadius = geoDimensionsTable->GetD( "down_rope_radius" ); G4double fDownRopeFlatRadius = geoDimensionsTable->GetD( "down_rope_flatradius" ); G4double fOuterAVradius = geoDimensionsTable->GetD( "inner_av_radius" ) + geoDimensionsTable->GetD( "av_thickness" ); fWidth=geoDimensionsTable->GetD("spreader_rope_halfwidth"); fZ2=geoDimensionsTable->GetD("spreader_rope_topz"); //Top of spreader rope fZ1=fZ2-2*fWidth; // Spreader rope is 20 mm thick. Based on 2/3 of normal rope thickness of 30 mm. fVertical1=G4ThreeVector(sin(aPhi), -cos(aPhi),0); // Outward normal defining the end of the spreader and intersection with the main ropenet fVertical2=G4ThreeVector(-sin(aPhi+0.1*M_PI), cos(aPhi+0.1*M_PI),0); // Outward Normal defining the end of the spreader and intersection with main ropenet fMainWidth=fDownRopeRadius; //half width of main rope fRmin=fOuterAVradius;// +geoDimensionsTable->GetD("rope_tolerance"); // Removed so that ropes sit directly on top of AV fRmax=fOuterAVradius+2*fDownRopeFlatRadius; double theta=acos((fZ1+fZ2)/2/fRmin); fZAxis=G4ThreeVector(sin(theta)*cos(aPhi),sin(theta)*sin(aPhi),cos(theta)).cross( G4ThreeVector(sin(theta)*cos(aPhi+0.1*M_PI),sin(theta)*sin(aPhi+0.1*M_PI),cos(theta))); fZAxis=fZAxis.unit(); fThreshold = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); fZ=fZ2-fWidth; // center height of rope fRho=sqrt(pow((fRmin+fRmax)/2,2)-fZ*fZ); fOverlapDistance=sqrt(fRmax*fRmax-fRmin*fRmin)+fMainWidth+5; //horizontal distance required for rope to be checked. } G4double SNOSpreaderRope::DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &n, const G4double dInner[2], const G4double dOuter[2])const{ // This routine enters with a proposed distance being the distance to the spherical radius. // if there are no intersections, returns kInfinity. double dtest; if(dInner[0]>fThreshold)dtest=dInner[0]; else dtest=dInner[1]; G4ThreeVector test=p+n*dtest; double retval=kInfinity; if(dtest>fThreshold && fabs(test.mag()-fRmin)fThreshold)dtest=dOuter[0]; else dtest=dOuter[1]; if(dtestfThreshold){ test=p+n*dtest; if(fabs(test.mag()-fRmax)fThreshold){ test=p+dn*n; if(test.mag()>fRmin &&test.mag()fThreshold){ test=p+dn*n; if(test.mag()>fRmin &&test.mag()(2*fWidth))return dist-(2*fWidth); else return 0; } /// DistanceToOut A spherical subregion needs to implement this to provide G4VSolid routines. G4double SNOSpreaderRope::DistanceToOut(const G4ThreeVector &p)const{ double retval; double r1= fRmax-p.mag(); //radial distance to the av surface, double r2= p.mag()-fRmin; double z=fabs(fabs(p*fZAxis)-fWidth); if(r1>r2)retval=r2; else retval=r1; if(retval>z)retval=z; if(retval<0)retval=0; return retval; } /// Inside A spherical subregion needs to implement this to provide G4VSolid routines. EInside SNOSpreaderRope::Inside(const G4ThreeVector &p)const{ EInside retval; if(p.mag()>fRmax+fThreshold || p.mag()fWidth+fThreshold || x1>-fMainWidth || x2>-fMainWidth)retval=kOutside; else if( p.mag()fRmin+fThreshold || fabs(z-fWidth)>fThreshold){ retval=kSurface; // Condition was wrong. Changed it to match SNORopeNet structure. } else retval=kInside; } return retval; } /// SurfaceNormal A spherical subregion needs to implement this to provide G4VSolid routines. G4ThreeVector SNOSpreaderRope::SurfaceNormal(const G4ThreeVector &p, G4bool &isValid)const{ G4ThreeVector n; isValid=false; double x1=p*fVertical1; double x2=p*fVertical2; double z=p*fZAxis; if(p.mag()fRmin-fThreshold){ if(x1<-fMainWidth && x2<-fMainWidth){ // inside length of rope if(fabs(z-fWidth)fRmax-fThreshold)n=p.unit(); else if(p.mag()fZ1-fOverlapDistance&&fabs(corners[i]*fZAxis)