Геометрия GEANT4

Базовые принцы и создание мирового объема

В предыдущей главе мы создали файлы DetectorConstruction.hh и DetectorConstruction.cc, теперь давайте разберемся что в них происходит. ДЛя того что бы задать геометрию в GEANT4, нужно унаследовать класс G4VUserDetectorConstruction и определить в нём метод Construct. Это и происходит в нашем классе DetectorConstruction. Геометрическая модель GEANT4 пердпологает три уровня абстрации и представляет собой иерахическую структуру геометрических примитивов, примитив верхнего уровня называется мировым объемом и указатель на этот мировой объем должен возращать метод Construct. Расмотрим с каким геометрическими абстракциями работает GEANT4:

  1. Тело (solid) — описывает форму и размеры реального геометрического объема.

  2. Логический объем (logical volume)— описывает материал, электромагние и прочие поля, а также содержит информацию об используемомо твердом теле и детекторе для данного объема.

  3. Физический объем (physical volume) — имменно через этот объем будут проходить частицы двигаясь в нашей гемеотрической модели. Здесь задаются координаты центра тела и его поворот относительно системы координат связанное с центром материнсокго логического объема.

Расмотрим детальнее метод Construct.

Для начала мы создадим тело нешего мира в виде прямоугольного параллепипеда. Обратите внимание что в классы отвечающих за создание тел, нужно указывать половины от линейных размеров, в частости здесь мы передаем полуширину параллепидеда и не полную ширину. Также каждое тело (также как и логические и физические объемы) имеет имя, которое используется для работы пользователя с геометрией:

G4double world_sizeXY = 20*meter;
G4double world_sizeZ  = 30*meter;
G4Box* solidWorld =
        new G4Box("World",                       //its name
                    0.5*world_sizeXY, 0.5*world_sizeXY, 0.5*world_sizeZ);     //its size

Теперь на основе этого тела, создадим логический объем. Но перед этим нам нужно получить экземпляр класса описывающего материал из которого состоит объем. Можно либо создать материал самостоятельно или взять один из готовых материалов, используя NistManager:

auto nist = G4NistManager::Instance();
G4Material* world_mat = nist->FindOrBuildMaterial("G4_AIR");

Логический объем:

G4LogicalVolume* logicWorld =
        new G4LogicalVolume(solidWorld,          //its solid
                            world_mat,           //its material
                            "World");            //its name

Отметим что на основе одно логического объема мы можем создавать много разных физических оюъемов, которые будут отличаться положением в пространтсве.

// Option to switch on/off checking of volumes overlaps
G4bool checkOverlaps = true;
G4VPhysicalVolume* physWorld =
        new G4PVPlacement(0,                     //no rotation
                            G4ThreeVector(),       //at (0,0,0)
                            logicWorld,            //its logical volume
                            "World",               //its name
                            0,                     //its mother  volume
                            false,                 //no boolean operation
                            0,                     //copy number
                            checkOverlaps);

Запуск визуализации

TODO()

Планируем структуру геометрии

TODO()

Создаем калориметер

TODO()

Раскрашиваем калориметр

Для того чтобы сделать модель калориметра немного нагляднее давайте раскрасим её, для этого в файл init_vis.mac добавим следующие строки:

/vis/geometry/set/colour lead 0 0.5 0.5 0.5
/vis/geometry/set/forceSolid lead
/vis/geometry/set/colour plastic 0 0.1 0.5 0.5
/vis/geometry/set/forceSolid plastic

Команда /vis/geometry/set/colour задает цвет физических объемов связанных с логическим объемом lead, следующая цифра задает насколько глубоко применять данный цвет к дочерним объема, а последние три цифры задают собсвтенно цвет в формате RGB. Команда /vis/geometry/set/forceSolid указывает что нужно отрисовывать не только грани объемов, но и их поверхность.

Кроме того давайте инвретируем цвета фона и граней объемов:

/vis/viewer/set/background white
/vis/geometry/set/colour all -1 0 0 0

Первая команда меняет фон сцены, вторая делает цвет граней всех объемов черным.

Также можно добавить на сцену координатные оси и текующую дату:

/vis/scene/add/axes
/vis/scene/add/date

Создаем трековый детектор

TODO()

Вращение физических объемов

Для того что бы создать второй детектор мы должны просто зеркально отразить первый детектор. Как мы знаем зеркальное отражение может быть выражено через повороты, а значит нам нужно просто правильно повернуть физический объем соответсвующий второму детектору. Повороты задаютс через матрицу повороов определяемую классом G4RotationMatrix. Данный класс имеет несколько констуркторов, использующие различные способы создания матрицы поворота. В нашем проекте я предлагаю использовать Углы Эйлера, давайте повернем наш объем на какие-нибудь произвольные углы:

auto rotation =  new G4RotationMatrix(CLHEP::pi,CLHEP::pi,CLHEP::pi);

Тогда физический объем второго детектора будет выглядет так:

 auto leftDetector = new G4PVPlacement(rotation, G4ThreeVector(0, 0, -detector_length / 2 - 0.1 * meter), detectorLogic,
                                          "leftDetector", logicWorld, false, 1);

Посмотрим на результат: ../../_images/ Попробуйте определить на какие углы нужно повернуть объем чтобы получить правильную копию. Обратите внимание на то что наша система обладает симметрией относительно центральной оси детектора, что затрудняет определение правильности расположения по визуализации. В таком случае можно например создать дополнительный объем нарушающий симметрию и отслеживать его расположение, добавляя его только при отладке приложения.

Создаем магнитное поле

Основная часть трекового детектора это поворотный магнит, который искривляет траекторию зараяженных частиц. Для того что создать магнит нужно описать логические и физические объемы задающие область с полем и прикрепить к логическому объему объекты описывающие магнитное поле. Обычно это делеают переопределив метод ConstructSDandField класса G4VUserDetectorConstruction:

void DetectorConstruction::ConstructSDandField() {
    G4VUserDetectorConstruction::ConstructSDandField();
    G4MagneticField *magField;
    magField = new G4UniformMagField(G4ThreeVector(0., 50*kilogauss, 0.0));
    auto fieldMgr = new G4FieldManager;
    fieldMgr->SetDetectorField(magField);
    fieldMgr->CreateChordFinder(magField);
    magnetLogic->SetFieldManager(fieldMgr, true);
}

Мы будем прикреплять поле к логическому объему magentLogic, который мы предварительно создали. Создание однородного магнитного поле это простая (по сравнению с неоднородными и смешанными полями) процедура, в которой нужно:

  • задать поле с помощью класса G4UniformMagField, который принимает на вход вектор магнитной индукции;

  • зарегестрировать поле в экземпляре класса G4FieldManager;

  • создать решатель уравнений движения в поле с помощью метода CreateChordFinder;

  • и наконец, проассоциировать менедеджер поля с логическим объемом: magnetLogic->SetFieldManager(fieldMgr, true);.

Готово, можно испытывать магнит, однако для этого нам нужно научиться запускать не только нейтральный гамма-кванты, но и зараяженные электроны и позитроны, о чем и пойдет речь в следующей главе.