#include #include #include #include #include #include #include #include #include #include #include using namespace RAT; #include #include using namespace CLHEP; using namespace std; void AcrylicVesselFactory::Construct( DBLinkPtr table, const bool checkOverlaps ) { RAT::DB* db = DB::Get(); bool inner = table->GetI( "inner" ) == 1; string name = table->GetIndex(); G4VSolid* av = GeoSolid::ConstructSolid( name + "_av", db->GetLink( "SOLID", table->GetS( "acrylic_vessel_definition" ) ) ); G4VSolid* bellyPlate = NULL; G4VSolid* bellyGroove = NULL; vector bellyX, bellyY, bellyZ, bellyRoll; bool addBellyPlates = true; try{ addBellyPlates = table->GetI( "add_belly_plates" ) == 1; } catch( DBNotFoundError& e ) { /* Optional */ } bool addBellyGrooves = !inner; try{ addBellyGrooves = table->GetI( "add_belly_grooves" ) == 1; } catch( DBNotFoundError& e ) { /* Optional */ } if( addBellyPlates ) bellyPlate = GeoSolid::ConstructSolid( name + "_belly_plate", db->GetLink( "SOLID", table->GetS( "belly_plate_definition" ) ) ); if( addBellyGrooves ) bellyGroove = GeoSolid::ConstructSolid( name + "_belly_groove", db->GetLink( "SOLID", table->GetS( "belly_groove_definition" ) ) ); if( addBellyPlates || addBellyGrooves ) { DBLinkPtr bellyLocationTable = db->GetLink( "GEO_LOCATIONS", table->GetS( "belly_plate_locations" ) ); bellyX = bellyLocationTable->GetDArray( "x" ); bellyY = bellyLocationTable->GetDArray( "y" ); bellyZ = bellyLocationTable->GetDArray( "z" ); bellyRoll = bellyLocationTable->GetDArray( "roll" ); } bool addNeckBoss = true; try{ addNeckBoss = table->GetI( "add_neck_boss" ) == 1; } catch( DBNotFoundError& e ) { /* Optional */ } if( inner ) { // Subtract belly plates if( addBellyPlates ) { for( size_t uPlate = 0; uPlate < bellyX.size(); uPlate++ ) { G4RotationMatrix* rotation = new G4RotationMatrix(); rotation->rotateZ( bellyRoll[uPlate] * deg ); G4ThreeVector position( bellyX[uPlate], bellyY[uPlate], bellyZ[uPlate] ); av = new G4SubtractionSolid( name + "_av_solid", av, bellyPlate, rotation, position ); } } // Subtract the neck boss if( false && addNeckBoss ) // Disable neck boss whilst fix is studied { G4VSolid* neckBoss = GeoSolid::ConstructSolid( name + "_neck_boss", db->GetLink( "SOLID", table->GetS( "neck_boss_definition" ) ) ); const double neckBossZ = table->GetD( "neck_boss_z" ); av = new G4SubtractionSolid( name + "_av_solid", av, neckBoss, NULL, G4ThreeVector( 0.0, 0.0, neckBossZ ) ); } // Add the ncd anchors bool addNCDAnchors = true; try{ addNCDAnchors = table->GetI( "add_ncd_anchors" ) == 1; } catch( DBNotFoundError& e ) { /* Optional */ } if( addNCDAnchors ) { G4VSolid* ncdAnchor = GeoSolid::ConstructSolid( name + "_ncd_anchor", db->GetLink( "SOLID", table->GetS( "ncd_anchor_definition" ) ) ); DBLinkPtr ncdLocationTable = db->GetLink( "GEO_LOCATIONS", table->GetS( "ncd_anchor_locations" ) ); vector ncdX = ncdLocationTable->GetDArray( "x" ); vector ncdY = ncdLocationTable->GetDArray( "y" ); vector ncdZ = ncdLocationTable->GetDArray( "z" ); vector ncdU = ncdLocationTable->GetDArray( "u" ); vector ncdV = ncdLocationTable->GetDArray( "v" ); vector ncdW = ncdLocationTable->GetDArray( "w" ); for( size_t uNCD = 0; uNCD < ncdX.size(); uNCD++ ) { G4RotationMatrix* rotation = DirectionToRotation( G4ThreeVector( ncdU[uNCD], ncdV[uNCD], ncdW[uNCD] ) ); G4ThreeVector position( ncdX[uNCD], ncdY[uNCD], ncdZ[uNCD] ); av = new G4UnionSolid( name + "_av_solid", av, ncdAnchor, rotation, position ); } } } else { // Add the belly plates if( addBellyPlates ) { for( size_t uPlate = 0; uPlate < bellyX.size(); uPlate++ ) { G4RotationMatrix* rotation = new G4RotationMatrix(); rotation->rotateZ( bellyRoll[uPlate] * deg ); G4ThreeVector position( bellyX[uPlate], bellyY[uPlate], bellyZ[uPlate] ); av = new G4UnionSolid( name + "_av_solid", av, bellyPlate, rotation, position ); } } // Subtract the belly grooves if( addBellyGrooves ) { for( size_t uPlate = 0; uPlate < bellyX.size(); uPlate++ ) { G4RotationMatrix* rotation = new G4RotationMatrix(); rotation->rotateZ( bellyRoll[uPlate] * deg ); G4ThreeVector position( bellyX[uPlate], bellyY[uPlate], bellyZ[uPlate] ); av = new G4SubtractionSolid( name + "_av_solid", av, bellyGroove, rotation, position ); } } // Add the neck boss if( addNeckBoss ) { G4VSolid* neckBoss = GeoSolid::ConstructSolid( name + "_neck_boss", db->GetLink( "SOLID", table->GetS( "neck_boss_definition" ) ) ); const double neckBossZ = table->GetD( "neck_boss_z" ); av = new G4UnionSolid( name + "_av_solid", av, neckBoss, NULL, G4ThreeVector( 0.0, 0.0, neckBossZ ) ); } } // See if the solid should be split try { double splitZ = table->GetD( "split_z" ); pair< G4VSolid*, G4VSolid* > solids = SplitSolid( av, name, splitZ ); G4LogicalVolume* logicalTop = BuildVolume( name + "_top", table, solids.first, G4Material::GetMaterial( table->GetS( "material_top" ) ) ); PlaceVolume( name + "_top", table, logicalTop, checkOverlaps ); G4LogicalVolume* logicalBottom = BuildVolume( name + "_bottom", table, solids.second, G4Material::GetMaterial( table->GetS( "material_bottom" ) ) ); PlaceVolume( name + "_bottom", table, logicalBottom, checkOverlaps ); } catch( DBNotFoundError& e ) // Just a single solid to place { G4LogicalVolume* logicalVolume = BuildVolume( name, table, av, G4Material::GetMaterial( table->GetS( "material" ) ) ); PlaceVolume( name, table, logicalVolume, checkOverlaps ); } }