// BLCMDtubs.cc /* This source file is part of G4beamline, http://g4beamline.muonsinc.com Copyright (C) 2003,2004,2005,2006 by Tom Roberts, all rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. http://www.gnu.org/copyleft/gpl.html */ #include "G4VisAttributes.hh" #include "G4Tubs.hh" #include "G4LogicalVolume.hh" #include "G4VPhysicalVolume.hh" #include "G4PVPlacement.hh" #include "G4Color.hh" #include "G4UserLimits.hh" #include "G4Material.hh" #include "BLCommandAlias.hh" #include "BLGroupElement.hh" #include "BLParam.hh" #include "BLManager.hh" #include "BLKillTrack.hh" /** BLCMDtubs implements a tube or cylinder of material, axis along Z. * **/ class BLCMDtubs : public BLGroupElement { G4double innerRadius; G4double outerRadius; G4double initialPhi; G4double finalPhi; G4double length; G4String material; G4String color; G4int kill; G4double maxStep; G4Tubs *tubs; public: /// Default constructor. Defines the command, args, etc. BLCMDtubs(); /// Destructor. virtual ~BLCMDtubs() { } /// Copy constructor. BLCMDtubs(const BLCMDtubs& r); /// clone() BLElement *clone() { return new BLCMDtubs(*this); } /// commandName() returns "tubs". G4String commandName() { return "tubs"; } /// command() implements the tubs command. int command(BLArgumentVector& argv, BLArgumentMap& namedArgs); /// defineNamedArgs() defines the named arguments for the command. void defineNamedArgs(); /// construct() - construct the tube/cylinder. virtual void construct(G4RotationMatrix *relativeRotation, G4ThreeVector relativePosition, G4LogicalVolume *parent, G4String parentName, G4RotationMatrix *parentRotation, G4ThreeVector parentPosition); /// getLength() returns the length of the tube/cylinder. G4double getLength() { return length; } /// getWidth() returns the width of the tube/cylinder. G4double getWidth() { return 2.0*outerRadius; } /// getHeight() returns the height of the tube/cylinder. G4double getHeight() { return 2.0*outerRadius; } /// isOK() returns true. G4bool isOK() { return true; } /// generatePoints() from BLElement void generatePoints(int npoints, std::vector &v); /// isOutside() from BLElement G4bool isOutside(G4ThreeVector &local, G4double tolerance); /// isWithin() from BLGroupElement bool isWithin(G4ThreeVector &local, G4double tolerance); }; BLCMDtubs defaultTubs; // default object BLCommandAlias aliasTubs("cylinder",defaultTubs); // Alias "cylinder" BLCommandAlias aliasTubs2("tube",defaultTubs); // Alias "tube" // Default constructor - be sure to use the default constructor BLGroupElement() BLCMDtubs::BLCMDtubs() : BLGroupElement() { // register the commandName(), and its synopsis and description. registerCommand(BLCMDTYPE_ELEMENT); setSynopsis("construct a tube or cylinder with axis along z."); setDescription("This is a direct interface to G4Tubs, which can\n" "implement a tube or cylinder; either can subtend less " "than 360 degrees in phi."); // provide initial values for fields innerRadius = 0.0; outerRadius = 0.0; initialPhi = 0.0; finalPhi = 360.0*deg; length = 0.0; material = "Vacuum"; color = "1,1,1"; kill = 0; maxStep = -1.0; tubs = 0; } // Copy constructor - be sure to use the copy constructor BLGroupElement(r) BLCMDtubs::BLCMDtubs(const BLCMDtubs& r) : BLGroupElement(r) { // copy fields one at a time (transfers default values from the // default object to this new object). innerRadius = r.innerRadius; outerRadius = r.outerRadius; initialPhi = r.initialPhi; finalPhi = r.finalPhi; length = r.length; material = r.material; color = r.color; kill = r.kill; maxStep = r.maxStep; tubs = r.tubs; } int BLCMDtubs::command(BLArgumentVector& argv, BLArgumentMap& namedArgs) { if(argv.size() != 1) { printError("tubs: Invalid command, must have name"); return -1; } if(argv[0] == "default") { return defaultTubs.handleNamedArgs(namedArgs); } BLCMDtubs *t = new BLCMDtubs(defaultTubs); t->setName(argv[0]); int retval = t->handleNamedArgs(namedArgs); if(t->maxStep < 0.0) t->maxStep = Param.getDouble("maxStep"); // check material exists if(t->material.size() > 0) getMaterial(t->material,false); t->print(argv[0]); return retval; } void BLCMDtubs::defineNamedArgs() { argDouble(innerRadius,"innerRadius","The inside of the tube, 0.0 for cylinder (mm)", mm); argDouble(outerRadius,"outerRadius","The outer radius of the tube or cylinder (mm)", mm); argDouble(initialPhi,"initialPhi","The initial Phi value (deg; 0 for all)", deg); argDouble(finalPhi,"finalPhi","The final Phi value (deg; 360 for all)", deg); argDouble(length,"length","The length of the tube or cylinder (mm)", mm); argDouble(maxStep,"maxStep","The maximum stepsize in the element (mm)", mm); argString(material,"material","The material of the tube or cylinder"); argString(color,"color","The color of the tube or cylinder (''=invisible)"); argInt(kill,"kill","Set nonzero to kill every track that enters."); argDouble(outerRadius,"radius","Synonym for outerRadius (mm)",mm); } void BLCMDtubs::construct(G4RotationMatrix *relativeRotation, G4ThreeVector relativePosition, G4LogicalVolume *parent, G4String parentName, G4RotationMatrix *parentRotation, G4ThreeVector parentPosition) { G4String thisname = parentName+getName(); if(!tubs) tubs = new G4Tubs(thisname+"Tubs", innerRadius, outerRadius, length/2.0, initialPhi,finalPhi-initialPhi); G4Material *mat = getMaterial(material); G4LogicalVolume *lv = new G4LogicalVolume(tubs,mat, thisname+"LogVol"); lv->SetVisAttributes(getVisAttrib(color)); if(maxStep < 0.0) maxStep = Param.getDouble("maxStep"); lv->SetUserLimits(new G4UserLimits(maxStep)); // geant4 rotation convention is backwards from g4beamline G4RotationMatrix *g4rot = 0; if(relativeRotation) g4rot = new G4RotationMatrix(relativeRotation->inverse()); G4VPhysicalVolume *pv = new G4PVPlacement(g4rot, relativePosition,lv, thisname, parent,false,0); if(kill) BLManager::getObject()-> registerSteppingAction(pv,new BLKillTrack(thisname)); // get globalRotation and globalPosition G4RotationMatrix *globalRotation = 0; if(relativeRotation && parentRotation) { globalRotation = new G4RotationMatrix(*parentRotation * *relativeRotation); } else if(relativeRotation) { globalRotation = relativeRotation; } else if(parentRotation) { globalRotation = parentRotation; } G4ThreeVector globalPosition(relativePosition + parentPosition); if(parentRotation) globalPosition = *parentRotation * relativePosition + parentPosition; constructChildren(lv,thisname,globalRotation,globalPosition); printf("BLCMDtubs::Construct %s parent=%s relZ=%.1f globZ=%.1f\n" "\tzmin=%.1f zmax=%.1f kill=%d\n", thisname.c_str(),parentName.c_str(),relativePosition[2], globalPosition[2], globalPosition[2]-getLength()/2.0, globalPosition[2]+getLength()/2.0, kill); } void BLCMDtubs::generatePoints(int npoints, std::vector &v) { generateTubs(npoints, innerRadius, outerRadius, initialPhi, finalPhi, length, v); } G4bool BLCMDtubs::isOutside(G4ThreeVector &local, G4double tolerance) { G4double r = sqrt(local[0]*local[0]+local[1]*local[1]); G4double phi = atan2(local[1],local[0]); bool phiInside = phi > initialPhi+0.001 && phi < finalPhi-0.001; if(!phiInside && phi < 0.0) { phi += pi+pi; phiInside = phi > initialPhi+0.001 && phi < finalPhi-0.001; } return r < innerRadius+tolerance || r > outerRadius-tolerance || fabs(local[2]) > length/2.0-tolerance || !phiInside; } bool BLCMDtubs::isWithin(G4ThreeVector &local, G4double tolerance) { G4double r = sqrt(local[0]*local[0]+local[1]*local[1]); G4double phi = atan2(local[1],local[0]); if(phi < 0.0 && phi < initialPhi-0.001) phi += pi+pi; return r > innerRadius-tolerance && r < outerRadius+tolerance && fabs(local[2]) < length/2.0+tolerance && phi >= initialPhi-0.001 && phi < finalPhi+0.001; }