Import Geant4 10.7.0.beta source tree
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (copied from B1ActionInitialization)
|
||||
|
||||
#include "FAActionInitialization.hh"
|
||||
#include "FAPrimaryGeneratorAction.hh"
|
||||
#include "FARunAction.hh"
|
||||
#include "FAEventAction.hh"
|
||||
#include "FASteppingAction.hh"
|
||||
|
||||
ActionInitialization::ActionInitialization()
|
||||
: G4VUserActionInitialization()
|
||||
{}
|
||||
|
||||
ActionInitialization::~ActionInitialization()
|
||||
{}
|
||||
|
||||
void ActionInitialization::BuildForMaster() const
|
||||
{
|
||||
RunAction* runAction = new RunAction;
|
||||
SetUserAction(runAction);
|
||||
}
|
||||
|
||||
void ActionInitialization::Build() const
|
||||
{
|
||||
SetUserAction(new PrimaryGeneratorAction);
|
||||
|
||||
RunAction* runAction = new RunAction;
|
||||
SetUserAction(runAction);
|
||||
|
||||
EventAction* eventAction = new EventAction(runAction);
|
||||
SetUserAction(eventAction);
|
||||
|
||||
SetUserAction(new SteppingAction(eventAction));
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (adapted from B2bChamberParameterisation)
|
||||
// Author: A.Knaian (ara@nklabs.com), N.MacFadden (natemacfadden@gmail.com)
|
||||
|
||||
#include "FACloudParameterisation.hh"
|
||||
|
||||
#include "G4VPhysicalVolume.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4Sphere.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
CloudParameterisation::CloudParameterisation(
|
||||
const std::vector<G4ThreeVector>& positions)
|
||||
: G4VPVParameterisation()
|
||||
{
|
||||
fPositions = positions;
|
||||
}
|
||||
|
||||
CloudParameterisation::~CloudParameterisation()
|
||||
{ }
|
||||
|
||||
void CloudParameterisation::ComputeTransformation
|
||||
(const G4int copyNo, G4VPhysicalVolume* physVol) const
|
||||
{
|
||||
physVol->SetTranslation(fPositions[copyNo]);
|
||||
}
|
||||
@@ -0,0 +1,561 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (adapted from B1DetectorConstruction)
|
||||
// Author: A.Knaian (ara@nklabs.com), N.MacFadden (natemacfadden@gmail.com)
|
||||
|
||||
#include "FADetectorConstruction.hh"
|
||||
#include "FADetectorConstructionMessenger.hh"
|
||||
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4NistManager.hh"
|
||||
|
||||
#include "G4LogicalVolume.hh"
|
||||
#include "G4PVPlacement.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
// shapes
|
||||
#include "G4Box.hh"
|
||||
#include "G4Cons.hh"
|
||||
#include "G4Orb.hh"
|
||||
#include "G4Sphere.hh"
|
||||
#include "G4Trd.hh"
|
||||
#include "G4Tubs.hh"
|
||||
#include "G4Ellipsoid.hh"
|
||||
|
||||
// to build FastAerosol cloud
|
||||
#include "FastAerosolSolid.hh"
|
||||
|
||||
// to build parameterised cloud
|
||||
#include "FACloudParameterisation.hh"
|
||||
#include "G4PVParameterised.hh"
|
||||
#include <fstream>
|
||||
|
||||
// step limits
|
||||
#include "G4UserLimits.hh"
|
||||
|
||||
// visualization
|
||||
#include "G4VisAttributes.hh"
|
||||
#include "G4Colour.hh"
|
||||
|
||||
// to save distribution
|
||||
#include <sys/stat.h>
|
||||
#include <ctime> // for measuring FastAerosol droplet center population time
|
||||
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
DetectorConstruction::DetectorConstruction()
|
||||
: G4VUserDetectorConstruction(),
|
||||
fScoringVolume(0)
|
||||
{
|
||||
fMessenger = new DetectorConstructionMessenger(this);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
DetectorConstruction::~DetectorConstruction()
|
||||
{
|
||||
delete fMessenger;
|
||||
|
||||
delete fStepLimits;
|
||||
|
||||
delete fCloudShape;
|
||||
delete fDropletShape;
|
||||
|
||||
delete fCloud;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VPhysicalVolume* DetectorConstruction::Construct()
|
||||
{
|
||||
//
|
||||
// Check cloud build settings
|
||||
//
|
||||
if (fFastAerosolCloud + fParameterisedCloud + fSmoothCloud > 1)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Must select at most one build type! Selections:" << G4endl
|
||||
<< " fFastAerosolCloud = " << fFastAerosolCloud << G4endl
|
||||
<< " fParameterisedCloud = " << fParameterisedCloud << G4endl
|
||||
<< " fSmoothCloud = " << fSmoothCloud << G4endl;
|
||||
G4Exception("DetectorConstruction::Construct()", "GeomSolids0002",
|
||||
FatalException, message);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Get nist material manager
|
||||
//
|
||||
G4NistManager* nist = G4NistManager::Instance();
|
||||
|
||||
|
||||
//
|
||||
// Option to switch on/off checking of volumes overlaps
|
||||
//
|
||||
G4bool checkOverlaps = false;
|
||||
|
||||
|
||||
//
|
||||
// Large scale geometry dimensions
|
||||
//
|
||||
G4double cloud_sizeXY = 0.5*m;
|
||||
G4double cloud_sizeZ = 5.0*m;
|
||||
|
||||
G4double world_sizeXY = 1.1*(cloud_sizeXY);
|
||||
G4double world_sizeZ= 1.1*(cloud_sizeZ);
|
||||
|
||||
|
||||
//
|
||||
// Cloud shape
|
||||
//
|
||||
if (fCloudShapeStr == "box")
|
||||
{
|
||||
G4cout << "Cloud shape = box" << G4endl;
|
||||
fCloudShape = new G4Box("cloudShape", 0.5*cloud_sizeXY, 0.5*cloud_sizeXY, 0.5*cloud_sizeZ);
|
||||
}
|
||||
else if (fCloudShapeStr == "ellipsoid")
|
||||
{
|
||||
G4cout << "Cloud shape = ellipsoid" << G4endl;
|
||||
fCloudShape = new G4Ellipsoid("cloudShape", 0.5*cloud_sizeXY, 0.5*cloud_sizeXY, 0.5*cloud_sizeZ, 0, 0);
|
||||
}
|
||||
else if (fCloudShapeStr == "cylinder")
|
||||
{
|
||||
G4cout << "Cloud shape = cylinder" << G4endl;
|
||||
fCloudShape = new G4Tubs("cloudShape", 0.0, 0.5*cloud_sizeXY, 0.5*cloud_sizeZ, 0, 360*deg);
|
||||
}
|
||||
else if (fCloudShapeStr == "pipe")
|
||||
{
|
||||
G4cout << "Cloud shape = pipe" << G4endl;
|
||||
fCloudShape = new G4Tubs("cloudShape", 0.25*cloud_sizeXY, 0.5*cloud_sizeXY, 0.5*cloud_sizeZ, 0, 360.*deg);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid cloud shape = " << fCloudShapeStr << "!";
|
||||
G4Exception("DetectorConstruction::Construct()", "GeomSolids0002",
|
||||
FatalException, message);
|
||||
}
|
||||
|
||||
//
|
||||
// Droplet Shape
|
||||
//
|
||||
|
||||
// The difference in radii of the maximal sphere (centered at the origin) contained in the droplet and the minimal sphere (centered at the origin) containing the droplet
|
||||
G4double sphericalUncertainty = 0.0;
|
||||
|
||||
if (fDropletShapeStr == "sphere")
|
||||
{
|
||||
G4cout << "Droplet shape = sphere" << G4endl;
|
||||
fDropletShape = new G4Orb("dropletSV", fDropletR);
|
||||
sphericalUncertainty = 0.0;
|
||||
}
|
||||
else if (fDropletShapeStr == "halfSphere")
|
||||
{
|
||||
G4cout << "Droplet shape = halfSphere" << G4endl;
|
||||
fDropletShape = new G4Sphere("dropletSV", 0.0, fDropletR,
|
||||
0.0, 180.*deg,
|
||||
0.0, 180.*deg);
|
||||
sphericalUncertainty = fDropletR;
|
||||
}
|
||||
else if (fDropletShapeStr == "cylinder")
|
||||
{
|
||||
G4cout << "Droplet shape = cylinder" << G4endl;
|
||||
fDropletShape = new G4Tubs("dropletSV", 0, fDropletR/std::sqrt(3), fDropletR/std::sqrt(3), 0, 360.*deg);
|
||||
sphericalUncertainty = fDropletR*(1-1/std::sqrt(3));
|
||||
}
|
||||
else if (fDropletShapeStr == "box")
|
||||
{
|
||||
G4cout << "Droplet shape = box" << G4endl;
|
||||
fDropletShape = new G4Box("dropletSV", fDropletR/std::sqrt(3), fDropletR/std::sqrt(3), fDropletR/std::sqrt(3));
|
||||
sphericalUncertainty = fDropletR*(1-1/std::sqrt(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Invalid droplet shape = " << fCloudShapeStr << "!";
|
||||
G4Exception("DetectorConstruction::Construct()", "GeomSolids0002",
|
||||
FatalException, message);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Materials
|
||||
//
|
||||
|
||||
// Compute the density of air at 14 km using the Barometric formula
|
||||
// see, e.g., https://en.wikipedia.org/wiki/Density_of_air
|
||||
G4double h = 14.0*km;
|
||||
G4double p0 = 101325*hep_pascal;
|
||||
G4double T0 = 288.15*kelvin;
|
||||
G4double grav = 9.80665*m/(s*s);
|
||||
G4double La = 0.0065*kelvin/m;
|
||||
G4double R = 8.31447*joule/(mole*kelvin);
|
||||
G4double M = 0.0289644*kg/mole;
|
||||
G4double T = T0 - La*h;
|
||||
G4double p = p0*std::pow(1-La*h/T0,grav*M/(R*La));
|
||||
G4double air_density = p*M/(R*T);
|
||||
|
||||
// make materials and set densities
|
||||
G4Material* air_mat = nist->BuildMaterialWithNewDensity("Atmosphere","G4_AIR",air_density);
|
||||
G4Material* water_mat = nist->FindOrBuildMaterial("G4_WATER");
|
||||
|
||||
G4double water_density = water_mat->GetDensity();
|
||||
G4double ice_density = 0.9168*g/cm3;
|
||||
|
||||
G4Material* ice_mat = new G4Material("Water ice ", ice_density, 1, kStateSolid, T, p);
|
||||
ice_mat->AddMaterial(water_mat, 1.);
|
||||
|
||||
|
||||
//
|
||||
// Droplets
|
||||
//
|
||||
G4double droplet_density = water_density;
|
||||
G4Material* droplet_mat = water_mat;
|
||||
|
||||
G4double droplet_count = fDropletNumDens*(fCloudShape->GetCubicVolume());
|
||||
|
||||
G4double droplet_volume = fDropletShape->GetCubicVolume();
|
||||
G4double droplet_total_volume = droplet_count*droplet_volume;
|
||||
|
||||
G4double droplet_total_mass = droplet_total_volume*droplet_density;
|
||||
|
||||
|
||||
//
|
||||
// Cloud macroscopic quantities
|
||||
//
|
||||
G4double cloud_volume = fCloudShape->GetCubicVolume();
|
||||
G4double cloud_air_volume = cloud_volume - droplet_total_volume;
|
||||
G4double cloud_air_mass = air_density*cloud_air_volume;
|
||||
|
||||
|
||||
//
|
||||
// Step limit
|
||||
//
|
||||
fStepLimits = new G4UserLimits(fStepLim);
|
||||
|
||||
|
||||
//
|
||||
// Build world
|
||||
//
|
||||
G4Box* solidWorld =
|
||||
new G4Box("World", //its name
|
||||
0.5*world_sizeXY, //half x-span
|
||||
0.5*world_sizeXY, //half y-span
|
||||
0.5*world_sizeZ); //half z-span
|
||||
|
||||
G4LogicalVolume* logicWorld =
|
||||
new G4LogicalVolume(solidWorld, //its solid
|
||||
air_mat, //its material
|
||||
"World"); //its name
|
||||
|
||||
logicWorld->SetUserLimits(fStepLimits);
|
||||
|
||||
G4VPhysicalVolume* physWorld =
|
||||
new G4PVPlacement(0, //no rotation
|
||||
G4ThreeVector(), //at (0,0,0)
|
||||
logicWorld, //its logical volume
|
||||
"World", //its name
|
||||
0, //its mothervolume
|
||||
false, //no boolean operation
|
||||
0, //copy number
|
||||
checkOverlaps); //overlaps checking
|
||||
|
||||
|
||||
//
|
||||
// Build cloud
|
||||
//
|
||||
G4LogicalVolume* logicCloud;
|
||||
|
||||
// **********************************************************
|
||||
//
|
||||
// Build the cloud using the FastAerosol geometry class
|
||||
//
|
||||
// ***********************************************************
|
||||
if (fFastAerosolCloud) {
|
||||
G4cout << "\nFastAerosol geometry with n=" << fDropletNumDens*mm3 << "/mm3, r=" << fDropletR/mm << "mm spheres.\n" << G4endl;
|
||||
|
||||
fCloud = new FastAerosol("cloud",
|
||||
fCloudShape, //cloud shape
|
||||
fDropletR, //bounding radius of droplets
|
||||
fMinSpacing, //minimum spacing between droplets
|
||||
fDropletNumDens, //approximate number of droplets in cloud
|
||||
sphericalUncertainty); //uncertainty in distance to droplet surface from outside using just droplet's origin as info
|
||||
fCloud->SetDropletsPerVoxel(4);
|
||||
|
||||
/*
|
||||
fCloud = new FastAerosol("fCloud",
|
||||
fCloudShape, //cloud shape
|
||||
fDropletR, //bounding radius of droplets
|
||||
fMinSpacing, //minimum spacing between droplets
|
||||
fDropletNumDens, //approximate number of droplets in cloud
|
||||
sphericalUncertainty, //uncertainty in distance to droplet surface from outside using just droplet's origin as info
|
||||
[](G4ThreeVector pos) {return pos.x();}); //number density distribution function
|
||||
*/
|
||||
|
||||
FastAerosolSolid* solidCloud =
|
||||
new FastAerosolSolid("cloudSV", //its name
|
||||
fCloud, //its shape
|
||||
fDropletShape); //its droplets
|
||||
|
||||
/*
|
||||
FastAerosolSolid* solidCloud =
|
||||
new FastAerosolSolid("cloudSV", //its name
|
||||
fCloud, //its shape
|
||||
fDropletShape, //its droplets
|
||||
[](G4ThreeVector) {G4RotationMatrix rotm = G4RotationMatrix(); rotm.rotateY(90.0*deg); return rotm;}); //droplet rotation function
|
||||
*/
|
||||
|
||||
solidCloud->SetStepLim(fStepLim); //FastAerosol can use step limit to speed calculations
|
||||
|
||||
logicCloud =
|
||||
new G4LogicalVolume(solidCloud, //its solid
|
||||
droplet_mat, //its material
|
||||
"cloudLV"); //its name
|
||||
logicCloud->SetUserLimits(fStepLimits);
|
||||
logicCloud->SetVisAttributes(G4VisAttributes(G4Colour(0.0,0.0,1.0,0.4)));
|
||||
|
||||
new G4PVPlacement(0, //no rotation
|
||||
G4ThreeVector(), //at position
|
||||
logicCloud, //its logical volume
|
||||
"cloudPV", //its name
|
||||
logicWorld, //its mother volume
|
||||
false, //no boolean operation
|
||||
0, //copy number
|
||||
checkOverlaps); //overlaps checking
|
||||
|
||||
|
||||
fCloud->SetSeed(fCloudSeed);
|
||||
|
||||
// fPrePopulate = whether to populate all voxels at the beginning or on the fly
|
||||
if (fPrePopulate) {
|
||||
// populate (proving it to the user by printing population reports)
|
||||
clock_t t;
|
||||
t = clock();
|
||||
|
||||
G4cout << "\nBefore populating" << G4endl;
|
||||
G4cout << "=================" << G4endl;
|
||||
fCloud->PrintPopulationReport();
|
||||
G4cout << "\nPopulating..." << G4endl;
|
||||
fCloud->PopulateAllGrids();
|
||||
G4cout << "\nAfter populating" << G4endl;
|
||||
G4cout << "================" << G4endl;
|
||||
fCloud->PrintPopulationReport();
|
||||
G4cout << G4endl;
|
||||
|
||||
t = clock() - t;
|
||||
|
||||
G4cout << "\nThis took " << ((float)t)/CLOCKS_PER_SEC << "s\n" << G4endl;
|
||||
|
||||
// make filename variables to save data
|
||||
G4String rStr = std::to_string(fDropletR/mm);
|
||||
rStr.erase ( rStr.find_last_not_of('0') + 1, std::string::npos ); // drop trailing 0
|
||||
replace( rStr.begin(), rStr.end(), '.', 'p');
|
||||
if (rStr.back() == 'p') { rStr.pop_back(); } // don't write "3p" for 3.0, just write "3"
|
||||
|
||||
// want to represent the number density as 1E-ApB for some A, B
|
||||
G4int order10 = (G4int) -round(10*std::log10(fDropletNumDens*mm3)); // gives 10x the exponent rounded to the int (10x so we get two decimals)
|
||||
G4int leading = order10 / 10; // first number
|
||||
G4int trailing = order10 % 10; // second number
|
||||
G4String nStr = "1E-" + std::to_string(leading) + "p" + std::to_string(trailing);
|
||||
|
||||
|
||||
// save population time
|
||||
std::ofstream file;
|
||||
file.open("popTime_r" + rStr + "mm_n" + nStr + "mm-3.csv");
|
||||
file << ((float)t)/CLOCKS_PER_SEC;
|
||||
file.close();
|
||||
|
||||
|
||||
|
||||
// save distribution
|
||||
G4String fName = "distribution_r" + rStr + "mm_n" + nStr + "mm-3.csv";
|
||||
fCloud->SaveToFile(fName);
|
||||
}
|
||||
}
|
||||
// **********************************************************
|
||||
//
|
||||
// (For comparision/benchmarking) Build the cloud using G4VParameterized (does not use FastAerosol)
|
||||
//
|
||||
// ***********************************************************
|
||||
|
||||
// the droplet positions for this cloud are those saved in the "distribution" folder of our data
|
||||
// this is to make comparable simulations between FastAerosol and parameterised clouds
|
||||
// this requires that we first simulate FastAerosol (pre-populated) to generate the positions
|
||||
|
||||
else if (fParameterisedCloud)
|
||||
{
|
||||
G4cout << "\nParameterised geometry with n=" << fDropletNumDens*mm3 << "/mm3 and r=" << fDropletR/mm << "mm spheres.\n" << G4endl;
|
||||
std::vector<G4ThreeVector> positions;
|
||||
G4double x,y,z;
|
||||
|
||||
// load distribution file
|
||||
G4String fName;
|
||||
|
||||
G4String rStr = std::to_string(fDropletR/mm);
|
||||
rStr.erase ( rStr.find_last_not_of('0') + 1, std::string::npos ); // drop trailing 0
|
||||
replace( rStr.begin(), rStr.end(), '.', 'p');
|
||||
if (rStr.back() == 'p') { rStr.pop_back(); } // don't write "3p" for 3.0, just write "3"
|
||||
|
||||
// want to represent the number density as 1E-ApB for some A, B
|
||||
G4int order10 = (G4int) -round(10*std::log10(fDropletNumDens*mm3)); // gives 10x the exponent rounded to the int (10x so we get two decimals)
|
||||
G4int leading = order10 / 10; // first number
|
||||
G4int trailing = order10 % 10; // second number
|
||||
G4String nStr = "1E-" + std::to_string(leading) + "p" + std::to_string(trailing);
|
||||
|
||||
fName = "distribution_r" + rStr + "mm_n" + nStr + "mm-3.csv";
|
||||
|
||||
std::ifstream infile(fName);
|
||||
std::string line;
|
||||
|
||||
while (getline(infile,line)) {
|
||||
std::istringstream stream(line);
|
||||
std::string field;
|
||||
|
||||
getline(stream,field,','); x = stod(field)*mm;
|
||||
getline(stream,field,','); y = stod(field)*mm;
|
||||
getline(stream,field,','); z = stod(field)*mm;
|
||||
|
||||
positions.push_back(G4ThreeVector(x,y,z));
|
||||
}
|
||||
|
||||
G4VPVParameterisation* cloudParam =
|
||||
new CloudParameterisation(positions);
|
||||
|
||||
G4Box* cloudBounding =
|
||||
new G4Box("cloudBounding", //its name
|
||||
0.5*cloud_sizeXY, //half x-span
|
||||
0.5*cloud_sizeXY, //half y-span
|
||||
0.5*cloud_sizeZ); //half z-span
|
||||
|
||||
logicCloud =
|
||||
new G4LogicalVolume(cloudBounding, //its solid
|
||||
air_mat, //its material
|
||||
"cloudLV"); //its name
|
||||
|
||||
logicCloud->SetSmartless(fSmartless);
|
||||
logicCloud->SetUserLimits(fStepLimits);
|
||||
logicCloud->SetVisAttributes(G4VisAttributes(false));
|
||||
|
||||
new G4PVPlacement(0, //no rotation
|
||||
G4ThreeVector(), //at position
|
||||
logicCloud, //its logical volume
|
||||
"cloudPV", //its name
|
||||
logicWorld, //its mothervolume
|
||||
false, //no boolean operation
|
||||
0, //copy number
|
||||
checkOverlaps); //overlaps checking
|
||||
|
||||
G4LogicalVolume* logicDroplet =
|
||||
new G4LogicalVolume(fDropletShape, //its solid
|
||||
droplet_mat, //its material
|
||||
"dropletLV"); //its name
|
||||
|
||||
logicDroplet->SetUserLimits(fStepLimits);
|
||||
|
||||
/*G4PVParameterised* paramDroplet =*/
|
||||
new G4PVParameterised("droplets", //its name
|
||||
logicDroplet, //droplet logical volume
|
||||
logicCloud, //mother logical volume
|
||||
kUndefined, //droplets placed along this axis
|
||||
positions.size(), //number of droplets
|
||||
cloudParam); //the parametrisation
|
||||
}
|
||||
// **********************************************************
|
||||
//
|
||||
// (For comparision/benchmarking) Simulate the cloud by smearing droplets out into a single solid (does not use FastAerosol)
|
||||
//
|
||||
// ***********************************************************
|
||||
else if (fSmoothCloud)
|
||||
{
|
||||
G4cout << "\nSmooth geometry based on a cloud of n=" << fDropletNumDens*mm3 << "/mm3 and r=" << fDropletR/mm << "mm spheres.\n" << G4endl;
|
||||
// build cloud by smearing the droplets uniformly across the cloud volume, for comparison/benchmarking purposes (does not use FastAerosol)
|
||||
G4Material* cloud_mat = new G4Material("Cloud", (droplet_total_mass+cloud_air_mass)/cloud_volume, 2);
|
||||
cloud_mat->AddMaterial(droplet_mat, droplet_total_mass/(cloud_air_mass+droplet_total_mass));
|
||||
cloud_mat->AddMaterial(air_mat, cloud_air_mass/(cloud_air_mass+droplet_total_mass));
|
||||
|
||||
logicCloud =
|
||||
new G4LogicalVolume(fCloudShape, //its solid
|
||||
cloud_mat, //its material
|
||||
"cloudLV"); //its name
|
||||
logicCloud->SetUserLimits(fStepLimits);
|
||||
logicCloud->SetVisAttributes(G4VisAttributes(G4Colour(0.0,0.0,1.0,0.4)));
|
||||
|
||||
new G4PVPlacement(0, //no rotation
|
||||
G4ThreeVector(), //at position
|
||||
logicCloud, //its logical volume
|
||||
"cloudPV", //its name
|
||||
logicWorld, //its mothervolume
|
||||
false, //no boolean operation
|
||||
0, //copy number
|
||||
checkOverlaps); //overlaps checking
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cout << "\nNo cloud.\n" << G4endl;
|
||||
}
|
||||
|
||||
//
|
||||
// Build detector
|
||||
//
|
||||
G4double detector_sizeXY = cloud_sizeXY;
|
||||
G4double detector_sizeZ = 0.05*m;
|
||||
G4Material* detector_mat = nist->FindOrBuildMaterial("G4_Al");
|
||||
G4ThreeVector detector_pos = G4ThreeVector(0, 0, 0.5*1.05*cloud_sizeZ);
|
||||
|
||||
G4Box* soldDetector =
|
||||
new G4Box("detectorSV", //its name
|
||||
0.5*detector_sizeXY, //half x-span
|
||||
0.5*detector_sizeXY, //half y-span
|
||||
0.5*detector_sizeZ); //half z-span
|
||||
|
||||
G4LogicalVolume* logicDetector =
|
||||
new G4LogicalVolume(soldDetector, //its solid
|
||||
detector_mat, //its material
|
||||
"detectorLV"); //its name
|
||||
|
||||
logicDetector->SetUserLimits(fStepLimits);
|
||||
|
||||
new G4PVPlacement(0, //no rotation
|
||||
detector_pos, //at position
|
||||
logicDetector, //its logical volume
|
||||
"detectorPV", //its name
|
||||
logicWorld, //its mothervolume
|
||||
false, //no boolean operation
|
||||
0, //copy number
|
||||
checkOverlaps); //overlaps checking
|
||||
|
||||
|
||||
//
|
||||
// Scoring Volume
|
||||
//
|
||||
fScoringVolume = logicDetector;
|
||||
|
||||
return physWorld;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (adapted from B2aDetectorMessenger)
|
||||
// Author: A.Knaian (ara@nklabs.com), N.MacFadden (natemacfadden@gmail.com)
|
||||
|
||||
#include "FADetectorConstructionMessenger.hh"
|
||||
#include "FADetectorConstruction.hh"
|
||||
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
#include "G4UIcmdWithADouble.hh"
|
||||
#include "G4UIcmdWithABool.hh"
|
||||
#include "G4UIcmdWithAString.hh"
|
||||
|
||||
DetectorConstructionMessenger::DetectorConstructionMessenger(DetectorConstruction* detectorIn)
|
||||
: G4UImessenger()
|
||||
{
|
||||
fDetector = detectorIn;
|
||||
|
||||
// Directory
|
||||
//
|
||||
// /geometry
|
||||
fGeometryDirectory = new G4UIdirectory("/geometry/");
|
||||
fGeometryDirectory->SetGuidance("Geometry setup.");
|
||||
|
||||
// Physics
|
||||
//
|
||||
// /geometry/stepLim
|
||||
fStepLimCmd = new G4UIcmdWithADoubleAndUnit("/geometry/stepLim",this);
|
||||
fStepLimCmd->SetGuidance("Maximum step length.");
|
||||
fStepLimCmd->SetParameterName("stepLim",false);
|
||||
fStepLimCmd->SetRange("stepLim>=0.");
|
||||
fStepLimCmd->SetDefaultValue(DBL_MAX);
|
||||
fStepLimCmd->SetDefaultUnit("mm");
|
||||
fStepLimCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// Cloud droplet settings
|
||||
// /geometry/dropletR
|
||||
fDropletRCmd = new G4UIcmdWithADoubleAndUnit("/geometry/dropletR",this);
|
||||
fDropletRCmd->SetGuidance("Minimal bounding radius of droplet.");
|
||||
fDropletRCmd->SetParameterName("dropletR",false);
|
||||
fDropletRCmd->SetRange("dropletR>0.");
|
||||
fDropletRCmd->SetDefaultValue(1.0);
|
||||
fDropletRCmd->SetDefaultUnit("mm");
|
||||
fDropletRCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/dropletNumDens
|
||||
fDropletNumDensCmd = new G4UIcmdWithADouble("/geometry/dropletNumDens", this);
|
||||
fDropletNumDensCmd->SetGuidance("Number of droplets per mm^3."); // would be nice to have official number density units
|
||||
fDropletNumDensCmd->SetParameterName("dropletCOunt",false);
|
||||
fDropletNumDensCmd->SetDefaultValue(0);
|
||||
fDropletNumDensCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// Cloud build type
|
||||
//
|
||||
// /geometry/fastAerosol
|
||||
fFastAerosolCloudCmd = new G4UIcmdWithABool("/geometry/fastAerosolCloud",this);
|
||||
fFastAerosolCloudCmd->SetGuidance("Whether or not to build the fastAerosol cloud.");
|
||||
fFastAerosolCloudCmd->SetParameterName("fastAerosol",false);
|
||||
fFastAerosolCloudCmd->SetDefaultValue(false);
|
||||
fFastAerosolCloudCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/parameterisedCloud
|
||||
fParameterisedCloudCmd = new G4UIcmdWithABool("/geometry/parameterisedCloud",this);
|
||||
fParameterisedCloudCmd->SetGuidance("Whether or not to build the parameterised cloud.");
|
||||
fParameterisedCloudCmd->SetParameterName("parameterisedCloud",false);
|
||||
fParameterisedCloudCmd->SetDefaultValue(false);
|
||||
fParameterisedCloudCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/smoothCloud
|
||||
fSmoothCloudCmd = new G4UIcmdWithABool("/geometry/smoothCloud",this);
|
||||
fSmoothCloudCmd->SetGuidance("Whether or not to build the smooth cloud.");
|
||||
fSmoothCloudCmd->SetParameterName("smoothCloud",false);
|
||||
fSmoothCloudCmd->SetDefaultValue(false);
|
||||
fSmoothCloudCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// fastAerosol cloud details
|
||||
//
|
||||
// /geometry/cloudShape
|
||||
fCloudShapeCmd = new G4UIcmdWithAString("/geometry/cloudShape",this);
|
||||
fCloudShapeCmd->SetGuidance("Cloud bulk shape");
|
||||
fCloudShapeCmd->SetParameterName("cloudShapeStr",false);
|
||||
fCloudShapeCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/dropletShape
|
||||
fDropletShapeCmd = new G4UIcmdWithAString("/geometry/dropletShape",this);
|
||||
fDropletShapeCmd->SetGuidance("Cloud droplet shape");
|
||||
fDropletShapeCmd->SetParameterName("dropletShapeStr",false);
|
||||
fDropletShapeCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/prePopulate
|
||||
fPrePopulateCmd = new G4UIcmdWithABool("/geometry/prePopulate",this);
|
||||
fPrePopulateCmd->SetGuidance("Whether or not to populate the cloud at the beginning.");
|
||||
fPrePopulateCmd->SetParameterName("prePopulate",false);
|
||||
fPrePopulateCmd->SetDefaultValue(false);
|
||||
fPrePopulateCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/minSpacing
|
||||
fMinSpacingCmd = new G4UIcmdWithADoubleAndUnit("/geometry/minSpacing",this);
|
||||
fMinSpacingCmd->SetGuidance("Minimum spacing between surfaces of spheres when generating random cloud of spheres.");
|
||||
fMinSpacingCmd->SetParameterName("minSpacing",false);
|
||||
fMinSpacingCmd->SetRange("minSpacing>0.");
|
||||
fMinSpacingCmd->SetDefaultValue(10.);
|
||||
fMinSpacingCmd->SetDefaultUnit("micrometer");
|
||||
fMinSpacingCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/setSmartless
|
||||
fSmartlessCmd = new G4UIcmdWithADouble("/geometry/smartless", this);
|
||||
fSmartlessCmd->SetGuidance("Set the 'smartless' parameter for the parameterised cloud.");
|
||||
fSmartlessCmd->SetParameterName("smartless",false);
|
||||
fSmartlessCmd->SetRange("smartless>0.");
|
||||
fSmartlessCmd->SetDefaultValue(2.0);
|
||||
fSmartlessCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
// /geometry/cloudSeed
|
||||
fCloudSeedCmd = new G4UIcmdWithAnInteger("/geometry/cloudSeed", this);
|
||||
fCloudSeedCmd->SetGuidance("Base of the random seed for the cloud sphere positions.");
|
||||
fCloudSeedCmd->SetParameterName("cloudSeed",false);
|
||||
fCloudSeedCmd->SetDefaultValue(0);
|
||||
fCloudSeedCmd->AvailableForStates(G4State_PreInit);
|
||||
}
|
||||
|
||||
DetectorConstructionMessenger::~DetectorConstructionMessenger()
|
||||
{
|
||||
delete fGeometryDirectory;
|
||||
|
||||
delete fStepLimCmd;
|
||||
|
||||
delete fDropletRCmd;
|
||||
delete fDropletNumDensCmd;
|
||||
|
||||
delete fFastAerosolCloudCmd;
|
||||
delete fParameterisedCloudCmd;
|
||||
delete fSmoothCloudCmd;
|
||||
|
||||
delete fCloudShapeCmd;
|
||||
delete fDropletShapeCmd;
|
||||
delete fPrePopulateCmd;
|
||||
delete fMinSpacingCmd;
|
||||
//delete fGridPitchCmd;
|
||||
|
||||
delete fSmartlessCmd;
|
||||
|
||||
delete fCloudSeedCmd;
|
||||
}
|
||||
|
||||
void DetectorConstructionMessenger::SetNewValue( G4UIcommand* command, G4String newValue)
|
||||
{
|
||||
// Geometry Commands
|
||||
|
||||
if( command == fFastAerosolCloudCmd ) {
|
||||
fDetector->fFastAerosolCloud = (fFastAerosolCloudCmd->GetNewBoolValue(newValue));
|
||||
}
|
||||
|
||||
if( command == fStepLimCmd ) {
|
||||
fDetector->fStepLim = (fStepLimCmd->GetNewDoubleValue(newValue));
|
||||
}
|
||||
|
||||
if( command == fDropletRCmd ) {
|
||||
fDetector->fDropletR = (fDropletRCmd->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fDropletNumDensCmd ) {
|
||||
fDetector->fDropletNumDens = (fDropletNumDensCmd->GetNewDoubleValue(newValue));
|
||||
}
|
||||
|
||||
if( command == fParameterisedCloudCmd ) {
|
||||
fDetector->fParameterisedCloud = (fParameterisedCloudCmd->GetNewBoolValue(newValue));
|
||||
}
|
||||
if( command == fSmoothCloudCmd ) {
|
||||
fDetector->fSmoothCloud = (fSmoothCloudCmd->GetNewBoolValue(newValue));
|
||||
}
|
||||
if( command == fPrePopulateCmd ) {
|
||||
fDetector->fPrePopulate = (fPrePopulateCmd->GetNewBoolValue(newValue));
|
||||
}
|
||||
|
||||
if( command == fCloudShapeCmd ) {
|
||||
fDetector->fCloudShapeStr = newValue;
|
||||
}
|
||||
if( command == fDropletShapeCmd ) {
|
||||
fDetector->fDropletShapeStr = newValue;
|
||||
}
|
||||
if( command == fMinSpacingCmd ) {
|
||||
fDetector->fMinSpacing = (fMinSpacingCmd->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fSmartlessCmd ) {
|
||||
fDetector->fSmartless = (fSmartlessCmd->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fCloudSeedCmd ) {
|
||||
fDetector->fCloudSeed = (fCloudSeedCmd->GetNewIntValue(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (copied from B1EventAction)
|
||||
|
||||
#include "FAEventAction.hh"
|
||||
#include "FARunAction.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4RunManager.hh"
|
||||
|
||||
EventAction::EventAction(RunAction* runAction)
|
||||
: G4UserEventAction(),
|
||||
fRunAction(runAction),
|
||||
fEdep(0.)
|
||||
{}
|
||||
|
||||
EventAction::~EventAction()
|
||||
{}
|
||||
|
||||
void EventAction::BeginOfEventAction(const G4Event*)
|
||||
{
|
||||
fEdep = 0.;
|
||||
}
|
||||
|
||||
void EventAction::EndOfEventAction(const G4Event*)
|
||||
{
|
||||
// accumulate statistics in run action
|
||||
fRunAction->AddEdep(fEdep);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (adapted from B1PrimaryGeneratorAction)
|
||||
// Author: A.Knaian (ara@nklabs.com), N.MacFadden (natemacfadden@gmail.com)
|
||||
|
||||
#include "FAPrimaryGeneratorAction.hh"
|
||||
#include "G4LogicalVolumeStore.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
#include "G4Box.hh"
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4ParticleGun.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "Randomize.hh"
|
||||
|
||||
PrimaryGeneratorAction::PrimaryGeneratorAction()
|
||||
: G4VUserPrimaryGeneratorAction(),
|
||||
fParticleGun(0),
|
||||
fWorldBox(0)
|
||||
{
|
||||
G4int n_particle = 1;
|
||||
fParticleGun = new G4ParticleGun(n_particle);
|
||||
|
||||
// default particle kinematic
|
||||
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
||||
G4String particleName;
|
||||
G4ParticleDefinition* particle
|
||||
= particleTable->FindParticle(particleName="proton");
|
||||
fParticleGun->SetParticleDefinition(particle);
|
||||
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0.,0.,1.));
|
||||
fParticleGun->SetParticleEnergy(50.*MeV);
|
||||
}
|
||||
|
||||
PrimaryGeneratorAction::~PrimaryGeneratorAction()
|
||||
{
|
||||
delete fParticleGun;
|
||||
}
|
||||
|
||||
void PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
|
||||
{
|
||||
G4double worldSizeXY = 0;
|
||||
G4double worldSizeZ = 0;
|
||||
|
||||
if (!fWorldBox)
|
||||
{
|
||||
G4LogicalVolume* worldLV
|
||||
= G4LogicalVolumeStore::GetInstance()->GetVolume("World");
|
||||
if ( worldLV ) fWorldBox = dynamic_cast<G4Box*>(worldLV->GetSolid());
|
||||
}
|
||||
|
||||
if ( fWorldBox ) {
|
||||
worldSizeXY = fWorldBox->GetXHalfLength()*2.;
|
||||
worldSizeZ = fWorldBox->GetZHalfLength()*2.;
|
||||
}
|
||||
else {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "World volume of box shape not found.\n";
|
||||
msg << "Perhaps you have changed geometry.\n";
|
||||
msg << "The gun will be place at the center.";
|
||||
G4Exception("PrimaryGeneratorAction::GeneratePrimaries()",
|
||||
"MyCode0002",JustWarning,msg);
|
||||
}
|
||||
|
||||
// shoot on XY disk centered on Z-axis behind the cloud
|
||||
G4double sigma = worldSizeXY/10.0; // spread in x and y
|
||||
G4double x0 = G4RandGauss::shoot(0,sigma);
|
||||
G4double y0 = G4RandGauss::shoot(0,sigma);
|
||||
G4double z0 = 0.95 * (-0.5) * worldSizeZ;
|
||||
|
||||
fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
|
||||
|
||||
fParticleGun->GeneratePrimaryVertex(anEvent);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (copied from B1RunAction)
|
||||
|
||||
#include "FARunAction.hh"
|
||||
#include "FAPrimaryGeneratorAction.hh"
|
||||
#include "FADetectorConstruction.hh"
|
||||
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4Run.hh"
|
||||
#include "G4AccumulableManager.hh"
|
||||
#include "G4LogicalVolumeStore.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
RunAction::RunAction()
|
||||
: G4UserRunAction(),
|
||||
fEdep(0.),
|
||||
fEdep2(0.)
|
||||
{
|
||||
// add new units for dose
|
||||
//
|
||||
const G4double milligray = 1.e-3*gray;
|
||||
const G4double microgray = 1.e-6*gray;
|
||||
const G4double nanogray = 1.e-9*gray;
|
||||
const G4double picogray = 1.e-12*gray;
|
||||
|
||||
new G4UnitDefinition("milligray", "milliGy" , "Dose", milligray);
|
||||
new G4UnitDefinition("microgray", "microGy" , "Dose", microgray);
|
||||
new G4UnitDefinition("nanogray" , "nanoGy" , "Dose", nanogray);
|
||||
new G4UnitDefinition("picogray" , "picoGy" , "Dose", picogray);
|
||||
|
||||
// Register accumulable to the accumulable manager
|
||||
G4AccumulableManager* accumulableManager = G4AccumulableManager::Instance();
|
||||
accumulableManager->RegisterAccumulable(fEdep);
|
||||
accumulableManager->RegisterAccumulable(fEdep2);
|
||||
}
|
||||
|
||||
RunAction::~RunAction()
|
||||
{}
|
||||
|
||||
void RunAction::BeginOfRunAction(const G4Run*)
|
||||
{
|
||||
// inform the runManager to save random number seed
|
||||
G4RunManager::GetRunManager()->SetRandomNumberStore(false);
|
||||
|
||||
// reset accumulables to their initial values
|
||||
G4AccumulableManager* accumulableManager = G4AccumulableManager::Instance();
|
||||
accumulableManager->Reset();
|
||||
|
||||
}
|
||||
|
||||
void RunAction::EndOfRunAction(const G4Run* run)
|
||||
{
|
||||
G4int nofEvents = run->GetNumberOfEvent();
|
||||
if (nofEvents == 0) return;
|
||||
|
||||
// Merge accumulables
|
||||
G4AccumulableManager* accumulableManager = G4AccumulableManager::Instance();
|
||||
accumulableManager->Merge();
|
||||
|
||||
// Compute dose = total energy deposit in a run and its variance
|
||||
//
|
||||
G4double edep = fEdep.GetValue();
|
||||
G4double edep2 = fEdep2.GetValue();
|
||||
|
||||
G4double rms = edep2 - edep*edep/nofEvents;
|
||||
if (rms > 0.) rms = std::sqrt(rms); else rms = 0.;
|
||||
|
||||
const DetectorConstruction* detectorConstruction
|
||||
= static_cast<const DetectorConstruction*>
|
||||
(G4RunManager::GetRunManager()->GetUserDetectorConstruction());
|
||||
G4double mass = detectorConstruction->GetScoringVolume()->GetMass();
|
||||
G4double dose = edep/mass;
|
||||
G4double rmsDose = rms/mass;
|
||||
|
||||
// Run conditions
|
||||
// note: There is no primary generator action object for "master"
|
||||
// run manager for multi-threaded mode.
|
||||
const PrimaryGeneratorAction* generatorAction
|
||||
= static_cast<const PrimaryGeneratorAction*>
|
||||
(G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction());
|
||||
G4String runCondition;
|
||||
if (generatorAction)
|
||||
{
|
||||
const G4ParticleGun* particleGun = generatorAction->GetParticleGun();
|
||||
runCondition += particleGun->GetParticleDefinition()->GetParticleName();
|
||||
runCondition += " of ";
|
||||
G4double particleEnergy = particleGun->GetParticleEnergy();
|
||||
runCondition += G4BestUnit(particleEnergy,"Energy");
|
||||
}
|
||||
|
||||
// Print
|
||||
//
|
||||
if (IsMaster()) {
|
||||
G4cout
|
||||
<< G4endl
|
||||
<< "--------------------End of Global Run-----------------------";
|
||||
}
|
||||
else {
|
||||
G4cout
|
||||
<< G4endl
|
||||
<< "--------------------End of Local Run------------------------";
|
||||
}
|
||||
|
||||
G4cout
|
||||
<< G4endl
|
||||
<< " The run consists of " << nofEvents << " "<< runCondition
|
||||
<< G4endl
|
||||
<< " Cumulated dose per run, in scoring volume : "
|
||||
<< G4BestUnit(dose,"Dose") << " rms = " << G4BestUnit(rmsDose,"Dose")
|
||||
<< G4endl
|
||||
<< "------------------------------------------------------------"
|
||||
<< G4endl
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
void RunAction::AddEdep(G4double edep)
|
||||
{
|
||||
fEdep += edep;
|
||||
fEdep2 += edep*edep;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// (copied from B1SteppingAction)
|
||||
|
||||
#include "FASteppingAction.hh"
|
||||
#include "FAEventAction.hh"
|
||||
#include "FADetectorConstruction.hh"
|
||||
|
||||
#include "G4Step.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
|
||||
SteppingAction::SteppingAction(EventAction* eventAction)
|
||||
: G4UserSteppingAction(),
|
||||
fEventAction(eventAction),
|
||||
fScoringVolume(0)
|
||||
{}
|
||||
|
||||
SteppingAction::~SteppingAction()
|
||||
{}
|
||||
|
||||
void SteppingAction::UserSteppingAction(const G4Step* step)
|
||||
{
|
||||
if (!fScoringVolume) {
|
||||
const DetectorConstruction* detectorConstruction
|
||||
= static_cast<const DetectorConstruction*>
|
||||
(G4RunManager::GetRunManager()->GetUserDetectorConstruction());
|
||||
fScoringVolume = detectorConstruction->GetScoringVolume();
|
||||
}
|
||||
|
||||
// get volume of the current step
|
||||
G4LogicalVolume* volume
|
||||
= step->GetPreStepPoint()->GetTouchableHandle()
|
||||
->GetVolume()->GetLogicalVolume();
|
||||
|
||||
// check if we are in scoring volume
|
||||
if (volume != fScoringVolume) return;
|
||||
|
||||
// collect energy deposited in this step
|
||||
G4double edepStep = step->GetTotalEnergyDeposit();
|
||||
fEventAction->AddEdep(edepStep);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,456 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Implementation for FastAerosolSolid class
|
||||
// Author: A.Knaian (ara@nklabs.com), N.MacFadden (natemacfadden@gmail.com)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "FastAerosolSolid.hh"
|
||||
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
// calculate extent
|
||||
#include "G4BoundingEnvelope.hh"
|
||||
#include "G4AffineTransform.hh"
|
||||
#include "G4VoxelLimits.hh"
|
||||
|
||||
// visualization
|
||||
#include "G4VGraphicsScene.hh"
|
||||
#include "G4VisExtent.hh"
|
||||
|
||||
// polyhedron
|
||||
#include "G4AutoLock.hh"
|
||||
#include "G4Polyhedron.hh"
|
||||
#include "HepPolyhedronProcessor.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
FastAerosolSolid::FastAerosolSolid(const G4String& pName,
|
||||
FastAerosol* pCloud,
|
||||
G4VSolid* pDroplet,
|
||||
std::function<G4RotationMatrix (G4ThreeVector)> pRotation)
|
||||
: G4VSolid(pName), fCloud(pCloud), fDroplet(pDroplet), fRotation(pRotation), fRebuildPolyhedron(false), fpPolyhedron(0)
|
||||
{
|
||||
// Get cloud size from fCloud
|
||||
G4ThreeVector cloudPMin, cloudPMax;
|
||||
fCloud->GetBoundingLimits(cloudPMin, cloudPMax);
|
||||
|
||||
fVisDx = cloudPMax.x();
|
||||
fVisDy = cloudPMax.y();
|
||||
fVisDz = cloudPMax.z();
|
||||
|
||||
// Check and set droplet radius
|
||||
G4double pR = fCloud->GetRadius();
|
||||
// would be nice to add a check to make sure pDroplet fits in sphere of radius pR
|
||||
fR = pR;
|
||||
|
||||
fBulk = fCloud->GetBulk();
|
||||
|
||||
farFromCloudDist = fCloud->GetPreSphereR()*fR;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Alternative constructor (constant rotation function)
|
||||
//
|
||||
FastAerosolSolid::FastAerosolSolid(const G4String& pName,
|
||||
FastAerosol* pCloud,
|
||||
G4VSolid* pDroplet):
|
||||
FastAerosolSolid(pName, pCloud, pDroplet,
|
||||
[](G4ThreeVector) {return G4RotationMatrix();})
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Fake default constructor - sets only member data and allocates memory
|
||||
// for usage restricted to object persistency.
|
||||
//
|
||||
FastAerosolSolid::FastAerosolSolid( __void__& a )
|
||||
: G4VSolid(a), fCloud(nullptr), fDroplet(nullptr),
|
||||
fBulk(nullptr), fR(0.),
|
||||
fVisDx(0.), fVisDy(0.), fVisDz(0.),
|
||||
fCubicVolume(0.), fSurfaceArea(0.),
|
||||
farFromCloudDist(0.),
|
||||
fRotation([](G4ThreeVector) {return G4RotationMatrix();}),
|
||||
fRebuildPolyhedron(false), fpPolyhedron(0)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
FastAerosolSolid::~FastAerosolSolid() {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy constructor
|
||||
//
|
||||
FastAerosolSolid::FastAerosolSolid(const FastAerosolSolid &rhs)
|
||||
: G4VSolid(rhs), fCloud(rhs.fCloud), fDroplet(rhs.fDroplet),
|
||||
fBulk(rhs.fBulk), fR(rhs.fR),
|
||||
fVisDx(rhs.fVisDx), fVisDy(rhs.fVisDy), fVisDz(rhs.fVisDz),
|
||||
fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
|
||||
farFromCloudDist(rhs.farFromCloudDist),
|
||||
fRotation(rhs.fRotation),
|
||||
fRebuildPolyhedron(rhs.fRebuildPolyhedron), fpPolyhedron(rhs.fpPolyhedron)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Assignment operator
|
||||
//
|
||||
FastAerosolSolid &FastAerosolSolid::operator = (const FastAerosolSolid &rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
//
|
||||
if (this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
G4VSolid::operator=(rhs);
|
||||
|
||||
// Copy data
|
||||
//
|
||||
fCloud = rhs.fCloud;
|
||||
fDroplet = rhs.fDroplet;
|
||||
fBulk = rhs.fBulk;
|
||||
fR = rhs.fR;
|
||||
fVisDx = rhs.fVisDx;
|
||||
fVisDy = rhs.fVisDy;
|
||||
fVisDz = rhs.fVisDz;
|
||||
fCubicVolume = rhs.fCubicVolume;
|
||||
fSurfaceArea = rhs.fSurfaceArea;
|
||||
farFromCloudDist = rhs.farFromCloudDist;
|
||||
fRotation = rhs.fRotation;
|
||||
fRebuildPolyhedron = rhs.fRebuildPolyhedron;
|
||||
fpPolyhedron = rhs.fpPolyhedron;
|
||||
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate extent under transform and specified limit
|
||||
//
|
||||
G4bool FastAerosolSolid::CalculateExtent(const EAxis pAxis,
|
||||
const G4VoxelLimits &pVoxelLimit,
|
||||
const G4AffineTransform &pTransform,
|
||||
G4double &pMin, G4double &pMax) const
|
||||
{
|
||||
// Get smallest box to fully contain the cloud of objects, not just the centers
|
||||
//
|
||||
G4ThreeVector bmin, bmax;
|
||||
fCloud->GetBoundingLimits(bmin, bmax);
|
||||
|
||||
// Find extent
|
||||
//
|
||||
G4BoundingEnvelope bbox(bmin, bmax);
|
||||
return bbox.CalculateExtent(pAxis, pVoxelLimit, pTransform, pMin, pMax);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return whether point inside/outside/on surface
|
||||
//
|
||||
// This function assumes the cloud has at least 1 droplet
|
||||
//
|
||||
EInside FastAerosolSolid::Inside(const G4ThreeVector &p) const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double closestDistance;
|
||||
|
||||
fCloud->GetNearestDroplet(p, center, closestDistance, fR, fDroplet, fRotation);
|
||||
|
||||
if (closestDistance==0.0)
|
||||
{
|
||||
G4RotationMatrix irotm = fRotation(center).inverse();
|
||||
|
||||
return fDroplet->Inside( irotm*(p - center) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return kOutside;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return unit normal of surface closest to p
|
||||
//
|
||||
// This function assumes the cloud has at least 1 droplet
|
||||
//
|
||||
G4ThreeVector FastAerosolSolid::SurfaceNormal(const G4ThreeVector &p) const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double closestDistance;
|
||||
|
||||
fCloud->GetNearestDroplet(p, center, closestDistance, DBL_MAX, fDroplet, fRotation);
|
||||
|
||||
G4RotationMatrix rotm = fRotation(center);
|
||||
|
||||
return rotm*( fDroplet->SurfaceNormal( rotm.inverse()*(p - center) ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate distance to shape from outside, along normalised vector
|
||||
//
|
||||
// This CANNOT be an underestimate
|
||||
//
|
||||
G4double FastAerosolSolid::DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double closestDistance;
|
||||
|
||||
if (fCloud->GetNearestDroplet(p, v, center, closestDistance, fStepLim, fDroplet, fRotation)) // if we found a droplet within fStepLim of query
|
||||
{
|
||||
return closestDistance;
|
||||
}
|
||||
else if (fCloud->DistanceToCloud(p,v)<DBL_MAX) // if there is cloud in front of us
|
||||
{
|
||||
return 1.1*fStepLim;
|
||||
}
|
||||
else // flying away from cloud
|
||||
{
|
||||
return kInfinity;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate distance (<= actual) to closest surface of shape from outside
|
||||
//
|
||||
// This function assumes the cloud has at least 1 droplet
|
||||
//
|
||||
// This can be an underestimate
|
||||
//
|
||||
G4double FastAerosolSolid::DistanceToIn(const G4ThreeVector &p) const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double closestDistance;
|
||||
|
||||
G4double distanceToCloud = fBulk->DistanceToIn(p);
|
||||
|
||||
if (fBulk->Inside(p)==kOutside && distanceToCloud>=farFromCloudDist)
|
||||
{
|
||||
return distanceToCloud;
|
||||
}
|
||||
else if (fCloud->GetNearestDroplet(p, center, closestDistance, fStepLim, fDroplet, fRotation)) // if we found a droplet within fStepLim of query
|
||||
{
|
||||
return closestDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1.1*fStepLim;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate distance (<= actual) to closest surface of shape from inside
|
||||
//
|
||||
// Despite being a vector distance, we find the absolutely closest
|
||||
// droplet to our point since we assume that p is in a droplet and p
|
||||
// could be past the center
|
||||
//
|
||||
// This CANNOT be an underestimate
|
||||
//
|
||||
G4double FastAerosolSolid::DistanceToOut(const G4ThreeVector &p,
|
||||
const G4ThreeVector &v,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n) const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double distanceToIn; // should be 0
|
||||
|
||||
fCloud->GetNearestDroplet(p, center, distanceToIn, fR, fDroplet, fRotation); // if we call this function, must be inside and thus must have a droplet within fR
|
||||
|
||||
G4RotationMatrix rotm = fRotation(center);
|
||||
G4RotationMatrix irotm = rotm.inverse();
|
||||
|
||||
G4ThreeVector relPos = irotm*(p-center);
|
||||
|
||||
if (fDroplet->Inside(relPos) == kOutside) // something went wrong... we should be inside
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << std::setprecision(15) << "The particle at point p = " << p/mm << "mm"
|
||||
<< std::setprecision(15) << " called DistanceToOut(p,v) and found the closest droplet to be at center = " << center/mm << "mm"
|
||||
<< " but p is outside the droplet!";
|
||||
G4Exception("FastAerosolSolid::DistanceToOut()", "GeomSolids0002",
|
||||
FatalErrorInArgument, message);
|
||||
}
|
||||
|
||||
G4double dist = fDroplet->DistanceToOut(relPos, irotm*v, calcNorm, validNorm, n);
|
||||
*n = rotm*(*n);
|
||||
*validNorm = false; // even if droplet is convex, the aerosol isn't
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calculate distance (<=actual) to closest surface of shape from inside
|
||||
//
|
||||
// This can be an underestimate
|
||||
//
|
||||
G4double FastAerosolSolid::DistanceToOut(const G4ThreeVector &p) const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double distanceToIn; // should be 0
|
||||
|
||||
fCloud->GetNearestDroplet(p, center, distanceToIn, fR, fDroplet, fRotation); // if we call this function, must be inside and thus must have a droplet within fR
|
||||
|
||||
G4RotationMatrix irotm = fRotation(center).inverse();
|
||||
G4ThreeVector relPos = irotm*(p-center);
|
||||
|
||||
if (fDroplet->Inside(relPos) == kOutside) // something went wrong... we should be inside
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "The particle at point p = " << p/mm << "mm"
|
||||
<< " called DistanceToOut(p) and found the closest droplet to be at center = " << center/mm << "mm"
|
||||
<< " but p is outside the droplet!";
|
||||
G4Exception("FastAerosolSolid::DistanceToOut()", "GeomSolids0002",
|
||||
FatalErrorInArgument, message);
|
||||
}
|
||||
|
||||
return fDroplet->DistanceToOut(relPos);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// G4EntityType
|
||||
//
|
||||
G4GeometryType FastAerosolSolid::GetEntityType() const
|
||||
{
|
||||
return G4String("FastAerosolSolid");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// G4EntityType
|
||||
//
|
||||
G4VSolid* FastAerosolSolid::Clone() const
|
||||
{
|
||||
return new FastAerosolSolid(*this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Stream object contents to an output stream
|
||||
//
|
||||
std::ostream &FastAerosolSolid::StreamInfo(std::ostream &os) const
|
||||
{
|
||||
os << "-----------------------------------------------------------\n"
|
||||
<< " *** Dump for solid - " << GetName() << " ***\n"
|
||||
<< " ===================================================\n"
|
||||
<< " Solid type: FastAerosolSolid\n"
|
||||
<< " Parameters: \n"
|
||||
<< " numDroplets: " << fCloud->GetNumDroplets() << "\n"
|
||||
<< " fDroplet type: " << fDroplet->GetName() << "\n"
|
||||
<< " fDroplet parameters: \n";
|
||||
fDroplet->StreamInfo(os);
|
||||
os << "-----------------------------------------------------------\n";
|
||||
return os;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GetPointOnSurface
|
||||
//
|
||||
// Currently hardcoded to look at all droplets, not just the populated ones
|
||||
//
|
||||
G4ThreeVector FastAerosolSolid::GetPointOnSurface() const
|
||||
{
|
||||
G4ThreeVector center;
|
||||
G4double closestDistance;
|
||||
|
||||
G4double fDx = fCloud->GetXHalfLength();
|
||||
G4double fDy = fCloud->GetYHalfLength();
|
||||
G4double fDz = fCloud->GetZHalfLength();
|
||||
|
||||
G4ThreeVector p(2.0*fDx*G4UniformRand(),2.0*fDy*G4UniformRand(),2.0*fDz*G4UniformRand());
|
||||
p -= G4ThreeVector(fDx, fDy, fDz);
|
||||
|
||||
fCloud->GetNearestDroplet(p, center, closestDistance, DBL_MAX, fDroplet, fRotation);
|
||||
|
||||
return(center + fRotation(center)*fDroplet->GetPointOnSurface());
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Methods for visualisation
|
||||
//
|
||||
void FastAerosolSolid::DescribeYourselfTo (G4VGraphicsScene& scene) const
|
||||
{
|
||||
scene.AddSolid(*this);
|
||||
}
|
||||
|
||||
G4VisExtent FastAerosolSolid::GetExtent() const
|
||||
{
|
||||
return G4VisExtent (-fVisDx, fVisDx, -fVisDy, fVisDy, -fVisDz, fVisDz);
|
||||
}
|
||||
|
||||
G4Polyhedron* FastAerosolSolid::CreatePolyhedron () const
|
||||
{
|
||||
return fBulk->CreatePolyhedron();
|
||||
}
|
||||
|
||||
|
||||
// copied from G4Ellipsoid
|
||||
G4Polyhedron* FastAerosolSolid::GetPolyhedron () const
|
||||
{
|
||||
if (!fpPolyhedron ||
|
||||
fRebuildPolyhedron ||
|
||||
fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
|
||||
fpPolyhedron->GetNumberOfRotationSteps())
|
||||
{
|
||||
G4AutoLock l(&polyhedronMutex);
|
||||
delete fpPolyhedron;
|
||||
fpPolyhedron = CreatePolyhedron();
|
||||
fRebuildPolyhedron = false;
|
||||
l.unlock();
|
||||
}
|
||||
return fpPolyhedron;
|
||||
}
|
||||
Reference in New Issue
Block a user