Trying to add new functionality to TGeom through inheritance

Note: Apologies for posting this originally in the support forum

Hello,

I am trying to build a monte-carlo simulation from the ground up using only ROOT to handle geometries and navigation (i.e: I am not using GEANT in any way). My simulation is of very low energy particles which move under gravity, so the simulation must do navigation along parabolic trajectories.

One way to do this would be to approximate the path as a series of small straight-line steps, such as using TGeoNavigator::FindNextBoundaryAndStep(). However I want to implement a system more akin to “FindNextBoundaryAndStep[b]AlongParabola/b”, that solves for the actual intersection between the boundary and the parabola.

To do this, I want to copy the process that ROOT uses in FindNextBoundaryAndStep, where I ask the current volume for its shape and then call TGeoShape::DistFromInside/Outside. To do this, I envisaged needing to add new methods to all of the shapes such as TimeFromInsideAlongParabola(), (or at least implement TGeoBBox, and any others that I wish to use in my program, such as the tube and the torus). I would also need to change the navigator to recognise the presence of a gravitational field object and then call these parabolic-intersection finding methods instead of the usual straight-line intersection methods.

One way to do all this would be for me to alter my local copy of the ROOT source code on my computer to add the new methods I wish to add. However I would strongly prefer not to tarnish ROOT with my handiwork, and would rather find a way to add this new functionality to new classes that I would make to inherit from those in ROOT.

So those are my aims and what I am trying to achieve. I am writing this post to ask for any advice with doing this sort of thing.

I have found it very difficult to implement any new functionality through inheritance because I imagine most of the classes in TGeom obviously weren’t designed expecting anything to inherit from them in this way. For example, supposing I wanted to make a new class: TMyGeoNavigator that inherits from TGeoNavigator, that re-implements ‘FindNextBoundaryAndStep()’ in a slightly different way. This is impossible since it isn’t virtual. So perhaps then I to create a new method - ‘FindNextBoundaryAndStepAlongParabola()’ - which I will have to access by casting down any TGeoNavigator-type pointer to this type before calling. However the difficultly here is that I cannot change the value of any of the private members of TGeoNavigator, for example the pointer fNextNode or the flag fIsOnBoundary - since they do not have any mutator methods.

To get around this then, I have to create new pointers and new flags to replicate those in TGeoNavigator, which then requires my program to always distinguish between when to use this flag and when to use the base-class flag… As you can see this is now getting extremely messy and difficult to actually implement in any sort of safe/debuggable way.

I could use composition to change the interface of the class, however I would then need to re-create the entire TGeoNavigator class-interface more or less intact in TMyGeoNavigator, and would then have to ensure that all other classes, such at TGeoManager, are also altered in some way so as to only make calls to TMyGeoNavigator.

I think I will not get into how I have added new methods to the TGeoShape’s for now, for the sake of post-length, but hopefully this illustrates how hackish/ugly what I am doing is. I have had some success in getting it to work, but it is far from pleasant and is becoming harder and harder to debug.

To be extremely cheeky, I suppose what I would like to ask is this: would it be at all possible/not-harmful to add the word virtual to the front of the methods in a few classes in TGeom in a future distribution of ROOT, and also add some simple mutator methods for those private data members that don’t have one (or make them protected).

Any other suggestions welcome. If your suggestion is ‘use Geant’, can you tell me why this would work there, and whether they have shapes and tracking methods that I can inherit from and adapt as indicated above.

Thanks,

Matthew

Hi Matthew,

I think what you want to do is very bold. Not that I don’t like bold or that I do not fully support the idea, but you should be aware what you are embarking into. As you have noticed, some classes were not meant or thought to be derived from. This can easily change and there is no problem to make some data members protected or to promote methods to virtual. The more serious problem is the implementation of the distance computation along a parabola for all (or most) shapes. This is a much more difficult task than you currently seem to imagine. For toruses it will even not work without numerical algorithms (try that on paper first) - you will have to solve a 5-th degree equation.

However, I already gave it a thought for a generalized FindNextBoundary(AndStep) method that would compute the distance from a point along a generic parametric curve like a parabola, helix, or a TFormula… Solving analytically the curve + shape intersections is not feasible, but using extensively the navigation feature called “safety” will certainly help a lot. What one can do is the following: compute the safety distance from current point (provided by the package), then extrapolate along the curve with a path length equal to this value. This will lead to a new point that will certainly not cross any boundary. One can continue doing this until close enough to a boundary so that the trajectory can be well approximated by a straight line - then you just cross the boundary using the standard FindNextBoundaryAndStep().

I have made an attempt to do this and started with the class TGeoHelix, but I got involved in other projects so did not find the time to finish. I would certainly support the idea of a FindNextBoundaryAndStep method that will just be the generalization of the current one and reuse all the existing flags and boundary crossing numerical errors treatment (that is also very complex…).

There is also a “hybrid” approach, where you provide the analytic algorithm for some shapes and use the other approach for the rest. This will improve a bit speed and precision in most cases (with a price of additional work)

You will of course get support also for your approach, but just keep this posting and never say you were not prevented…

Very good luck !

All of your issues have been addresses by G4 people already:

geant4.cern.ch/G4UsersDocuments/ … Field.html

Analogous to EM field you can write your own gravitational or any other field class and add it to G4.

Here is a link to a blog where somebody tried to do just that:

hypernews.slac.stanford.edu/Hype … /27/1.html

Writing from scratch is a waste of time most of the time :slight_smile: