Problem 1103 - photons do not interact with optical surfaces when using G4TessellatedSolid
Summary: photons do not interact with optical surfaces when using G4TessellatedSolid
Status: RESOLVED FIXED
Alias: None
Product: Geant4
Classification: Unclassified
Component: geometry/solids (show other problems)
Version: 9.3
Hardware: All All
: P5 normal
Assignee: PRTruscott
URL:
: 1105 (view as problem list)
Depends on:
Blocks:
 
Reported: 2010-02-09 06:07 CET by Akira Okumura
Modified: 2010-06-28 09:38 CEST (History)
4 users (show)

See Also:


Attachments
escaping photon (62.43 KB, image/png)
2010-02-11 04:49 CET, Akira Okumura
Details
verbose output of optical process (5.22 KB, text/plain)
2010-02-11 05:04 CET, Akira Okumura
Details
vis output of modified exampleN06 using optPhoton.mac (67.83 KB, image/png)
2010-04-13 14:21 CEST, Pete Truscott
Details
vis output of MinimumTest3 (126.69 KB, image/png)
2010-04-13 14:22 CEST, Pete Truscott
Details
Modified G4TessellatedSolid.cc to deal with optical photons (36.07 KB, text/x-c++src)
2010-04-13 14:22 CEST, Pete Truscott
Details
Modified G4TriangularFacet.cc to overcome bugs with optical photons (23.14 KB, text/x-c++src)
2010-04-13 14:23 CEST, Pete Truscott
Details
Modified ExN06DetectorConstruction.cc with correction for -Z face definition (9.52 KB, text/x-c++src)
2010-04-13 14:25 CEST, Pete Truscott
Details
lost photon after reflection at a Quad (19.34 KB, text/plain)
2010-04-15 17:41 CEST, Oliver Merle
Details

Note You need to log in before you can comment on or make changes to this problem.
Description Akira Okumura 2010-02-09 06:07:00 CET
When I simulate optical photons with G4TessellatedSolid objects, they do not interact at surfaces after first interaction. This problem is already reported at the hypernews.

http://hypernews.slac.stanford.edu/HyperNews/geant4/get/opticalphotons/309.html?inline=-1
http://hypernews.slac.stanford.edu/HyperNews/geant4/get/opticalphotons/295.html?inline=-1
Comment 1 Akira Okumura 2010-02-11 04:49:25 CET
Created attachment 63 [details]
escaping photon
Comment 2 Akira Okumura 2010-02-11 04:49:37 CET
It seems that G4TessellatedSolid::DistanceToIn does not check "on surface" condition.
http://www-geant4.kek.jp/lxr-dev/source/geometry/solids/specific/src/G4TessellatedSolid.cc#L672

If I modified the code as follows,

      if (distFromSurface > 0.5*kCarTolerance && dist >= 0.0 && dist < minDist)
      {
        minDist  = dist;
      }
      if(-0.5*kCarTolerance <= dist && dist <= 0.5*kCarTolerance){
        return 0.0;
      }

photons are reflected at boundaries. But after a few reflection, they escape the BGO block again. Before they escape, "StepTooSmall" process is repeated several times. I attache an image which shows this situation.
Comment 3 Akira Okumura 2010-02-11 05:04:54 CET
Created attachment 64 [details]
verbose output of optical process
Comment 4 Akira Okumura 2010-02-11 18:43:48 CET
When a photon escapes from BGO block as shown in the attached image (id=64), std::sqrt(sqrDist) is larger than 0.5*kCarTolerance (see G4TriangularFacet::Intersect), though it must be small enough because the photon is at a surface. Therefore, the distance to next boundary is set to kInfinity.

Any idea?
Comment 5 Pete Truscott 2010-02-18 02:21:30 CET
I'm currently investigating this and modifying G4TessellatedSolid, G4TriangularFacet and G4VFacet.
Comment 6 Gabriele Cosmo 2010-02-19 15:00:24 CET
*** Problem 1105 has been marked as a duplicate of this problem. ***
Comment 7 Oliver Merle 2010-02-19 17:14:20 CET
(In reply to comment #6)
> *** Problem 1105 has been marked as a duplicate of this problem. ***

Confirmed.

I've investigated this problem a few weeks ago and was not able to find any report on bugzilla. I have not expected a new on either.
Comment 8 Oliver Merle 2010-02-19 20:26:38 CET
In bug 1105 I reported a "quick fix". Here is the complete list of changes to the sources of Geant 4.9.3:

** Changes to G4TriangularFacet.cc:

Line 544:  
change "" distance = -0.5*kCarTolerance; ""  
to "" distance = 0.0; ""

Insert after Line 697 :
"" distance=std::fabs(distance); ""

**In G4TessellatedSolid.cc:

Line 672:

change the following line:

"" if (distFromSurface > 0.5*kCarTolerance && dist >= 0.0 && dist < minDist)if (distFromSurface > 0.5*kCarTolerance && dist >= 0.0 && dist < minDist) ""

to 

"" if (distFromSurface > -0.5*kCarTolerance && dist >= 0.0 && dist < minDist) ""


I did a quick DIRC simulation with this fix and the results look fine (qualitative). Photons propagate through the radiator like a charm. Anyhow, I have not done a quantitative analysis yet. I have to do finish other code first.

Hope this will help until an official solution is available.
Comment 9 Pete Truscott 2010-02-19 20:39:48 CET
There appear to be three errors which need to be treated:

(1) The treatment of rays entering the G4TessellatedSolid for points starting at the surface is incorrect (as stated by the bug-reporters).

(2) In G4TriangularFacet the distance to the surface is within +/- kCarTolerance it is set to -0.5 kCarTolerance when really it should be 0.0 (just confirmed by Oliver).

(3) The calculation of sqrDist in G4TriangularFacet::Distance(p) can suffer rounding errors when p is very close to the trianglar facet.  in some cases it's better to use (D+s*E[0]+t*E[1]).mag2() instead, although this too may suffer rounding errors!!

Before I implement and distribute a bug correction, I need to confirm something offline with Gabriele and would appreciate a copy of the application (or a simplified version) which Oliver is using.  Is this possible Oliver or is the application too difficult to port?
Comment 10 gum 2010-02-19 21:45:18 CET
Pete,

There is a modified version of exampleN06 posted at:

http://hypernews.slac.stanford.edu/HyperNews/geant4/get/opticalphotons/309/1/1.html

which also shows the problem.

Peter
Comment 11 Akira Okumura 2010-02-20 10:54:58 CET
Hello Pete.

Thank you for looking at this problem. I can also help you in debugging with my simulation code which is focused in only optical photon propagation in BGO scintillation blocks which is created from CAD files. If you already have modified versions of G4TessellatedSolid and G4TriangularFacet, and it is possible to distribute it by private e-mails, I will test them.
Comment 12 Oliver Merle 2010-02-24 13:12:04 CET
(In reply to comment #9)

> Before I implement and distribute a bug correction, I need to confirm something
> offline with Gabriele and would appreciate a copy of the application (or a
> simplified version) which Oliver is using.  Is this possible Oliver or is the
> application too difficult to port?

My main application would be a little bit overkill I guess, but I could send you a minimal example which propagates a single photon (ore more) in an G4 extruded solid (in fact a tessellated) octagon by total internal reflection. This volume can be replaced by a polyhedra to compare the results. 

Bug (3) occurs when I decrease the photons angle relative to the face normal, therefore it was not apparent to me in my previous testcase. I can reproduce this problem, and for me it looks like G4ThreeVector v = Distance(p) in G4TriangularFacet::Distance(const G4ThreeVector,const G4double,const G4bool) has rounding errors and therefore the projection on the face normal (dir) indicates "wrong direction". In that case dist will remain equal to kInfinity.

I think this could be the main problem, because rounding errors in sqrDist seem to occur all the time - even on "working reflections".
Comment 13 Oliver Merle 2010-02-25 20:59:01 CET
Ok, after a deeper look into the code I think the following change in G4TriangularFacet::Distance(const G4ThreeVector&) could help until a more performant solution is available:

G4ThreeVector v = D + s*E[0] + t*E[1];
G4double vmag2 = v.mag2();
if(sqrDist>vmag2) sqrDist = vmag2;
return v;

I don't like the additional mag2, but with this change I got my second testcase working.
Comment 14 Pete Truscott 2010-02-25 23:56:36 CET
(In reply to comment #13)
> Ok, after a deeper look into the code I think the following change in
> G4TriangularFacet::Distance(const G4ThreeVector&) could help until a more
> performant solution is available:
> G4ThreeVector v = D + s*E[0] + t*E[1];
> G4double vmag2 = v.mag2();
> if(sqrDist>vmag2) sqrDist = vmag2;
> return v;
> I don't like the additional mag2, but with this change I got my second testcase
> working.

This is the approach I've been testing.  I agree that the calculation from v.mag2() is less desirable, but not sure there's a simple way around it.
Comment 15 Oliver Merle 2010-02-26 20:18:31 CET
> This is the approach I've been testing.  I agree that the calculation from
> v.mag2() is less desirable, but not sure there's a simple way around it.

I assume that only some of the sqrDist computations contribute to the problem, eg.:

s       = s / det;
t       = t / det;
sqrDist = s*(a*s + b*t + 2.0*d) + t*(b*s + c*t + 2.0*e) + f; 

in "region 0". If this is correct (I've not testet enough constellations), it would be enough to replace them with ""G4ThreeVector v = D + s*E[0] + t*E[1]; sqrDist=v.mag2(); return v; ""

In fact, changing the above sqrDist computation in region 0 is enough to avoid the bug in my second testcase - but this may change at different incident angles or positions. And replacing this computation by a mag2() should be even faster, right? 

Anyway, this would need more testing that you might have done already.
Comment 16 Oliver Merle 2010-02-28 18:08:00 CET
1) Replacing only the computation in "region 0" works fine for me (tested multiple incident angles, but always larger than 48 deg !!). 

2) I found another problem (4) that causes this bug: 
The quads Distance(const G4ThreeVector&, const G4double, const G4bool) has problems with rounding errors in dist. I replaced this code with the same logic as in G4TriangularFacet what solved all observed problems. Again, this has to be tested with higher statistics.
Comment 17 Pete Truscott 2010-04-11 02:03:23 CEST
I've been trying to solve the problem by making the equations which determine sqrDist more accurate.  In general terms, the roundoff error results from the nature of double-precision numbers A, B and C which are such that:

sqrDist = A + B + C

but when sqrDist is very small:

(A + B) + C != A + (B + C) i.e. commutativity breaks down

I've implemented a fast method of adding the numbers in the right order to always maximise accuracy ... but this still doesn't resolve the problem because of the limiting accuracy of double defining A, B and C.

So we're stuck with calculating sqrDist from the square of the magnitude of the vector D + s*E[0] + t*E[1].

I'll upload the source code later this morning.
Comment 18 Akira Okumura 2010-04-12 09:33:11 CEST
(In reply to comment #17)
> I'll upload the source code later this morning.

Hello Pete,

Thank you so much for using your time for tracking this problem. Is the new code available in public or for the developer team only? I would love to try the new one for my purpose.

Akira
Comment 19 Pete Truscott 2010-04-13 14:21:12 CEST
Created attachment 66 [details]
vis output of modified exampleN06 using optPhoton.mac
Comment 20 Pete Truscott 2010-04-13 14:22:03 CEST
Created attachment 67 [details]
vis output of MinimumTest3
Comment 21 Pete Truscott 2010-04-13 14:22:57 CEST
Created attachment 68 [details]
Modified G4TessellatedSolid.cc to deal with optical photons
Comment 22 Pete Truscott 2010-04-13 14:23:36 CEST
Created attachment 69 [details]
Modified G4TriangularFacet.cc to overcome bugs with optical photons
Comment 23 Pete Truscott 2010-04-13 14:25:18 CEST
Created attachment 70 [details]
Modified ExN06DetectorConstruction.cc with correction for -Z face definition
Comment 24 Pete Truscott 2010-04-13 14:37:51 CEST
I've just attached updated G4TessellatedSolids.cc and G4TriangularFacet.cc files updated as discussed in comments #9 and #17.  Thanks also to Akira and Oliver for comments and suggested corrections.  It seems to work OK with MinimumTest (see graphic), I stumbled a bit with the updated N06 example Peter pointed me to on the SLAC web-site - I needed to update the ExN06DetectorConstruction from Akira (-Z side facets pointing in wrong direction) to get total internal reflection on all surfaces until photon absorption (see graphic & attached C++ file).

I note that in the detailed tracking for the optical photon, there are many instances of "StepTooSmall" as mentioned by Akira.  However, I'm assuming this is a natural artifact of the reflection process where the photon doesn't move and only its direction is changed in the step.

I'll get this uploaded to the G4 repository this afternoon, hopefully, with Fan Lei's help.
Comment 25 Oliver Merle 2010-04-13 16:48:35 CEST
(In reply to comment #24)

Nice to see an official patch. One question: 

I'm currently using a self patched version that seems to work fine - but to get rid of some rounding errors, I had to change the Quad's code too. Do you use Quads or Triangles in your test geometry? 

> I note that in the detailed tracking for the optical photon, there are many
> instances of "StepTooSmall" as mentioned by Akira.  However, I'm assuming this
> is a natural artifact of the reflection process where the photon doesn't move
> and only its direction is changed in the step.

Exactly. As far as I understand the boundary process, this "step to small" HAS to occur on every reflection because the navigator assigns the reflected photon to the neighbour volume. In the next step the photon is still located on the boundary and reenters the first volume, so the resulting steplength is 0 in a perfect world, or "too small" in floats.
Comment 26 Pete Truscott 2010-04-13 17:19:13 CEST
(In reply to comment #25)

Thanks for the comment, Oliver.  I did recall your ealier comment on  G4QuadrangularFacet and was uncertain whether this really needed updating as well.  Therefore during lunchtime I did re-implement the test geometry from Akira using Quads rather than triangular facets and repeated the run.  For me this worked fine without any modification to G4QuadrangularFacet.  Furthermore, I cannot see why Quads needs to be changed because .... it cheats!  Internally, a Quad is treated as two triangular facets.  However, do you think I'm missing something, Oliver?
Comment 27 Oliver Merle 2010-04-13 21:27:26 CEST
(In reply to comment #26)
> ... For me
> this worked fine without any modification to G4QuadrangularFacet.  Furthermore,
> I cannot see why Quads needs to be changed because .... it cheats!  Internally,
> a Quad is treated as two triangular facets.  

I would say: yes and no. The Quad wraps two triangles, but not all functions are exactly equal to the implementation in G4TriangularFacet.

Distance(const G4ThreeVector&, const G4double, const bool) behaves not exactly like the function for triangles: The Quad one uses kDirTolerance, while the triangle uses kCarTolerance and sqrt(sqrDist) which is not available in the Quad. 

When I tested my fix, I still observed a few photon tracks that left the volume. All of them were reflected at Quads. Triangles worked fine. After some debugging I decided to go dirty, make Quad a friend of the triangle and use sqrDist and kCarTolerance like its done in G4TriangularFacet::Distance( , , )   

After these changes, everything worked fine. Therefore I think there might be a problem with that function. 

> However, do you think I'm missing
> something, Oliver?

I'm not sure. I don't see why your changes to the Distance computation should solve this specific problem.

However, I try to find some time to check these issues again with a clean geant tree and your changes.
Comment 28 Oliver Merle 2010-04-15 17:41:29 CEST
Created attachment 71 [details]
lost photon after reflection at a Quad

The last steps at the bottom of the file show that the photon is not reentering the radiator volume after total internal reflection.

I used the files uploaded by Pete with a clean geant4 tree.

I'll try to find out why this happens. My previous solution was based on an "educated guess" and is not usable in a mainstream release. I think this has to be understood.
Comment 29 Oliver Merle 2010-04-19 14:51:32 CEST
The dirTolerance was slightly too small in the given case (dir larger than 1E-14 but less than 1E-13, so same order of magnitude).

Is there any reason why dirTolerance is fixed to 1E-14 ? Maybe its just too small and therefore causing problems in case of precision errors. I'll try 1E-13.

And why are quads and triangles using different distance implementations, isn't it reasonable to use the better/faster/more precise one for both?
Comment 30 Oliver Merle 2010-04-19 15:40:29 CEST
"dirTolerance = 1E-13" resolved all issues I have observed, but maybe its still too small in other situations.
Comment 31 Pete Truscott 2010-04-19 16:08:26 CEST
(In reply to comment #29)
> The dirTolerance was slightly too small in the given case (dir larger than
> 1E-14 but less than 1E-13, so same order of magnitude).
> Is there any reason why dirTolerance is fixed to 1E-14 ? Maybe its just too
> small and therefore causing problems in case of precision errors. I'll try
> 1E-13.

It's set to 1E-14 to be close to the tolerance for correct computation of double precision numbers.  I believe it was originally introduced to determine the transition from 3D triangle-line intersection to 2D triangle-line intersection.  However, I agree that some tuning may be necessary based on more extensive experience.

> And why are quads and triangles using different distance implementations, isn't
> it reasonable to use the better/faster/more precise one for both?

Quad uses the fact that it's defined as two separate triangles, and calculates the distance for each, but then taking the minimum.  I developed G4TessellatedSolids etc purely as a prototype and purely for as an internal project for simulating microelectronics geometries.  At that time I did want to develop G4QuadrangularFacet in a similar manner to G4TriangularFacet, but for a prototype it was ultimately quicker set the quad to be two adjacent and co-planar triangles.  You're absolutely correct that, given time, one should have a dedicated an efficient algorithm to treat distances for quads.  I guess I should say, "watch this space..."
Comment 32 Gabriele Cosmo 2010-06-28 09:38:14 CEST
The fix is now available in release 9.4-beta.