Squared fiber on a helix path

Good morning/evening geant4 guru!
I need to simulate the following geometry:
scintillating square fibers coiled in the shape of a cylinder but running at an oblique angle. Basically the fibers follow a helix. so I guess the geometry I’m looking for is a “square helix”. We are talking about 250-500 microm square fibers wound along a 5cm diameter cylinder and 30cm long.
To top it off there are going to be two cylinders with fibers with different orientations.
Added a picture to help understand the problem
Clearly the cutout in the green fibers is just to better see the blue fibers. :slight_smile:

Clearly I only need a single fiber and then I can duplicate and rotate along the cylinder axis. but how do i create the shape?
I was hoping TwistedTubs might do the trick (even if it’s not a perfect square it would be “close enough”) or something similar; ChatGPT suggests using G4ExtrudedSolid (but the examples it gave me are mostly broken…); I can try to glue different sections; G4TessellatedSolid might be an option. This would involve quite a lot of C++ to define triangles, but it can be done…
Or do I just need to bite the bullet and go with CAD->GDML
Since the geometry isn’t final, I’d like to have a “parametric” solution and the cad on this side would be slow. But it seems to me that there is no practical way to define my geometry.
Opinions? Thanks a lot!
Cheers from Italy

Additional info: the scintillating part is already taken care of. I’m already running a simulation with fibers. I’m currently using Geant4 11.1.1 but if needed I can downgrade. My code was working fine a week ago with 10.7.4

Please look at G4GenericTrap.

BTW, do you have a sketch image of the geometry? This would help to better understand the problem.

Good evening.
As soon as I can I will take a look at G4GenericTrap.
Is my first time hearing of it so it might be my solution.

(I added a picture to the post. thanks for pointing it out)

The fibres have a non-trivial shape that cannot be directly specified by one of the Geant4 solid. You can try to approximate the shape either by G4TesselatedSolid, or as a sequence of G4GenericTrap solids.

The fibres can be constructed in relatively easy way using G4TwistedBox. The lateral faces of this solid are helicoids:


If from one thin twisted box subtract another one that has smaller x-dimension, then the result will be a pair of fibers with a square cross section:


Replication of this pair of fibres will produce a cylindrical group of fibres:


In the attachment you can find DetectorConstruction.cc for the example B1 that constructs this geometry.

Please note:

  • The twist angle in G4TwistedBox should be less than 90 degrees, that results in not very long fibres;
  • If, for some reason, you will need a single fiber instead of a pair, then this can be achieved by applying the intersection with a sector of a tube, see corresponding commented line in the attachment. The result will be an almost square cross section, one side will be a short circular arc instead of a line segment.

DetectorConstruction.cc (3.8 KB)

1 Like

Awesome! This solution is very elegant, thank you very much for pointing it out.
I actually ended up doing it ‘by hand’ with G4TessellatedSolid:

  • Is not pretty but it works and allows me to change the shape of the fiber from squared to circular quite easily.
  • Changing the ‘path for the extrusion’ the shape can be changed from helix to whatever easily too. Not needed for me right now but perhaps one day.
  • I added an optional extrusion ‘box’ at both ends of the fiber. This is useful in the case of the multi-layer structure, to bool out the core from the cladding.

I will add some info and a piece of code when I’m done polishing it, in case can be of any help to someone

@evc, can we also start with G4TwistedTubs (not exactly squared …) ?

A circular cross-section fiber of any form can be approximated by G4CutTubs. In the attachment you can find a function that constructs a sequence of cylinders along a sequence of points.

testCreateCutTubsChain.cc (2.1 KB)

Yes, you can. I even expect a better performance than in the case G4TwistedBox.

You can also consider G4GenericTrap. Relative to this particular task, I don’t see much difference in approximating a small part of the fiber by G4TwistedTubs or by G4GenericTrap. The difference between these two solids will be the following:

  • In case of G4TwistedTubs the radial surfaces will be approximated by a one-sheeted hyperboloid;
  • In case of G4GenericTtrap the radial surfaces will be approximated by a hyperbolic paraboloid;

The surfaces along helicoid part in the both cases will be approximated as hyperbolic paraboloid.

Good morning again, additional question on performance:
whichever way I create them, if the fibers are thin and I need many the positioning and “overlap check” takes quite a bit.
Let’s say i need 1k of them. Would fitting 200 of them in a 'chunk-mother-volume" and duplicating this 5 times help? I’m guessing it would require simple checks…
Thanks a lot for all your help!

PS: I’m still a ‘noob’ so I just made a loop calling G4PVPlacement with different rotations. Perhaps that’s the problem? Would using G4Replica or G4PVParameterised improve the efficiency?

if you are certain there are no overlaps there is no need for checking.

You are completely right. I’m so dumb I forgot the check is optional…
I can just run it one time if I change the geometry and then turn it OFF.
Sorry for the silly question. :sweat_smile:

I would do in a different way.

If a fiber is defined as a single volume, then it can substantially slow down not only the overlap check, but also the simulation performance. The reason is that the bounding boxes of the fibers intersect each other, so most of the performance optimisation technics used in Geant4 will not work.

The performance can be improved by dividing a fiber into smaller parts along its length. Try to construct a small part of you geometry where the fibres have 1 cm length instead of 30 cm. You will see that performance will be much better despite the fact that the number of volumes remains the same.

So, I would suggest:

  • define a fiber of small length;
  • place as many as necessary small fibers into a short tube;
  • then, build a stack of such tubes;

Long story short, I stuck with G4TessellatedSolid. Was it a good idea? Probably not and in either case I will find out at some point. Eventually, I might end up switching back to the G4TwistedBox/G4TwistedTubs idea.

Attached here you can find my CreateHelix.cpp/hh. I’m quite sure any decent programmer might get nauseous looking at it but I’m quite pleased overall… Honestly, I don’t expect anyone to use it or really read it but at least I learned something writing it.

NB: I didn’t know G4QuadrangularFacet was a thing so I used G4TriangularFacet, which was a useless exercise. I guess i might change it at some point but i think shouldn’t change the end result.

In the detector construction i just

#include "CreateHelix.cpp"

and then call the function

G4TessellatedSolid* CreateHelix(G4String name, TVector3 center, double size, double angle, double length, int steps, double extrusion)

The axis of the cylinder is along the z-axis.

  • name = name of the fiber
  • center = the x,y,z center of the fiber (assumed to be on the xy plane)
  • size = thickness of the fiber, to be used to create the base around the center. This defines the radius of the cylinder
  • angle = at which angle the fiber run
  • length = length of the cylinder
  • steps = number of steps (aka mesh density)
  • extrusion = I added a straight final section of length = extrusion to fit some sensor, like a SiPM or a VD to collect the photons coming to the ends.

Semi-example might be something like

	G4double CyFi_length = 15*cm;
	G4double CyFi_radius = 3.5*cm;
	G4double FiberThickness  = 5*mm;
	TVector3 center = TVector3(CyFi_radius,0,0);
	double angle = 60*deg;
	double steps = 200;
    double SiPMSize = 0.5*mm

	G4TessellatedSolid* FiberSolid = CreateHelix("TriangularHelix", center, FiberThickness, angle, CyFi_length, steps, SiPMSize);	

The extrusion can be also useful if the fiber has one or multiple cladding: with a longer version of the core you can bool_out the central part of the cladding.
NB cpp is not supported for whatever reason so i change it to cc
CreateHelix.hh (2.2 KB)
CreateHelix.cc (6.7 KB)

Thank you very much for your patience, help and guidance!!
And ‘sorry’ I ended up sticking to my dumb ideas…
I hope I will not regret it too much :upside_down_face:

1 Like