Randomized Particle Directions from Track to Track

Howdy,

My simulation is of a bremsstrahlung X-ray source with a defined beam profile. I don’t want to simulate the actual bremsstrahlung process as I have a spectra from my sponsor but I need to create a randomized cone beam from a point source. I can get a single randomized momentum for X and Y (and then calculate Z) but it doesn’t change with repeat runs (i.e. running main.cc with a run1.mac with beam of 10) across a few different minutes or if I make multiple particles in the fparticlegun with G4ParticleGun(10). All the momentums and energies are the same across all the particles.

MyPrimaryGenerator::MyPrimaryGenerator()
{
	fParticleGun = new G4ParticleGun(1);

	// Define Particle
	G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
	G4String ParticleName = "gamma";
	G4ParticleDefinition* particle = particleTable->FindParticle(ParticleName);

	// Define Starting Position and Momentum 
	CLHEP::HepRandom::setTheSeed((unsigned)clock());  //Added off of a suggestion post
	G4double Hang = 0.1;
	G4double Xmag = Hang * ((G4UniformRand() - 0.5));
	//G4cout << "X Magnitude: " << Xmag << G4endl;
	G4double Ymag = Hang * ((G4UniformRand() - 0.5));
	//G4cout << "Y Magnitude: " << Ymag << G4endl;
	G4double Zrem = 1.0 - sqrt(pow(Xmag,2) + pow(Ymag,2));
	//G4cout << "X Angle " << Xmag / Zrem << ", Y Angle " << Ymag / Zrem; // << G4endl;
	G4ThreeVector pos(0.0, 0.0, -1.5 * m);
	G4ThreeVector mom(Xmag, Ymag, Zrem);

	fParticleGun->SetParticlePosition(pos);
	fParticleGun->SetParticleMomentumDirection(mom);
	fParticleGun->SetParticleMomentum(G4RandGauss::shoot(0.45,0.1) * MeV);
	//G4cout << ", Energy " << fParticleGun->GetParticleMomentum() << "MeV" << G4endl;
	fParticleGun->SetParticleDefinition(particle);
}

How do I make each particle independently random, at this point I’m less concerned about run_n being the same as run_m if nothing else changes so the randoms can wander all they want.

Thanks

Geant4 version Name: geant4-10-07-patch-03 [MT] (19-November-2021)
Operating System:_CentOS Linux 7 (Core)
Compiler/Version:_Unsure, CMakeCache.txt looks like it’s pointed at spark-base inside of CentOS
CMake Version:_3.22.2

Don’t set the momentum in your constructor. If you do that, then you’re explicitly choosing to have the identical direction for every event.

I presume that your MyPrimaryGenerator is a subclass of G4PrimaryGeneratorAction? If that’s the case, then you should be implementing a GeneratePrimaries() member function (see the .hh file). That’s where you would set your momentum direction (and your energy, position, etc., if you want those to vary). Finally, in that function, you call

  fParticleGun->GeneratePrimaryVertex(anEvent);

to actually throw the particle. If you want to generate multiple primaries in a single event, then you need to do the loop yourself, so you get separate directions for each one. Otherwise ParticleGun will throw N identical particles.

I’ll admit I’m very rusty at C++ having not used it since around 2001 so I’m picking that up as I go with this effort. I’m tracking that by making this a constructor action, it gets locked in.

Generator.hh

#ifndef GENERATOR_HH
#define GENERATOR_HH

#include "Randomize.hh"
#include <cmath>

#include "G4VUserPrimaryGeneratorAction.hh"
#include "G4ParticleGun.hh"
#include "G4SystemOfUnits.hh"
#include "G4ParticleTable.hh"


class MyPrimaryGenerator : public G4VUserPrimaryGeneratorAction
{
public:
	MyPrimaryGenerator();
	~MyPrimaryGenerator();

	virtual void GeneratePrimaries(G4Event*);

private:
	G4ParticleGun *fParticleGun;

};

#endif

Generator.cc

#include "Generator.hh"

MyPrimaryGenerator::MyPrimaryGenerator()
// Posted above

MyPrimaryGenerator::~MyPrimaryGenerator()
{
	delete fParticleGun;
}

void MyPrimaryGenerator::GeneratePrimaries(G4Event *anEvent)
{
	fParticleGun->GeneratePrimaryVertex(anEvent);
}

I’m not quite following where I need to put the calls to the random vs. in the constructor even though I know that it doesn’t go there. Pardon my learning curve on the program construction.

Thanks

So you are asking basic C++ questions, but they’re easy to answer. The constructor is only called one time, at the point where you create a new object (like new MyPrimaryGenerator). Other member functions may be called multiple times. In this instance, we “know” (from reading the G4 documentation :slight_smile: ), that ::GeneratePrimaries() is called for you, by Geant4, at the start of each event.

So you can do a few things. You could move all of the ParticleGun configuration stuff into GeneratePrimaries(). Then it’s all together, you can see what it’s doing coherently, and if you decide later you want random positions, random energies, or even multiple random particle types, those changes will be easier.

But you might think that’s a waste of time. If you’re setting a fixed value, why set it, and reset it, and reset it, on every event? So you could leave everything except momentum in the constructor. Then it’s pre-set, never changes, and you don’t have to worry about it.

1 Like

Thank you for the detailed explanation and reminding me that do need to read the manual about what is done automatically vs. having to call it on my own.

I went ahead and did a split approach as the facility defines part of the problem but the rest I want to follow the random cone of a collimated source and there are multiple spectra they want me to model so I moved those bits down to the GeneratePrimaries() method. I reran it with some trackers in the detector and I was able to verify that it is both random in vector and in energy as desired.

Thanks again for helping me with this one and hopefully it helps others at some point.

Glad to be of help! Would you be willing to tick the “solution” box under my reply? That flags this topic in the listing as “solved”, and identifies where in the thread the solution can be found.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.