Angle of incidence for optical photon


I have faced a problem of getting the angle of incidence when optical photon approaches the optical boundary.
I see there’s G4OpBoundaryProcess::GetIncidentAngle() method which likely should provide me this angle, but it is private and I don’t see any public way to get it.
What I am doing wrong? Is there a way to get an incidence angle in the boundary process?
Especially i am interested in total internal reflection.

Thank you in advance.

I don’t know of a simple way.

If you want the angle between the particle’s momentum direction and the macroscopic surface, it should be possible to get it from the direction in G4Track and volume in G4StepPoint.

If you want the angle between the momentum direction and the facet, it’s not clear what this means. There may be multiple reflections off multiple facets if the surface is rough. The calculation happens internal to G4OpBoundaryProcess. If the surface is smooth you could calculate the incident angle knowing input and output directions, and indices of refraction if needed.

What is your use case?

I actually have smooth surface so the problem looks easy pretty easy, but there’s a lot of (flat) surfaces with different angles so doesn’t look obvious for me how to get incidence angle from direction and a surface.

I have already implemented calculations for the case of total internal reflection (the main case for my problem) by dot multiplying momentum directions in pre-step point and post-step point, and i think i can do this also for the fresnel reflection.

But for a refracted light can i just simply apply a snell’s law and calculate an angle due to the refractive index and diffraction? I don’t sure how it works internally in geant.

Knowing the coordinates of the interaction point on the surface, you can iterate over all the surfaces and find the one the interaction point is on. This might get complicated.

We added example extended/optical/OpNovice2 for this reason. Shoot photons at a flat surface and see what happens.

If you know the volume you’re in (which you will from the Track or Step), then you can go from PV to LV to Solid.

Use the volume’s Touchable (which you can also get from the Step) to get the global-to-local coordinate transformation.

Take the step position, transform it to local coordinates for the volume, and call G4VSolid::SurfaceNormal(pos).

This will return the outward normal at that position, which you can use appropriately to apply Snell’s law.

Thank you, you solution looks pretty native for this problem.
I have implemented the calculations as far as i understood in order to calculate an angle of incidence.

I was not sure if the rotation acts on coordinates or basis, but I’ve checked on 3d visualization of local step positions and they all belong to the expected surface of solid i have, so direct rotation should be done in order to represent vector in local basis.

G4double L_SteppingAction::GetIncidenceAngle(const G4Step *aStep)
    G4StepPoint *preStep = aStep->GetPreStepPoint();
    G4ThreeVector photonDirection = preStep->GetMomentum() / preStep->GetMomentum().mag();
    G4ThreeVector stepPos = preStep->GetPosition();

    const G4VTouchable *touchable = preStep->GetTouchable();

    const G4RotationMatrix *rotation = touchable->GetRotation();
    G4RotationMatrix rotation_inv = rotation->inverse();
    G4ThreeVector translation = touchable->GetTranslation();
    G4VSolid *sector = touchable->GetSolid();

    G4ThreeVector posLocal = *rotation * (stepPos - translation);
    G4ThreeVector normal =  - sector->SurfaceNormal(posLocal);

    G4ThreeVector photonDirectionLocal = *rotation * photonDirection;

    G4double incidenceAngle = acos( );

    return incidenceAngle;

But I have got results which I did not really expect (Total internal reflections below an angle of TIR, Fresnel processes above it).

Did you get this to work? If you don’t think the results are physically correct, I recommend trying the simple geometry (a planar surface) of example OpNovice2. You should be able to see that the result is correct by inspection (either stepping verbose, or visualisation). Then add your GetIncidenceAngle and compare the results.

@vyeroshe thank you for the angle of incidence calculation. This is very helpful.

To others using this in the future, please see this topic that clears up some of the subtleties in implementation and differences between what’s returned by G4OpBoundaryProcess::GetIncidentAngle():

Hello, I want to know more about G4VSolid::SurfaceNormal(pos) method. Why do you konw the pos is localpos. Is there any offical manual?Geant4/geometry/management/include/G4VSolid.hh
There is no any describe about localpos in this link.