Полный рабочий пример на Geant4 с визуализацией
Рассмотрим полностью рабочий пример на Geant4 с визуализацией, который «хоть что-то делает». Этот проект является более сложным, чем первый пример на Geant4, однако этот пример позволяет полноценно провести моделирование установки, записать спектр в файл, угловое распределение при попадании в детектор. Вто же время, предыдущий пример существенно более прост, в том числе и для понимания основных частей проекта на Джанте.
Запуск примера
Для запуска проекта в консоли смотрите сюда. Если же вы хотите все сделать "по человечески", с возможностью отлаживать программу, тогда вам нужно посмотреть статью об интеграции QtCreator и Geant4.
Схема установки примера
И начнем мы разбирать этот пример со схемы установки.
У нас есть некий источник начальных частиц, из которого вылетают протоны. Обозначено через вектор P на рисунке. Далее частицы попадают на мишень 1, которая представляет собой некую пластинку. Первичные частицы взаимодействуют с мишенью и вместе с вторичными частицами попадают на детектор 2.
В детекторе у нас размещена чувствительная область, в которой мы и регистрируем частицы, узнаем их энергию и направление полета. Так как далее они нам не нужны, то все их "убиваем", т.е. уничтожаем. И после моделирование выводим спектр протонов и их угловое распределение.
Исходный код проекта
Основной файл проекта example2.cpp
В нем мы подключаем физику, геометрию системы и интерфейс пользователя и многое другое.
// Подключаем заголовочные файлы
#include "G4RunManager.hh" // RunManager, класс из ядра Geant4,
//должен быть включен обязательно
#include "G4UImanager.hh" // Менеджер взаимодействия с пользователем
#include "ExG4DetectorConstruction01.hh" // Конструкция и структура детектора,
//должна определяться пользователем
#include "FTFP_BERT.hh" // Подключение физического листа из Geant4, где определяется
// используемые физические процессы и частицы
#include "ExG4ActionInitialization01.hh" // Пользовательский класс
//для задания начального источника частиц
#ifdef G4UI_USE //Если используется интерфейс пользователя то включаем визуализацию
#include "G4VisExecutive.hh"//Визуализация
#include "G4UIExecutive.hh"//Выбор соответствующего интерфейса пользователя
#endif
int main(int argc,char** argv)
{
// Создание класса G4RunManager, он контролирует выполнение программы и
// управляет событиями (запуском начальных частиц) при запуске проекта
G4RunManager* runManager = new G4RunManager;
// Установка обязательных инициализирующих классов
// Создание геометрии, материала детектора и мишени
// т.е. моделируемой установки
runManager->SetUserInitialization(new ExG4DetectorConstruction01);
// Создание физического листа - набора моделируемых частиц и физических процессов
// которые используются в данном моделировании.
// Используется готовый физический лист из Geant4
runManager->SetUserInitialization(new FTFP_BERT);
// Объявление начальных частиц (параметры пучка) и
// подключение прочих классов, используемых
// для получения данных о частицах в процессе моделирования
runManager->SetUserInitialization(new ExG4ActionInitialization01);
// Инициализация ядра Geant4
runManager->Initialize();
// Объявления менеджера визуализации
G4VisManager* visManager = new G4VisExecutive;
// Инициализация менеджера визуализации
visManager->Initialize();
// Получение указателя на менеджера взаимодействия с пользователем
// нужен, что бы можно было отправлять команды в проект
G4UImanager* UImanager = G4UImanager::GetUIpointer();
// Проверяем или были переданы через командную сроку параметры
if ( argc == 1 ) {//Если через командную строку ничего не передавалось
// То устанавливаем интерактивный режим
#ifdef G4UI_USE
G4UIExecutive* ui = new G4UIExecutive(argc, argv);//Создание интерфейса пользователя
UImanager->ApplyCommand("/control/execute vis.mac");
//Параметры отображения берем из заранее подготовленного
// файла vis.mac
ui->SessionStart();//Запуск интерфейса пользователя
delete ui;//Удаление интерфейса пользователя
#endif
}
else {
// Если были переданы параметры, по включаем пакетный режим
G4String command = "/control/execute ";//Записываем в строковую переменную
// команду выполнить
G4String fileName = argv[1];//Имя файла из командной строки при запуске проекта
// Мы считаем, что первым параметром было передано имя файла с командами для запуска
// проекта в пакетном режиме
UImanager->ApplyCommand(command+fileName);//Выполнение команды
}
// Окончание работы, вызов деструктора (удаление) G4RunManager
delete runManager;
return 0;
}
Задание геометрии детектора
Далее приведем заголовочный файл класса создания установки, детектора и объявления всех необходимых материалов ExG4DetectorConstruction01.hh
#ifndef ExG4DetectorConstruction01_h
#define ExG4DetectorConstruction01_h 1
#include "G4VUserDetectorConstruction.hh"
#include "globals.hh"
class G4VPhysicalVolume;
class G4LogicalVolume;
/// \brief The ExG4DetectorConstruction01 class Класс геометрии установки,
/// объявление материалов и детекторов
class ExG4DetectorConstruction01 : public G4VUserDetectorConstruction
{
public:
//Конструктор, вызывается при создании экземпляра класса
//Обычно используется для задания начальных значений и значений по умолчанию
//при создании геометрии и материалов
ExG4DetectorConstruction01();
//Деструктор, вызывается при удалении экземпляра класса
//Обычно используется для освобождения памяти инициализированных массивов внутри класса
virtual ~ExG4DetectorConstruction01();
//Объявление и создание детекторов и среды
virtual G4VPhysicalVolume* Construct();
//Установка чувствительного объема. Когда частица в нем, тогда извлекается
//вся информация о треке и параметрах частицы на каждом шаге моделирования
//Не работает в многопоточном режиме
virtual void ConstructSDandField();
protected:
};
#endif
И заголовочные файлы класса чувствительной области детектора, где снимаются параметры частиц ExG4DetectorSD.hh
Однако следует помнить, что таким образом можно снимать параметры только для проекта не использующего распаралеливание.
#include<G4VSensitiveDetector.hh>
#ifndef ExG4DetectorSD_h
#define ExG4DetectorSD_h 1
class G4Step;
class G4TouchableHistory;
/// Класс определения чувствительной области детектора
class ExG4DetectorSD: public G4VSensitiveDetector
{
private:
//Создадим гистограмму в которую запишем распределение
//энергии протонов
//Число бинов (интервалов в гистограмме)
static const int NOBINS = 1000;
//Максимальная энергия в гистограмме
const double HIST_MAX;
//Минимальная энергия в гистограмме
const double HIST_MIN;
//Объявляем саму гистограмму
int histogram[NOBINS];
//Постоим также угол, на который рассеялся протон
int histogram_angle[NOBINS];
public:
//Контструктор, в нем обнуляем гистограммы
ExG4DetectorSD(G4String name);
//Декструктор, в нем выведем гистограммы в файл
//Вывод данных в файл лучше делать здесь чем в ProcessHits, так как
//вызов деструктора происходит в конце работы программы,
//а если записывать в процессе моделирования, то значительное
//время будет тратится на ожидание записи в файл. А это относительно
//медленная процедура и занимает много времени и в результате
//моделирование будет занимать больше времени чем нужно.
~ExG4DetectorSD();
//Когда частица попадает в этот чувствительный объем, тогда на каждом
//её шаге моделирования вызывается эта функция.
//В ней мы получаем и собираем информацию о состоянии
//частицы и ее треке
G4bool ProcessHits(G4Step* step, G4TouchableHistory* history);
};
#endif /* SENSITIVEDETECTOR */
А теперь файл реализации конструкции установки и детектора ExG4DetectorConstruction01.cpp
/// \file ExG4DetectorConstruction01.cpp
/// \brief Implementation of the ExG4DetectorConstruction01 class
#include "ExG4DetectorConstruction01.hh"
#include "ExG4DetectorSD.hh"
#include "G4RunManager.hh"
#include "G4SDManager.hh"
// Менеджер предопределенных материалов
#include "G4NistManager.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
// Подключаем систему едениц измерения, что бы пользоваться еденицами cm, MeV.
#include "G4SystemOfUnits.hh"
// Конструктор класса объявления материалов и геометрии всей моделируемой системы
ExG4DetectorConstruction01::ExG4DetectorConstruction01()
: G4VUserDetectorConstruction()
{ }
// Деструктор
ExG4DetectorConstruction01::~ExG4DetectorConstruction01()
{ }
// Функция определения материалов и геометрии всей системы,
// должна возвращать физический объем - ссылку на экземпляр класса G4VPhysicalVolume
// Геометрию проектировать будем следующую: пучок протонов попадает на мишень
// вольфрамовый лист толщиной 1 мм, а за мишенью поставим детектор
// таких же размеров, он будет регистрировать что в него попало.
G4VPhysicalVolume* ExG4DetectorConstruction01::Construct()
{
// Для простоты используем предопределенные в Geant4 материалы
// Так объявляется менеджер, из которого можно извлечь
// ранее предопределенные материалы
G4NistManager* nist = G4NistManager::Instance();
// Определяем размеры детектора
G4double det_sizeXY = 25*cm, det_sizeZ = 0.15*cm;
// Материал детектора, здесь выбираем вольфрам
G4Material* det_mat = nist->FindOrBuildMaterial("G4_W");
// Опция для включения/выключения проверки перекрытия объемов
G4bool checkOverlaps = true;
// World
// Объем мира, самый большой объем, включающий остальные, аналог экспериментального
// зала
G4double world_sizeXY = 30*cm;//Размер по x и y здесь будут одинаковы - ширина и высота
G4double world_sizeZ = 20*cm;//Размер по z - толщина
// Выбор материала для мира из предопределенных в Geant4, для зала берем воздух
G4Material* world_mat = nist->FindOrBuildMaterial("G4_AIR");
// Создание объема для мира установки (экспериментального зала),
// определяется сама форма объема,
// берем параллелепипед, это просто геометрическая фигура
G4Box* solidWorld =
new G4Box("World", //its name, название объема
0.5*world_sizeXY, 0.5*world_sizeXY, 0.5*world_sizeZ); //its size, его размеры
// указываются половины размеров высоты, ширины и глубины
// Логический объем, здесь подключается материал, из которого сделан объем
G4LogicalVolume* logicWorld =
new G4LogicalVolume(solidWorld, //its solid, геометрический объем, объявлен выше
world_mat, //its material, материал объема
"World"); //its name, название логического объема
//совпадает с названием объема, но
//для Geant4 это разные объекты
//геометрический объем и логический объем
//Физический объем, а теперь наш логический объем помещаем в "реальный" мир
G4VPhysicalVolume* physWorld =
new G4PVPlacement(0, //no rotation, нет вращения
G4ThreeVector(), //at (0,0,0), расположение в центре (0,0,0)
logicWorld, //its logical volume, логический объем этого физического
"World", //its name, название физического объема
0, //its mother volume, материнский объем, этот самый первый, поэтому 0
false, //no boolean operation, без логических (булевых) операций
0, //copy number, номер копии
checkOverlaps); //overlaps checking, флаг проверки перекрытия объемов
// Детектор, для него также используем параллелепипед
G4Box* solidDet =
new G4Box("Detector", //its name, имя
0.5*det_sizeXY, 0.5*det_sizeXY, 0.5*det_sizeZ); //its size, размеры
//Логический объем
G4LogicalVolume* logicDet =
new G4LogicalVolume(solidDet, //its solid, объем
det_mat, //its material, указываем материал детектора
"Detector"); //its name, его имя
//Физический объем детектора
new G4PVPlacement(0, //no rotation, так же без вращения
G4ThreeVector(0,0,5*cm), //at (0,0,5 см) положение центра детектора, он смещен на 5 см от центра объема World
logicDet, //its logical volume, подключаем логический объем
"Detector", //its name, имя физического объема
logicWorld, //its mother volume, родительский логический объем, помещаем в world!
false, //no boolean operation, без булевых операций
0, //copy number, номер копии
checkOverlaps); //overlaps checking, флаг проверки перекрытия объемов
// Для мишени, на которую будет падать пучек, возьмем геометрические размеры как
// у детектора, параллелепипед - лист вольфрама.
//Логический объем
G4LogicalVolume* logicTar =
new G4LogicalVolume(solidDet, //its solid, объем
det_mat, //its material, указываем материал мишени
"Target"); //its name, его имя
//Физический объем мишени
new G4PVPlacement(0, //no rotation, так же без вращения
G4ThreeVector(0,0,-5*cm),//at (0,0,-5 см) положение центра мишени в другую сторону от детектора, смещена на 5 см от центра объема World
logicTar, //its logical volume, подключаем логический объем
"Target", //its name, имя физического объема
logicWorld, //its mother volume, родительский логический объем!
false, //no boolean operation, без булевых операций
0, //copy number, номер копии
checkOverlaps);
//Всегда возвращает физический объем
return physWorld;
}
void ExG4DetectorConstruction01::ConstructSDandField()
{
// Объявление чувствительной области детектора, в которой можно получить подробную
// информацию о состоянии и движении частицы, не работает в многопоточной версии
// Назовем чувствительную область DetectorSD
G4String trackerChamberSDname = "DetectorSD";
// Создаем экземпляр чувствительной области
ExG4DetectorSD* aTrackerSD = new ExG4DetectorSD(trackerChamberSDname);
// Передаем указатель менеджеру
G4SDManager::GetSDMpointer()->AddNewDetector(aTrackerSD);
// Добавляем чувствительный объем ко всем логическим областям с
// именем Detector
SetSensitiveDetector("Detector", aTrackerSD, true);
}
И файл реализации чувствительного объема ExG4DetectorSD.cpp
#include<G4Step.hh>
// Для работы с файлами
#include<fstream>
// Для работы с покотками ввода и вывода
#include<iostream>
// Подключаем систему едениц измерения, что бы пользоваться еденицами cm, MeV.
#include "G4SystemOfUnits.hh"
#include "G4ThreeVector.hh"
#include "ExG4DetectorSD.hh"
// Используем пространство имен std, что бы не писать много где std::
using namespace std;
// Конструктор чувствительной области, по умолчанию инициализируем нижнюю и верхнюю
// границы гистограммы в 0 и 50 МэВ
ExG4DetectorSD::ExG4DetectorSD(G4String name): G4VSensitiveDetector(name),
HIST_MAX(50*MeV),// Инициализация верхней границы
HIST_MIN(0 *MeV)// Инициализация нижней границы
{
// Обнуляем гистограммы
for(int i = 0; i<NOBINS; i++){
histogram[i] = 0;
histogram_angle[i] = 0;
}
}
//Вызывается на каждом шаге моделирования частицы, когда она попадает в этот чувствительный объем
G4bool ExG4DetectorSD::ProcessHits(G4Step* step, G4TouchableHistory* history)
{
// Получаем кинетическую энергии частицы с предыдущего шага, т.е. начальную
// кинетическую энегрию перед текущим шагом
double energy = step->GetPreStepPoint()->GetKineticEnergy();
// Вычисляем ширину бина (интерва) гистограммы
double bin_width = (HIST_MAX - HIST_MIN) / NOBINS;
// Если имя частицы протон (proton), тогда заполняем гистограммы
if(step->GetTrack()->GetDefinition()->GetParticleName() == "proton" ){
// Определяем индекс (номер) бина гистограммы энергии
int index = int(floor((energy-HIST_MIN)/bin_width));
// Добавляем +1 в соответствующий бин
if(index >= 0 && index < NOBINS)
histogram[index]++;
// Далее заполняем гистограмму углового распределения
// Получаем вектор направления частицы
G4ThreeVector ang = step->GetPreStepPoint()->GetMomentumDirection();
// Задаем единичный вектор в направлении оси OZ
G4ThreeVector *centerVector = new G4ThreeVector(0, 0, 1);
// Применяем фунцию класса G4ThreeVector - находим угол относительно
// вектора centerVector
double angle=ang.angle(*centerVector);
// Определяем ширину бина в гистограмме углового распределения.
// Так как у нас измеряются углы между векторами, то максимальный
// угол равен пи 3.14, минимальный 0
double bin_width_ang = (3.14) / NOBINS;
// Получаем номер бина
index = int(floor((angle)/bin_width_ang));
// Заполняем гистограмму
if(index >= 0 && index < NOBINS)
histogram_angle[index]++;
}
// Так как мы хотим только измерить параметры частиц после прохождения
// мишени и не интересуемся дальнейшей их судьбой в детекторе, то их убиваем -
// устанавливаем статус остановлено и уничтожено (fStopAndKill)
step->GetTrack()->SetTrackStatus(fStopAndKill);
return true;
}
ExG4DetectorSD::~ExG4DetectorSD()
{
// В деструкторе выводим гистограммы в файлы
// Открываем файл (существующий файл полностью перезаписывается)
std::ofstream file("spectrum.dat");
// Вычисляем ширину бина
double bin_width = (HIST_MAX - HIST_MIN) / NOBINS;
// Выводим гистограмму
for(int i = 0; i<NOBINS; i++)
{
// Вычисляем энергию
double energy = i*bin_width + HIST_MIN;
// Выводим в файл
file << std::setw(15) << energy/MeV << " "
<< std::setw(15) << histogram[i] << std::endl;
}
// Закрываем файл
file.close();
// Открываем файл для вывода гистограммы углового распределения
file.open("angle.dat");
// Вычисляем ширину бина
bin_width = (3.14) / NOBINS;
// Выводим гистограмму
for(int i = 0; i<NOBINS; i++)
{
// Вычисляем угол
double angle = i*bin_width;
// Выводим в файл
file << std::setw(15) << angle << " "
<< std::setw(15) << histogram_angle[i] << std::endl;
}
// Закрываем файл
file.close();
}
Классы инициализации проекта
Далее идут важные и обязательные файлы инициализации проекта ExG4ActionInitialization01.hh
/// \file ExG4ActionInitialization01.hh
/// \brief Definition of the ExG4ActionInitialization01 class
#ifndef ExG4ActionInitialization01_h
#define ExG4ActionInitialization01_h 1
#include "G4VUserActionInitialization.hh"
/// Обязательный класс, который должен быть объявлен в проекте Geant4
/// Имя класса может быть другим, и он должен наследоваться от
/// класса G4VUserActionInitialization
class ExG4ActionInitialization01 : public G4VUserActionInitialization
{
public:
ExG4ActionInitialization01();//Конструктор
virtual ~ExG4ActionInitialization01();//Деструктор
virtual void Build() const;//Создание источника первичных частиц
};
#endif
И файл класса задания начальных частиц ExG4PrimaryGeneratorAction01.hh
/// \file ExG4PrimaryGeneratorAction01.hh
/// \brief Definition of the ExG4PrimaryGeneratorAction01 class
#ifndef B1PrimaryGeneratorAction_h
#define B1PrimaryGeneratorAction_h 1
#include "G4VUserPrimaryGeneratorAction.hh"
#include "G4ParticleGun.hh"
#include "globals.hh"
class G4ParticleGun;
class G4Event;
class G4Box;
/// Класс определения источника первичных частиц
class ExG4PrimaryGeneratorAction01 : public G4VUserPrimaryGeneratorAction
{
public:
///
/// \brief ExG4PrimaryGeneratorAction01 Конструктор
///
ExG4PrimaryGeneratorAction01();
///
/// \brief ~ExG4PrimaryGeneratorAction01 Деструктор
///
virtual ~ExG4PrimaryGeneratorAction01();
///
/// \brief GeneratePrimaries Метод из базового класса, задает параметры источника начальных частиц
///
virtual void GeneratePrimaries(G4Event*);
///
/// \brief GetParticleGun Метод для доступа к источнику частиц (пушке частиц ;) )
/// \return Указатель на источник частиц
///
const G4ParticleGun* GetParticleGun() const { return fParticleGun; }
private:
G4ParticleGun* fParticleGun; //указатель на источник частиц
// Временная переменная объема
G4Box* fEnvelopeBox;
};
#endif
Файл реализации инициализации ExG4ActionInitialization01.cpp
/// \file ExG4ActionInitialization01.cpp
/// \brief Implementation of the ExG4ActionInitialization01 class
#include "ExG4ActionInitialization01.hh"
#include "ExG4PrimaryGeneratorAction01.hh"//Подключаем обязательный класс
//в котором описывается источник начальных частиц
/// Обязательный класс, который должен быть объявлен в проекте Geant4
/// Имя класса может быть другим, и он должен наследоваться от
/// класса G4VUserActionInitialization
/// Конструктор
ExG4ActionInitialization01::ExG4ActionInitialization01()
: G4VUserActionInitialization()
{}
//Деструктор, ничего не объявляли, поэтому оставим пустым
ExG4ActionInitialization01::~ExG4ActionInitialization01()
{}
//Создание источника первичных частиц
void ExG4ActionInitialization01::Build() const
{
SetUserAction(new ExG4PrimaryGeneratorAction01);//Задается источник первичных частиц
// через обязательный класс ExG4PrimaryGeneratorAction01
}
И файл реализации задания начального источника частиц ExG4PrimaryGeneratorAction01.cpp
/// \file ExG4PrimaryGeneratorAction01.cpp
/// \brief Implementation of the ExG4PrimaryGeneratorAction01 class
// Подключаем необходимые заголовочные файлы
#include "ExG4PrimaryGeneratorAction01.hh"
// Подключаем необходимы заголовочные файлы
#include "G4LogicalVolumeStore.hh"
#include "G4LogicalVolume.hh"
#include "G4Box.hh"
#include "G4RunManager.hh"
// Источник частиц
#include "G4ParticleGun.hh"
// Таблица указателей на данные частиц
#include "G4ParticleTable.hh"
// Данные частиц
#include "G4ParticleDefinition.hh"
// Подключаем систему едениц измерения, что бы пользоваться еденицами cm, MeV.
#include "G4SystemOfUnits.hh"
// Генератор случайных чисел
#include "Randomize.hh"
///
/// \brief ExG4PrimaryGeneratorAction01::ExG4PrimaryGeneratorAction01 Формирование начального пучка.
/// Класс, в котором описывается положение, тип, энергия, направление вылета
/// и распределение начальных частиц
///
ExG4PrimaryGeneratorAction01::ExG4PrimaryGeneratorAction01()
: G4VUserPrimaryGeneratorAction(),
fParticleGun(0),
fEnvelopeBox(0)
{
// Данные, которые здесь задаются после могут быть изменены через команды в mac файле,
// или в консольном режиме.
// По умолчанию у источника частиц поставим 1 частицу
G4int n_particle = 1;
fParticleGun = new G4ParticleGun(n_particle);
// Получаем встроеную в Geant4 таблицу частиц
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
G4String particleName;
// Ищем частицу, в нашем случае протон
G4ParticleDefinition* particle
= particleTable->FindParticle(particleName="proton");
// Устанавливаем полученную частицу в качестве испускаемого типа начальных частиц в источнике
fParticleGun->SetParticleDefinition(particle);
// Устанавливаем направление движение частицы по (x,y,z)
// Здесь устанавливается направление вдоль оси Z
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0.,0.,1.));
// Установка начальной энергии испускаемых частиц, 50 МэВ
fParticleGun->SetParticleEnergy(50*MeV);
}
/// Деструктор, удаляем созданный в конструкторе экземпляр класса источника G4ParticleGun
/// для очистки памяти
ExG4PrimaryGeneratorAction01::~ExG4PrimaryGeneratorAction01()
{
// удаляем созданный в конструкторе экземпляр класса источника G4ParticleGun
delete fParticleGun;
}
/// Эта функция вызывается в начале каждого события и генерирует начальные частицы.
/// Определенные здесь условия переписывают команды из файла mac и команды из
/// консольного режима.
void ExG4PrimaryGeneratorAction01::GeneratePrimaries(G4Event* anEvent)
{
// Для избежания зависимости этого класса от класса DetectorConstruction,
// мы получаем ссылку на объем детектора через класс G4LogicalVolumeStore
G4double envSizeXY = 0;
G4double envSizeZ = 0;
// Проверяем или ссылка на fEnvelopeBox пустая
if (!fEnvelopeBox)
{
// Если пустая, то получаем ссылку на объем детектора
G4LogicalVolume* envLV
= G4LogicalVolumeStore::GetInstance()->GetVolume("Detector");
if ( envLV ) fEnvelopeBox = dynamic_cast<G4Box*>(envLV->GetSolid());
}
// Получаем размеры объема, предполагается что, стороны по x и y одинаковы
if ( fEnvelopeBox ) {
envSizeXY = fEnvelopeBox->GetXHalfLength()*2.;
envSizeZ = fEnvelopeBox->GetZHalfLength()*2.;
}
else {//Если ссылка на fEnvelopeBox пустая, выдаем предупреждение
G4ExceptionDescription msg;
msg << "Envelope volume of box shape not found.\n";
msg << "Perhaps you have changed geometry.\n";
msg << "The gun will be place at the center.";
G4Exception("B1PrimaryGeneratorAction::GeneratePrimaries()",
"MyCode0002",JustWarning,msg);
}
// Задаем координаты где будет источник начальных частиц
G4double x0 = 0;
G4double y0 = 0;
// Устанавливаем в положение -10 см, 0 означает цент мирового объема
G4double z0 = -0.5 * 20*cm;
// Команда устанавливает позицию источника начальных частиц
fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
// Генерируем первичное событие
fParticleGun->GeneratePrimaryVertex(anEvent);
}
Make файл
Так как изменилось имя проекта, то соответственно немного изменился CMakeLists.txt
# $Id: CMakeLists.txt 2023-01-19 Виктор Гавриловец $
#CMakeList.txt, с его помощью собирается проект Geant4
#Как правило здесь настраивать ничего не надо
# Запуск проекта, проверка необходимой версии Cmake
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
# Название проекта
project(example2)
# Поиск пакетов Geant4, включение всех доступных интерфейсов пользователя
# (Qt, GAG, tcsh, csh) и драйверов визуализации по умолчанию.
# Можно использовать переменную окружения WITH_GEANT4_UIVIS, установить в OFF (выключено)
# через командную строку или с помощью ccmake/cmake-gui для сборки проекта только в
# пакетном режимом
#
option(WITH_GEANT4_UIVIS "Build example with Geant4 UI and Vis drivers" ON)
if(WITH_GEANT4_UIVIS)
find_package(Geant4 REQUIRED ui_all vis_all)
else()
find_package(Geant4 REQUIRED)
endif()
# Подключение директорий из Geant4
include(${Geant4_USE_FILE})
# Подключение директорий проекта
include_directories(${PROJECT_SOURCE_DIR}/include)
# Расположение искодного кода и заголовочных файлов этого проекта
# Заголовочные файлы подключаются, значит что они будут показаны в
# IDE - среде разработки
file(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cpp)
file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)
# Иногда возникает проблема, что не находит файлы проекта
# это потому, что у файлов исходников могут быть другие расширения, например
# file(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc)
# file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.h)
# Добавление исполняемого файла и линковка его с библиотеками Geant4
#
add_executable(example2 example2.cpp ${sources} ${headers})
target_link_libraries(example2 ${Geant4_LIBRARIES})
# Копирование скриптов в директорию сборки - туда, где мы собираем проект.
# Таким образом мы сможем запустить проект в директории сборки - текущей рабочей
# директории, что нужно например, при отладке.
#
set(EXAMPLE1_SCRIPTS
run1.mac
vis.mac
)
foreach(_script ${EXAMPLE1_SCRIPTS})
configure_file(
${PROJECT_SOURCE_DIR}/${_script}
${PROJECT_BINARY_DIR}/${_script}
COPYONLY
)
endforeach()
# Для внутеренего использования в Geant4, но не имеет влияния если проект
# компилируется для отдельного использования
#
add_custom_target(ex1 DEPENDS example2)
# Установка исполняемого файла в 'bin' директорию по пути
# установки CMAKE_INSTALL_PREFIX
#
install(TARGETS example2 DESTINATION bin)
Визуализация и консольный запуск
Для визуализации используется следующий файлvis.mac
# Macro file for the visualization setting in the initialization phase
# of the project example 2 when running in interactive mode
#
# Use these open statements to open selected visualization
#
# Use this open statement to create an OpenGL view:
/vis/open OGL 600x600-0+0
#
# Use this open statement to create an OpenInventor view:
#/vis/open OI
#
# Use this open statement to create a .prim file suitable for
# viewing in DAWN:
#/vis/open DAWNFILE
#
# Use this open statement to create a .heprep file suitable for
# viewing in HepRApp:
#/vis/open HepRepFile
#
# Use this open statement to create a .wrl file suitable for
# viewing in a VRML viewer:
#/vis/open VRML2FILE
#
# Disable auto refresh and quieten vis messages whilst scene and
# trajectories are established:
/vis/viewer/set/autoRefresh false
/vis/verbose errors
#
# Draw geometry:
/vis/drawVolume
#
# Specify view angle:
/vis/viewer/set/viewpointVector -1 0 0
/vis/viewer/set/lightsVector -1 0 0
#
# Specify style (surface, wireframe, auxiliary edges,...)
/vis/viewer/set/style wireframe
/vis/viewer/set/auxiliaryEdge true
/vis/viewer/set/lineSegmentsPerCircle 100
#
# Draw smooth trajectories at end of event, showing trajectory points
# as markers 2 pixels wide:
/vis/scene/add/trajectories smooth
/vis/modeling/trajectories/create/drawByCharge
/vis/modeling/trajectories/drawByCharge-0/default/setDrawStepPts true
/vis/modeling/trajectories/drawByCharge-0/default/setStepPtsSize 2
# (if too many tracks cause core dump => /tracking/storeTrajectory 0)
#
# Draw hits at end of event:
#/vis/scene/add/hits
#
# To draw only gammas:
#/vis/filtering/trajectories/create/particleFilter
#/vis/filtering/trajectories/particleFilter-0/add gamma
#
# To invert the above, drawing all particles except gammas,
# keep the above two lines but also add:
#/vis/filtering/trajectories/particleFilter-0/invert true
#
# Many other options are available with /vis/modeling and /vis/filtering.
# For example, to select colour by particle ID:
#/vis/modeling/trajectories/create/drawByParticleID
#/vis/modeling/trajectories/drawByParticleID-0/default/setDrawStepPts true
# To select or override default colours (note: e+ is blue by default):
#/vis/modeling/trajectories/list
#/vis/modeling/trajectories/drawByParticleID-0/set e+ yellow
#
# To superimpose all of the events from a given run:
/vis/scene/endOfEventAction accumulate
#
# Decorations
# Name
#/vis/set/textColour green
#/vis/set/textLayout right
#/vis/scene/add/text2D 0.9 -.9 24 ! ! exampleB1
# or, if your system does not support right-adjustment
#/vis/scene/add/text2D 0 -.9 24 ! ! exampleB1
#/vis/set/textLayout # Revert to normal (left adjusted) layout
#/vis/set/textColour # Revert to default text colour (blue)
#
# Axes, scale, etc.
/vis/scene/add/scale # Simple scale line
/vis/scene/add/axes # Simple axes: x=red, y=green, z=blue.
/vis/scene/add/eventID # Drawn at end of event
#/vis/scene/add/date # Date stamp
#/vis/scene/add/logo2D # Simple logo
#/vis/scene/add/logo # 3D logo
#
# Frame
#/vis/set/colour red
#/vis/set/lineWidth 2
#/vis/scene/add/frame # Simple frame around the view
/vis/set/colour # Revert to default colour (white)
/vis/set/lineWidth # Revert to default line width (1.)
#
# Attach text to one edge of Shape1, with a small, fixed offset
#/vis/scene/add/text 0 6 -4 cm 18 4 4 Shape1
# Attach text to one corner of Shape2, with a small, fixed offset
#/vis/scene/add/text 6 7 10 cm 18 4 4 Shape2
#
# To get nice view
# Make the "World" box invisible
/vis/geometry/set/visibility World 0 true
/vis/geometry/set/colour World 0 0 0 1 .3
# "Envelope" is transparent blue to represent water
/vis/geometry/set/colour Detector 0 0 1 1 .5
/vis/viewer/set/style surface
/vis/viewer/set/hiddenMarker true
/vis/viewer/set/viewpointThetaPhi 120 150
#
# Re-establish auto refreshing and verbosity:
/vis/viewer/set/autoRefresh true
/vis/verbose warnings
#
# For file-based drivers, use this to create an empty detector view:
#/vis/viewer/flush
А для программы с использованием файла mac - run1.mac
# Macro file for example 2
#
# Can be run in batch, without graphic
# or interactively: Idle> /control/execute run1.mac
#
# Change the default number of workers (in multi-threading mode)
#/run/numberOfWorkers 4
#
# Initialize kernel
/run/initialize
#
/control/verbose 1
/run/verbose 1
/event/verbose 0
#
# gamma 6 MeV to the direction (0.,0.,1.)
#
#/gun/particle gamma
#/gun/energy 6 MeV
#
#/run/beamOn 5
#
# proton 210 MeV to the direction (0.,0.,1.)
# Установка типа частиц, протонов
/gun/particle proton
# Установка энергии частиц, 50 МэВ
/gun/energy 50 MeV
# Установка уровня
/tracking/verbose 0
# Запуск частиц, 10 тысяч
/run/beamOn 10000
В других статья будут подробней разбираться команды отрисовки и запуска примеров Geant4.
Весь представленный код примера находится здесь.