How to rotate replicated logical volumes after using G4PVReplica?

Hello, I have been trying to rotate the logical volumes (array of white hollow cylinders in the attached figure) after replicating it using the G4PVReplica. How can I rotate the cylinders shown in the figure? I want to rotate it along the x-axis by 90 degrees. But not sure how can I incorporate rotation after the replication of logical volumes! Any help would be appreciated.

The code is also attached.
screenshot

#include "DetectorConstruction.hh"

DetectorConstruction::DetectorConstruction()  
{;}

DetectorConstruction::~DetectorConstruction() 
{;}

G4VPhysicalVolume* DetectorConstruction::Construct()
{
  // Material Information imported from NIST database
  G4NistManager* nist = G4NistManager::Instance();
  G4Material* Air   = nist->FindOrBuildMaterial("G4_AIR");
  G4Material* Water = nist->FindOrBuildMaterial("G4_WATER");

  // Polystyrene (C8H8)n
  G4Material* Pstyrene = new G4Material("Polystyrene", 1.03*g/cm3, 2);
  Pstyrene->AddElement(nist->FindOrBuildElement("C"), 8);
  Pstyrene->AddElement(nist->FindOrBuildElement("H"), 8);

  //
  // Print all the materials defined.
  G4cout << G4endl << "The materials defined are : " << G4endl << G4endl;
  G4cout << *(G4Material::GetMaterialTable()) << G4endl;


  // Define a World Volume
  G4VSolid* solidWorld = new G4Box("solidbox", 120*mm,120*mm,120*mm);     // half length of sides
  G4LogicalVolume* logicWorld = new G4LogicalVolume(solidWorld, Air, "logicWorld");
  G4VPhysicalVolume* physWorld = new G4PVPlacement(0,                     // no rotation of daughter frame wrt mother frame
                                                  G4ThreeVector(),        // position in mother volume at (0,0,0)
                                                  logicWorld,             // logical volume
                                                  "physWorld",            // name
                                                  0,                      // mother volume
                                                  false,                  // no boolean operation, set it to false
                                                  0,                      // copy number, unique arbitary number
                                                  true);                  // optional overlap check                     

  // Define outer box
  G4VSolid* outerbox = new G4Box("phantombox", 63.88*mm, 7.3*mm, 42.74*mm); //half length of cell well

  G4LogicalVolume* logicCell_well = new G4LogicalVolume(outerbox, Pstyrene, "logicCell_well"); // logical volume - assign properties to object material
  
  G4VPhysicalVolume* fPhantomPhysOuter = new G4PVPlacement(0, 
                                                           G4ThreeVector(),
                                                           logicCell_well, "fPhantomPhysOuter",   // physical voloume - place the created object in the coordinate system of mother volume
                                                           logicWorld, false, 0);

 
  // Visualization attributes -- outer box
  // logicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());            // world volume box will dissappear
  // G4VisAttributes* outerBoxVisAtt= new G4VisAttributes(G4Colour(1, 1, 1));  // white volume
  // outerBoxVisAtt-> SetVisibility(true);
  // outerBoxVisAtt-> SetForceSolid(true);
  // logicCell_well-> SetVisAttributes(outerBoxVisAtt);


  // Define inner box
  G4VSolid* innerbox = new G4Box("innerBox", 46.0*mm, 5.09*mm, 32.74*mm); 
  G4LogicalVolume* logicCell_well_inner = new G4LogicalVolume(innerbox, Pstyrene, "logicCell_well_inner");
  G4VPhysicalVolume* fPhantomPhysInner = new G4PVPlacement(0, 
                                                           G4ThreeVector(0., 2.545*mm, 0.),
                                                           logicCell_well_inner,
                                                           "fPhantomPhysInner", 
                                                           logicWorld, 
                                                           false, 0);

  // Visualization attributes -- inner box
  // G4VisAttributes* innerBoxVisAtt= new G4VisAttributes(G4Colour(1, 1, 0));
  // innerBoxVisAtt-> SetVisibility(true);
  // innerBoxVisAtt-> SetForceSolid(true);
  // logicCell_well_inner-> SetVisAttributes(innerBoxVisAtt);


  // // Subtract inner box from outer box
  G4VSolid* solidShape = new G4SubtractionSolid("outer-inner",                 
                                                 outerbox, 
                                                 innerbox,
                                                 0,                                 // no rotation
                                                 G4ThreeVector(0*mm, 0*mm, 0*mm));  // no translation

  G4LogicalVolume* logicCellWell = new G4LogicalVolume(solidShape, Pstyrene, "logicCellWell", 0, 0, 0);

  G4VPhysicalVolume* physCellWell = new G4PVPlacement(0, 
                                                      G4ThreeVector(0, 0, 0), 
                                                      logicCellWell, 
                                                      "physCellWell",
                                                      logicWorld,   // its mother volume
                                                      true,         // Boolean operation
                                                      0, false);	  // check overlaps	


  // Visualization attributes -- subtracted volume
  G4VisAttributes* cellwellVisAtt= new G4VisAttributes(G4Colour(1.0, 0.0, 0.0));  // red color
  cellwellVisAtt-> SetVisibility(true);
  cellwellVisAtt-> SetForceSolid(false);
  logicCellWell->SetVisAttributes(cellwellVisAtt); 

 

  // Construct cells_wells (hollow cylinders with outer thickness of 5 mm and inner 4.5 mm and height 9.18 mm
  G4Tubs* cylinder = new G4Tubs("hollow_cylinder", 4.5*mm, 5*mm, 10.8*mm, 0., 360*degree);
  G4LogicalVolume* logicCylinder = new G4LogicalVolume(cylinder,         // its name
                                                       Water,            // material
                                                       "logicCylinder",  // in place of "logicWorld", cylinder->GetName() also works
                                                       0, 0, 0);         // FieldManager, SensitiveDetector, ULimits

  
  // Rotate logical volumes by 90 degrees in X-axis
  G4RotationMatrix* replicatedCylinder= new G4RotationMatrix;
  replicatedCylinder-> rotateX(90.*deg);

  // Let us use G4Replica to create a array of hollow cylinders
  {
  G4PVReplica* physHollowCylinder = new G4PVReplica(cylinder->GetName(),   // its name ("hollow_cylinder")
                                       logicCylinder,        // its logical volume
                                       logicCell_well_inner, // its mother logical volume (innerbox, length 46*2 =92 mm)
                                       kXAxis,               // axis of replication
                                       9,                    // # of Replicas
                                       10.0*mm,              // width of replica (9*10.0 = 90.0 < 92 mm, OK), this width is equal to the diameter of cylinder/well
                                       0);                   // offset                                
  }

  // G4VPhysicalVolume* physHollowCylinder;
  // physHollowCylinder = new G4PVPlacement(replicatedCylinder, G4ThreeVector(0.*mm, (5.09+0.61)*mm, 0.*mm),
  //                                        logicCylinder, "physHollowCylinder",
  //                                        logicWorld, false, 0);

  // Visualization of cylinders
  G4VisAttributes* CylinderVisAtt= new G4VisAttributes(G4Colour(1, 1, 1));
  CylinderVisAtt-> SetVisibility(true);
  CylinderVisAtt-> SetForceSolid(true);
  logicCylinder-> SetVisAttributes(CylinderVisAtt);


  return physWorld;
}
1 Like

Rather than using G4PVReplica, I end up using a for loop given below, which worked well, and thus was able to generate the rotation I wanted.

    for (int i=0; i<9; ++i) {
    G4ThreeVector pos((40-i*10)*mm, (5.09+0.61)*mm, 0.); // 40 mm is the length of innerbox
    new G4PVPlacement(rot,                               // 90 degrees rotation                                                                    
                      pos,                               // position of all cylinders                                                                     
                      logicCylinder,                     // logical volume                                                                 
                      "physHollowCylinder",              // its name                                                                       
                      logicWorld,                        // its mother  volume                                                             
                      false,                             // no boolean operation                                                           
                      0);                                //copy number                                                                           
    } 
![Screen Shot 2022-09-15 at 5.06.20 PM|690x400](upload://rh7E9NiXOVQXyPVAG1ZrF2RT8E4.png)

Why rotate each one individually? Why not just rotate the mother volume around X?

Or are you wanting to be able to specify individual cylinders to be rotated? If you, so you need to make sure the mother volume is big enough to hold the cylinders in both orientations.

1 Like