// +----+--------------+ +--| AliFMDDigitizer |
// | | +-----------------+
// | +---------------------+ |
-// | +- | AliFMDBaseDigitizer |<--+
+// | +--| AliFMDBaseDigitizer |<--+
// V 1 | +---------------------+ |
// +--------+<>--+ | +------------------+
// | AliFMD | +--| AliFMDSDigitizer |
// +--------+<>--+ +------------------+
-// 1 | +-----------------+
-// +-| AliFMDSimulator |
-// +-----------------+
-// ^
-// |
-// +-------------+-------------+
-// | |
-// +--------------------+ +-------------------+
-// | AliFMDGeoSimulator | | AliFMDG3Simulator |
-// +--------------------+ +---------+---------+
+// 1 | +-----------------+
+// +--| AliFMDSimulator |
+// +-----------------+
+// ^
+// |
+// +-------------+-------------+
+// | |
+// +--------------------+ +-------------------+
+// | AliFMDGeoSimulator | | AliFMDG3Simulator |
+// +--------------------+ +-------------------+
+// ^ ^
+// | |
+// +-----------------------+ +----------------------+
+// | AliFMDGeoOldSimulator | | AliFMDG3OldSimulator |
+// +-----------------------+ +----------------------+
//
//
// * AliFMD
#include "AliFMDSimulator.h" // ALIFMDSIMULATOR_H
#include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H
#include "AliFMDGeoSimulator.h" // ALIFMDGEOSIMULATOR_H
+#include "AliFMDG3OldSimulator.h" // ALIFMDG3OLDSIMULATOR_H
+#include "AliFMDGeoOldSimulator.h" // ALIFMDGEOOLDSIMULATOR_H
#include "AliFMDRawWriter.h" // ALIFMDRAWWRITER_H
//____________________________________________________________________
// Default constructor for class AliFMD
//
AliDebug(10, "\tDefault CTOR");
- fHits = 0;
- fDigits = 0;
- fIshunt = 0;
+ fHits = 0;
+ fDigits = 0;
+ fIshunt = 0;
+ fUseOld = kFALSE;
+ fUseDivided = kFALSE;
+ fUseAssembly = kFALSE;
+ fUseGeo = kTRUE;
}
//____________________________________________________________________
fSimulator(other.fSimulator)
{
// Copy constructor
+ fUseOld = other.fUseOld;
+ fUseDivided = other.fUseDivided;
+ fUseAssembly = other.fUseAssembly;
+ fUseGeo = other.fUseGeo;
}
//____________________________________________________________________
// Standard constructor for Forward Multiplicity Detector
//
AliDebug(10, "\tStandard CTOR");
+ fUseOld = kFALSE;
+ fUseDivided = kFALSE;
+ fUseAssembly = kFALSE;
+ fUseGeo = kTRUE;
// Initialise Hit array
HitsArray();
}
AliFMDGeometry* geometry = AliFMDGeometry::Instance();
geometry->Init();
-// TVirtualMC* mc = TVirtualMC::GetMC();
-// Bool_t geo = mc->IsRootGeometrySupported();
-// if (geo)
-// fSimulator = new AliFMDGeoSimulator(this, fDetailed);
-// else
- fSimulator = new AliFMDG3Simulator(this, fDetailed);
-
+ TVirtualMC* mc = TVirtualMC::GetMC();
+ Bool_t geo = mc->IsRootGeometrySupported();
+ if (geo && fUseGeo) {
+ if (fUseOld)
+ fSimulator = new AliFMDGeoOldSimulator(this, fDetailed);
+ else
+ fSimulator = new AliFMDGeoSimulator(this, fDetailed);
+ }
+ else {
+ if (fUseOld)
+ fSimulator = new AliFMDG3OldSimulator(this, fDetailed);
+ else
+ fSimulator = new AliFMDG3Simulator(this, fDetailed);
+ }
+ AliDebug(1, Form("using a %s as simulation backend",
+ fSimulator->IsA()->GetName()));
+ fSimulator->UseDivided(fUseDivided);
+ fSimulator->UseAssembly(fUseAssembly);
fSimulator->DefineMaterials();
}
AliFMD(const AliFMD& other);
virtual ~AliFMD();
AliFMD& operator=(const AliFMD& other);
-
+ // Use old implementation
+ void UseOld(Bool_t use=kTRUE) { fUseOld = use; }
+ void UseDivided(Bool_t use=kTRUE) { fUseDivided = use; }
+ void UseAssembly(Bool_t use=kTRUE) { fUseAssembly = use; }
+ void UseGeo(Bool_t use=kTRUE) { fUseGeo = use; }
+
+
// GEometry ANd Tracking (GEANT :-)
virtual void CreateGeometry();
virtual void CreateMaterials();
TClonesArray* fSDigits; // Summable digits
Int_t fNsdigits; // Number of digits
Bool_t fDetailed; // Use detailed geometry
+ Bool_t fUseOld; // Use old approx geometry
+ Bool_t fUseDivided; // Use divided volumes
+ Bool_t fUseAssembly; // Use divided volumes
+ Bool_t fUseGeo; // Allow use of TGeo impl.
AliFMDSimulator* fSimulator; // Simulator task
--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/* $Id$ */
+
+//____________________________________________________________________
+//
+// Forward Multiplicity Detector based on Silicon wafers. This class
+// contains the base procedures for the Forward Multiplicity detector
+// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
+// which has 1 or 2 rings of silicon sensors.
+//
+// This is the base class for all FMD manager classes.
+//
+// The actual code is done by various separate classes. Below is
+// diagram showing the relationship between the various FMD classes
+// that handles the simulation
+//
+// +--------+ 1 +-----------------+
+// | AliFMD |<>-----| AliFMDSimulator |
+// +--------+ +-----------------+
+// ^
+// |
+// +-------------+-------------+
+// | |
+// +--------------------+ +-------------------+
+// | AliFMDGeoSimulator | | AliFMDG3Simulator |
+// +--------------------+ +-------------------+
+// ^
+// |
+// +----------------------+
+// | AliFMDG3OldSimulator |
+// +----------------------+
+//
+//
+// * AliFMD
+// This defines the interface for the various parts of AliROOT that
+// uses the FMD, like AliFMDSimulator, AliFMDDigitizer,
+// AliFMDReconstructor, and so on.
+//
+// * AliFMDSimulator
+// This is the base class for the FMD simulation tasks. The
+// simulator tasks are responsible to implment the geoemtry, and
+// process hits.
+//
+// * AliFMDGeoSimulator
+// This is a concrete implementation of the AliFMDSimulator that
+// uses the TGeo classes directly only. This defines the active
+// volume as an ONLY XTRU shape with a divided MANY TUBS shape
+// inside to implement the particular shape of the silicon
+// sensors.
+//
+// * AliFMDG3OldSimulator
+// This is a concrete implementation of the AliFMDSimulator that
+// uses the TVirtualMC interface with GEANT 3.21-like messages.
+// This implements the active volume as a divided TUBS shape. Hits
+// in the corners should be cut away at run time (but currently
+// isn't).
+//
+#include <math.h>
+#include "AliFMDG3OldSimulator.h" // ALIFMDG3OLDSIMULATOR_H
+#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h" // ALIFMDDETECTOR_H
+#include "AliFMDRing.h" // ALIFMDRING_H
+#include "AliFMD1.h" // ALIFMD1_H
+#include "AliFMD2.h" // ALIFMD2_H
+#include "AliFMD3.h" // ALIFMD3_H
+#include "AliFMD.h" // ALIFMD_H
+#include <AliLog.h> // ALILOG_H
+#include <TVector2.h> // ROOT_TVector2
+#include <TVirtualMC.h> // ROOT_TVirtualMC
+#include <TArrayI.h> // ROOT_TArrayI
+
+//====================================================================
+ClassImp(AliFMDG3OldSimulator)
+#if 0
+ ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDG3OldSimulator::AliFMDG3OldSimulator()
+{
+ // Default constructor
+ fSectorOff = 1;
+ fModuleOff = -1;
+ fRingOff = 3;
+ fDetectorOff = 4;
+ fUseDivided = kTRUE;
+}
+
+//____________________________________________________________________
+AliFMDG3OldSimulator::AliFMDG3OldSimulator(AliFMD* fmd, Bool_t detailed)
+ : AliFMDG3Simulator(fmd, detailed)
+{
+ // Normal constructor
+ //
+ // Parameters:
+ //
+ // fmd Pointer to AliFMD object
+ // detailed Whether to make a detailed simulation or not
+ //
+ fSectorOff = 1;
+ fModuleOff = -1;
+ fRingOff = 3;
+ fDetectorOff = 4;
+ fUseDivided = detailed;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDG3OldSimulator::RingGeometry(AliFMDRing* r)
+{
+ // Setup the geometry of a ring. The defined TGeoVolume is
+ // returned, and should be used when setting up the rest of the
+ // volumes.
+ //
+ // Parameters:
+ //
+ // r Pointer to ring geometry object
+ //
+ // Returns:
+ // true on success
+ //
+ if (!r) {
+ AliError("Didn't get a ring object");
+ return kFALSE;
+ }
+ Char_t id = r->GetId();
+ Double_t siThick = r->GetSiThickness();
+ // const Int_t nv = r->GetNVerticies();
+ TVector2* a = r->GetVertex(5);
+ TVector2* b = r->GetVertex(3);
+ TVector2* c = r->GetVertex(4);
+ Double_t theta = r->GetTheta();
+ Double_t off = (TMath::Tan(TMath::Pi() * theta / 180)
+ * r->GetBondingWidth());
+ Double_t rmax = b->Mod();
+ Double_t rmin = r->GetLowR();
+ Double_t pcbThick = r->GetPrintboardThickness();
+ Double_t copperThick = r->GetCopperThickness(); // .01;
+ Double_t chipThick = r->GetChipThickness(); // .01;
+ Double_t modSpace = r->GetModuleSpacing();
+ Double_t legr = r->GetLegRadius();
+ Double_t legl = r->GetLegLength();
+ Double_t legoff = r->GetLegOffset();
+ Int_t ns = r->GetNStrips();
+ Int_t nsec = Int_t(360 / theta);
+ Double_t stripoff = a->Mod();
+ Double_t dstrip = (rmax - stripoff) / ns;
+ Double_t par[10];
+ TString name;
+ TString name2;
+ TVirtualMC* mc = TVirtualMC::GetMC();
+
+ Int_t siId = fFMD->GetIdtmed()->At(kSiId);
+ Int_t airId = fFMD->GetIdtmed()->At(kAirId);
+ Int_t pcbId = fFMD->GetIdtmed()->At(kPcbId);
+ Int_t plaId = fFMD->GetIdtmed()->At(kPlasticId);
+ Int_t copId = fFMD->GetIdtmed()->At(kCopperId);
+ Int_t chiId = fFMD->GetIdtmed()->At(kSiChipId);
+
+ Double_t ringWidth = (siThick + 2 * (pcbThick + copperThick + chipThick));
+ // Virtual volume shape to divide - This volume is only defined if
+ // the geometry is set to be detailed.
+ // Ring mother volume
+ par[0] = rmin;
+ par[1] = rmax;
+ par[2] = ringWidth / 2;
+ name = Form(fgkRingName, id);
+ mc->Gsvolu(name.Data(), "TUBE", airId, par, 3);
+
+ par[2] = siThick / 2;
+ name2 = name;
+ name = Form(fgkActiveName, id);
+ Double_t z = - ringWidth / 2 + siThick / 2;
+ mc->Gsvolu(name.Data(), "TUBE", (fDetailed ? airId : siId), par, 3);
+ mc->Gspos(name.Data(), 1, name2.Data(), 0, 0, z, 0);
+
+ Int_t sid = mc->VolId(name.Data());
+ if (fUseDivided) {
+ name2 = name;
+ name = Form(fgkSectorName, id);
+ mc->Gsdvn(name.Data(), name2.Data(), nsec, 2);
+
+ name2 = name;
+ name = Form(fgkStripName, id);
+ mc->Gsdvn(name.Data(), name2.Data(), ns, 1);
+ sid = mc->VolId(name.Data());
+ AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
+ }
+
+ switch (id) {
+ case 'i':
+ case 'I': fActiveId[0] = sid; break;
+ case 'o':
+ case 'O': fActiveId[2] = sid; break;
+ }
+
+ // Shape of Printed circuit Board
+ Double_t boardThick = (pcbThick + copperThick + chipThick);
+ par[0] = rmin - .1;
+ par[1] = rmax - .1;
+ par[2] = boardThick / 2;
+ name2 = Form(fgkRingName, id);
+ name = Form(fgkPCBName, id, 'B');
+ z += siThick / 2 + boardThick / 2;
+ mc->Gsvolu(name.Data(), "TUBE", pcbId, par, 3);
+ mc->Gspos(name.Data(), 1, name2.Data(), 0, 0, z, 0);
+ mc->Gspos(name.Data(), 2, name2.Data(), 0, 0, z + boardThick, 0);
+ mc->Gsatt(name.Data(), "seen", -2);
+ // PCB
+ par[2] = pcbThick / 2;
+ name2 = name;
+ name = Form("F%cPC", id);
+ z = -boardThick / 2 + pcbThick / 2;
+ mc->Gsvolu(name.Data(), "TUBE", pcbId, par, 3);
+ mc->Gspos(name.Data(), 1, name2.Data(), 0, 0, z, 0);
+ // Copper
+ par[2] = copperThick / 2;
+ name2 = name;
+ name = Form("F%cCO", id);
+ z += pcbThick / 2 + copperThick / 2;
+ mc->Gsvolu(name.Data(), "TUBE", copId, par, 3);
+ mc->Gspos(name.Data(), 1, name2.Data(), 0, 0, z, 0);
+ // Chip
+ par[2] = chipThick / 2;
+ name2 = name;
+ name = Form("F%cCH", id);
+ z = boardThick / 2 - chipThick / 2;
+ mc->Gsvolu(name.Data(), "TUBE", chiId, par, 3);
+ mc->Gspos(name.Data(), 1, name2.Data(), 0, 0, z, 0);
+
+ return kTRUE;
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
--- /dev/null
+#ifndef ALIFMDG3OLDSIMULATOR_H
+#define ALIFMDG3OLDSIMULATOR_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved.
+ *
+ * Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+ *
+ * See cxx source for full Copyright notice
+ */
+#ifndef ALIFMDG3SIMULATOR
+# include <AliFMDG3Simulator.h>
+#endif
+class AliFMD;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+//____________________________________________________________________
+class AliFMDG3OldSimulator : public AliFMDG3Simulator
+{
+public:
+ AliFMDG3OldSimulator();
+ /** CTOR */
+ AliFMDG3OldSimulator(AliFMD* fmd, Bool_t detailed=kTRUE);
+ virtual ~AliFMDG3OldSimulator() {}
+ virtual void UseDivided(Bool_t) { fUseDivided = kTRUE; }
+protected:
+ /** Make a ring volume
+ @param r Ring geometry
+ @return Ring volume */
+ Bool_t RingGeometry(AliFMDRing* r);
+ ClassDef(AliFMDG3OldSimulator,1);
+};
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+// mode: C++
+// End:
+//
+// EOF
+//
+
// | |
// +--------------------+ +-------------------+
// | AliFMDGeoSimulator | | AliFMDG3Simulator |
-// +--------------------+ +---------+---------+
-//
+// +--------------------+ +-------------------+
+// ^
+// |
+// +--------------------+
+// | AliFMDOldSimulator |
+// +--------------------+
//
// * AliFMD
// This defines the interface for the various parts of AliROOT that
// in the corners should be cut away at run time (but currently
// isn't).
//
+// * AliFMDOldSimulator
+// This is a concrete implementation of AliFMDSimulator. It
+// approximates the of the rings as segmented disks.
+//
#include <math.h>
#include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H
#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
Double_t legl = r->GetLegLength();
Double_t legoff = r->GetLegOffset();
Int_t ns = r->GetNStrips();
+ Double_t space = r->GetSpacing();
Double_t stripoff = a->Mod();
Double_t dstrip = (rmax - stripoff) / ns;
Double_t par[10];
TString name2;
TVirtualMC* mc = TVirtualMC::GetMC();
- Int_t siId = fFMD->GetIdtmed()->At(kSiId);
+ Int_t siId = fFMD->GetIdtmed()->At(kSiId);
Int_t airId = fFMD->GetIdtmed()->At(kAirId);
Int_t pcbId = fFMD->GetIdtmed()->At(kPcbId);
Int_t plaId = fFMD->GetIdtmed()->At(kPlasticId);
+ Int_t copId = fFMD->GetIdtmed()->At(kCopperId);
+ Int_t chiId = fFMD->GetIdtmed()->At(kSiChipId);
+
+ Double_t ringWidth = r->GetRingDepth();
+ Double_t x = 0;
+ Double_t y = 0;
+ Double_t z = 0;
+ Double_t backWidth = siThick + pcbThick + legl + space;
+ Double_t frontWidth = backWidth + modSpace;
- // Virtual volume shape to divide - This volume is only defined if
- // the geometry is set to be detailed.
// Ring mother volume
par[0] = rmin;
par[1] = rmax;
- par[2] = (siThick + pcbThick + legl + modSpace) / 2;
+ par[2] = ringWidth / 2;
name = Form(fgkRingName, id);
mc->Gsvolu(name.Data(), "TUBE", airId, par, 3);
+ // Back container volume
par[0] = rmin;
par[1] = rmax;
- par[2] = siThick / 2;
+ par[2] = backWidth / 2;
par[3] = -theta;
- par[4] = theta;
- name = Form(fgkActiveName, id);
- mc->Gsvolu(name.Data(), "TUBS", (fDetailed ? airId : siId), par, 5);
-
- Int_t sid = -1;
- if (fDetailed) {
- name2 = name;
- name = Form(fgkSectorName, id);
- mc->Gsdvn2(name.Data(), name2.Data(), 2, 2, -theta, airId);
+ par[4] = +theta;
+ TString backName(Form(fgkBackVName, id));
+ mc->Gsvolu(backName.Data(), "TUBS", airId, par, 5);
+
+ // Front container volume
+ par[2] = frontWidth / 2;
+ TString frontName(Form(fgkFrontVName, id));
+ mc->Gsvolu(frontName.Data(), "TUBS", airId, par, 5);
+
+ Double_t topL = (b->X() - c->X());
+ Double_t botL = (c->X() - a->X());
+ Int_t rot;
+ mc->Matrix(rot, 90, 90, 0, 90, 90, 0);
+
+ Double_t zFront = - frontWidth / 2 + siThick / 2;
+ Double_t zBack = - backWidth / 2 + siThick / 2;
+ if (fUseDivided) {
+ fSectorOff = 1;
+ fModuleOff = 3;
+ fRingOff = 4;
+ fDetectorOff = 5;
+
+ // Virtual volume shape to divide - This volume is only defined if
+ // the geometry is set to be detailed.
+ par[0] = rmin;
+ par[1] = rmax;
+ par[2] = siThick / 2;
+ par[3] = -theta;
+ par[4] = theta;
+ name = Form(fgkActiveName, id);
+ mc->Gsvolu(name.Data(), "TUBS", (fDetailed ? airId : siId), par, 5);
+
+ mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, 0, "ONLY");
+ mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, 0, "ONLY");
- name2 = name;
- name = Form(fgkStripName, id);
- mc->Gsdvt2(name.Data(), name2.Data(), dstrip, 1, stripoff, siId, ns);
- sid = mc->VolId(name.Data());
- AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
+ Int_t sid = -1;
+ if (fDetailed) {
+ // Divide the volume into sectors
+ name2 = name;
+ name = Form(fgkSectorName, id);
+ mc->Gsdvn2(name.Data(), name2.Data(), 2, 2, -theta, siId);
+
+ // Divide the volume into strips
+ name2 = name;
+ name = Form(fgkStripName, id);
+ mc->Gsdvt2(name.Data(), name2.Data(), dstrip, 1, stripoff, siId, ns);
+ sid = mc->VolId(name.Data());
+ AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
+ }
+
+ switch (id) {
+ case 'i': case 'I': fActiveId[0] = sid; break;
+ case 'o': case 'O': fActiveId[2] = sid; break;
+ }
}
+ else {
+ fSectorOff = -1;
+ fModuleOff = 1;
+ fRingOff = 2;
+ fDetectorOff = 3;
+
+ // Create top of module shape
+ par[0] = c->Y();
+ par[1] = b->Y();
+ par[2] = siThick / 2;
+ par[3] = topL / 2;
+ name = Form(fgkModuleName, id);
+ name[3] = 'T';
+ mc->Gsvolu(name.Data(), "TRD1", siId, par, 4);
+ Int_t tid = mc->VolId(name.Data());
+ x = rmin + botL + topL / 2;
+ mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
+ mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
+
+
+ // Create bottom of module shape
+ par[0] = a->Y();
+ par[1] = c->Y();
+ par[3] = botL / 2;
+ name = Form(fgkModuleName, id);
+ name[3] = 'B';
+ mc->Gsvolu(name.Data(), "TRD1", siId, par, 4);
+ Int_t bid = mc->VolId(name.Data());
+ x = rmin + botL / 2;
+ z = - backWidth / 2 + siThick / 2;
+ mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
+ mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
- switch (id) {
- case 'i':
- case 'I':
- fInnerId = sid;
- // fInnerV = moduleVolume->GetNumber();
- break;
- case 'o':
- case 'O':
- fOuterId = sid;
- // fOuterV = moduleVolume->GetNumber();
- break;
+ switch (id) {
+ case 'i': case 'I': fActiveId[0] = tid; fActiveId[1] = bid; break;
+ case 'o': case 'O': fActiveId[2] = tid; fActiveId[3] = bid; break;
+ }
}
-
+
+
// Shape of Printed circuit Board
// Top
- par[0] = c->Y() - off;
- par[1] = b->Y() - off;
- par[2] = pcbThick / 2;
- par[3] = (b->X() - c->X()) / 2;
- par[4] = off;
+ par[0] = c->Y() - off;
+ par[1] = b->Y() - off;
+ par[2] = pcbThick / 2;
+ par[3] = topL / 2;
+ x = rmin + botL + topL / 2;
+ zBack += siThick / 2 + space + pcbThick / 2;
+ zFront += siThick / 2 + space + pcbThick / 2;
name = Form(fgkPCBName, id, 'T');
mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4);
+ mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
+ mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
+
// Bottom
par[0] = a->Y() - off;
par[1] = c->Y() - off;
- par[3] = (c->X() - a->X()) / 2;
+ par[3] = botL / 2;
name = Form(fgkPCBName, id, 'B');
+ x = rmin + botL / 2;
mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4);
+ mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, rot, "ONLY");
+ mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, rot, "ONLY");
+ Double_t x1, y1;
// Short leg volume
- par[0] = legr - .1;
- par[1] = legr;
- par[2] = legl / 2;
+ par[0] = legr - .1;
+ par[1] = legr;
+ par[2] = legl / 2;
+ x = a->X() + legoff + legr;
+ x1 = c->X();
+ y1 = c->Y() - legoff - legr - off;
+ zBack += pcbThick / 2 + legl / 2;
+ zFront += pcbThick / 2 + legl / 2 + modSpace / 2;
name = Form(fgkShortLegName, id);
mc->Gsvolu(name.Data(), "TUBE", plaId, par, 3);
+ mc->Gspos(name.Data(), 0, backName.Data(), x, y, zBack, 0, "ONLY");
+ mc->Gspos(name.Data(), 1, backName.Data(), x1, y1, zBack, 0, "ONLY");
+ mc->Gspos(name.Data(), 2, backName.Data(), x1, -y1, zBack, 0, "ONLY");
// Long leg volume
par[2] += modSpace / 2;
name = Form(fgkLongLegName, id);
mc->Gsvolu(name.Data(), "TUBE", plaId, par, 3);
+ mc->Gspos(name.Data(), 0, frontName.Data(), x, y, zFront, 0, "ONLY");
+ mc->Gspos(name.Data(), 1, frontName.Data(), x1, y1, zFront, 0, "ONLY");
+ mc->Gspos(name.Data(), 2, frontName.Data(), x1, -y1, zFront, 0, "ONLY");
- // Back container volume
- par[0] = rmin;
- par[1] = rmax;
- par[2] = (siThick + pcbThick + legl) / 2;
- par[3] = -theta;
- par[4] = +theta;
- name = Form(fgkBackVName, id);
- mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
-
- Double_t x = 0;
- Double_t y = 0;
- Double_t z = - par[2] + siThick / 2;
- name2 = name;
- name = Form(fgkActiveName, id);
- mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY");
-
- Double_t pbTopL = (b->X() - c->X());
- Double_t pbBotL = (c->X() - a->X());
- Int_t pbRot;
- mc->Matrix(pbRot, 90, 90, 0, 90, 90, 0);
-
- x = rmin + pbBotL + pbTopL / 2;
- z += siThick / 2 + pcbThick / 2;
- name = Form(fgkPCBName, id, 'T');
- mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, pbRot, "ONLY");
-
- x = rmin + pbBotL / 2;
- name = Form(fgkPCBName, id, 'B');
- mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, pbRot, "ONLY");
-
- x = a->X() + legoff + legr;
- y = 0;
- z += pcbThick / 2 + legl / 2;
- name = Form(fgkShortLegName, id);
- mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY");
-
- x = c->X();
- y = c->Y() - legoff - legr - off;
- mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY");
-
- y = -y;
- mc->Gspos(name.Data(), 2, name2.Data(), x, y, z, 0, "ONLY");
-
-
- // Front container volume
- par[2] += modSpace / 2;
- name = Form(fgkFrontVName, id);
- mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
-
- x = 0;
- y = 0;
- z = - par[2] + siThick / 2;
- name2 = name;
- name = Form(fgkActiveName, id);
- mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY");
-
- pbTopL = (b->X() - c->X());
- pbBotL = (c->X() - a->X());
- x = rmin + pbBotL + pbTopL / 2;
- z += siThick / 2 + pcbThick / 2;
- name = Form(fgkPCBName, id, 'T');
- mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, pbRot, "ONLY");
-
- x = rmin + pbBotL / 2;
- name = Form(fgkPCBName, id, 'B');
- mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, pbRot, "ONLY");
-
- x = a->X() + legoff + legr;
- y = 0;
- z += pcbThick / 2 + legl / 2 + modSpace / 2;
- name = Form(fgkLongLegName, id);
- mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY");
-
- x = c->X();
- y = c->Y() - legoff - legr - off;
- mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY");
-
- y = -y;
- mc->Gspos(name.Data(), 2, name2.Data(), x, y, z, 0, "ONLY");
-
-
-
+ // Place modules+pcb+legs in ring volume
Int_t nmod = r->GetNModules();
name2 = Form(fgkRingName, id);
AliDebug(10, Form("making %d modules in ring %c", nmod, id));
for (Int_t i = 0; i < nmod; i++) {
Double_t th = (i + .5) * 2 * theta;
Bool_t isFront = (i % 2 == 0);
- name = (isFront ? Form(fgkFrontVName,id) :
- Form(fgkBackVName,id));
- Double_t z = (isFront ? 0 : modSpace) / 2;
- Int_t rot;
+ name = (isFront ? frontName : backName);
+ z = (isFront ? 0 : modSpace) / 2;
mc->Matrix(rot, 90, th, 90, fmod(90 + th, 360), 0, 0);
mc->Gspos(name.Data(), i, name2.Data(), 0, 0, z, rot, "ONLY");
}
-
+
return kTRUE;
}
/** Make a ring volume
@param r Ring geometry
@return Ring volume */
- Bool_t RingGeometry(AliFMDRing* r);
+ virtual Bool_t RingGeometry(AliFMDRing* r);
/** Make a detector volume
@param d Detector geometry
@param mother Mother volume (detector volume)
@param inner Inner ring volume
@param outer Outer ring volume
@return Detector volume */
- Bool_t DetectorGeometry(AliFMDDetector* d, Double_t zmother);
+ virtual Bool_t DetectorGeometry(AliFMDDetector* d, Double_t zmother);
/** Make FMD1 volume
@param d Detector geometry
@param inner Inner ring volume
@return FMD1 volume */
- Bool_t FMD1Geometry(AliFMD1* d);
+ virtual Bool_t FMD1Geometry(AliFMD1* d);
/** Make FMD2 volume
@param d Detector geometry
@param inner Inner ring volume
@param outer Outer ring volume
@return FMD2 volume */
- Bool_t FMD2Geometry(AliFMD2* d);
+ virtual Bool_t FMD2Geometry(AliFMD2* d);
/** Make FMD3 volume
@param d Detector geometry
@param inner Inner ring volume
@param outer Outer ring volume
@return FMD3 volume */
- Bool_t FMD3Geometry(AliFMD3* d);
+ virtual Bool_t FMD3Geometry(AliFMD3* d);
ClassDef(AliFMDG3Simulator,1);
};
--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/* $Id$ */
+
+//____________________________________________________________________
+//
+// Forward Multiplicity Detector based on Silicon wafers. This class
+// contains the base procedures for the Forward Multiplicity detector
+// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
+// which has 1 or 2 rings of silicon sensors.
+//
+// This is the base class for all FMD manager classes.
+//
+// The actual code is done by various separate classes. Below is
+// diagram showing the relationship between the various FMD classes
+// that handles the simulation
+//
+// +--------+ 1 +-----------------+
+// | AliFMD |<>-----| AliFMDSimulator |
+// +--------+ +-----------------+
+// ^
+// |
+// +-------------+-------------+
+// | |
+// +--------------------+ +-------------------+
+// | AliFMDGeoSimulator | | AliFMDG3Simulator |
+// +--------------------+ +-------------------+
+// ^
+// |
+// +----------------------+
+// | AliFMDG3OldSimulator |
+// +----------------------+
+//
+//
+// * AliFMD
+// This defines the interface for the various parts of AliROOT that
+// uses the FMD, like AliFMDSimulator, AliFMDDigitizer,
+// AliFMDReconstructor, and so on.
+//
+// * AliFMDSimulator
+// This is the base class for the FMD simulation tasks. The
+// simulator tasks are responsible to implment the geoemtry, and
+// process hits.
+//
+// * AliFMDGeoSimulator
+// This is a concrete implementation of the AliFMDSimulator that
+// uses the TGeo classes directly only. This defines the active
+// volume as an ONLY XTRU shape with a divided MANY TUBS shape
+// inside to implement the particular shape of the silicon
+// sensors.
+//
+// * AliFMDG3OldSimulator
+// This is a concrete implementation of the AliFMDSimulator that
+// uses the TVirtualMC interface with GEANT 3.21-like messages.
+// This implements the active volume as a divided TUBS shape. Hits
+// in the corners should be cut away at run time (but currently
+// isn't).
+//
+#include <math.h>
+#include "AliFMDGeoOldSimulator.h" // ALIFMDG3OLDSIMULATOR_H
+#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h" // ALIFMDDETECTOR_H
+#include "AliFMDRing.h" // ALIFMDRING_H
+#include "AliFMD1.h" // ALIFMD1_H
+#include "AliFMD2.h" // ALIFMD2_H
+#include "AliFMD3.h" // ALIFMD3_H
+#include "AliFMD.h" // ALIFMD_H
+#include <AliLog.h> // ALILOG_H
+#include <TVector2.h> // ROOT_TVector2
+#include <TVirtualMC.h> // ROOT_TVirtualMC
+#include <TArrayI.h> // ROOT_TArrayI
+#include <TGeoVolume.h> // ROOT_TGeoVolume
+#include <TGeoTube.h> // ROOT_TGeoTube
+#include <TGeoMatrix.h> // ROOT_TGeoMatrix
+
+//====================================================================
+ClassImp(AliFMDGeoOldSimulator)
+#if 0
+ ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDGeoOldSimulator::AliFMDGeoOldSimulator()
+{
+ // Default constructor
+ fSectorOff = 1;
+ fModuleOff = -1;
+ fRingOff = 3;
+ fDetectorOff = 4;
+ fUseDivided = kTRUE;
+}
+
+//____________________________________________________________________
+AliFMDGeoOldSimulator::AliFMDGeoOldSimulator(AliFMD* fmd, Bool_t detailed)
+ : AliFMDGeoSimulator(fmd, detailed)
+{
+ // Normal constructor
+ //
+ // Parameters:
+ //
+ // fmd Pointer to AliFMD object
+ // detailed Whether to make a detailed simulation or not
+ //
+ fSectorOff = 1;
+ fModuleOff = -1;
+ fRingOff = 3;
+ fDetectorOff = 4;
+ fUseDivided = kTRUE;
+}
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeoOldSimulator::RingGeometry(AliFMDRing* r)
+{
+ // Setup the geometry of a ring. The defined TGeoVolume is
+ // returned, and should be used when setting up the rest of the
+ // volumes.
+ //
+ // Parameters:
+ //
+ // r Pointer to ring geometry object
+ //
+ // Returns:
+ // true on success
+ //
+ if (!r) {
+ AliError("Didn't get a ring object");
+ return kFALSE;
+ }
+ Char_t id = r->GetId();
+ Double_t siThick = r->GetSiThickness();
+ // const Int_t nv = r->GetNVerticies();
+ TVector2* a = r->GetVertex(5);
+ TVector2* b = r->GetVertex(3);
+ TVector2* c = r->GetVertex(4);
+ Double_t theta = r->GetTheta();
+ Double_t off = (TMath::Tan(TMath::Pi() * theta / 180)
+ * r->GetBondingWidth());
+ Double_t rmax = b->Mod();
+ Double_t rmin = r->GetLowR();
+ Double_t pcbThick = r->GetPrintboardThickness();
+ Double_t copperThick = r->GetCopperThickness(); // .01;
+ Double_t chipThick = r->GetChipThickness(); // .01;
+ Double_t modSpace = r->GetModuleSpacing();
+ Double_t legr = r->GetLegRadius();
+ Double_t legl = r->GetLegLength();
+ Double_t legoff = r->GetLegOffset();
+ Int_t ns = r->GetNStrips();
+ Int_t nsec = Int_t(360 / theta);
+ Double_t stripoff = a->Mod();
+ Double_t dstrip = (rmax - stripoff) / ns;
+ Double_t par[10];
+ TString name;
+ TString name2;
+ TVirtualMC* mc = TVirtualMC::GetMC();
+
+ Int_t siId = fFMD->GetIdtmed()->At(kSiId);
+ Int_t airId = fFMD->GetIdtmed()->At(kAirId);
+ Int_t pcbId = fFMD->GetIdtmed()->At(kPcbId);
+ Int_t plaId = fFMD->GetIdtmed()->At(kPlasticId);
+ Int_t copId = fFMD->GetIdtmed()->At(kCopperId);
+ Int_t chiId = fFMD->GetIdtmed()->At(kSiChipId);
+
+ Double_t ringWidth = (siThick + 2 * (pcbThick + copperThick + chipThick));
+ // Virtual volume shape to divide - This volume is only defined if
+ // the geometry is set to be detailed.
+ // Ring mother volume
+ TGeoShape* ringShape = new TGeoTube(rmin, rmax, ringWidth / 2);
+ name = Form(fgkRingName, id);
+ TGeoVolume* ringVolume = new TGeoVolume(name.Data(), ringShape, fAir);
+
+ TGeoShape* activeShape = new TGeoTube(rmin, rmax, siThick / 2);
+ name = Form(fgkActiveName, id);
+ Double_t z = - ringWidth / 2 + siThick / 2;
+ TGeoVolume* activeVolume = new TGeoVolume(name.Data(), activeShape, fSi);
+ ringVolume->AddNode(activeVolume, 1, new TGeoTranslation(0, 0, z));
+
+ Int_t sid = activeVolume->GetNumber();
+ if (fUseDivided) {
+ name = Form(fgkSectorName, id);
+ TGeoVolume* sectorVolume = activeVolume->Divide(name.Data(), 2, nsec,
+ 0, 0, 0, "N");
+
+ name = Form(fgkStripName, id);
+ TGeoVolume* stripVolume = sectorVolume->Divide(name.Data(), 1, ns,
+ 0, 0, 0, "N");
+ sid = stripVolume->GetNumber();
+ AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
+ }
+ switch (id) {
+ case 'i':
+ case 'I': fActiveId[0] = sid; break;
+ case 'o':
+ case 'O': fActiveId[2] = sid; break;
+ }
+
+ // Shape of Printed circuit Board
+ Double_t boardThick = (pcbThick + copperThick + chipThick);
+ TGeoShape* boardShape = new TGeoTube(rmin + .1, rmax - .1, boardThick/ 2);
+ name = Form(fgkPCBName, id, 'B');
+ TGeoVolume* boardVolume = new TGeoVolume(name.Data(), boardShape, fAir);
+ z += siThick / 2 + boardThick / 2;
+ ringVolume->AddNode(boardVolume, 0, new TGeoTranslation(0, 0, z));
+ ringVolume->AddNode(boardVolume, 1, new TGeoTranslation(0,0,z+boardThick));
+
+ // PCB
+ TGeoShape* pcbShape = new TGeoTube(rmin+.1, rmax-.1, pcbThick / 2);
+ name = Form("F%cPC", id);
+ z = -boardThick / 2 + pcbThick / 2;
+ TGeoVolume* pcbVolume = new TGeoVolume(name.Data(), pcbShape, fPCB);
+ boardVolume->AddNode(pcbVolume, 0, new TGeoTranslation(0, 0, z));
+
+ // Copper
+ TGeoShape* cuShape = new TGeoTube(rmin+.1, rmax-.1, copperThick / 2);
+ name = Form("F%cCO", id);
+ z += -pcbThick / 2 + copperThick / 2;
+ TGeoVolume* cuVolume = new TGeoVolume(name.Data(), cuShape, fCopper);
+ boardVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
+
+ // Chip
+ TGeoShape* chipShape = new TGeoTube(rmin+.1, rmax-.1, chipThick / 2);
+ name = Form("F%cCH", id);
+ z = -copperThick / 2 + chipThick / 2;
+ TGeoVolume* chipVolume = new TGeoVolume(name.Data(), chipShape, fChip);
+ boardVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
+
+ return ringVolume;
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
--- /dev/null
+#ifndef ALIFMDGEOOLDSIMULATOR_H
+#define ALIFMDGEOOLDSIMULATOR_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved.
+ *
+ * Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+ *
+ * See cxx source for full Copyright notice
+ */
+#ifndef ALIFMDGEOSIMULATOR
+# include <AliFMDGeoSimulator.h>
+#endif
+class AliFMD;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+//____________________________________________________________________
+class AliFMDGeoOldSimulator : public AliFMDGeoSimulator
+{
+public:
+ AliFMDGeoOldSimulator();
+ /** CTOR */
+ AliFMDGeoOldSimulator(AliFMD* fmd, Bool_t detailed=kTRUE);
+ virtual ~AliFMDGeoOldSimulator() {}
+ virtual void UseDivided(Bool_t) { fUseDivided = kTRUE; }
+protected:
+ /** Make a ring volume
+ @param r Ring geometry
+ @return Ring volume */
+ TGeoVolume* RingGeometry(AliFMDRing* r);
+ ClassDef(AliFMDGeoOldSimulator,1);
+};
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+// mode: C++
+// End:
+//
+// EOF
+//
+
// +--------------------+ +-------------------+
// | AliFMDGeoSimulator | | AliFMDG3Simulator |
// +--------------------+ +---------+---------+
+// ^
+// |
+// +--------------------+
+// | AliFMDOldSimulator |
+// +--------------------+
//
-//
// * AliFMD
// This defines the interface for the various parts of AliROOT that
// uses the FMD, like AliFMDSimulator, AliFMDDigitizer,
// in the corners should be cut away at run time (but currently
// isn't).
//
+// * AliFMDOldSimulator
+// This is a concrete implementation of AliFMDSimulator. It
+// approximates the of the rings as segmented disks.
+//
#include "AliFMDGeoSimulator.h" // ALIFMDGEOSIMULATOR_H
#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
#include "AliFMDDetector.h" // ALIFMDDETECTOR_H
fSi = gGeoManager->GetMedium("FMD_Si$");
fC = gGeoManager->GetMedium("FMD_Carbon$");
fAl = gGeoManager->GetMedium("FMD_Aluminum$");
- fChip = gGeoManager->GetMedium("FMD_Chip$");
+ fChip = gGeoManager->GetMedium("FMD_Si Chip$");
fAir = gGeoManager->GetMedium("FMD_Air$");
fPCB = gGeoManager->GetMedium("FMD_PCB$");
fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
+ fCopper = gGeoManager->GetMedium("FMD_Copper$");
}
//____________________________________________________________________
Int_t ns = r->GetNStrips();
Double_t stripoff = a->Mod();
Double_t dstrip = (rmax - stripoff) / ns;
+ Double_t space = r->GetSpacing();
TArrayD xs(nv);
TArrayD ys(nv);
for (Int_t i = 0; i < nv; i++) {
ys[i] = vv->Y();
}
- // Virtual volume shape to divide - This volume is only defined if
- // the geometry is set to be detailed.
- Int_t sid = -1;
- TGeoVolume* activeVolume = 0;
- if (fDetailed) {
- TGeoTubeSeg* activeShape =
- new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta);
- activeVolume = new TGeoVolume(Form(fgkActiveName, id), activeShape, fSi);
- TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName, id),
- 2, 2, -theta, 0, 0, "N");
- TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id), 1,
- ns, stripoff, dstrip,
- 0, "SX");
- sid = stripVolume->GetNumber();
- }
-
// Shape of actual sensor
TGeoXtru* moduleShape = new TGeoXtru(2);
moduleShape->DefinePolygon(nv, xs.fArray, ys.fArray);
moduleShape->DefineSection(1, siThick/2);
TGeoVolume* moduleVolume = new TGeoVolume(Form(fgkModuleName, id),
moduleShape, fSi);
- // Add divived MANY volume to the true shape of the module, but only
- // if a detailed simulation is reguested.
- if (activeVolume) moduleVolume->AddNodeOverlap(activeVolume, 0);
+ Int_t sid = moduleVolume->GetNumber();
+ fSectorOff = -1;
+ fModuleOff = 1;
+ fRingOff = 2;
+ fDetectorOff = 3;
+ if (fUseDivided) {
+ fSectorOff = 1;
+ fModuleOff = 4;
+ fRingOff = 5;
+ fDetectorOff = 6;
+ // Virtual volume shape to divide - This volume is only defined if
+ // the geometry is set to be detailed.
+ TGeoVolume* activeVolume = 0;
+ if (fDetailed) {
+ TGeoTubeSeg* activeShape =
+ new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta);
+ activeVolume = new TGeoVolume(Form(fgkActiveName, id), activeShape, fSi);
+ TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName, id),
+ 2, 2, -theta, 0, 0, "N");
+ TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id),
+ 1, ns, stripoff, dstrip,
+ 0, "SX");
+ sid = stripVolume->GetNumber();
+ }
+ // Add divived MANY volume to the true shape of the module, but only
+ // if a detailed simulation is reguested.
+ if (activeVolume) moduleVolume->AddNodeOverlap(activeVolume, 0);
+ }
switch (id) {
case 'i':
- case 'I':
- fInnerId = sid;
- // fInnerV = moduleVolume->GetNumber();
- break;
+ case 'I': fActiveId[0] = sid; break;
case 'o':
- case 'O':
- fOuterId = sid;
- // fOuterV = moduleVolume->GetNumber();
- break;
+ case 'O': fActiveId[2] = sid; break;
}
// Shape of Printed circuit Board
pcbShape, fPCB);
// Short leg shape
- TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2);
+ TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2);
TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id),
shortLegShape, fPlastic);
// Long leg shape
- TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2);
+ TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2);
TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id),
longLegShape, fPlastic);
TGeoMatrix* matrix = 0;
// Back container volume
- Double_t contThick = siThick + pcbThick + legl;
+ Double_t contThick = siThick + pcbThick + legl;
TGeoTubeSeg* backShape = new TGeoTubeSeg(rmin, rmax, contThick/2,
- theta, theta);
TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackVName, id),
matrix = new TGeoTranslation(Form("FMD Ring %c mod 1 transform", id),
x, y, z);
backVolume->AddNode(moduleVolume, 0, matrix);
- z += siThick / 2 + pcbThick / 2;
+ z += siThick / 2 + space + pcbThick / 2;
matrix = new TGeoTranslation(Form("FMD Ring %c pcb 1 transfrom", id),
x, y, z);
backVolume->AddNode(pcbVolume, 0, matrix);
matrix = new TGeoTranslation(Form("FMD Ring %c mod 2 transfrom", id),
0, 0, z);
frontVolume->AddNode(moduleVolume, 1, matrix);
- z += siThick / 2 + pcbThick / 2;
+ z += siThick / 2 + space + pcbThick / 2;
matrix = new TGeoTranslation(Form("FMD Ring %c pcb 2 transfrom", id),
x, y, z);
frontVolume->AddNode(pcbVolume, 1, matrix);
Double_t hcThick = fmd1->GetHoneycombThickness();
Double_t w = fmd1->GetInner()->GetRingDepth() + hcThick;
Double_t z = fmd1->GetInnerZ() + w / 2;
-
- TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2);
- TGeoVolume* fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir);
+
+ TGeoVolume* fmd1Volume = 0;
+ if (!fUseAssembly) {
+ TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2);
+ fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir);
+ }
+ else
+ fmd1Volume = new TGeoVolumeAssembly(fmd1->GetName());
TGeoVolume* top = gGeoManager->GetVolume("ALIC");
TGeoMatrix* matrix = new TGeoTranslation("FMD1 transform", 0, 0, z);
Double_t w = TMath::Abs(oz - iz) + ow + hcThick;
Double_t z = oz + w / 2;
- TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2);
- TGeoVolume* fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir);
+ TGeoVolume* fmd2Volume = 0;
+ if (!fUseAssembly) {
+ TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2);
+ fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir);
+ }
+ else
+ fmd2Volume = new TGeoVolumeAssembly(fmd2->GetName());
TGeoVolume* top = gGeoManager->GetVolume("ALIC");
TGeoMatrix* matrix = new TGeoTranslation("FMD2 transform", 0, 0, z);
Double_t zi;
// FMD3 volume
- TGeoPcon* fmd3Shape = new TGeoPcon(0, 360, 8);
- zi = z - nz;
- fmd3Shape->DefineSection(0, zi, noser1, noser2);
- zi = z - (nz - nlen);
- fmd3Shape->DefineSection(1, zi, noser1, fmd3->ConeR(z - zi)+.15);
- zi = z - innerZ;
- fmd3Shape->DefineSection(2, zi, innerr1, fmd3->ConeR(z - zi)+.15);
- zi = z - innerZh;
- fmd3Shape->DefineSection(3, zi, innerr1, fmd3->ConeR(z - zi)+.15);
- fmd3Shape->DefineSection(4, zi, outerr1, fmd3->ConeR(z - zi)+.15);
- zi = z - nz + zdist + nlen;
- fmd3Shape->DefineSection(5, zi, outerr1, fmd3->ConeR(z - zi)+.15);
- zi = z - nz + nlen + zdist;
- fmd3Shape->DefineSection(6, zi, outerr1, flanger+1.5);
- zi = z - minZ;
- fmd3Shape->DefineSection(7, zi, outerr1, flanger+1.5);
- TGeoVolume* fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir);
+ TGeoVolume* fmd3Volume = 0;
+ if (!fUseAssembly) {
+ TGeoPcon* fmd3Shape = new TGeoPcon(0, 360, 8);
+ zi = z - nz;
+ fmd3Shape->DefineSection(0, zi, noser1, noser2);
+ zi = z - (nz - nlen);
+ fmd3Shape->DefineSection(1, zi, noser1, fmd3->ConeR(z - zi)+.15);
+ zi = z - innerZ;
+ fmd3Shape->DefineSection(2, zi, innerr1, fmd3->ConeR(z - zi)+.15);
+ zi = z - innerZh;
+ fmd3Shape->DefineSection(3, zi, innerr1, fmd3->ConeR(z - zi)+.15);
+ fmd3Shape->DefineSection(4, zi, outerr1, fmd3->ConeR(z - zi)+.15);
+ zi = z - nz + zdist + nlen;
+ fmd3Shape->DefineSection(5, zi, outerr1, fmd3->ConeR(z - zi)+.15);
+ zi = z - nz + nlen + zdist;
+ fmd3Shape->DefineSection(6, zi, outerr1, flanger+1.5);
+ zi = z - minZ;
+ fmd3Shape->DefineSection(7, zi, outerr1, flanger+1.5);
+ fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir);
+ }
+ else
+ fmd3Volume = new TGeoVolumeAssembly(fmd3->GetName());
TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
rot->RotateY(180);
TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
zi = z - nz + nlen / 2;
TGeoMatrix* nmatrix = new TGeoTranslation("FMD3 Nose translation", 0, 0, zi);
- fmd3Volume->AddNodeOverlap(noseVolume, 0, nmatrix);
+ // fmd3Volume->AddNodeOverlap(noseVolume, 0, nmatrix);
+ fmd3Volume->AddNode(noseVolume, 0, nmatrix);
// Back
TGeoTube* backShape = new TGeoTube(backr1, backr2, backl / 2);
rot->RotateZ(phi);
TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 flange transform %d",
i), x, y, zi, rot);
- fmd3Volume->AddNodeOverlap(flangeVolume, i, matrix);
+ // fmd3Volume->AddNodeOverlap(flangeVolume, i, matrix);
+ fmd3Volume->AddNode(flangeVolume, i, matrix);
}
// The Beams
TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2,
- fmd3->GetBeamWidth() / 2,
+ fmd3->GetBeamWidth() / 2 - .1,
beaml / 2);
TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
n = fmd3->GetNBeam();
Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi);
Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi);
TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
- rot->RotateZ(phi);
+ // Order is important
rot->RotateY(-theta);
+ rot->RotateZ(phi);
TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam transform %d", i),
x, y, zi, rot);
fmd3Volume->AddNode(beamVolume, i, matrix);
/** Make a ring volume
@param r Ring geometry
@return Ring volume */
- TGeoVolume* RingGeometry(AliFMDRing* r);
+ virtual TGeoVolume* RingGeometry(AliFMDRing* r);
/** Make a detector volume
@param d Detector geometry
@param mother Mother volume (detector volume)
@param inner Inner ring volume
@param outer Outer ring volume
@return Detector volume */
- TGeoVolume* DetectorGeometry(AliFMDDetector* d,
- TGeoVolume* mother,
- Double_t zmother,
- TGeoVolume* inner,
- TGeoVolume* outer=0);
+ virtual TGeoVolume* DetectorGeometry(AliFMDDetector* d,
+ TGeoVolume* mother,
+ Double_t zmother,
+ TGeoVolume* inner,
+ TGeoVolume* outer=0);
/** Make FMD1 volume
@param d Detector geometry
@param inner Inner ring volume
@return FMD1 volume */
- TGeoVolume* FMD1Geometry(AliFMD1* d, TGeoVolume* inner);
+ virtual TGeoVolume* FMD1Geometry(AliFMD1* d, TGeoVolume* inner);
/** Make FMD2 volume
@param d Detector geometry
@param inner Inner ring volume
@param outer Outer ring volume
@return FMD2 volume */
- TGeoVolume* FMD2Geometry(AliFMD2* d, TGeoVolume* inner,
+ virtual TGeoVolume* FMD2Geometry(AliFMD2* d, TGeoVolume* inner,
TGeoVolume* outer);
/** Make FMD3 volume
@param d Detector geometry
@param inner Inner ring volume
@param outer Outer ring volume
@return FMD3 volume */
- TGeoVolume* FMD3Geometry(AliFMD3* d, TGeoVolume* inner,
+ virtual TGeoVolume* FMD3Geometry(AliFMD3* d, TGeoVolume* inner,
TGeoVolume* outer);
TGeoMedium* fSi; //! Si Medium
TGeoMedium* fC; //! C Medium
TGeoMedium* fChip; //! Chip Medium
TGeoMedium* fAir; //! Air Medium
TGeoMedium* fPlastic; //! Plastic Medium
+ TGeoMedium* fCopper; //! Copper Medium
ClassDef(AliFMDGeoSimulator,1)
};
SetLegOffset();
SetModuleSpacing();
SetPrintboardThickness();
+ SetCopperThickness();
+ SetChipThickness();
if (fId == 'I' || fId == 'i') {
SetLowR(4.3);
fVerticies.AddAt(new TVector2(fLowR, yA), 5);
fRingDepth = (fSiThickness + fPrintboardThickness
- + fLegLength + fModuleSpacing);
+ + fCopperThickness + fChipThickness
+ + fLegLength + fModuleSpacing + fSpacing);
}
//____________________________________________________________________
void SetModuleSpacing(Double_t x=1) { fModuleSpacing = x; }
/** @param x Value of Thickness of print board */
void SetPrintboardThickness(Double_t x=.1) { fPrintboardThickness = x; }
-
+ /** @param x Value of Thickness of copper on print board */
+ void SetCopperThickness(Double_t x=.01) { fCopperThickness = x; }
+ /** @param x Value of Thickness of chip on print board */
+ void SetChipThickness(Double_t x=.01) { fChipThickness = x; }
+ /** @param x Value of spacing between si and PCB */
+ void SetSpacing(Double_t x=.05) { fSpacing = x; }
+
/** @return The Id of this ring type */
Char_t GetId() const { return fId; }
/** @return With of bonding pad on sensor */
Double_t GetModuleSpacing() const { return fModuleSpacing; }
/** @return Thickness of print board */
Double_t GetPrintboardThickness() const { return fPrintboardThickness; }
+ /** @return Thickness copper of print board */
+ Double_t GetCopperThickness() const { return fCopperThickness; }
+ /** @return Thickness chip of print board */
+ Double_t GetChipThickness() const { return fChipThickness; }
+ /** @return Value of spacing between si and PCB */
+ Double_t GetSpacing() const { return fSpacing; }
+
/** @return List of verticies */
const TObjArray& GetVerticies() const { return fVerticies; }
/** @return Number of verticies */
Double_t fLegOffset; // Radius of support legs
Double_t fModuleSpacing; // Staggering offset
Double_t fPrintboardThickness; // Thickness of print board
+ Double_t fCopperThickness; // Thickness of Cu on print board
+ Double_t fChipThickness; // Thickness of chip on print board
+ Double_t fSpacing; // Spacing between si and PCB
+
TObjArray fVerticies; // List of verticies
ClassDef(AliFMDRing, 0);
// | |
// +--------------------+ +-------------------+
// | AliFMDGeoSimulator | | AliFMDG3Simulator |
-// +--------------------+ +---------+---------+
+// +--------------------+ +-------------------+
+// ^
+// |
+// +----------------------+
+// | AliFMDG3OldSimulator |
+// +----------------------+
//
-//
// * AliFMD
// This defines the interface for the various parts of AliROOT that
// uses the FMD, like AliFMDSimulator, AliFMDDigitizer,
// in the corners should be cut away at run time (but currently
// isn't).
//
+// * AliFMDG3OldSimulator
+// This is a concrete implementation of AliFMDSimulator. It
+// approximates the of the rings as segmented disks.
+//
#include "AliFMDSimulator.h" // ALIFMDSIMULATOR_H
#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
#include "AliFMDDetector.h" // ALIFMDDETECTOR_H
: fFMD(0),
fDetailed(kFALSE),
fInnerId(-1),
- fOuterId(-1)
+ fOuterId(-1),
+ fActiveId(4),
+ fUseDivided(kFALSE),
+ fUseAssembly(kTRUE)
{
// Default constructor
}
//____________________________________________________________________
AliFMDSimulator::AliFMDSimulator(AliFMD* fmd, Bool_t detailed)
- : TTask("FMDsimulator", "Forward Multiplicity Detector Simulator"),
+ : TTask("FMDSimulator", "Forward Multiplicity Detector Simulator"),
fFMD(fmd),
fDetailed(detailed),
fInnerId(-1),
- fOuterId(-1)
+ fOuterId(-1),
+ fActiveId(4),
+ fUseDivided(kFALSE),
+ fUseAssembly(kTRUE)
{
// Normal constructor
//
maxStepSize, maxEnergyLoss, precision, minStepSize);
+ // Copper
+ a = 63.546;
+ z = 29;
+ density = 8.96;
+ radiationLength = 1.43;
+ id = kCopperId;
+ fFMD->AliMaterial(id, "Copper$",
+ a, z, density, radiationLength, absorbtionLength);
+ fFMD->AliMedium(kCopperId, "Copper$",
+ id, 0, fieldType, maxField, maxBending,
+ maxStepSize, maxEnergyLoss, precision, minStepSize);
+
+
// Silicon chip
{
Float_t as[] = { 12.0107, 14.0067, 15.9994,
- 1.00794, 28.0855, 107.8682 };
+ 1.00794, 28.0855, 107.8682 };
Float_t zs[] = { 6., 7., 8.,
1., 14., 47. };
Float_t ws[] = { 0.039730642, 0.001396798, 0.01169634,
0.004367771, 0.844665, 0.09814344903 };
- density = 2.36436;
+ density = 2.36436;
maxBending = 10;
maxStepSize = .01;
precision = .003;
minStepSize = .003;
- id = kSiChipId;
+ id = kSiChipId;
fFMD->AliMixture(id, "Si Chip$", as, zs, density, 6, ws);
fFMD->AliMedium(kSiChipId, "Si Chip$",
id, 0, fieldType, maxField, maxBending,
maxStepSize, maxEnergyLoss, precision, minStepSize);
}
-#if 0
// Kaption
{
Float_t as[] = { 1.00794, 12.0107, 14.010, 15.9994};
maxStepSize = .001;
precision = .001;
minStepSize = .001;
- id = KaptionId;
+ id = kKaptonId;
fFMD->AliMixture(id, "Kaption$", as, zs, density, 4, ws);
- fFMD->AliMedium(kAlId, "Kaption$",
+ fFMD->AliMedium(kKaptonId, "Kaption$",
id,0,fieldType,maxField,maxBending,
maxStepSize,maxEnergyLoss,precision,minStepSize);
}
-#endif
// Air
{
}
}
+//____________________________________________________________________
+Bool_t
+AliFMDSimulator::IsActive(Int_t volId) const
+{
+ for (Int_t i = 0; i < fActiveId.fN; i++)
+ if (volId == fActiveId[i]) return kTRUE;
+ return kFALSE;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDSimulator::VMC2FMD(TLorentzVector& v, UShort_t& detector,
+ Char_t& ring, UShort_t& sector, UShort_t& strip)
+{
+ TVirtualMC* mc = TVirtualMC::GetMC();
+
+ // Get track position
+ mc->TrackPosition(v);
+ Int_t moduleno; mc->CurrentVolOffID(fModuleOff, moduleno);
+ Int_t iring; mc->CurrentVolOffID(fRingOff, iring); ring = Char_t(iring);
+ Int_t det; mc->CurrentVolOffID(fDetectorOff, det); detector = det;
+
+
+ // Get the ring geometry
+ AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+ //Int_t nsec = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors();
+ Int_t nstr = fmd->GetDetector(detector)->GetRing(ring)->GetNStrips();
+ Double_t lowr = fmd->GetDetector(detector)->GetRing(ring)->GetLowR();
+ Double_t highr= fmd->GetDetector(detector)->GetRing(ring)->GetHighR();
+ Double_t theta= fmd->GetDetector(detector)->GetRing(ring)->GetTheta();
+
+ // Figure out the strip number
+ Double_t r = TMath::Sqrt(v.X() * v.X() + v.Y() * v.Y());
+ Double_t pitch = (highr - lowr) / nstr;
+ Int_t str = Int_t((r - lowr) / pitch);
+ if (str < 0 || str >= nstr) return kFALSE;
+ strip = str;
+
+ // Figure out the sector number
+ Double_t phi = TMath::ATan2(v.Y(), v.X()) * 180. / TMath::Pi();
+ if (phi < 0) phi = 360. + phi;
+ Double_t t = phi - 2 * moduleno * theta;
+ sector = 2 * moduleno;
+ if (t < 0 || t > 2 * theta) return kFALSE;
+ else if (t > theta) sector += 1;
+
+ AliDebug(40, Form("<1> Inside an active FMD volume FMD%d%c[%2d,%3d] %s",
+ detector, ring, sector, strip, mc->CurrentVolPath()));
+ return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDSimulator::VMC2FMD(Int_t copy, TLorentzVector& v,
+ UShort_t& detector, Char_t& ring,
+ UShort_t& sector, UShort_t& strip)
+{
+ TVirtualMC* mc = TVirtualMC::GetMC();
+
+ strip = copy - 1;
+ Int_t sectordiv; mc->CurrentVolOffID(fSectorOff, sectordiv);
+ if (fModuleOff >= 0) {
+ Int_t module; mc->CurrentVolOffID(fModuleOff, module);
+ sector = 2 * module + sectordiv;
+ }
+ else
+ sector = sectordiv;
+ Int_t iring; mc->CurrentVolOffID(fRingOff, iring); ring = Char_t(iring);
+ Int_t det; mc->CurrentVolOffID(fDetectorOff, det); detector = det;
+
+ AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+ Double_t rz = fmd->GetDetector(detector)->GetRingZ(ring);
+ Int_t n = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors();
+#if 0
+ if (rz < 0) {
+ Int_t s = ((n - sector + n / 2) % n) + 1;
+ AliDebug(1, Form("Recalculating sector to %d (=%d-%d+%d/2%%%d+1 z=%f)",
+ s, n, sector, n, n, rz));
+ sector = s;
+ }
+#endif
+ if (sector < 1 || sector > n) {
+ Warning("Step", "sector # %d out of range (0-%d)", sector-1, n-1);
+ return kFALSE;
+ }
+ sector--;
+ // Get track position
+ mc->TrackPosition(v);
+ AliDebug(40, Form("<2> Inside an active FMD volume FMD%d%c[%2d,%3d] %s",
+ detector, ring, sector, strip, mc->CurrentVolPath()));
+
+ return kTRUE;
+}
+
//____________________________________________________________________
void
AliFMDSimulator::Exec(Option_t* /* option */)
// - ENDIF
//
TVirtualMC* mc = TVirtualMC::GetMC();
- static int nCall = 0;
-
if (!mc->IsTrackAlive()) return;
- if (TMath::Abs(mc->TrackCharge()) <= 0) return;
+ Double_t absQ = TMath::Abs(mc->TrackCharge());
+ if (absQ <= 0) return;
Int_t copy;
Int_t vol = mc->CurrentVolID(copy);
- if (vol != fInnerId && vol != fOuterId) {
- AliDebug(25, Form("Not an FMD volume %d '%s' (%d or %d)",
+ if (!IsActive(vol)) {
+ AliDebug(50, Form("Not an FMD volume %d '%s' (%d or %d)",
vol, mc->CurrentVolName(), fInnerId, fOuterId));
return;
}
-
- nCall++;
- // Check that the track is actually within the active area
- Bool_t entering = mc->IsTrackEntering();
- Bool_t inside = mc->IsTrackInside();
- Bool_t out = (mc->IsTrackExiting()|| mc->IsTrackDisappeared()||
- mc->IsTrackStop());
- static Int_t lastPdg = 0;
- static Double_t lastEtot = 0;
- static Int_t lastTrack = 0;
- static Int_t nBad = 0;
+ TLorentzVector v;
+ UShort_t detector;
+ Char_t ring;
+ UShort_t sector;
+ UShort_t strip;
- // Reset the energy deposition for this track, and update some of
- // our parameters.
- if (entering) {
- AliDebug(15, Form("Track # %8d entering active FMD volume %s: "
- "Edep=%f (call # %d)",
- gAlice->GetMCApp()->GetCurrentTrackNumber(),
- mc->CurrentVolPath(), 1000 * mc->Edep(), nCall));
- fCurrentDeltaE = 0;
-
- // Get production vertex and momentum of the track
- mc->TrackMomentum(fCurrentP);
- mc->TrackPosition(fCurrentV);
- fCurrentPdg = mc->IdFromPDG(mc->TrackPid());
+ if (fUseDivided) {
+ if (!VMC2FMD(copy, v, detector, ring, sector, strip)) return;
+ } else {
+ if (!VMC2FMD(v, detector, ring, sector, strip)) return;
}
-
- if (mc->Edep() > mc->Etot()/*fCurrentP.E()*/) {
- // The track deposited an obscene amount of energy in this step
- Int_t trackno = gAlice->GetMCApp()->GetCurrentTrackNumber();
- // TMCProcess process = mc->ProdProcess(trackno);
- // TString process_name(TMCProcessName[process]);
+ TLorentzVector p;
+ mc->TrackMomentum(p);
+ Int_t trackno = gAlice->GetMCApp()->GetCurrentTrackNumber();
+ Int_t pdg = mc->TrackPid();
+ Double_t mass = mc->TrackMass();
+ Double_t edep = mc->Edep() * 1000; // keV
+ Double_t poverm = (mass == 0 ? 0 : p.P() / mass);
+
+ // This `if' is to debug abnormal energy depositions. We trigger on
+ // p/m approx larger than or equal to a MIP, and a large edep - more
+ // than 1 keV - a MIP is 100 eV.
+ if (mc->Edep() * 1000 > absQ * absQ && poverm > 1) {
TArrayI procs;
mc->StepProcesses(procs);
- Int_t currentPdg = mc->TrackPid();
TString processes;
for (Int_t ip = 0; ip < procs.fN; ip++) {
if (ip != 0) processes.Append(",");
processes.Append(TMCProcessName[procs.fArray[ip]]);
}
- // Int_t currentPdg = mc->IdFromPDG(mc->TrackPid());
- TParticlePDG* particleType = TDatabasePDG::Instance()->GetParticle(currentPdg);
- TParticlePDG* lastType = TDatabasePDG::Instance()->GetParticle(lastPdg);
- TLorentzVector currentV; //! Current hit postition
- TLorentzVector currentP; //! Current hit momentum
- mc->TrackMomentum(currentP);
- mc->TrackPosition(currentV);
- TString origin("???");
- if (mc->IsRootGeometrySupported()) {
- TGeoNode* node = gGeoManager->FindNode(fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z());
- if (node) origin = node->GetName();
- }
+ TDatabasePDG* pdgDB = TDatabasePDG::Instance();
+ TParticlePDG* particleType = pdgDB->GetParticle(pdg);
+ TString pname(particleType ? particleType->GetName() : "???");
TString what;
if (mc->IsTrackEntering()) what.Append("entering ");
if (mc->IsTrackExiting()) what.Append("exiting ");
if (mc->IsTrackOut()) what.Append("out ");
Int_t mother = gAlice->GetMCApp()->GetPrimary(trackno);
- AliDebug(0, Form("Track # %5d deposited an obsence amout of energy (call # %d)\n"
- " Volume: %s\n"
- " Momentum: (%8.4f,%8.4f,%8.4f)\n"
- " Vertex: (%8.4f,%8.4f,%8.4f) [%s]\n"
- " PDG: %d (%s) [last %d (%s)]\n"
- " Edep: %-16.8f (mother %d)\n"
- " Energy: %-16.8f (last %16.8f from track %d)\n"
- " Processes: %s\n"
- " What: %s\n",
- trackno, nCall, mc->CurrentVolPath(),
- currentP.X(), currentP.Y(), currentP.Z(),
- currentV.X(), currentV.Y(), currentV.Z(), origin.Data(),
- currentPdg, (particleType ? particleType->GetName() : "???"),
- lastPdg, (lastType ? lastType->GetName() : "???"),
- mc->Edep(), mother, mc->Etot() /*currentP.E()*/,
- lastEtot, lastTrack, processes.Data(), what.Data()));
- // gAlice->GetMCApp()->DumpPStack();
- // mother->Print();
- nBad++;
- if (nBad > 10) exit (1);
+ Warning("Step", "Track # %5d deposits a lot of energy\n"
+ " Volume: %s\n"
+ " Momentum: (%8.4f,%8.4f,%8.4f)\n"
+ " PDG: %d (%s)\n"
+ " Edep: %-16.8f keV (mother %d)\n"
+ " p/m: %-16.8f\n"
+ " Processes: %s\n"
+ " What: %s\n",
+ trackno, mc->CurrentVolPath(), p.X(), p.Y(), p.Z(),
+ pdg, pname.Data(), edep, mother, poverm, processes.Data(),
+ what.Data());
}
+ // Check that the track is actually within the active area
+ Bool_t entering = mc->IsTrackEntering();
+ Bool_t inside = mc->IsTrackInside();
+ Bool_t out = (mc->IsTrackExiting()|| mc->IsTrackDisappeared()||
+ mc->IsTrackStop());
+ // Reset the energy deposition for this track, and update some of
+ // our parameters.
+ if (entering) {
+ AliDebug(15, Form("Track # %8d entering active FMD volume %s: "
+ "Edep=%f",
+ gAlice->GetMCApp()->GetCurrentTrackNumber(),
+ mc->CurrentVolPath(), 1000 * mc->Edep()));
+ fCurrentP = p;
+ fCurrentV = v;
+ fCurrentDeltaE = edep;
+ fCurrentPdg = mc->IdFromPDG(pdg);
+ }
// If the track is inside, then update the energy deposition
if (inside && fCurrentDeltaE >= 0) {
- fCurrentDeltaE += 1000 * mc->Edep();
+ fCurrentDeltaE += edep;
AliDebug(15, Form("Track # %8d inside active FMD volume %s: Edep=%f, "
- "Accumulated Edep=%f (call # %d)",
- gAlice->GetMCApp()->GetCurrentTrackNumber(),
- mc->CurrentVolPath(), 1000 * mc->Edep(),
- fCurrentDeltaE, nCall));
+ "Accumulated Edep=%f",
+ trackno, mc->CurrentVolPath(), edep,
+ fCurrentDeltaE));
}
-
// The track exits the volume, or it disappeared in the volume, or
// the track is stopped because it no longer fulfills the cuts
// defined, then we create a hit.
if (out && fCurrentDeltaE >= 0) {
-
- Int_t strip = copy - 1;
- Int_t sectordiv;
- mc->CurrentVolOffID(fSectorOff, sectordiv);
- Int_t module;
- mc->CurrentVolOffID(fModuleOff, module);
- Int_t sector = 2 * module + sectordiv;
- Int_t iring;
- mc->CurrentVolOffID(fRingOff, iring);
- Char_t ring = Char_t(iring);
- Int_t detector;
- mc->CurrentVolOffID(fDetectorOff, detector);
-
-
- AliFMDGeometry* fmd = AliFMDGeometry::Instance();
- Double_t rz = fmd->GetDetector(detector)->GetRingZ(ring);
- Int_t n = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors();
- if (rz < 0) {
- Int_t s = ((n - sector + n / 2) % n) + 1;
- AliDebug(40, Form("Recalculating sector to %d (=%d-%d+%d/2%%%d+1 z=%f)",
- s, n, sector, n, n, rz));
- sector = s;
- }
- if (sector < 1 || sector > n) {
- Warning("Step", "sector # %d out of range (0-%d)", sector-1, n-1);
- return;
- }
- sector--;
- fCurrentDeltaE += 1000 * mc->Edep();
- AliDebug(15, Form("Track # %8d leaving active FMD volume %s: Edep=%f, "
- "Accumulated Edep=%f (call # %d nCall)",
- gAlice->GetMCApp()->GetCurrentTrackNumber(),
- mc->CurrentVolPath(),
- 1000 * mc->Edep(), fCurrentDeltaE, nCall));
-
- AliDebug(20, Form("Processing hit in FMD%d%c[%2d,%3d]: %f",
- detector, ring, sector, strip, fCurrentDeltaE));
-
- fFMD->AddHitByFields(gAlice->GetMCApp()->GetCurrentTrackNumber(),
- UShort_t(detector), ring, UShort_t(sector),
- UShort_t(strip),
- fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(),
- fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(),
- fCurrentDeltaE, fCurrentPdg, fCurrentV.T());
+ fCurrentDeltaE += edep;
+ fFMD->AddHitByFields(trackno, detector, ring, sector, strip,
+ fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(),
+ fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(),
+ fCurrentDeltaE, fCurrentPdg, fCurrentV.T());
fCurrentDeltaE = -1;
}
- lastPdg = fCurrentPdg;
- lastEtot = mc->Etot();
- lastTrack = gAlice->GetMCApp()->GetCurrentTrackNumber();
-
}
#ifndef TLorentzVector
# include <TLorentzVector.h>
#endif
+#ifndef TArrayI
+# include <TArrayI.h>
+#endif
class TVector3;
class AliFMD;
class AliFMDRing;
virtual void DefineGeometry() = 0;
/** Deal with a hit in the FMD */
virtual void Exec(Option_t* option="");
-
+ virtual void UseDivided(Bool_t use=kTRUE) { fUseDivided = use; }
+ virtual void UseAssembly(Bool_t use=kTRUE) { fUseAssembly = use; }
protected:
AliFMD* fFMD; //! Pointer to module
Bool_t fDetailed; // Whether to make a detailed simulation
Int_t fOuterId; //! ID of outer ring strips
TLorentzVector fCurrentV; //! Current hit postition
TLorentzVector fCurrentP; //! Current hit momentum
+ TArrayI fActiveId; //! Active volume ID's
Int_t fCurrentPdg; //! Current hit particle code
Double_t fCurrentDeltaE; //! Current hit energy loss
+ Bool_t fUseDivided; // Divided volumes
+ Bool_t fUseAssembly; // Assembly volumes
+
+ Bool_t IsActive(Int_t volId) const;
+ Bool_t VMC2FMD(Int_t copy, TLorentzVector& v,
+ UShort_t& detector, Char_t& ring,
+ UShort_t& sector, UShort_t& stripe);
+ Bool_t VMC2FMD(TLorentzVector& v, UShort_t& detector,
+ Char_t& ring, UShort_t& sector, UShort_t& strip);
static const Char_t* fgkActiveName; // Name of Active volumes
static const Char_t* fgkSectorName; // Name of Sector volumes
kPcbId, // ID index of PCB medium
kSiChipId, // ID index of Si Chip medium
kAlId, // ID index of Al medium
- kCarbonId // ID index of Carbon medium
+ kCarbonId, // ID index of Carbon medium
+ kCopperId, // ID index of Copper Medium
+ kKaptonId // ID index of Kapton Medium
};
Int_t fSectorOff; // Sector offset in volume tree
//____________________________________________________________________
// This part for configuration
//static EG_t eg = test50;
- EG_t eg = kParam_fmd;
+ //EG_t eg = kParam_fmd;
+ EG_t eg = kParam_2000; // kPythia;
Geo_t geo = kNoHoles;
Rad_t rad = kGluonRadiation;
Mag_t mag = k5kG;
Int_t seed = 12345; //Set 0 to use the current time
- MC_t mc = kGEANT3TGEO;
+ MC_t mc = kGEANT3;
//____________________________________________________________________
// Comment line
new TFluka("C++ Interface to Fluka", 0/*verbosity*/);
break;
case kGEANT3:
- //
- // Libraries needed by GEANT 3.21
- //
- gSystem->Load("libgeant321");
-
- //
- // GEANT 3.21 MC
- //
- new TGeant3("C++ Interface to Geant3");
+ {
+ //
+ // Libraries needed by GEANT 3.21
+ //
+ gSystem->Load("libgeant321");
+
+ //
+ // GEANT 3.21 MC
+ //
+ TGeant3* gmc = new TGeant3("C++ Interface to Geant3");
+ gmc->SetSWIT(4, 1000);
+ }
break;
case kGEANT3TGEO:
- //
- // Libraries needed by GEANT 3.21
- //
- gSystem->Load("libgeant321");
+ {
+ //
+ // Libraries needed by GEANT 3.21
+ //
+ gSystem->Load("libgeant321");
- //
- // GEANT 3.21 MC
- //
- new TGeant3TGeo("C++ Interface to Geant3");
- Printf("Making a TGeant3TGeo objet");
+ //
+ // GEANT 3.21 MC
+ //
+ TGeant3TGeo* gmc = new TGeant3TGeo("C++ Interface to Geant3");
+ gmc->SetSWIT(4, 1000);
+ Printf("Making a TGeant3TGeo objet");
+ }
break;
default:
gAlice->Fatal("Config.C", "No MC type chosen");
//__________________________________________________________________
//
// Set External decayer
+#if 0
AliDecayer *decayer = new AliDecayerPythia();
switch (eg) {
case kD0PbPb5500: decayer->SetForceDecay(kHadronicD); break;
}
decayer->Init();
gMC->SetExternalDecayer(decayer);
+#endif
//__________________________________________________________________
// ************* STEERING parameters FOR ALICE SIMULATION **************
gMC->SetCut("PPCUTM", cut);
gMC->SetCut("TOFMAX", tofmax);
-
+
//__________________________________________________________________
// Generator Configuration
AliGenerator* gener = GeneratorFactory(eg, rad, comment);
//
// Used detectors
//
- Bool_t useABSO = kTRUE;
- Bool_t useCRT = kTRUE;
- Bool_t useDIPO = kTRUE;
+ Bool_t useABSO = kFALSE;
+ Bool_t useCRT = kFALSE;
+ Bool_t useDIPO = kFALSE;
Bool_t useFMD = kTRUE;
- Bool_t useFRAME = kTRUE;
+ Bool_t useFRAME = kFALSE;
Bool_t useHALL = kFALSE;
- Bool_t useITS = kTRUE;
- Bool_t useMAG = kTRUE;
- Bool_t useMUON = kTRUE;
- Bool_t usePHOS = kTRUE;
- Bool_t usePIPE = kTRUE;
- Bool_t usePMD = kTRUE;
- Bool_t useRICH = kTRUE;
- Bool_t useSHIL = kTRUE;
- Bool_t useSTART = kTRUE;
- Bool_t useTOF = kTRUE;
- Bool_t useTPC = kTRUE;
- Bool_t useTRD = kTRUE;
+ Bool_t useITS = kFALSE;
+ Bool_t useMAG = kFALSE;
+ Bool_t useMUON = kFALSE;
+ Bool_t usePHOS = kFALSE;
+ Bool_t usePIPE = kFALSE;
+ Bool_t usePMD = kFALSE;
+ Bool_t useRICH = kFALSE;
+ Bool_t useSHIL = kFALSE;
+ Bool_t useSTART = kFALSE;
+ Bool_t useTOF = kFALSE;
+ Bool_t useTPC = kFALSE;
+ Bool_t useTRD = kFALSE;
Bool_t useZDC = kFALSE;
- Bool_t useEMCAL = kTRUE;
- Bool_t useVZERO = kTRUE;
+ Bool_t useEMCAL = kFALSE;
+ Bool_t useVZERO = kFALSE;
cout << "\t* Creating the detectors ..." << endl;
//=================== Alice BODY parameters =============================
if (useFMD) {
//=================== FMD parameters ============================
AliFMD *FMD = new AliFMDv1("FMD", "normal FMD");
- AliLog::SetModuleDebugLevel("FMD", 16);
+ AliLog::SetModuleDebugLevel("FMD", 1);
+ // FMD->UseDivided();
+ FMD->UseOld();
+ // FMD->UseGeo(kFALSE);
}
if (useMUON) {
#pragma link C++ class AliFMDv1+;
#pragma link C++ class AliFMDSimulator+;
#pragma link C++ class AliFMDGeoSimulator+;
+#pragma link C++ class AliFMDGeoOldSimulator+;
#pragma link C++ class AliFMDG3Simulator+;
+#pragma link C++ class AliFMDG3OldSimulator+;
#pragma link C++ class AliFMDBaseDigitizer+;
#pragma link C++ class AliFMDDigitizer+;
#pragma link C++ class AliFMDSDigitizer+;
AliFMDv1.cxx \
AliFMDSimulator.cxx \
AliFMDGeoSimulator.cxx \
+ AliFMDGeoOldSimulator.cxx \
AliFMDG3Simulator.cxx \
+ AliFMDG3OldSimulator.cxx \
AliFMDHit.cxx \
AliFMDDigitizer.cxx \
AliFMDEdepMap.cxx \