# Drawing Vacuum chamber using boolean solid

Hello, I’ve to draw a vacuum chamber and to put my targerts in it. The vacuum chamber is a cylinder with the inner empty. So I’m using the boolean solid.

``````	G4double pSPhi = 0.;
G4double pDPhi = 2*pi;
``````
``````	// Vacuum chamber
G4double pRMaxCE = 30.*cm; //external radius
G4double ChambThickness = 0.1*cm; //Thickness of chamber
//	G4double pRMaxCI = 2*pRMaxCE-ChambThickness; //Internal radius
G4double pRMaxCI = 29*cm; //Internal radius
G4double pDzCE = 60.*cm; //Height
//G4double pDzCI = pDzCE- 2.*ChambThickness; //Internal height
G4double pDzCI = 58*cm; //Internal height
``````
`````` //vacuum chamber
G4LogicalVolume* ChamblogicEnv;
G4Material* ChambMat = Mylar;
G4RotationMatrix* ChambRot = new G4RotationMatrix();
ChambRot->rotateX(90.*deg);

G4Tubs* ChambTubExt;
G4Tubs* ChambTubInt;
G4VSolid* ChambEnv;
G4ThreeVector positionChambInt(0,0,0);
if (fVacuumChambFlag) {
ChambTubExt = new G4Tubs("ChambTubExt",  0., fpRMaxCE, 0.5*fpDzCE, fpSPhi, fpDPhi);
ChambTubInt = new G4Tubs("ChambTubInt",  0., fpRMaxCI, 0.5*fpDzCI, fpSPhi, fpDPhi);
ChambEnv = new G4SubtractionSolid("ChambEnv", ChambTubExt, ChambTubInt, &identity, positionChambInt);
ChamblogicEnv= new G4LogicalVolume(ChambEnv, ChambMat, "VacuumChamber");

new G4PVPlacement(ChambRot,    //rotation
G4ThreeVector(0,0,0),         //at (0,0,fzFirDummyPos)
ChamblogicEnv,                //its logical volume
"VacuumChamber",              //its name
logicWorld,              //its mother  volume
false,                   //no boolean operation
0,                       //copy number
checkOverlaps);          //overlaps checking
}
``````

I’m drawing a first G4Tube then I’m drawing a second one with lower height and radius than the first one and Im subcrating the volume of the second one to the first one…i.e. I want a close cylinder with closed bottom and top surfaces, empty in the inner (just a low thickness of lateral surface).

This is the visualization

it looks like I’ve the two cylinders instead that only one of low thickness, I don’t know if I’m doing something wrong or it’s just an optical effect…
The reason because it’s important that I’m really subcrating the volume of the second cylinder is that the inner of the vacuum chamber must be vacuum…so…given that the world is made of vacuum and the vacuum chamber surface is made of myler, I need to delete the volume of the second G4tube to have vacuum

maybe @evc can help me to know if I’m doing it fine?

Thank you

exampleB1.cc (12.9 KB)
B1DetectorConstruction.cc (18.2 KB)

1 Like

Hello, the drawing looks OK for me. You can subtract one cylinder from another, however a better way to describe the chamber is to define the inner cylinder as a daughter volume of the outer cylinder.

So, the material of the world will be vacuum, the material of the outer cylinder - mylar, and the material of inner cylinder - vacuum.

Thank you @evc

1. In this way (boolean substraction) don’t I have outer cylinder in mylar and inner cylinder in vacuum?
2. How do I define the daughter volume?
3. This is just the proof…in this proof I’ve to draw the outer cylinder made of mylar. Instradamento, for the final simulation, I’ve to draw the vacuum chamber made of steel and with 3 windows made of mylar, the first one the windows where the beam enters, the second one where the beam exits and the third one bevande Invece to put a scintillator close to the vacuum chamber. How ro draw it? In this case, I can’t simply draw rhe boolean solid, because I need 2 materials (i.e. steel for the camper surface and mylar for the windows)

Thank you

1 Like
1. Boolean subtraction can be used to define the chamber, but the performance of the simulation will be worse than in case when one cylinder is placed into another.

BTW, the chamber can be also defined as three separate volumes, one tube and two discs, at bottom and top of the tube.

1. Mother-daughter relation arises when you apply G4PVPlacement. For example, in your code `ChamblogicEnv` is a daughter volume of `logicWorld`. Respectively `logicWorld` is the mother volume of `ChamblogicEnv`.

2. Different approaches can be used to define windows, depending on how the actual geometry looks like. For example, if a window has the same thickness as the wall of the chamber, then the window can be defined as a daughter volume of the chamber. Another approach is to subdivide the chamber into several parts.

It is difficult to advice on how to draw, Geant4 is a simulation toolkit, visualisation in Geant4 is mainly used to verify correctness of the geometry description. Producing nice drawing, which will look like real geometry, can be rather tricky.

Thank you @evc , then I will modify using the daughter volume

This should be the final version…I’ve the vacuum chamber made of steel and 3 windows (2 for the in and out beam and one for the scintillator)…yes, the thickness of the windows can be the same than the vacuum chamber wall (i.e. 1mm), but the windows must be made of mylar and the vacuum chamber wall made of steel.

For the windows, we handle it in our geometry with Boolean subtraction: create a cylinder solid the diameter of your window, and a Z height larger than the thickness of your chamber wall. Use a MultiUnion to arrange all three cylinders in the position of your windows in the diagram above. Then you can make cylindrical disk windows of Mylar and place them into those holes (place them in the same mother volume as the cylinder).

Ok, so in this case I’ve just use the boolean solid, not the daughter volume, true?

The following code constructs a chamber with three windows:

``````  // Create logical volumes
G4double dx, dy, dz;
dx = dy = dz = 0.5*WorldSize;
G4VSolid* solidWorld = new G4Box("World", dx, dy, dz);
G4LogicalVolume* logicWorld =
new G4LogicalVolume(solidWorld, mat_vacuum, "World");

G4double rmax, rmin, dphi;
dz = 0.5*ChambHeight - ChambThickness;
G4VSolid* solidBarrel =
new G4Tubs("Barrel", rmin, rmax, dz, 0., twopi);
G4LogicalVolume* logicBarrel =
new G4LogicalVolume(solidBarrel, mat_steel, "Barrel");

dz = 0.5*ChambThickness;
G4VSolid* solidEndCup =
new G4Tubs("End_Cup", 0., rmax, dz, 0., twopi);
G4LogicalVolume* logicEndCup =
new G4LogicalVolume(solidEndCup, mat_steel, "End_Cup");

dz = 0.5*WindowSize;
G4VSolid* solidWindow =
new G4Tubs("Window", rmin, rmax, dz, -0.5*dphi, dphi);
G4LogicalVolume* logicWindow =
new G4LogicalVolume(solidWindow, mat_mylar, "Window");

// Create physical volumes
G4VPhysicalVolume* physWorld =
new G4PVPlacement(0, G4ThreeVector(), logicWorld, "World", 0,
false, 0, checkOverlaps);
new G4PVPlacement(0, G4ThreeVector(), logicBarrel, "Barrel", logicWorld,
false, 0, checkOverlaps);

G4ThreeVector endcup_pos(0.,0.,0.5*(ChambHeight - ChambThickness));
new G4PVPlacement(0, endcup_pos, logicEndCup, "Top_End_Cup", logicWorld,
false, 0, checkOverlaps);
new G4PVPlacement(0, -endcup_pos, logicEndCup, "Bottom_End_Cup", logicWorld,
false, 0, checkOverlaps);
new G4PVPlacement(0, G4ThreeVector(), logicWindow, "Window_Out", logicBarrel,
false, 0, checkOverlaps);
G4RotationMatrix* rot180 = new G4RotationMatrix(G4ThreeVector(0,0,1), 180*deg);
new G4PVPlacement(rot180, G4ThreeVector(), logicWindow, "Window_In", logicBarrel,
false, 0, checkOverlaps);
G4RotationMatrix* rotA = new G4RotationMatrix(G4ThreeVector(0,0,1), 202.5*deg);
new G4PVPlacement(rotA, G4ThreeVector(), logicWindow, "Window_A", logicBarrel,
false, 0, checkOverlaps);

``````

Thank you @evc you are always very precious!

Hello @evc, I ended the simulations using an all mylar chambers, so I tried to build the steel chamber with the 3 mylar windows following you code…

I think that in our simulations we have 2 different coordinate system. I started my simulation by B1 example so my reference system have the beam directed along the z axis, the x-axis pointing upwards and y-axis pointing towards the reader.

Then, following you code, the vacuum chamber is rotated along the z axis instead of along the y axis as you can see

I’m trying to rotate it but I’ve some problems because I’ve to change the cups and the windows (just rotating the barreel the windows positions arent directed along the beam in/out direction and along the plastic scintillator that is at 22.5° from the beam out)

This is the code

B1.cc

``````
// Vacuum chamber
G4double pRMaxCE = 30.*cm; //external radius
G4double ChambThickness = 0.1*cm; //Thickness of chamber
G4double pRMaxCI = pRMaxCE-ChambThickness; //Internal radius
G4double WindowSize = 5.*cm; // length of the mylar windows
G4double pDzCE = 60.*cm; //Height

/ Plastic Scintillator
G4double Scint_sizeX = 5*cm;	// Total x-length
G4double Scint_sizeY = 5*cm;	// Total y-length
G4double Scint_sizeZ = 5*mm;	// Total z-length
G4double alphaScint = 202.5*deg;	// x-Angle of the scintillator with respect to the beam
G4double xScintPos = pRMaxCE*sin(alphaScint); //x-position scintillator
G4double zScintDist = 1*cm; //z-distance of the scintillator from the vacuum chamber
G4double zScintPos = -(pRMaxCE+zScintDist); //z-position scintillator
G4double betaScint = -22.5*deg; //y- Rotation of the scintillator

``````

and DETECTOR CONSTRUCTION

``````//vacuum chamber
G4double fdz, fdphi;
G4double fpi = 3.14159265358979323846;
G4double twopi=2.*fpi;
G4VSolid* solidBarrel;
G4LogicalVolume* logicBarrel;
G4VSolid* solidEndCup;
G4LogicalVolume* logicEndCup;
G4VSolid* solidWindow;
G4LogicalVolume* logicWindow;
G4RotationMatrix* rot180;
G4RotationMatrix* rotA;
if (fVacuumChambFlag) {
fdz = 0.5*fpDzCE - fChambThickness;
solidBarrel = new G4Tubs("Barrel", fpRMaxCI, fpRMaxCE, fdz, 0., twopi);
logicBarrel = new G4LogicalVolume(solidBarrel, mat_steel, "Barrel");
fdz = 0.5*fChambThickness;
solidEndCup = new G4Tubs("End_Cup", 0., fpRMaxCE, fdz, 0., twopi);
logicEndCup = new G4LogicalVolume(solidEndCup, mat_steel, "End_Cup");
fdz = 0.5*fWindowSize;
fdphi = fWindowSize/fpRMaxCE;
solidWindow = new G4Tubs("Window", fpRMaxCI, fpRMaxCE, fdz, -0.5*fdphi, fdphi);
logicWindow = new G4LogicalVolume(solidWindow, Mylar, "Window");
new G4PVPlacement(0, G4ThreeVector(), logicBarrel, "Barrel", logicWorld, false, 0, checkOverlaps);
G4ThreeVector endcup_pos(0.,0.,0.5*(fpDzCE - fChambThickness));
new G4PVPlacement(0, endcup_pos, logicEndCup, "Top_End_Cup", logicWorld, false, 0, checkOverlaps);
new G4PVPlacement(0, -endcup_pos, logicEndCup, "Bottom_End_Cup", logicWorld, false, 0, checkOverlaps);
new G4PVPlacement(0, G4ThreeVector(), logicWindow, "Window_Out", logicBarrel, false, 0, checkOverlaps);
rot180 = new G4RotationMatrix(G4ThreeVector(0,0,1), 180*deg);
new G4PVPlacement(rot180, G4ThreeVector(), logicWindow, "Window_In", logicBarrel, false, 0, checkOverlaps);
rotA = new G4RotationMatrix(G4ThreeVector(0,0,1), 202.5*deg);
new G4PVPlacement(rotA, G4ThreeVector(), logicWindow, "Window_A", logicBarrel, false, 0, checkOverlaps);
}

// plastic scintillator
G4Box* PlastScint;
G4LogicalVolume* logicScint;
G4RotationMatrix* ScintRot = new G4RotationMatrix();
ScintRot->rotateY(fbetaScint);
G4Material* ScintMat = scintillator;
if (!fPlastScintFlag)  ScintMat = world_mat;
PlastScint = new G4Box("PlastScint", 0.5*fScint_sizeX, 0.5*fScint_sizeY, 0.5*fScint_sizeZ);
logicScint = new G4LogicalVolume(PlastScint, ScintMat, "PlasticScintillator");

new G4PVPlacement(ScintRot,    //rotation
G4ThreeVector(fxScintPos,0,fzScintPos),         //at (0,0,fzFirDummyPos)
logicScint,                //its logical volume
"PlasticScintillator",              //its name
logicWorld,              //its mother  volume
false,                   //no boolean operation
0,                       //copy number
checkOverlaps);          //overlaps checking
``````

exampleB1.cc (14.0 KB)
B1DetectorConstruction.cc (20.5 KB)

Thank you

All logical volumes have their own local coordinate system. Placement of child volumes is done in the local system of the mother volume.

When a mother volume is placed to another volume, all its child volumes are transformed together with the mother volume.

The code below places the windows like requires, I believe. I’ve simplified slightly the construction of the Barrel to get rid of the End cups.

``````  // Create logical volumes
G4double dx, dy, dz;
dx = dy = dz = 0.5*WorldSize;

G4VSolid* solidWorld = new G4Box("World", dx, dy, dz);
G4LogicalVolume* logicWorld =
new G4LogicalVolume(solidWorld, mat_vacuum, "World");

G4double rmax, zmax;
zmax = 0.5*ChambHeight;
G4VSolid* solidBarrel =
new G4Tubs("Barrel", 0., rmax, zmax, 0., twopi);
G4LogicalVolume* logicBarrel =
new G4LogicalVolume(solidBarrel, mat_steel, "Barrel");

G4double rmin, zmin;
zmin = 0.5*ChambHeight - ChambThickness;
G4VSolid* solidVacuum =
new G4Tubs("Vacuum", 0., rmin, zmin, 0., twopi);
G4LogicalVolume* logicVacuum =
new G4LogicalVolume(solidVacuum, mat_vacuum, "Vacuum");

G4double dphi;
dz = 0.5*WindowSize;
G4VSolid* solidWindow =
new G4Tubs("Window", rmin, rmax, dz, -0.5*dphi, dphi);
G4LogicalVolume* logicWindow =
new G4LogicalVolume(solidWindow, mat_mylar, "Window");

// Create physical volumes
G4VPhysicalVolume* physWorld =
new G4PVPlacement(0, G4ThreeVector(), logicWorld, "World", 0,
false, 0, checkOverlaps);

// Place vacuum and windows in barrel
new G4PVPlacement(0, G4ThreeVector(), logicVacuum, "Vacuum", logicBarrel,
false, 0, checkOverlaps);

G4double ang_Window_In = -90*deg;
G4double ang_Window_Out = ang_Window_In + 180*deg;
G4double ang_Window_A = ang_Window_Out - 22.5*deg;

G4RotationMatrix* rot_Window_In = new G4RotationMatrix(G4ThreeVector(0,0,1), ang_Window_In);
G4RotationMatrix* rot_Window_Out = new G4RotationMatrix(G4ThreeVector(0,0,1), ang_Window_Out);
G4RotationMatrix* rot_Window_A = new G4RotationMatrix(G4ThreeVector(0,0,1), ang_Window_A);

new G4PVPlacement(rot_Window_In, G4ThreeVector(), logicWindow, "Window_In", logicBarrel,
false, 0, checkOverlaps);
new G4PVPlacement(rot_Window_Out, G4ThreeVector(), logicWindow, "Window_Out", logicBarrel,
false, 0, checkOverlaps);
new G4PVPlacement(rot_Window_A, G4ThreeVector(), logicWindow, "Window_A", logicBarrel,
false, 0, checkOverlaps);

// Place barrel to world
G4double ang_Barrel = 90*deg;
G4RotationMatrix* rot_Barrel = new G4RotationMatrix(G4ThreeVector(1,0,0), ang_Barrel);
new G4PVPlacement(rot_Barrel, G4ThreeVector(), logicBarrel, "Barrel", logicWorld,
false, 0, checkOverlaps);
``````

Thank you @evc, I’ve just last question. In front of the window_A, I’ve a scintillator 1 cm far from the vacuum chamber (on the radial axis)
I defined it as

FILE EXAMPLE B1:

``````// Vacuum chamber
G4double pRMaxCE = 30.*cm; //external radius
G4double ChambThickness = 0.1*cm; //Thickness of chamber
G4double pRMaxCI = pRMaxCE-ChambThickness; //Internal radius
G4double WindowSize = 5.*cm; // length of the mylar windows
G4double pDzCE = 60.*cm; //Height
G4double pDzCI = 0.5*pDzCE-ChambThickness; //Internal height

// Plastic Scintillator
G4double Scint_sizeX = 5*cm;	// Total x-length
G4double Scint_sizeY = 5*cm;	// Total y-length
G4double Scint_sizeZ = 5*mm;	// Total z-length
G4double alphaScint = 203.5*deg;	// x-Angle of the scintillator with respect to the beam
G4double xScintPos = pRMaxCE*sin(alphaScint); //x-position scintillator
G4double zScintDist = 1*cm; //z-distance of the scintillator from the vacuum chamber
G4double zScintPos = -(pRMaxCE+zScintDist); //z-position scintillator
G4double betaScint = -23.5*deg; //y- Rotation of the scintillator

``````

DETECTOR CONSTRUCTION

``````//vacuum chamber
G4double fdz, fdphi;
G4double fpi = 3.14159265358979323846;
G4double twopi=2.*fpi;
G4VSolid* solidBarrel;
G4LogicalVolume* logicBarrel;
G4VSolid* solidVacuum;
G4LogicalVolume* logicVacuum;
G4VSolid* solidWindow;
G4LogicalVolume* logicWindow;
G4double ang_Window_In = -90*deg;
G4double ang_Window_Out = ang_Window_In + 180*deg;
G4double ang_Window_A = ang_Window_In - 22.5*deg;
G4double ang_Barrel = 90*deg;
G4RotationMatrix* rot_Window_In = new G4RotationMatrix(G4ThreeVector(0,0,1), ang_Window_In);
G4RotationMatrix* rot_Window_Out = new G4RotationMatrix(G4ThreeVector(0,0,1), ang_Window_Out);
G4RotationMatrix* rot_Window_A = new G4RotationMatrix(G4ThreeVector(0,0,1), ang_Window_A);
G4RotationMatrix* rot_Barrel = new G4RotationMatrix(G4ThreeVector(1,0,0), ang_Barrel);
if (fVacuumChambFlag) {

solidBarrel = new G4Tubs("Barrel", 0., fpRMaxCE, 0.5*fpDzCE, 0., twopi);
logicBarrel = new G4LogicalVolume(solidBarrel, mat_steel, "Barrel");
solidVacuum = new G4Tubs("Vacuum", 0., fpRMaxCI, fpDzCI, 0., twopi);
logicVacuum = new G4LogicalVolume(solidVacuum, world_mat, "Vacuum");
fdz = 0.5*fWindowSize;
fdphi = fWindowSize/fpRMaxCE;
solidWindow = new G4Tubs("Window", fpRMaxCI, fpRMaxCE, fdz, -0.5*fdphi, fdphi);
logicWindow = new G4LogicalVolume(solidWindow, Mylar, "Window");
new G4PVPlacement(0, G4ThreeVector(), logicVacuum, "Vacuum", logicBarrel, false, 0, checkOverlaps);
new G4PVPlacement(rot_Window_In, G4ThreeVector(), logicWindow, "Window_In", logicBarrel, false, 0, checkOverlaps);
new G4PVPlacement(rot_Window_Out, G4ThreeVector(), logicWindow, "Window_Out", logicBarrel, false, 0, checkOverlaps);
new G4PVPlacement(rot_Window_A, G4ThreeVector(), logicWindow, "Window_A", logicBarrel, false, 0, checkOverlaps);
new G4PVPlacement(rot_Barrel, G4ThreeVector(), logicBarrel, "Barrel", logicWorld, false, 0, checkOverlaps);
}

// plastic scintillator
G4Box* PlastScint;
G4LogicalVolume* logicScint;
G4RotationMatrix* ScintRot = new G4RotationMatrix();
ScintRot->rotateY(fbetaScint);
G4Material* ScintMat = scintillator;
if (!fPlastScintFlag)  ScintMat = world_mat;
PlastScint = new G4Box("PlastScint", 0.5*fScint_sizeX, 0.5*fScint_sizeY, 0.5*fScint_sizeZ);
logicScint = new G4LogicalVolume(PlastScint, ScintMat, "PlasticScintillator");
new G4PVPlacement(ScintRot,    //rotation
G4ThreeVector(fxScintPos,0,fzScintPos),         //at
logicScint,                //its logical volume
"PlasticScintillator",              //its name
logicWorld,              //its mother  volume
false,                   //no boolean operation
0,                       //copy number
checkOverlaps);          //overlaps checking
``````

but it didn’t look like just in front of the window (it is more on the left)

so I had to move it of 1° writing

``````G4double alphaScint = 203.5*deg;|// x-Angle of the scintillator with respect to the beam
G4double betaScint = -23.5*deg; //y- Rotation of the scintillator|
``````

and now it looks like more aligned

should it depend because of the window is curve?Or did I make a mistake with the scintillator?

G4PVPlacement has a constructor with G4Transfrom3D, which is very convenient in case of compound transformation.

The scintillator is located in the World coordinate system. To place it in front of Window_A, it should be moved along negative direction of Z axis, and then rotated on 22.5 degrees around Y axis:

``````new G4PVPlacement(G4RotateY3D(22.5*deg)*G4TranslateZ3D(-ScintDist), logicScint, "Scint", logicWorld, false, 0, checkOverlaps);
``````

Thank you @evc, it’s perfect!

Sorry @evc, I know that I’m asking you many thing…but I noticed some problems when I enable the Vacuum chamber…

The geometry is perfect because the beam enter the first windows, hits the target and out from the second window

But I noticed two problems

1. I used two differnt targets (carbon and tungsten) and I get same results in the scintillator (deposited energy in it number of particles hittiing it, their kinetic energy, etc)

2. I get zero deposited energy in the target

Instead, if disable the vacuum chamber I get deposited energy in the target. To use the vacuum chamber, Should I change something in the targets too?

B1DetectorConstruction.cc (20.2 KB)
?

The targets should be placed in the Vacuum logical volume, not in the World.

I’ve noticed that `checkOverlaps` is set to `true`, so you should have warnings saying that the targets are overlapping with the Barrel volume. Warnings on overlapping volumes usually mean that there is something wrong with the geometry setup.

Hello @evc, sincerly, before wiriting here, I changed the mother volume of the targets defining two cases i.e. if there is the vacuum chamber and if there isn’t

``````
if (fVacuumChambFlag) {
...
TarRot1->rotateX(90.*deg);
TarRot2->rotateX(90.*deg);
new G4PVPlacement(TarRot1, G4ThreeVector(), logicEnv, "Target1", logicBarrel, false, 0, checkOverlaps);
new G4PVPlacement(TarRot2, G4ThreeVector(0,fSecTarPos,0), logicEnv2, "Target2", logicBarrel, false, 0, checkOverlaps);
}
``````
``````	if (!fVacuumChambFlag) {
new G4PVPlacement(TarRot1,    //rotation
G4ThreeVector(),         //at (0,0,0)
logicEnv,                //its logical volume
"Target1",              //its name
logicWorld,              //its mother  volume
false,                   //no boolean operation
0,                       //copy number
checkOverlaps);          //overlaps checking

new G4PVPlacement(TarRot2,            //rotation
G4ThreeVector(0,0,fSecTarPos), //at (0,0,fSecTarPos)
logicEnv2,                //its logical volume
"Target2",                //its name
logicWorld,               //its mother  volume
false,                    //no boolean operation
0,                       //copy number
checkOverlaps);          //overlaps checking
}
``````

but I had the same problem

B1DetectorConstruction.cc (20.5 KB)

Sure, placing the target either in logicBarrel or in logicWorld will have the same effect - the target will be skipped. The target should be placed in logicVacuum.

To understand why, just imaging how the beam will reach the target: it starts with logicWorld, then enters to logicBarrel and then enters to logicVacuum.

Oh yes! rigth! thank you @evc!

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