Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Geant4-object pointer comparisons instead of string-comparisons where possible #1376

Open
EinarElen opened this issue Jul 17, 2024 · 5 comments
Assignees
Labels
help wanted simcore SimCore and Geant4 simulation module

Comments

@EinarElen
Copy link
Contributor

We have a lot of code in SimCore and Biasing which does things like

auto MyThing {track->GetThing()->GetThingName()};
if (MyThing.compare(SomeString)) {
   // Do the work here
}

Where thing can be something like

  • A particular process, e.g. photoNuclear
  • A particular geometry region, e.g. "CalorimeterRegion"
  • A particular physical/logical volume, e.g. "hadronic_calorimeter"

This has two big downsides

  1. It is way too easy to mess this up and introduce bugs. For example:
    /**
    * Check if the photon will be exiting the ecal
    *
    * The 'hcal_PV' volume name is automatically constructed by Geant4's
    * GDML parser and was found by inspecting the geometry using a
    * visualization. This Physical Volume (PV) is associated with the
    * hcal parent volume and so it will break if the hcal parent volume
    * changes its name.
    */
    if (auto volume{track->GetNextVolume()->GetName()};
    volume.compareTo("hcal_PV") == 0) {

This is a bug. There is no physical volume called hcal_PV so that condition will never trigger. The volume in question happens to be called "hadronic_calorimeter" which differs from all the others that have names like tagger_PV etc. If we are using pointers as our comparison tool, we can enforce at configuration time that these are initialized and throw otherwise (so issues like the hcal name here would be caught).

  1. String comparisons can be really slow, especially for anything that is called ~at every Geant4 step (biasing operators and stepping actions). I made a quick and dirty comparison and there was a ~30% performance improvement by moving from string comparisons to pointer comparisons for EcalPN samples (!!!)

I think the best way to do this would be to have a helper type in SimCore that can be used to get the various pointers people might need and make sure that things like biasing wrappers are handled correctly.

class Geant4ObjectUtility // Someone please suggest a better name 
{ 
   const G4VProcess* GetPhotonuclearProcess() const {
   return GetProcess(G4Gamma::Definition(), "photonNuclear");
   }
   const G4VProcess* GetProcess(G4ParticleDefinition* particle, std::string processName) const {
         const auto manager {particle->GetProcessManager()};
      const auto processes {manager->GetProcessList()};
      for (int i{0}; i < processes->size(); ++i) {
        const auto process {(*processes)[i]};
        const auto name {process->GetProcessName()};
        if (name.contains(processName)) {
          return process;
        }
      }
      return nullptr;

   }
  G4Region* GetRegion(std::string name) {
  return G4RegionStore::GetInstance()->GetRegion(name);
  }
};

etc

@tomeichlersmith
Copy link
Member

I don't think we want a class since it would never hold its own data, instead maybe just a namespace? ptr_retrieval?

namespace ptr_retrieval { 
const G4VProcess* GetPhotonuclearProcess() const {
  return GetProcess(G4Gamma::Definition(), "photonNuclear");
}
const G4VProcess* GetProcess(G4ParticleDefinition* particle, std::string processName) const {
  const auto manager {particle->GetProcessManager()};
  const auto processes {manager->GetProcessList()};
  for (int i{0}; i < processes->size(); ++i) {
    const auto process {(*processes)[i]};
    const auto name {process->GetProcessName()};
    if (name.contains(processName)) {
      return process;
    }
  }
  // for processes from the particle table, I can't think of a situation where this would be useful
  // maybe code-in the exception here?
  return nullptr;
}
G4Region* GetRegion(std::string name) {
  return G4RegionStore::GetInstance()->GetRegion(name);
}
} // namespace ptr_retrieval

and then the call-site would look readable like

auto pn = ptr_retrieval::GetPhotonuclearProcess();

@EinarElen
Copy link
Contributor Author

Yeah, that seems sensible :)

@tvami
Copy link
Member

tvami commented Sep 4, 2024

So where should this go? And then have a GetProcess for all other kinda processes?

It's not clear to me how the proposed snippet gets rid of string comparisons, there is still a name.contains() in it.

But I guess if we do this, it will resolve #1286 by having the same things for the detector elements, right?

@tomeichlersmith
Copy link
Member

This would be utility functions available from within SimCore and then the places that know they need to do region or volume checks (e.g. in filters) would store the values of these pointers and then only use the values of the pointers during running.

@EinarElen
Copy link
Contributor Author

You only do the string comparison once :)

@tvami tvami added simcore SimCore and Geant4 simulation module help wanted labels Sep 21, 2024
@LiamBrennan-UCSB LiamBrennan-UCSB self-assigned this Feb 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted simcore SimCore and Geant4 simulation module
Projects
None yet
Development

No branches or pull requests

4 participants