// $Id$ // Category: geometry // // C++ interface to Geant3 basic routines // for building Geant4 geometry // // by V. Berejnoi, 25.2.1999 // materials, tracking media support // added by I.Hrivnacova, 27.5.1999 #include "TG4GeometryManager.h" #include "TG4GeometryOutputManager.h" #include "TG4GeometryServices.h" #include "TG4G3Units.h" #include "TG4Globals.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // extern global method from g3tog4 void G3CLRead(G4String &, char *); TG4GeometryManager* TG4GeometryManager::fgInstance = 0; //_____________________________________________________________________________ TG4GeometryManager::TG4GeometryManager() : fMediumCounter(0), fMaterialCounter(0), fMatrixCounter(0), fUseG3TMLimits(false), fWriteGeometry(true) { // if (fgInstance) { TG4Globals::Exception( "TG4GeometryManager: attempt to create two instances of singleton."); } fOutputManager = new TG4GeometryOutputManager(); fGeometryServices = new TG4GeometryServices(&fMediumIdVector, &fNameMap); fgInstance = this; // instantiate the default element table //TG4ElementTable::Instance(); } //_____________________________________________________________________________ TG4GeometryManager::TG4GeometryManager(const TG4GeometryManager& right) { // TG4Globals::Exception( "Attempt to copy TG4GeometryManager singleton."); } //_____________________________________________________________________________ TG4GeometryManager::~TG4GeometryManager() { // delete fOutputManager; delete fGeometryServices; } //============================================================================= // // operators // //============================================================================= //_____________________________________________________________________________ TG4GeometryManager& TG4GeometryManager::operator=(const TG4GeometryManager& right) { // check assignement to self if (this == &right) return *this; TG4Globals::Exception( "Attempt to assign TG4GeometryManager singleton."); return *this; } //============================================================================= // // private methods // //============================================================================= //_____________________________________________________________________________ void TG4GeometryManager::FillMediumIdVector() { // The second index for materials (having its origin in // G3 tracking media concept) is stored in a vector of G4int // parallel to G4MaterialTable. // --- // initialize vector G4int nofMaterials = G4Material::GetNumberOfMaterials(); G4int i; for (i=0; iGetMaterial()->GetIndex(); // medium index (ID of G3MedTableEntry) G4int mediumIndex = mte->GetID(); // store medium index in the vector fMediumIdVector[materialIndex] = mediumIndex; } // add verbose G4cout << "Total nof materials: " << nofMaterials << G4endl; G4cout << "Total nof tracking medias: " << fMediumCounter << G4endl; } //_____________________________________________________________________________ void TG4GeometryManager::SetUserLimits() { // Sets user limits defined in G3MedTable for all logical volumes. // --- G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance(); for (G4int i=0; isize(); i++) { G4LogicalVolume* lv = (*lvStore)[i]; // get limits from G3Med G4int materialIndex = lv->GetMaterial()->GetIndex(); G4int mediumIndex = fMediumIdVector[materialIndex]; G4UserLimits* limits = G3Med.get(mediumIndex)->GetLimits(); lv->SetUserLimits(limits); } } //============================================================================= // // public methods - AliMC implementation // //============================================================================= //_____________________________________________________________________________ void TG4GeometryManager::Material(Int_t& kmat, const char* name, Float_t a, Float_t z, Float_t dens, Float_t radl, Float_t absl, Float_t* buf, Int_t nwbuf) { // Creates G4Material. // !! Parameters radl, absl, buf, nwbuf are ignored in G4gsmate // Comment: // absl - this parameter is ignored by GEANT3, too // --- kmat = ++fMaterialCounter; G4double* bufin = fGeometryServices->CreateG4doubleArray(buf, nwbuf); // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsmate(kmat, name, a, z, dens, radl, nwbuf, bufin); G4gsmate(kmat, name, a, z, dens, radl, nwbuf, bufin); delete [] bufin; if (nwbuf > 0) { G4String matName = name; G4String text = "TG4GeometryManager: user defined parameters for material "; text = text + matName; text = text + " are ignored by Geant4."; TG4Globals::Warning(text); } } //_____________________________________________________________________________ void TG4GeometryManager::Mixture(Int_t& kmat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat) { // Creates G4Material composed of more elements. // !! Parameters radl, absl, buf, nwbuf are ignored in G4gsmate // Comment: // absl - this parameter is ignored by GEANT3, too // --- Int_t npar = abs(nlmat); G4double *ain = fGeometryServices->CreateG4doubleArray(a, npar); G4double *zin = fGeometryServices->CreateG4doubleArray(z, npar); G4double *wmatin = fGeometryServices->CreateG4doubleArray(wmat, npar); kmat = ++fMaterialCounter; // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsmixt(kmat, name, ain, zin, dens, nlmat, wmatin); G4gsmixt(kmat, name, ain, zin, dens, nlmat, wmatin); // !!! in Geant3: // After a call with ratios by number (negative number of elements), // the ratio array is changed to the ratio by weight, so all successive // calls with the same array must specify the number of elements as // positive // wmatin may be modified for (G4int i=0; iWriteGstmed(kmed, name, nmat, isvol, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin, 0, 0); G4gstmed(kmed, name, nmat, isvol, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin, 0, fUseG3TMLimits); // !! instead of the nbuf argument the bool fIsG3Default is passed if (nbuf > 0) { G4String medName = name; G4String text = "TG4GeometryManager: user defined parameters for medium "; text = text + medName; text = text + " are ignored by Geant4."; TG4Globals::Warning(text); } } //_____________________________________________________________________________ void TG4GeometryManager::Matrix(Int_t& krot, Double_t thetaX, Double_t phiX, Double_t thetaY, Double_t phiY, Double_t thetaZ, Double_t phiZ) { // Creates G4RotationMatrix. // --- krot = ++fMatrixCounter; // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsrotm(krot, thetaX, phiX, thetaY, phiY, thetaZ, phiZ); G4gsrotm(krot, thetaX, phiX, thetaY, phiY, thetaZ, phiZ); } //_____________________________________________________________________________ void TG4GeometryManager::Matrix(Int_t& krot, Float_t thetaX, Float_t phiX, Float_t thetaY, Float_t phiY, Float_t thetaZ, Float_t phiZ) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Matrix in single precision."); Double_t dthetaX = thetaX; Double_t dphiX = phiX; Double_t dthetaY = thetaY; Double_t dphiY = phiY; Double_t dthetaZ = thetaZ; Double_t dphiZ = phiZ; Matrix(krot, dthetaX, dphiX, dthetaY, dphiY, dthetaZ, dphiZ); } //_____________________________________________________________________________ void TG4GeometryManager::Ggclos() { // Sets the top VTE in temporary G3 volume table. // Close geometry output file (if fWriteGeometry is set true). // // Geant3 desription: // ================== // close out the geometry // --- if (fWriteGeometry) fOutputManager->WriteGgclos(); G4ggclos(); } //_____________________________________________________________________________ void TG4GeometryManager::Gfmate(Int_t imat, char *name, Float_t &a, Float_t &z, Float_t &dens, Float_t &radl, Float_t &absl, Float_t* ubuf, Int_t& nbuf) { // Geant3 desription: // ================== // Return parameters for material IMAT // --- G4Material* material = G3Mat.get(imat); if (material) { // to do: change this correctly // !! unsafe conversion const char* chName = material->GetName(); name = (char*)chName; a = fGeometryServices->GetEffA(material); z = fGeometryServices->GetEffZ(material); dens = material->GetDensity(); dens /= TG4G3Units::MassDensity(); radl = material->GetRadlen(); radl /= TG4G3Units::Length(); // the following parameters are not defined in Geant4 absl = 0.; ubuf = 0; nbuf = 0; } else { TG4Globals::Exception( "TG4GeometryManager::Gfmate: material has not been found."); } } //_____________________________________________________________________________ void TG4GeometryManager::Gstpar(Int_t itmed, const char *param, Float_t parval) { // Write token to the output file only, // the method is performed by TG4PhysicsManager. // --- if (fWriteGeometry) fOutputManager->WriteGstpar(itmed, param, parval); } //_____________________________________________________________________________ void TG4GeometryManager::SetCerenkov(Int_t itmed, Int_t npckov, Float_t* ppckov, Float_t* absco, Float_t* effic, Float_t* rindex) { // // Geant3 desription: // ================== // // Stores the tables for UV photon tracking in medium ITMED // Please note that it is the user's responsability to // provide all the coefficients: // // // ITMED Tracking medium number // NPCKOV Number of bins of each table // PPCKOV Value of photon momentum (in GeV) // ABSCO Absorbtion coefficients // dielectric: absorbtion length in cm // metals : absorbtion fraction (0<=x<=1) // EFFIC Detection efficiency for UV photons // RINDEX Refraction index (if=0 metal) // --- G4double* ppckovDbl = fGeometryServices->CreateG4doubleArray(ppckov, npckov); G4double* abscoDbl = fGeometryServices->CreateG4doubleArray(absco, npckov); G4double* efficDbl = fGeometryServices->CreateG4doubleArray(effic, npckov); G4double* rindexDbl = fGeometryServices->CreateG4doubleArray(rindex, npckov); // add units G4int i; for (i=0; iAddProperty("ABSLENGTH", ppckovDbl, abscoDbl, npckov); // used in G4OpAbsorption process table->AddProperty("EFFICIENCY", ppckovDbl, efficDbl, npckov); // used in G4OpBoundary process table->AddProperty("RINDEX", ppckovDbl, rindexDbl, npckov); // used in G4Cerenkov, G4OpRayleigh, G4OpBoundary // get material of medium from table G3MedTableEntry* medium = G3Med.get(itmed); if (!medium) { G4String text = "TG4GeometryManager::SetCerenkov: \n"; text = text + " Medium not found."; G4Exception(text); } G4Material* material = medium->GetMaterial(); // set material properties table material->SetMaterialPropertiesTable(table); G4cout << "The tables for UV photon tracking set for " << material->GetName() << G4endl; for (i=0; iWriteGsdvn(name, mother, ndiv, iaxis); G4gsdvn(fGeometryServices->CutName(name), fGeometryServices->CutName(mother), ndiv, iaxis); // register name in name map fNameMap.AddName(fGeometryServices->CutName(name)); } //_____________________________________________________________________________ void TG4GeometryManager::Gsdvn2(const char *name, const char *mother, Int_t ndiv, Int_t iaxis, Double_t c0i, Int_t numed) { // Geant3 desription: // ================== // DIVIDES MOTHER INTO NDIV DIVISIONS CALLED NAME // ALONG AXIS IAXIS STARTING AT COORDINATE VALUE C0. // THE NEW VOLUME CREATED WILL BE MEDIUM NUMBER NUMED. // --- // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsdvn2(name, mother, ndiv, iaxis, c0i, numed); G4gsdvn2(fGeometryServices->CutName(name), fGeometryServices->CutName(mother), ndiv, iaxis, c0i, numed); // register name in name map fNameMap.AddName(fGeometryServices->CutName(name)); } //_____________________________________________________________________________ void TG4GeometryManager::Gsdvn2(const char *name, const char *mother, Int_t ndiv, Int_t iaxis, Float_t c0i, Int_t numed) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Gsdvn2 in single precision."); G4double dc0i = c0i; Gsdvn2(name, mother, ndiv, iaxis, dc0i, numed); } //_____________________________________________________________________________ void TG4GeometryManager::Gsdvt(const char *name, const char *mother, Double_t step, Int_t iaxis, Int_t numed, Int_t ndvmx) { // Geant3 desription: // ================== // Divides MOTHER into divisions called NAME along // axis IAXIS in steps of STEP. If not exactly divisible // will make as many as possible and will centre them // with respect to the mother. Divisions will have medium // number NUMED. If NUMED is 0, NUMED of MOTHER is taken. // NDVMX is the expected maximum number of divisions // (If 0, no protection tests are performed) // --- // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsdvt(name, mother, step, iaxis, numed, ndvmx); G4gsdvt(fGeometryServices->CutName(name), fGeometryServices->CutName(mother), step, iaxis, numed, ndvmx); // register name in name map fNameMap.AddName(fGeometryServices->CutName(name)); } //_____________________________________________________________________________ void TG4GeometryManager::Gsdvt(const char *name, const char *mother, Float_t step, Int_t iaxis, Int_t numed, Int_t ndvmx) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Gsdvt in single precision."); G4double dstep = step; Gsdvt(name, mother, dstep, iaxis, numed, ndvmx); } //_____________________________________________________________________________ void TG4GeometryManager::Gsdvt2(const char *name, const char *mother, Double_t step, Int_t iaxis, Double_t c0, Int_t numed, Int_t ndvmx) { // Geant3 desription: // ================== // Create a new volume by dividing an existing one // // Divides MOTHER into divisions called NAME along // axis IAXIS starting at coordinate value C0 with step // size STEP. // The new volume created will have medium number NUMED. // If NUMED is 0, NUMED of mother is taken. // NDVMX is the expected maximum number of divisions // (If 0, no protection tests are performed) // --- // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsdvt2(name, mother, step, iaxis, c0, numed, ndvmx); G4gsdvt2(fGeometryServices->CutName(name), fGeometryServices->CutName(mother), step, iaxis, c0, numed, ndvmx); // register name in name map fNameMap.AddName(fGeometryServices->CutName(name)); } //_____________________________________________________________________________ void TG4GeometryManager::Gsdvt2(const char *name, const char *mother, Float_t step, Int_t iaxis, Float_t c0, Int_t numed, Int_t ndvmx) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Gsdvt2 in single precision."); G4double dstep = step; G4double dc0 = c0; Gsdvt2(name, mother, dstep, iaxis, dc0, numed, ndvmx); } //_____________________________________________________________________________ void TG4GeometryManager::Gsord(const char *name, Int_t iax) { // No corresponding action in G4. // // Geant3 desription: // ================== // Flags volume CHNAME whose contents will have to be ordered // along axis IAX, by setting the search flag to -IAX // IAX = 1 X axis // IAX = 2 Y axis // IAX = 3 Z axis // IAX = 4 Rxy (static ordering only -> GTMEDI) // IAX = 14 Rxy (also dynamic ordering -> GTNEXT) // IAX = 5 Rxyz (static ordering only -> GTMEDI) // IAX = 15 Rxyz (also dynamic ordering -> GTNEXT) // IAX = 6 PHI (PHI=0 => X axis) // IAX = 7 THETA (THETA=0 => Z axis) // --- TG4Globals::Warning("TG4GeometryManager::Gsord: dummy method."); } //_____________________________________________________________________________ void TG4GeometryManager::Gspos(const char *vname, Int_t num, const char *vmoth, Double_t x, Double_t y, Double_t z, Int_t irot, const char *vonly) { // Geant3 desription: // ================== // Position a volume into an existing one // // NAME Volume name // NUMBER Copy number of the volume // MOTHER Mother volume name // X X coord. of the volume in mother ref. sys. // Y Y coord. of the volume in mother ref. sys. // Z Z coord. of the volume in mother ref. sys. // IROT Rotation matrix number w.r.t. mother ref. sys. // ONLY ONLY/MANY flag // // It positions a previously defined volume in the mother. // --- // write token to the output file if (fWriteGeometry) fOutputManager->WriteGspos(vname, num, vmoth, x, y, z, irot, vonly); G4gspos(fGeometryServices->CutName(vname), num, fGeometryServices->CutName(vmoth), x, y, z, irot, vonly); // register name in name map fNameMap.AddName(fGeometryServices->CutName(vname)); } //_____________________________________________________________________________ void TG4GeometryManager::Gspos(const char *vname, Int_t num, const char *vmoth, Float_t x, Float_t y, Float_t z, Int_t irot, const char *vonly) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Gspos in single precision."); G4double dx = x; G4double dy = y; G4double dz = z; Gspos(vname, num, vmoth, dx, dy, dz, irot, vonly); } //_____________________________________________________________________________ void TG4GeometryManager::Gsposp(const char *name, Int_t nr, const char *mother, Double_t x, Double_t y, Double_t z, Int_t irot, const char *konly, Double_t *upar, Int_t np ) { // Geant3 desription: // ================== // Place a copy of generic volume NAME with user number // NR inside MOTHER, with its parameters UPAR(1..NP) // --- // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsposp(name, nr, mother, x, y, z, irot, konly, upar, np); G4gsposp(fGeometryServices->CutName(name), nr, fGeometryServices->CutName(mother), x, y, z, irot, konly, upar, np); // register name in name map fNameMap.AddName(fGeometryServices->CutName(name)); } //_____________________________________________________________________________ void TG4GeometryManager::Gsposp(const char *name, Int_t nr, const char *mother, Float_t x, Float_t y, Float_t z, Int_t irot, const char *konly, Float_t *upar, Int_t np ) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Gsposp in single precision."); G4double dx = x; G4double dy = y; G4double dz = z; G4double* parin = fGeometryServices->CreateG4doubleArray(upar, np); Gsposp(name, nr, mother, dx, dy, dz, irot, konly, parin, np); delete [] parin; } //_____________________________________________________________________________ Int_t TG4GeometryManager::Gsvolu(const char *name, const char *shape, Int_t nmed, Double_t *upar, Int_t npar) { // Geant3 desription: // ================== // NAME Volume name // SHAPE Volume type // NUMED Tracking medium number // NPAR Number of shape parameters // UPAR Vector containing shape parameters // // It creates a new volume in the JVOLUM data structure. // --- // write token to the output file if (fWriteGeometry) fOutputManager->WriteGsvolu(name, shape, nmed, upar, npar); G4gsvolu(fGeometryServices->CutName(name), fGeometryServices->CutName(shape), nmed, upar, npar); // register name in name map fNameMap.AddName(fGeometryServices->CutName(name)); return 0; } //_____________________________________________________________________________ Int_t TG4GeometryManager::Gsvolu(const char *name, const char *shape, Int_t nmed, Float_t *upar, Int_t npar) { // Single precision interface. // --- //TG4Globals::Warning("TG4GeometryManager::Gsvolu in single precision."); G4double* parin = fGeometryServices->CreateG4doubleArray(upar, npar); G4int result = Gsvolu(name, shape, nmed, parin, npar); delete [] parin; return result; } //_____________________________________________________________________________ void TG4GeometryManager::WriteEuclid(const char* fileName, const char* topVolName, Int_t number, Int_t nlevel) { // Geant3 desription: // ================== // // ****************************************************************** // * * // * Write out the geometry of the detector in EUCLID file format * // * * // * filnam : will be with the extension .euc * // * topvol : volume name of the starting node * // * number : copy number of topvol (relevant for gsposp) * // * nlevel : number of levels in the tree structure * // * to be written out, starting from topvol * // * * // * Author : M. Maire * // * * // ****************************************************************** // // File filnam.tme is written out with the definitions of tracking // medias and materials. // As to restore original numbers for materials and medias, program // searches in the file euc_medi.dat and comparing main parameters of // the mat. defined inside geant and the one in file recognizes them // and is able to take number from file. If for any material or medium, // this procedure fails, ordering starts from 1. // Arrays IOTMED and IOMATE are used for this procedure // --- TG4Globals::Warning( "TG4GeometryManager::WriteEuclid(..) is not yet implemented."); } //============================================================================= // // public methods - Geant4 only // //============================================================================= //_____________________________________________________________________________ G4VPhysicalVolume* TG4GeometryManager::CreateG4Geometry() { // Creates G4 geometry objects according to the G3VolTable // and returns the top physical volume in case it was created // (return zero otherwise). // --- // set the first entry in the G3Vol table Ggclos(); G3VolTableEntry* first = G3Vol.GetFirstVTE(); // create G4 geometry G3toG4BuildTree(first,0); // print G3 volume table statistics G3Vol.VTEStat(); // print G4 geometry statistics G4cout << "G4 Stat: instantiated " << fGeometryServices->NofG4LogicalVolumes() << " logical volumes \n" << " " << fGeometryServices->NofG4PhysicalVolumes() << " physical volumes" << G4endl; // position the first entry // (in Geant3 the top volume cannot be positioned) // G4VPhysicalVolume* top = 0; if (first->GetLV()->GetNoDaughters() == 0) { top = new G4PVPlacement(0, G4ThreeVector(), first->GetName(), first->GetLV(), 0, false, 0); } return top; } //_____________________________________________________________________________ void TG4GeometryManager::ReadG3Geometry(G4String filePath) { // Processes g3calls.dat file and fills G3 tables. // --- // add verbose G4cout << "Reading the call list file " << filePath << "..." << G4endl; G3CLRead(filePath, NULL); G4cout << "Call list file read completed. Build geometry" << G4endl; } //_____________________________________________________________________________ void TG4GeometryManager::UseG3TrackingMediaLimits() { // Sets fUseG3TMLimits option. // !! This method has to be called only before starting // creating geometry. // --- if (fMediumCounter == 0) { fUseG3TMLimits = true; } else { G4String text = "TG4GeometryManager::UseG3TMLimits: \n"; text = text + " It is too late to set G3 defaults. \n"; text = text + " Some media has been already processed."; TG4Globals::Exception(text); } } //_____________________________________________________________________________ void TG4GeometryManager::ClearG3Tables() { // Clears G3 volumes, materials, rotations(?) tables // and sensitive volumes vector. // The top volume is kept in the vol table. // --- // clear volume table // but keep the top volume in the table G3VolTableEntry* top = G3Vol.GetFirstVTE(); G4String name = top->GetName(); G4String shape = top->GetShape(); G3VolTableEntry* keep = new G3VolTableEntry(name, shape, top->GetRpar(), top->GetNpar(), top->GetNmed(), top->GetSolid(), false); keep->SetLV(top->GetLV()); G3Vol.Clear(); G3Vol.PutVTE(keep); // clear other tables G3Mat.Clear(); //G3Rot.Clear(); G3SensVol.clear(); } //_____________________________________________________________________________ void TG4GeometryManager::ClearG3TablesFinal() { // Clears G3 medias and volumes tables // (the top volume is removed from the vol table) // --- SetUserLimits(); G3Med.Clear(); G3Vol.Clear(); // reset medium counter //fMaterialCounter = 0; fMediumCounter = 0; } //_____________________________________________________________________________ void TG4GeometryManager::OpenOutFile(G4String filePath) { // Opens output file. // --- fOutputManager->OpenFile(filePath); } //_____________________________________________________________________________ void TG4GeometryManager::CloseOutFile() { // Closes output file. // --- fOutputManager->CloseFile(); } //_____________________________________________________________________________ void TG4GeometryManager::PrintNameMap() { // Prints the map of volumes names to second names. // --- fNameMap.PrintAll(); } //_____________________________________________________________________________ void TG4GeometryManager::SetWriteGeometry(G4bool writeGeometry) { // Controls geometry output. // --- fWriteGeometry = writeGeometry; } //_____________________________________________________________________________ void TG4GeometryManager::SetMapSecond(const G4String& name) { // Sets the second name for the map of volumes names. // --- fNameMap.SetSecond(name); }