// VolumeList.cc // Contact person: Phil Jones // See VolumeList.hh for more details //———————————————————————// #include #include #include #include #include #include #include #include #include using std::string; using std::vector; namespace RAT{ // File-private utility methods: // Locate a volume named "name" that is a descendant of "ancestor", // by recursively traversing all daughter volumes. // Return true if "name" is a descendant of "ancestor", false otherwise. // Construct a local-to-global transform on the way out, // by recursively composing the daughter-to-mother transforms. // If successful, store volume and transform in "result". void FindVolume(G4LogicalVolume const* ancestor, G4String const& name, vector& result) { // For simplicity, do not check if the name of 'ancestor' is 'name' - // 'name' is assumed to be a strict descendant of 'ancestor'. for (int i = 0; i < ancestor->GetNoDaughters(); i++) { G4VPhysicalVolume* daughter = ancestor->GetDaughter(i); if (daughter->GetName() == name) { G4AffineTransform trans(daughter->GetRotation(), daughter->GetTranslation()); // Translation/Rotation are daughter-to-mother transforms result.push_back(VolumeList::VolTransform(daughter,trans)); } unsigned int subtreeIndex = result.size(); FindVolume(daughter->GetLogicalVolume(), name, result); for(; subtreeIndex < result.size(); subtreeIndex++) result.at(subtreeIndex).fTransform *= G4AffineTransform(daughter->GetRotation(),daughter->GetTranslation()); } } //Class method implementations: void VolumeList::AddVolTransform(VolTransform const& vol) { fList.push_back(vol); } void VolumeList::AddVolume(std::string const& name, volumes vol) { G4VPhysicalVolume* worldVolume = G4TransportationManager::GetTransportationManager()-> GetNavigatorForTracking()->GetWorldVolume(); vector result; // Look for "name" as a descendant of the world, or die. FindVolume(worldVolume->GetLogicalVolume(), G4String(name),result); Log::Assert(result.size() > 0, "Failed to find volume: "+name); if(result.size() > 1) { warn << "Found multiple volumes by name " << name << ": " << result.size() << newline; debug << "Volumes have local to global translations: " << newline; for(unsigned int i=0; i::iterator it; for(it=result.begin(); it GetNavigatorForTracking(); // LocateGlobalPointAndSetup finds the volume, and sets up nav // for computing GetLocalToGlobalTransform G4VPhysicalVolume* volume = nav->LocateGlobalPointAndSetup(point); G4AffineTransform transform = nav->GetLocalToGlobalTransform(); VolTransform voltrans(volume, transform); if(vol == BOTH) { fList.push_back(voltrans); AddDaughters(voltrans); } else if(vol == DAUGHTERS) { AddDaughters(voltrans); } else if(vol == SELF) { fList.push_back(voltrans); } } void VolumeList::AddString(std::string const& value, volumes vol) { // Split on whitespace, and decide how to add based on number of fields vector values = split(trim(value), " "); switch(values.size()) { case 1: AddVolume(values[0], vol); break; case 3: // IMPORTANT: to_double does not throw if passed something that // doesn't look like a double, it will just make a best guess; // i.e. "a" -> 0.0 AddVolume(G4ThreeVector(to_double(values[0]), to_double(values[1]), to_double(values[2])), vol); break; default: Log::Die("Volume must be specified either by one field" " representing a name, or three fields representing" " the x, y, and z coordinates of a point"); break; } } void VolumeList::AddDaughters(VolTransform const& vol) { int noDaughters = vol.fVolume->GetLogicalVolume()->GetNoDaughters(); for(int iDaughter=0; iDaughter < noDaughters; iDaughter++) { G4VPhysicalVolume* daughter = vol.fVolume->GetLogicalVolume()->GetDaughter(iDaughter); G4AffineTransform daughterTrans(daughter->GetRotation(),daughter->GetTranslation()); fList.push_back(VolTransform(daughter, vol.fTransform * daughterTrans)); } } double VolumeList::ComputeVolume(const G4VPhysicalVolume* volume) { if(fSolidVolumes.count(volume->GetName())) return fSolidVolumes[volume->GetName()]; else { double solidVolume = volume->GetLogicalVolume()->GetSolid()->GetCubicVolume(); int numDaughters = volume->GetLogicalVolume()->GetNoDaughters(); for(int iDaughter = 0; iDaughter < numDaughters; iDaughter++) { G4VSolid* daughterSolid = volume->GetLogicalVolume()->GetDaughter(iDaughter)->GetLogicalVolume()->GetSolid(); solidVolume -= daughterSolid->GetCubicVolume(); } fSolidVolumes[volume->GetName()] = solidVolume; return solidVolume; } } std::map VolumeList::fSolidVolumes; } //namespace RAT