Our experimental simulation framework makes use of the external G4CMP package, in order to model to production, transport and detection of phonons and charge carriers in semiconductor crystals. The G4CMP package includes its own Geant4 surface property class, inheriting from
G4SurfaceProperty. This allows us to define reflection and absorption for phonons and charge carriers at the crystal surface, including wavevector-dependent behaviour.
At the same time, a non-trivial background source for our cryogenic detectors are optical photons at infrared and microwave energies. These can be produced as thermal emission from the surrounding fridge cans, or via low energy transition radiation from particles traversing those (copper) cans. To support these background studies, we want to attach Geant4 optical surfaces with
G4OpticalSurface instances to our detectors.
The two surface property objects are incompatible. While they both inherit from a common base class, once one of them is attached to a volume, the other can’t also be attached. This leads to errors from either G4 optics or from G4CMP, depending on which one sees the “wrong” surface property container.
Is there a mechanism in G4 to attach multiple types of surface properties, or to define multiple different “skins” to the same volume?
It is possible (in principle) for a surface (boundary between physical volumes) to have both a G4LogicalSkinSurface and a G4LogicalBoundarySurface attached to it. I wonder if similar logic would work for you.
Create a G4LogicalCMPSurface class, inheriting from G4LogicalSurface, similar to G4LogicalSkinSurface. In your detector construction, attach both a G4LogicalCMPSurface and a G4LogicalSkinSurface to a physical volume [EDIT: G4LogicalSkinSurface gets attached to a logical volume]. Then, create a G4CMPSurface and a G4OpticalSurface. Attach those to your G4LogicalCMPSurface and G4LogicalSkinSurface, respectively.
In your process class, get the G4LogicalSurface, cast to G4LogicalCMPSurface and/or G4LogicalSkinSurface, and check for nullptr (as in G4OpBoundaryProcess.cc).
(Replace G4LogicalSkinSurface with G4LogicalBoundarySurface as appropriate.)
Maybe this is what you’re trying already (it’s not clear to me). But, it seems you’re trying to attach one or more G4SurfaceProperty objects directly to a physical volume. I don’t see how this would work.
Let me know what you find.
Thanks, Daren! I’ll look at that. What we had been doing was defining a single set of skin or border surfaces, and then attaching the appropriate surface property object to that. I had been thinking in terms of attaching more than one SurfaceProperty entity to the same skin or border surface.
I’d need to define both
G4CMPBorderSurface classes, because we do make use of both in our simulation (for bare crystal sides vs. sides with sensors attached).
Your suggestion about attaching different surface objects themselves makes a lot of sense. Doing it that way would allow the optical folks to choose whichever surface types are most appropriate, and could be different than my G4CMP ones. Your description makes it sound like we could have two different skin surfaces (for example) attached to the same LV. Can you confirm that that would work? If not, I’ll just try it and see.
I think there can only be one G4LogicalSkinSurface attached to an LV. If you want more than one skin surface, the suggestion is to create another class that inherits from G4LogicalSurface.
To be clear, I haven’t tried this. I’m extrapolating based on the existing skin/border surfaces.
I think we’re saying the same thing. I wrote,
where I meant your suggestion – one
G4LogicalSkinSurface, and a separate
G4CMPSkinSurface. From looking at the
G4LogicalSkinSurface code, the “surface table” registry is just a simple vector (not even a nice std::map!), which
GetSurface(G4LV*) loops over to find the surface for the specified volume.
We’re going to look into how invasive this would be to implement, but I like it. It lets us decouple G4CMP from optics entirely, so the optical code won’t even know that there are “G4CMP surfaces” at all, and G4CMP won’t be interacting with optical classes, except by developer inspiration.
Hi Mike, Daren,
I either invented or played a part in their creation of the concepts of Skin and Logical border surfaces in Geant4 - as I recall … We did not consider a use case where both could be necessary. I was also responsible for the naive implementations. Doesn’t at least one class now have a map now ?
Trying to combine the two types of surface in one logical volume appears fragile to me, and the results would depend on which is considered first in the implementation of the relevant process(es).
Maybe it is possible to examine the logic by which the relevant processes order the choice between border and logical surfaces, and document it as the current norm. ( I don’t think that this existing practice is codified, but it may be that a single practice is currently respected because the optical processes’ logic has been the starting point for others. )
Alternatively I would consider to
a) add ‘fake’ external volumes (in the geometry) which can act as border surfaces, and then trigger an action in the ‘real’ volume, possibly by user action;
b) create a new sort of enhanced logical surface class - which knows that some of its surfaces are really border surfaces (which would need enhancement of the process code, but at least could become reliable). Likely it would be best to do this together with creating a helper class (or a reference class) which would be used by all the processes who care about surfaces, and would codify the priority or logic.
Daren suggestion to decouple from the G4 logic, refining the concepts in which the two types of surfaces could be mixed could also serve as a prototype for a future revision of these in G4.
Hi, John! You wrote:
In fact, both classes have a “map” (a simple std::vector<> with brute-force searching) now. It is possible to have both a skin surface and border surfaces assigned to the same volume – in
G4OpBoundaryProcess, it looks for a border surface first matching the two PVs at the boundary, then a skin surface if one is not found.
What I’m looking to do is be able to define separate surface properties for G4 optics and G4CMP on the same volume. Daren’s recommendation to write our own Logical*Surface classes makes sense. Each one will have it’s own registry, and won’t be looking for the “wrong type.”