Are there limitations on World Volume solids?

In our simulation, we want to have our detector apparatus at (0,0,0) in the world, to make alignments, primary generators, etc. more convenient. But the detector is placed in a “laboratory hall” which may not be centered. To achieve this, I defined the world volume as a box, using a G4DisplacedSolid to shift the origin of coordinates to where we want it to be.

This works exactly as intended in visualization, and when we create G4Touchable objects “manually” using our own G4Navigator.

But when we run events, we have found that the world volume seems to “lose” it’s coordinate offset, resulting in “stuck track” and “position shifted” errors during tracking. With visualization, we see the world-volume outline jump to be centered on the origin, rather than the displaced solid. Once the run finishes, the visualization goes back to what we intended.

Does the world volume have to be a simple solid, like a box or a sphere? Or can it be a more complex object?

Hi Mike, there is no restriction on the kind of solid to be used as world, other than the recommendation to use a simple shape (best is a box) for efficiency reasons and optimal generation of the optimisation structure in 3D space.

btw, the world volume must be centered in (0,0,0) and should not be displaced or rotated.

Hi Mike, G4DisplacedSolid was introduced as an auxiliary solid for Boolean solids only, and was not intended to be used as an ordinary solid.

To achieve what you want, you can either use multiple nested boxes (ex: world + laboratory hall + the detector surrounding box), or try to define the world as G4ExtrudedSolid. For simple shapes like a box, G4ExtrudedSolid is quite effective.

Ah! @evc It didn’t occur to me to use ExtrudedSolid for the box. That’s a possibility. We are applying our shift along the X axis, so it may not work. As an alternative, I can also take the visual “inefficiency” and just make the world volume much longer in X, to allow the cavern/lab to placed at a non-zero position in the world. There will be a bunch of “extra” world volume on one side compared to the other, but it should keep things happy.

With ExtrudedSolid it is possible to define a box at any position in space, I am sure.

I see it: the “off1” and “off2” arguments give the (x,y) center of the polygon at the bottom and top, respectively. It’s marginally more complicated to code (instead of three half-lengths, there are six G4TwoVectors), but much simpler to place and use. Great idea!

@evc Ugh! G4ExtrudedSolid is a great solution, and I’m implementing it now. Unfortunately, I have discovered that G4ExtrudedSolid::ZSection doesn’t have a default constructor, so you can’t pre-create a vector and fill it:

  std::vector<G4ExtrudedSolid::ZSection> ends(2);	// Apply offsets here

fails at compile time with about 60 lines of error, ending with

/Applications/GEANT4/geant4.10.06.p03/lib/Geant4-10.6.3/../../bin/../include/Geant4/G4ExtrudedSolid.hh:78:7: note: 
      candidate constructor not viable: requires 3 arguments, but 0 were
      ZSection(G4double z, const G4TwoVector& offset, G4double scale)

I know how to work around this, but it’s annoying nevertheless.

Here’s the code that I wanted to use, for clarity and compactness:

  std::vector<G4ExtrudedSolid::ZSection> ends(2);	// Apply offsets here
  ends[0].fZ = -halfSize.z()-1*mm+cavernOffset.z();
  ends[0].fOffset.set(cavernOffset.x(), cavernOffset.y());
  ends[0].fScale = 1.;
  ends[1].fZ =  halfSize.z()+1*mm + cavernOffset.z();
  ends[1].fOffset = ends[0].fOffset;
  ends[1].fScale = 1.;

Instead, here’s the code I’ve got that works:

  std::vector<G4ExtrudedSolid::ZSection> ends;	// Apply offsets here
  G4TwoVector xycenter(cavernOffset.x(), cavernOffset.y());
			     xycenter, 1.));
  ends.push_back(G4ExtrudedSolid::ZSection( halfSize.z()+1*mm+cavernOffset.z(),
				 xycenter, 1.));

I kind of preferred my original, because it self-documents what the arguments represent, by way of the ZSection struct members.

I would suggest the following code:

  G4ExtrudedSolid::ZSection zsect(0., G4TwoVector(), 1.);
  std::vector<G4ExtrudedSolid::ZSection> ends(2, zsect);
  ends[0].fZ = -halfSize.z() - 1*mm + cavernOffset.z();
  ends[0].fOffset.set(cavernOffset.x(), cavernOffset.y());
  ends[1].fZ =  halfSize.z() + 1*mm + cavernOffset.z();
  ends[1].fOffset = ends[0].fOffset;

In case if caverOffset is G4ThreeVector then it is possible to write even more compact code:

G4ExtrudedSolid::ZSection zsect(0., G4TwoVector(cavernOffset), 1.);
std::vector<G4ExtrudedSolid::ZSection> ends(2, zsect);
ends[0].fZ = -halfSize.z() - 1*mm + cavernOffset.z();
ends[1].fZ =  halfSize.z() + 1*mm + cavernOffset.z();

Oh, duh. I should have checked that TwoVector had a ThreeVector ctor.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.