Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • clantz2/zdclg
  • shengy3/zdclg
  • dmaclea2/zdclg
3 results
Show changes
Commits on Source (58)
///\file "optical/OpNovice/.README.txt"
///\brief Example OpNovice README page
/*! \page ExampleOpNovice Example OpNovice
This example presently illustrates the following basic concepts, and in
particular (indicated with ***), how to use G4 for optical photon
generation and transport. Other extended example of what is possible
in Geant4 with optical photons can be found at
examples/extended/optical/LXe and wls
\section ExampleOpNovice_s1 main()
Define Random Number Engine and initial seed
\section ExampleOpNovice_s2 G4VUserPhysicsList
- Define particles; including - *** G4OpticalPhoton ***
- Define processes; including
- *** G4Cerenkov ***
- *** G4Scintillation ***
- *** G4OpAbsorption ***
- *** G4OpRayleigh ***
- *** G4OpBoundaryProcess ***
A messenger command allows to define interactivly the
verbose level and the maximum number of Cerenkov photons per step
(see for instance OpNovice.in)
\section ExampleOpNovice_s3 G4VUserDetectorConstruction
- Define material: Air and Water
- Define simple G4box geometry
- *** add G4MaterialPropertiesTable to G4Material ***
- *** define G4LogicalSurface(s) ***
- *** define G4OpticalSurface ***
- *** add G4MaterialPropertiesTable to G4OpticalSurface ***
\section ExampleOpNovice_s4 G4VUserPrimaryGeneratorAction
Use G4ParticleGun to shoot a charge particle into a Cerenkov radiator
A messenger command allows to define interactivly the polarization of an
primary optical photon (see for instance optPhoton.mac)
\section ExampleOpNovice_s5 G4UserRunAction
- Define G4Timer (start/stop)
- Set verbose levels
\section ExampleOpNovice_s6 G4UserStackingAction
Show how to count the number of secondary particles in an event
\section ExampleOpNovice_s7 Visualisation
The Visualization Manager is set in the main().
The initialisation of the drawing is done via a set of /vis/ commands
in the macro vis.mac. This macro is automatically read from
the main in case of interactive running mode.
The detector has a default view which is a longitudinal view of the tank.
The tracks are drawn at the end of event, and erased at the end of run.
\section ExampleOpNovice_s8 How to start
- compile and link to generate an executable
\verbatim
% cd OpNovice
% gmake
\endverbatim
This example handles the program arguments in a new way.
It can be run with the following optional arguments:
\verbatim
% OpNovice [-m macro ] [-u UIsession] [-t nThreads]
\endverbatim
The -t option is available only in multi-threading mode
and it allows the user to override the Geant4 default number of
threads. The number of threads can be also set via G4FORCENUMBEROFTHREADS
environment variable which has the top priority.
- execute OpNovice in 'batch' mode from macro files
\verbatim
% OpNovice -m OpNovice.in
\endverbatim
- execute OpNovice in 'interactive mode' with visualization
\verbatim
% OpNovice
....
Idle> type your commands. For instance:
Idle> /control/execute optPhoton.mac
....
Idle> exit
\endverbatim
*/
#include "TCanvas.h"
#include "TH2.h"
#include "TFile.h"
#include "TTree.h"
#include "TStyle.h"
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[]){
float xRange, zRange;
if(argc == 0) return 0;
TFile *f = new TFile( argv[1] );
if(f->IsZombie()){
cout << Form("%s.root does not exist... exiting",argv[1]) << endl;
return 0;
}
string name = argv[1];
if(name.find("/") != string::npos) name.erase( 0, name.find_last_of("/") + 1 );
if(name.find(".") != string::npos) name.erase( name.find_last_of(".") );
TTree *t = (TTree*)f->Get("lightGuide");
vector<double> *x=0,*z=0;
t->SetBranchAddress("X",&x);
t->SetBranchAddress("Z",&z);
xRange = (argc > 2) ? atof( argv[2] ) : 40.;
zRange = (argc > 3) ? atof( argv[3] ) : 80.;
TCanvas *c = new TCanvas("Data","Data",1280,720);
TH2D *h = new TH2D("eff","Relative Efficiency",44,-1*zRange/2.,zRange/2.,21,-1*xRange/2.,xRange/2.);
//h->SetCanExtend(0);
int nEvents = t->GetEntries();
for(int ev = 0; ev < nEvents; ev++){
t->GetEntry(ev);
int nPoints = x->size();
for(int i = 0; i < nPoints; i++){
h->Fill(z->at(i),x->at(i));
}
}
gStyle->SetOptStat(0);
h->Scale(1.0/h->GetMaximum());
h->Draw("COLZ");
h->SetAxisRange(0.4,1.0,"Z");
c->Print( Form("%s.png",name.c_str()) );
delete f;
return 1;
}
#----------------------------------------------------------------------------
# Setup the project
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(OpNovice)
project(lightGuide)
#----------------------------------------------------------------------------
# Find Geant4 package, activating all available UI and Vis drivers by default
......@@ -12,14 +12,13 @@ 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)
find_package(Geant4 REQUIRED )
endif()
#----------------------------------------------------------------------------
# Find ROOT
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
find_package (ROOT REQUIRED)
include(${ROOT_USE_FILE})
#----------------------------------------------------------------------------
# Setup Geant4 include directories and compile definitions
#
......@@ -36,24 +35,30 @@ file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)
#----------------------------------------------------------------------------
# Add the executable, and link it to the Geant4 libraries
#
add_executable(OpNovice OpNovice.cc ${sources} ${headers})
target_link_libraries(OpNovice ${Geant4_LIBRARIES} ${ROOT_LIBRARIES} )
add_executable(lightGuide lightGuide.cc ${sources} ${headers})
target_link_libraries(lightGuide ${Geant4_LIBRARIES} ${ROOT_LIBRARIES})
add_executable(plotHisto ${DEPENDENCIES} Analysis/plotHisto.cc)
TARGET_LINK_LIBRARIES(plotHisto ${ROOT_LIBRARIES})
#----------------------------------------------------------------------------
#Add Compiler flags
#
add_definitions(-Wno-shadow)
#----------------------------------------------------------------------------
# Copy all scripts to the build directory, i.e. the directory in which we
# build OpNovice. This is so that we can run the executable directly because it
# build lightGuide. This is so that we can run the executable directly because it
# relies on these scripts being in the current working directory.
#
set(OpNovice_SCRIPTS
OpNovice.out
OpNovice.in
optPhoton.mac
gui.mac
set(lightGuide_SCRIPTS
vis.mac
run1.mac
beam.mac
geometry.mac
)
foreach(_script ${OpNovice_SCRIPTS})
foreach(_script ${lightGuide_SCRIPTS})
configure_file(
${PROJECT_SOURCE_DIR}/${_script}
${PROJECT_BINARY_DIR}/${_script}
......@@ -64,4 +69,11 @@ endforeach()
#----------------------------------------------------------------------------
# Install the executable to 'bin' directory under CMAKE_INSTALL_PREFIX
#
install(TARGETS OpNovice DESTINATION bin)
install(TARGETS lightGuide DESTINATION bin )
install(TARGETS plotHisto DESTINATION bin )
install(FILES run1.mac DESTINATION bin )
install(FILES geometry.mac DESTINATION bin )
install(FILES beam.mac DESTINATION bin )
install(FILES vis.mac DESTINATION bin)
install(FILES hist.mac DESTINATION bin)
install(DIRECTORY models/ DESTINATION models)
......@@ -6,6 +6,8 @@ name := OpNovice
G4TARGET := $(name)
G4EXLIB := true
include ../../cadmesh.gmk
ifndef G4INSTALL
G4INSTALL = ../../..
endif
......
-------------------------------------------------------------------
=========================================================
Geant4 - an Object-Oriented Toolkit for Simulation in HEP
=========================================================
Example OpNovice History file
-----------------------------
This file should be used by the G4 example coordinator to briefly
summarize all major modifications introduced in the code and keep
track of all tags.
----------------------------------------------------------
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
July 31, 2018 I. Hrivnacova (OpNovice-V10-04-02)
- Macro review:
- Added test for /OpNovice/phys/cerenkovMaxPhotons command at the end
of OpNovice.in macro
- Updated README files
May 17, 2018 J. Allison (OpNovice-V10-04-01)
- Remove G4UI_USE and G4VIS_USE.
- Move instantiation of G4UIExecutive to start of main.
May 08, 2018 B. Morgan (OpNovice-V10-04-00)
- Include G4Types before use of G4MULTITHREADED. For forward
compatibility with move to #defines over -D for G4 preprocessor
symbols.
August 18, 2017 J.Allison (OpNovice-V10-03-02)
- Fix gui.mac, which executed vis.mac (it should not!).
Mar 22, 2017 P.Gumplinger (OpNovice-V10-03-00/OpNovice-V10-03-01)
- exercise the new DAVIS LUT surface model
Nov 02, 2016 L.Garnier (OpNovice-V10-02-01)
- Remove icons.mac. Automatically include since interfaces-V10-02-07
Nov 02, 2016 I. Hrivnacova (OpNovice-V10-02-00)
- Added file descriptions for Doxygen documentation
Oct 14, 2016 G.Folger (OpNovice-V10-00-00) - not tagged
- remove direct use of theParticleIterator, use GetParticleTableIterator().
fix required by clang39 on Linux and MAC
Jun 15, 2015 - P. Gumplinger (OpNovice-V10-01-04)
- introduce G4ThreadLocal in OpNovicePhysicsList class
Jun 09, 2015 - P. Gumplinger (OpNovice-V10-01-03)
- revert back to kernel initialization in main
Jun 05, 2015 - P. Gumplinger (OpNovice-V10-01-02)
- reduce output size and move kernel initialization to input macro
May 22, 2015 - P. Gumplinger (OpNovice-V10-01-01)
- apply coding guideline 3.3
May 16, 2015 J. Allison (OpNovice-V10-01-00)
- Replaced !G4Threading::IsWorkerThread() by G4Threading::IsMasterThread().
October 27, 2014 A. Dotti (OpNovice-V10-00-06)
- Migration to new UI system. Requires:
xrays-V10-00-06, op-V10-00-09, phys-ctro-em-V10-00-17
July 11, 2014 P. Gumplinger (OpNovice-V10-00-05)
- Use implicit dimensioning for all arrays in
OpNoviceDetectorConstruction.cc and assert that they are the
same (thanks to M. Kelsey for suggesting this)
December 23, 2013 M. Asai (OpNovice-V10-00-04)
- Limit invokation of static method only from master/sequential.
December 22, 2013 M. Asai (OpNovice-V10-00-03)
- Avoid static G4Scintillation method invoked through a pointer.
December 18, 2013 M. Asai/P. Gumplinger (OpNovice-V10-00-02)
- allows changes to G4Cerenkov and G4Scintillation in Idle state
December 16, 2013 M. Asai (OpNovice-V10-00-01)
- Fix race condision issue in OpNovicePhysicsList.
December 04, 2013 P. Gumplinger (OpNovice-V10-00-00)
- Fixes in gui.mac:
Commented out command specific to B2 example
Let execute vis.mac first to make the command in added menus available;
Corrected wireframe parameter
November 28, 2013 P. Gumplinger (OpNovice-V09-06-11)
- add gui.mac, icons.mac and run.png
November 2, 2013 P. Gumplinger (OpNovice-V09-06-10)
- place G4Random::setTheSeed(myseed) so that it is executed for both
sequential and MT mode
October 31, 2013 P. Gumplinger (OpNovice-V09-06-09)
- to work with ctests-V09-06-19
October 29, 2013 P. Gumplinger (OpNovice-V09-06-08)
- remove all reference to LXeWorkerInitialization and remove SetNumberOfThreads
October 25, 2013 P. Gumplinger (OpNovice-V09-06-07)
- Instantiate SteppingVerbose in a new method in OpNoviceActionInitialization
and removed LXeWorkerInitialization (not needed anymore)
- Add OpNoviceSteppingAction to count secondary optical photons to compare
with OpNoviceStackingAction
11 June 2013, V.Ivanchenko (OpNovice-V09-06-06)
- OpNovicePhysicsList - construct all particles to avoid exception
in execution of ConstructParticle() method; removed unnecessary
methods to construct individual particle types
02 June 2013, P.Gumplinger (OpNovice-V09-06-05)
- make MultiThread (MT) capable
27 May 2013, I.Hrivnacova (OpNovice-V09-06-04)
- Updated .README file
27 May 2013, I.Hrivnacova (OpNovice-V09-06-03)
- Apply Examples Coding Guidelines
(data members/base class initialization)
13 May 2013 P. Gumplinger (OpNovice-V09-06-02)
- Add .README file
06 May 2013 P. Gumplinger (OpNovice-V09-06-01)
- Apply all Examples Coding Guidelines
18 Dec 2012 I. Hrivnacova (OpNovice-V09-06-00)
- Fixed CMake build: removed add_custom_target(..)
17 Dec 2012 P. Gumplinger
- move the example to /extended/optical/novice (from /novice/N06) and
rename N06 to OpNovice
20 June 2012 P. Gumplinger (exampleN06-V09-05-01)
- remove SetModel from ExN06PhysicsList.cc to cowork with op-V09-05-04
24 January 2012 P. Gumplinger (exampleN06-V09-05-00)
- set /tracking/verbose 3 in exampleN06.in and optPhoton.mac
to also test timing of optical photons - see Problem #1275
29 November 2011 Ben Morgan (exampleN06-V09-04-01)
- CMakeLists.txt edited to add standard UI/Vis activation and copying of scripts
to build directory, plus comments and neatification.
14th October 2011 P. Gumplinger (exampleN06-V09-04-00)
- modify to work with materials-V09-04-15 and use spline interpolation
for some of the G4MaterialPropertyVector (e.g. G4PhysicsOrderedFreeVector)
23rd October 2010 P. Gumplinger (exampleN06-V09-03-01)
- add G4OpMieHG scattering process and associated material properties
4th June 2010 Joseph Perl (exampleN06-V09-03-00)
- Updated vis usage
09th November 2009 Peter Gumplinger (exampleN06-V09-02-01)
- use G4eMultipleScattering, G4MuMultipleScattering and
G4hMultipleScattering instead of G4MultipleScattering
30th October 2009 John Allison (exampleN06-V09-02-00)
- Introduced G4UIExecutive.
20th November 2008 P. Gumplinger (exampleN06-V09-01-03)
- add theCerenkovProcess->SetMaxBetaChangePerStep in ExN06PhysicsList
16th July 2008 P. Gumplinger (exampleN06-V09-01-02)
- use dynamic_cast <G4OpticalSurface*> in ExN06DetectorConstruction.cc
12th June 2008 P. Gumplinger (exampleN06-V09-01-01)
- now use G4EmSaturation to implement the Birks Correction
for G4Scintillation
07th May 2008 J.Allison (exampleN06-V09-01-00)
- Protected "/control/execute vis.mac" with G4VIS_USE flag.
30 Sept 2007 Peter Gumplinger (exampleN06-V09-00-00)
- adjust to the G4Cerenkov process now being a G4VDiscreteProcess
October 18th 2006 J.Allison (exampleN06-V08-01-00)
- Migrate to new trajectory modeling commands.
16th June 2006 Gabriele Cosmo (exampleN06-V08-00-02)
- Use coherent allocation scheme for user-classes and
initialisation in main().
15th June 2006 Peter Gumplinger (exampleN06-V08-00-01)
- add new method ExN06PrimaryGeneratorAction::SetOptPhotonPolar()
to set a random linear polarization when the command -
/N06/gun/optPhotonPolar - is given without arguments
15th June 2006 Gabriele Cosmo (exampleN06-V08-00-00)
- Separate instantiation of the user-stepping-verbose class from
initialisation of the G4VSteppingVerbose singleton.
6th December 2005 Gabriele Cosmo
- Trivial changes for support of CLHEP-2.0.X series.
4th December 2005 John Allison (exampleN06-V07-01-00)
- Replaced vis code in EndOfEventAction by suitable vis commands in vis.mac.
16 May 2005 Peter Gumplinger (exampleN06-V07-00-01)
- use SetProcessOrdering for theDecayProces
11 May 2005 Michel Maire (exampleN06-V07-00-00)
- UI command cerenkovMaxPhotons available in Idle state only
3rd May 2005 John Allison (examples-V07-00-03)
- Replaced vis manager with G4VisExecutive.
June 1, 2004 Peter Gunplinger (exampleN06-V06-01-01)
- Updated README file.
April 2, 2004 Michel Maire (exampleN06-V06-01-00)
- PrimaryGenerator: e+ 500 keV
- Removed vis commands from RunAction
March 17, 2004 Peter Gumplinger (exampleN06-V06-00-00)
- DetectorConstruction: change surface model between OpWaterSurface
and OpAirSurface
December 1, 2003 Peter Gumplinger (exampleN06-V05-02-02)
- DetectorConstruction: use G4SurfaceProperty.
November 13, 2003 John Allison
- Removed OPACS from Vis Manager.
October 24, 2003 Michel Maire (exampleN06-V05-02-01)
- PhysicsList: AddProcess(Bremsstrahlung,-1,3,3) ..etc..
October 06, 2003 Michel Maire (exampleN06-V05-02-00)
- Cosmetic cleanup of material definition
April 17, 2003 Peter Gumplinger (exampleN06-V05-00-03)
- Changed OpWaterSurface to dielectric_dielectric in class
ExN06DetectorConstruction
March 26, 2003 Michel Maire (exampleN06-V05-00-02)
- G4PVPlacement in logical mother
Febuary 11, 2003 Michel Maire (exampleN06-V05-00-01)
- Added a blank in steppingVerbose !
January 23, 2003 Michel Maire (exampleN06-V05-00-00)
- Added tools for interactive session : UItcsh, visualisation of tracks.
- Added 2 messenger classes : PhysicsList and PrimaryGenerator
- exampleN06.in changed --> exampleN06.out reduced
November 21, 2002 Peter Gumplinger (exampleN06-V04-01-02)
- exampleN06.out output changed because of small change in G4Scintillation
November 14, 2002 Peter Gumplinger (exampleN06-V04-01-01)
- Reduced the scintillation photon yield to reduce the output size
November 12, 2002 Peter Gumplinger (exampleN06-V04-01-00)
- Added ExN06StackingAction
- Changed user interface to new version of G4Scintillation
May 30, 2002 Gabriele Cosmo (exampleN06-V04-00-02)
- Renamed file ExN06PrimaryGeneratoraction.cc to ExN06PrimaryGeneratorAction.cc
to be consistent with class name.
May 16, 2002 Peter Gumplinger (exampleN06-V04-00-01)
- Added G4Scintillation to the example and update reference output
Oct 19, 2001 Steve O'Neale (examples-V03-02-00)
- Updated reference output
06-02-2001 Update reference output for op-V03-00-05 S.W.O'Neale
June 17, 2000 John Allison (exampleN06-V01-01-00)
- Updated exampleN06.out for geant4-01-01-ref-06.
16th April 1999 Hisaya Kurashige
- Modified ExN06RunAction
- Modified ExN06PhysicsList::SetCuts
21st August 1998 John Allison
- Changed file names from N06* to ExN06*.
9th August 1998 John Allison
- Changed G4UIterminal to G4UIGAG.
April 09, 98 Gabriele Cosmo
- Created.
MIT License
Copyright (c) 2024 srlund2
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
/control/verbose 2
/tracking/verbose 0
#
/gun/particle e+
/gun/energy 500 keV
#
/OpNovice/phys/verbose 0
#
/run/beamOn 1
#
/OpNovice/phys/cerenkovMaxPhotons 15 # default: 20
#
/run/beamOn 1
############################################
!!! WARNING - FPE detection is activated !!!
############################################
**************************************************************
Geant4 version Name: geant4-10-05-ref-00 (7-December-2018)
Copyright : Geant4 Collaboration
References : NIM A 506 (2003), 250-303
: IEEE-TNS 53 (2006), 270-278
: NIM A 835 (2016), 186-225
WWW : http://geant4.org/
**************************************************************
Water G4MaterialPropertiesTable
0: RINDEX
2.034e-06 1.3435
2.068e-06 1.344
2.103e-06 1.3445
2.139e-06 1.345
2.177e-06 1.3455
2.216e-06 1.346
2.256e-06 1.3465
2.298e-06 1.347
2.341e-06 1.3475
2.386e-06 1.348
2.433e-06 1.3485
2.481e-06 1.3492
2.532e-06 1.35
2.585e-06 1.3505
2.64e-06 1.351
2.697e-06 1.3518
2.757e-06 1.3522
2.82e-06 1.353
2.885e-06 1.3535
2.954e-06 1.354
3.026e-06 1.3545
3.102e-06 1.355
3.181e-06 1.3555
3.265e-06 1.356
3.353e-06 1.3568
3.446e-06 1.3572
3.545e-06 1.358
3.649e-06 1.3585
3.76e-06 1.359
3.877e-06 1.3595
4.002e-06 1.36
4.136e-06 1.3608
9: GROUPVEL
2.034e-06 218.243
2.051e-06 218.204
2.0855e-06 218.183
2.121e-06 218.157
2.158e-06 218.246
2.1965e-06 218.204
2.236e-06 218.158
2.277e-06 218.212
2.3195e-06 218.155
2.3635e-06 218.188
2.4095e-06 218.208
2.457e-06 216.507
2.5065e-06 215.846
2.5585e-06 218.128
2.6125e-06 218.11
2.6685e-06 215.856
2.727e-06 218.798
2.7885e-06 215.988
2.8525e-06 218.001
2.9195e-06 218.046
2.99e-06 218.029
3.064e-06 218.046
3.1415e-06 218.01
3.223e-06 218.041
3.309e-06 216.226
3.3995e-06 218.568
3.4955e-06 216.325
3.597e-06 217.945
3.7045e-06 217.962
3.8185e-06 217.941
3.9395e-06 217.951
4.136e-06 216.443
10: MIEHG
1.56962e-06 1.67024e+08
1.58974e-06 1.58727e+08
1.61039e-06 1.50742e+08
1.63157e-06 1.43062e+08
1.65333e-06 1.3568e+08
1.67567e-06 1.28587e+08
1.69863e-06 1.21776e+08
1.72222e-06 1.1524e+08
1.74647e-06 1.0897e+08
1.77142e-06 1.02959e+08
1.7971e-06 9.72004e+07
1.82352e-06 9.16869e+07
1.85074e-06 8.64113e+07
1.87878e-06 8.13668e+07
1.90769e-06 7.65464e+07
1.93749e-06 7.19435e+07
1.96825e-06 6.75513e+07
1.99999e-06 6.33634e+07
2.03278e-06 5.93732e+07
2.06666e-06 5.55746e+07
2.10169e-06 5.19612e+07
2.13793e-06 4.8527e+07
2.17543e-06 4.52659e+07
2.21428e-06 4.21719e+07
2.25454e-06 3.92394e+07
2.29629e-06 3.64625e+07
2.33962e-06 3.38357e+07
2.38461e-06 3.13534e+07
2.43137e-06 2.90103e+07
2.47999e-06 2.6801e+07
2.53061e-06 2.47204e+07
2.58333e-06 2.27634e+07
2.63829e-06 2.09249e+07
2.69565e-06 1.92001e+07
2.75555e-06 1.75842e+07
2.81817e-06 1.60724e+07
2.88371e-06 1.46604e+07
2.95237e-06 1.33435e+07
3.02438e-06 1.21173e+07
3.09999e-06 1.09777e+07
3.17948e-06 9.92042e+06
3.26315e-06 8.94141e+06
3.35134e-06 8.03671e+06
3.44444e-06 7.20247e+06
3.54285e-06 6.43493e+06
3.64705e-06 5.73043e+06
3.75757e-06 5.08542e+06
3.87499e-06 4.49647e+06
3.99999e-06 3.96021e+06
4.13332e-06 3.47341e+06
4.27585e-06 3.03294e+06
4.42856e-06 2.63575e+06
4.59258e-06 2.27891e+06
4.76922e-06 1.95959e+06
4.95999e-06 1.67506e+06
5.16665e-06 1.42271e+06
5.39129e-06 1.2e+06
5.63635e-06 1.00453e+06
5.90475e-06 833967
6.19998e-06 686106
14: ABSLENGTH
2.034e-06 3448
2.068e-06 4082
2.103e-06 6329
2.139e-06 9174
2.177e-06 12346
2.216e-06 13889
2.256e-06 15152
2.298e-06 17241
2.341e-06 18868
2.386e-06 20000
2.433e-06 26316
2.481e-06 35714
2.532e-06 45455
2.585e-06 47619
2.64e-06 52632
2.697e-06 52632
2.757e-06 55556
2.82e-06 52632
2.885e-06 52632
2.954e-06 47619
3.026e-06 45455
3.102e-06 41667
3.181e-06 37037
3.265e-06 33333
3.353e-06 30000
3.446e-06 28500
3.545e-06 27000
3.649e-06 24500
3.76e-06 22000
3.877e-06 19500
4.002e-06 17500
4.136e-06 14500
15: FASTCOMPONENT
2.034e-06 1
2.068e-06 1
2.103e-06 1
2.139e-06 1
2.177e-06 1
2.216e-06 1
2.256e-06 1
2.298e-06 1
2.341e-06 1
2.386e-06 1
2.433e-06 1
2.481e-06 1
2.532e-06 1
2.585e-06 1
2.64e-06 1
2.697e-06 1
2.757e-06 1
2.82e-06 1
2.885e-06 1
2.954e-06 1
3.026e-06 1
3.102e-06 1
3.181e-06 1
3.265e-06 1
3.353e-06 1
3.446e-06 1
3.545e-06 1
3.649e-06 1
3.76e-06 1
3.877e-06 1
4.002e-06 1
4.136e-06 1
16: SLOWCOMPONENT
2.034e-06 0.01
2.068e-06 1
2.103e-06 2
2.139e-06 3
2.177e-06 4
2.216e-06 5
2.256e-06 6
2.298e-06 7
2.341e-06 8
2.386e-06 9
2.433e-06 8
2.481e-06 7
2.532e-06 6
2.585e-06 4
2.64e-06 3
2.697e-06 2
2.757e-06 1
2.82e-06 0.01
2.885e-06 1
2.954e-06 2
3.026e-06 3
3.102e-06 4
3.181e-06 5
3.265e-06 6
3.353e-06 7
3.446e-06 8
3.545e-06 9
3.649e-06 8
3.76e-06 7
3.877e-06 6
4.002e-06 5
4.136e-06 4
5: MIEHG_FORWARD
0.99
6: MIEHG_BACKWARD
0.99
7: MIEHG_FORWARD_RATIO
0.8
8: SCINTILLATIONYIELD
50
9: RESOLUTIONSCALE
1
10: FASTTIMECONSTANT
1
12: SLOWTIMECONSTANT
10
14: YIELDRATIO
0.8
Air G4MaterialPropertiesTable
0: RINDEX
2.034e-06 1
2.068e-06 1
2.103e-06 1
2.139e-06 1
2.177e-06 1
2.216e-06 1
2.256e-06 1
2.298e-06 1
2.341e-06 1
2.386e-06 1
2.433e-06 1
2.481e-06 1
2.532e-06 1
2.585e-06 1
2.64e-06 1
2.697e-06 1
2.757e-06 1
2.82e-06 1
2.885e-06 1
2.954e-06 1
3.026e-06 1
3.102e-06 1
3.181e-06 1
3.265e-06 1
3.353e-06 1
3.446e-06 1
3.545e-06 1
3.649e-06 1
3.76e-06 1
3.877e-06 1
4.002e-06 1
4.136e-06 1
9: GROUPVEL
2.034e-06 299.792
2.051e-06 299.792
2.0855e-06 299.792
2.121e-06 299.792
2.158e-06 299.792
2.1965e-06 299.792
2.236e-06 299.792
2.277e-06 299.792
2.3195e-06 299.792
2.3635e-06 299.792
2.4095e-06 299.792
2.457e-06 299.792
2.5065e-06 299.792
2.5585e-06 299.792
2.6125e-06 299.792
2.6685e-06 299.792
2.727e-06 299.792
2.7885e-06 299.792
2.8525e-06 299.792
2.9195e-06 299.792
2.99e-06 299.792
3.064e-06 299.792
3.1415e-06 299.792
3.223e-06 299.792
3.309e-06 299.792
3.3995e-06 299.792
3.4955e-06 299.792
3.597e-06 299.792
3.7045e-06 299.792
3.8185e-06 299.792
3.9395e-06 299.792
4.136e-06 299.792
LUT DAVIS - data file: /cvmfs/geant4.cern.ch/share/data/RealSurface2.1.1/Rough_LUT.dat read in!
Reflectivity LUT DAVIS - data file: /cvmfs/geant4.cern.ch/share/data/RealSurface2.1.1/Rough_LUTR.dat read in!
Surface type = 3
Surface finish = 30
Surface model = 3
Surface parameter
-----------------
0
Surface type = 1
Surface finish = 0
Surface model = 0
Surface parameter
-----------------
1
Water Surface G4MaterialPropertiesTable
0: RINDEX
2.034e-06 1.35
4.136e-06 1.4
6: SPECULARLOBECONSTANT
2.034e-06 0.3
4.136e-06 0.3
7: SPECULARSPIKECONSTANT
2.034e-06 0.2
4.136e-06 0.2
8: BACKSCATTERCONSTANT
2.034e-06 0.2
4.136e-06 0.2
9: GROUPVEL
2.034e-06 211.055
4.136e-06 203.878
Air Surface G4MaterialPropertiesTable
1: REFLECTIVITY
2.034e-06 0.3
4.136e-06 0.5
4: EFFICIENCY
2.034e-06 0.8
4.136e-06 1
### Birks coefficients used in run time
Water 0.126 mm/MeV 0.0126 g/cm^2/MeV massFactor= 85.0756 effCharge= 62.0606
AddDiscreteProcess to OpticalPhoton
Visualization Manager instantiating with verbosity "warnings (3)"...
Visualization Manager initialising...
Registering graphics systems...
You have successfully registered the following graphics systems.
Current available graphics systems are:
ASCIITree (ATree)
DAWNFILE (DAWNFILE)
G4HepRep (HepRepXML)
G4HepRepFile (HepRepFile)
RayTracer (RayTracer)
VRML1FILE (VRML1FILE)
VRML2FILE (VRML2FILE)
gMocrenFile (gMocrenFile)
OpenGLImmediateQt (OGLIQt, OGLI)
OpenGLStoredQt (OGLSQt, OGL, OGLS)
OpenGLImmediateXm (OGLIXm, OGLIQt_FALLBACK)
OpenGLStoredXm (OGLSXm, OGLSQt_FALLBACK)
OpenGLImmediateX (OGLIX, OGLIQt_FALLBACK, OGLIXm_FALLBACK)
OpenGLStoredX (OGLSX, OGLSQt_FALLBACK, OGLSXm_FALLBACK)
RayTracerX (RayTracerX)
Registering model factories...
You have successfully registered the following model factories.
Registered model factories:
generic
drawByAttribute
drawByCharge
drawByOriginVolume
drawByParticleID
drawByEncounteredVolume
Registered filter factories:
attributeFilter
chargeFilter
originVolumeFilter
particleFilter
encounteredVolumeFilter
You have successfully registered the following user vis actions.
Run Duration User Vis Actions: none
End of Event User Vis Actions: none
End of Run User Vis Actions: none
Some /vis commands (optionally) take a string to specify colour.
"/vis/list" to see available colours.
/tracking/verbose 0
#
/gun/particle e+
/gun/energy 500 keV
#
/OpNovice/phys/verbose 0
#
/run/beamOn 1
conv: for gamma SubType= 14 BuildTable= 1
Lambda table from 1.022 MeV to 100 TeV, 18 bins per decade, spline: 1
===== EM models for the G4Region DefaultRegionForTheWorld ======
BetheHeitler : Emin= 0 eV Emax= 80 GeV AngularGenUrban
BetheHeitlerLPM : Emin= 80 GeV Emax= 100 TeV AngularGenUrban
compt: for gamma SubType= 13 BuildTable= 1
Lambda table from 100 eV to 1 MeV, 7 bins per decade, spline: 1
LambdaPrime table from 1 MeV to 100 TeV in 56 bins
===== EM models for the G4Region DefaultRegionForTheWorld ======
Klein-Nishina : Emin= 0 eV Emax= 100 TeV
phot: for gamma SubType= 12 BuildTable= 0
LambdaPrime table from 200 keV to 100 TeV in 61 bins
===== EM models for the G4Region DefaultRegionForTheWorld ======
PhotoElectric : Emin= 0 eV Emax= 100 TeV AngularGenSauterGavrila
msc: for e- SubType= 10
RangeFactor= 0.04, stepLimitType: 1, latDisplacement: 1
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
eIoni: for e- SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
MollerBhabha : Emin= 0 eV Emax= 100 TeV
eBrem: for e- SubType= 3
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
LPM flag: 1 for E > 1 GeV, VertexHighEnergyTh(GeV)= 100000
===== EM models for the G4Region DefaultRegionForTheWorld ======
eBremSB : Emin= 0 eV Emax= 1 GeV AngularGenUrban
eBremLPM : Emin= 1 GeV Emax= 100 TeV AngularGenUrban
msc: for e+ SubType= 10
RangeFactor= 0.04, stepLimitType: 1, latDisplacement: 1
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
eIoni: for e+ SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
MollerBhabha : Emin= 0 eV Emax= 100 TeV
eBrem: for e+ SubType= 3
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
LPM flag: 1 for E > 1 GeV, VertexHighEnergyTh(GeV)= 100000
===== EM models for the G4Region DefaultRegionForTheWorld ======
eBremSB : Emin= 0 eV Emax= 1 GeV AngularGenUrban
eBremLPM : Emin= 1 GeV Emax= 100 TeV AngularGenUrban
annihil: for e+, integral: 1 SubType= 5 BuildTable= 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
eplus2gg : Emin= 0 eV Emax= 100 TeV
msc: for proton SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for proton SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
Bragg : Emin= 0 eV Emax= 2 MeV
BetheBloch : Emin= 2 MeV Emax= 100 TeV
msc: for GenericIon SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV
hIoni: for GenericIon SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
Bragg : Emin= 0 eV Emax= 2 MeV
BetheBloch : Emin= 2 MeV Emax= 100 TeV
msc: for alpha SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for alpha SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
Bragg : Emin= 0 eV Emax= 7.9452 MeV
BetheBloch : Emin= 7.9452 MeV Emax= 100 TeV
msc: for anti_proton SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for anti_proton SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
ICRU73QO : Emin= 0 eV Emax= 2 MeV
BetheBloch : Emin= 2 MeV Emax= 100 TeV
msc: for kaon+ SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for kaon+ SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
Bragg : Emin= 0 eV Emax= 1.05231 MeV
BetheBloch : Emin= 1.05231 MeV Emax= 100 TeV
msc: for kaon- SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for kaon- SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
ICRU73QO : Emin= 0 eV Emax= 1.05231 MeV
BetheBloch : Emin= 1.05231 MeV Emax= 100 TeV
msc: for mu+ SubType= 10
RangeFactor= 0.2, step limit type: 0, lateralDisplacement: 0, polarAngleLimit(deg)= 180
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
muIoni: for mu+ SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
Bragg : Emin= 0 eV Emax= 200 keV
BetheBloch : Emin= 200 keV Emax= 1 GeV
MuBetheBloch : Emin= 1 GeV Emax= 100 TeV
muBrems: for mu+ SubType= 3
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
===== EM models for the G4Region DefaultRegionForTheWorld ======
MuBrem : Emin= 0 eV Emax= 100 TeV
muPairProd: for mu+ SubType= 4
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
Sampling table 21x1001 from 1 GeV to 100 TeV
===== EM models for the G4Region DefaultRegionForTheWorld ======
muPairProd : Emin= 0 eV Emax= 100 TeV
msc: for mu- SubType= 10
RangeFactor= 0.2, step limit type: 0, lateralDisplacement: 0, polarAngleLimit(deg)= 180
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
muIoni: for mu- SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
ICRU73QO : Emin= 0 eV Emax= 200 keV
BetheBloch : Emin= 200 keV Emax= 1 GeV
MuBetheBloch : Emin= 1 GeV Emax= 100 TeV
muBrems: for mu- SubType= 3
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
===== EM models for the G4Region DefaultRegionForTheWorld ======
MuBrem : Emin= 0 eV Emax= 100 TeV
muPairProd: for mu- SubType= 4
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
Sampling table 21x1001 from 1 GeV to 100 TeV
===== EM models for the G4Region DefaultRegionForTheWorld ======
muPairProd : Emin= 0 eV Emax= 100 TeV
msc: for pi+ SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for pi+ SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
Bragg : Emin= 0 eV Emax= 297.505 keV
BetheBloch : Emin= 297.505 keV Emax= 100 TeV
msc: for pi- SubType= 10
RangeFactor= 0.2, stepLimitType: 0, latDisplacement: 0
===== EM models for the G4Region DefaultRegionForTheWorld ======
UrbanMsc : Emin= 0 eV Emax= 100 TeV Table with 84 bins Emin= 100 eV Emax= 100 TeV
hIoni: for pi- SubType= 2
dE/dx and range tables from 100 eV to 100 TeV in 84 bins
Lambda tables from threshold to 100 TeV, 7 bins per decade, spline: 1
finalRange(mm)= 0.1, dRoverRange= 0.2, integral: 1, fluct: 1, linLossLimit= 0.01
===== EM models for the G4Region DefaultRegionForTheWorld ======
ICRU73QO : Emin= 0 eV Emax= 297.505 keV
BetheBloch : Emin= 297.505 keV Emax= 100 TeV
========= Table of registered couples ==============================
Index : 0 used in the geometry : Yes
Material : Air
Range cuts : gamma 1 mm e- 1 mm e+ 1 mm proton 1 mm
Energy thresholds : gamma 990 eV e- 990 eV e+ 990 eV proton 100 keV
Region(s) which use this couple :
DefaultRegionForTheWorld
Index : 1 used in the geometry : Yes
Material : Water
Range cuts : gamma 1 mm e- 1 mm e+ 1 mm proton 1 mm
Energy thresholds : gamma 2.94056 keV e- 351.877 keV e+ 342.545 keV proton 100 keV
Region(s) which use this couple :
DefaultRegionForTheWorld
====================================================================
### Run 0 start.
Number of Scintillation photons produced in this event : 69
Number of Cerenkov photons produced in this event : 22
number of event = 1 User=0.010000s Real=0.002789s Sys=0.000000s
#
/OpNovice/phys/cerenkovMaxPhotons 15
#
/run/beamOn 1
### Run 1 start.
Number of Scintillation photons produced in this event : 61
Number of Cerenkov photons produced in this event : 14
number of event = 1 User=0.000000s Real=0.000693s Sys=0.000000s
Graphics systems deleted.
Visualization Manager deleting...
-------------------------------------------------------------------
=========================================================
Geant4 - an Object-Oriented Toolkit for Simulation in HEP
=========================================================
OpNovice
--------
This example presently illustrates the following basic concepts, and in
particular (indicated with ***), how to use G4 for optical photon
generation and transport. Other extended example of what is possible
in Geant4 with optical photons can be found at
examples/extended/optical/LXe and wls.
main()
------
==> define Random Number Engine and initial seed
G4VUserPhysicsList
------------------
==> define particles; including *** G4OpticalPhoton ***
define processes; including *** G4Cerenkov ***
*** G4Scintillation ***
*** G4OpAbsorption ***
*** G4OpRayleigh ***
*** G4OpBoundaryProcess ***
==> A messenger command allows to define interactivly the
verbose level and the maximum number of Cerenkov photons per step
(see for instance OpNovice.in)
G4VUserDetectorConstruction
---------------------------
==> define material: Air and Water
define simple G4box geometry
*** add G4MaterialPropertiesTable to G4Material ***
*** define G4LogicalSurface(s) ***
*** define G4OpticalSurface ***
*** add G4MaterialPropertiesTable to G4OpticalSurface ***
G4VUserPrimaryGeneratorAction
-----------------------------
==> Use G4ParticleGun to shoot a charge particle into a Cerenkov radiator
==> A messenger command allows to define interactively the polarization of an
primary optical photon (see for instance optPhoton.mac)
G4UserRunAction
---------------
==> define G4Timer (start/stop)
set verbose levels
G4UserStackingAction
--------------------
==> show how to count the number of secondary particles in an event
Visualisation
-------------
The Visualization Manager is set in the main().
The initialisation of the drawing is done via a set of /vis/ commands
in the macro vis.mac. This macro is automatically read from
the main in case of interactive running mode.
The detector has a default view which is a longitudinal view of the tank.
The tracks are drawn at the end of event, and erased at the end of run.
HOW TO START
------------
- compile and link to generate an executable
% cd OpNovice
% gmake
This example handles the program arguments in a new way.
It can be run with the following optional arguments:
% OpNovice [-m macro ] [-u UIsession] [-t nThreads]
The -t option is available only in multi-threading mode
and it allows the user to override the Geant4 default number of
threads. The number of threads can be also set via G4FORCENUMBEROFTHREADS
environment variable which has the top priority.
- execute OpNovice in 'batch' mode from macro files
% OpNovice -m OpNovice.in
- execute OpNovice in 'interactive mode' with visualization
% OpNovice
....
Idle> type your commands. For instance:
Idle> /control/execute optPhoton.mac
....
Idle> exit
### ZDC Light Guide Monte Carlo
This simulation is based on OpNovice and OpNovice2
#### Build requirements
- Geant4 compiled with GDML and additional datasets. Be sure to source geant4make.sh
```
source /path/to/geant4-install/share/Geant4-[version]/geant4make/geant4make.sh
```
- CERN ROOT
#### main()
define Random Number Engine, initial seed, CAD input and GDML output
#### G4VUserPhysicsList
- Define particles; including
- *** G4OpticalPhoton ***
- Define processes; including
- *** G4Cerenkov ***
- *** G4Scintillation ***
- *** G4OpAbsorption ***
- *** G4OpRayleigh ***
- *** G4OpBoundaryProcess ***
#### Materials
defines many materials for potential use
For our purposes the G4OpticalSurface AlSurface and the G4Material Al and Air
will be given optical properties and used for construction.
#### G4VUserDetectorConstruction
A light guide is made either by simple G4trd or by importing a model
via CADMesh.
define G4LogicalBorderSurface between the light guide and world volume
defines a PMT window sensitive detector at the top of the light guide
AlSurface properties can be modified via DetectorMessenger via the following commands
```
/lightGuide/surface/Model
/lightGuide/surface/Type
/lightGuide/surface/Finish
/lightGuide/surface/SigmaAlpha
/lightGuide/surface/Property
```
CAD models can be imported and positioned via
```
/lightGuide/model/CADmodel
/lightGuide/model/rotate
/lightGuide/model/translate
/lightGuide/model/translatePMT
```
The models must be in ASCII STL format in the current implementation.
And the optical properties of a sub volume of G4Air which the light guide sits in can be configured via
```
/lightGuide/gasProperty
```
examples of all of these can be found in run1.mac
#### G4VUserPrimaryGeneratorAction
Use G4GeneralParticleSource to shoot an optical photon into the light guide
Particle type and distribution is set in run1.mac
#### G4UserRunAction
define G4Timer (start/stop)
define G4AnalysisManager (output .root file)
set verbose levels
#### PMTHit
stores G4int trackID,
G4ThreeVector pos; // Origin position of the photon
G4ThreeVector hit; // Location where the photon hit the PMT window
G4double energy; // Energy of the photon
G4ThreeVector momentum; // Momentum of the photon (direction)
G4double time; // Time of arrival of the photon
for each hit on the PMT sensitive detector
#### PMTSD
Records a PMTHit if the photon strikes the PMT window
#### G4UserEventAction
Show how to count the number of secondary particles in an event
#### Visualisation
The Visualization Manager is set in the main().
The initialisation of the drawing is done via a set of /vis/ commands
in the macro vis.mac. This macro is automatically read from
the main in case of interactive running mode.
#### How to start
- compile and link to generate an executable
```
$ mkdir zdclg-build zdclg-install
$ cd zdclg-build
$ cmake -DCMAKE_INSTALL_PREFIX=../zdclg-install /path/to/zdclg
```
This example handles the program arguments in a new way.
It can be run with the following optional arguments:
```
$ ./lightGuide [-m macro ]
[-u UIsession]
[-t nThreads]
[-r seed]
[-o outputFileName]
```
The -t option is available only in multi-threading mode
and it allows the user to override the Geant4 default number of
threads. The number of threads can be also set via G4FORCENUMBEROFTHREADS
environment variable which has the top priority.
- execute lightGuide in 'batch' mode from macro files
```
$ ./lightGuide -m run1.mac
```
- execute lightGuide in 'interactive mode' with visualization
```
$ lightGuide
....
Idle> type your commands. For instance:
Idle> /control/execute run1.mac
....
Idle> exit
```
#----- Set the beam energy profile -----
/gps/particle opticalphoton
/gps/ene/type Gauss
/gps/ene/mono 4.75 eV
/gps/ene/sigma 10 eV
/gps/ene/min 1.9 eV
/gps/ene/max 7.6 eV
/gps/ene/gradient -200 MeV
/gps/polarization 0 0 0
#----- Set the beam geometry -----
# Circular beam source. Simulates a single fiber optic
#/gps/pos/type Beam
#/gps/pos/shape Circle
#/gps/pos/radius 0.75 mm
#/gps/pos/radius 1.5 mm
#/gps/pos/sigma_r 0.002 mm
# Rectangular plane for infinite resolution
/gps/pos/type Plane
/gps/pos/shape Rectangle
/gps/pos/halfx 40 mm
/gps/pos/halfy 68 mm
# the incident surface is in the x-z plane just below the gas
/gps/pos/rot1 1 0 0
/gps/pos/rot2 0 0 1
/gps/pos/centre 0. -0.1 0. mm
# the photons are emitted around the y-axis
/gps/ang/rot1 1 0 0
/gps/ang/rot2 0 0 1
/gps/ang/type beam1d
#----- Set beam angular dispersion from histogram -----
/gps/ang/surfnorm false
/gps/ang/type user
/control/execute hist.mac
#----- Set beam angular dispersion for fiber optic -----
# N.A. is 0.22 so acceptance cone is ~25.4 degrees
#/gps/ang/sigma_r 25.40 deg
/lightGuide/worldVolume 0.25 0.25 0.25 m
/lightGuide/envelope 89.75 113. 165. mm
/lightGuide/model/PMTDiameter 53 mm
/lightGuide/model/nSegmentsX 1
/lightGuide/model/nSegmentsZ 1
#----- Set the light guide to be used and position it -----
#If no model is selected, the program will default to a
#simplified version of the 2018 testbeam light guide
/lightGuide/model/CADmodel ../models/run2.stl
/lightGuide/model/translate 200 -125 0 mm
/lightGuide/model/translatePMT 0 -74.5 0 mm
#/lightGuide/model/CADmodel ../models/EMprototype.stl
#/lightGuide/model/translate 0 0 0 mm
#/lightGuide/model/translatePMT 0 -74.5 0 mm
#/lightGuide/model/CADmodel ../models/EMprototypeSingle.stl
#/lightGuide/model/translate 175.25 -27.75 -8 mm
#/lightGuide/model/translatePMT 0 0 0 mm
#/lightGuide/model/CADmodel ../models/2020WC.stl
#/lightGuide/model/rotate 0 0 90
#/lightGuide/model/translate 0 -319 0 mm
#/lightGuide/model/translatePMT 0 -119 0 mm
#----- Set surface properties of the light guide -----
#/lightGuide/surface/Model unified
#/lightGuide/surface/Type dielectric_metal
#/lightGuide/surface/Finish ground
#/lightGuide/surface/SigmaAlpha .1
#/lightGuide/surface/Property SPECULARLOBECONSTANT 0.000002 .4 0.000008 .4
#/lightGuide/surface/Property SPECULARSPIKECONSTANT 0.000002 .1 0.000008 .1
#/lightGuide/surface/Property BACKSCATTERCONSTANT 0.000002 .05 0.000008 .05
#/lightGuide/surface/Property REFLECTIVITY 0.000002 .89 0.000008 .89
#----- Set the refractive index of the gas the light guide is inside of -----
#/lightGuide/gasProperty RINDEX 0.000002 1.0 0.000008 1.0
#
# This file permits to customize, with commands,
# the menu bar of the G4UIXm, G4UIQt, G4UIWin32 sessions.
# It has no effect with G4UIterminal.
#
# File menu :
/gui/addMenu file File
/gui/addButton file Quit exit
#
# Run menu :
/gui/addMenu run Run
/gui/addButton run "beamOn 1" "/run/beamOn 1"
#/gui/addButton run run1 "/control/execute run1.mac"
#/gui/addButton run run2 "/control/execute run2.mac"
#
# Gun menu :
/gui/addMenu gun Gun
/gui/addButton gun "50 MeV" "/gun/energy 50 MeV"
/gui/addButton gun "1 GeV" "/gun/energy 1 GeV"
/gui/addButton gun "10 GeV" "/gun/energy 10 GeV"
/gui/addButton gun "e-" "/gun/particle e-"
/gui/addButton gun "pi0" "/gun/particle pi0"
/gui/addButton gun "pi+" "/gun/particle pi+"
/gui/addButton gun "neutron" "/gun/particle neutron"
/gui/addButton gun "proton" "/gun/particle proton"
#
# Field menu :
#/gui/addMenu field Field
#/gui/addButton field "off" "/B2/det/setField 0.2 tesla"
#/gui/addButton field "0.2 tesla" "/B2/det/setField 0.2 tesla"
#/gui/addButton field "2.0 tesla" "/B2/det/setField 2.0 tesla"
#
# Viewer menu :
/gui/addMenu viewer Viewer
/gui/addButton viewer "Set style surface" "/vis/viewer/set/style surface"
/gui/addButton viewer "Set style wireframe" "/vis/viewer/set/style wireframe"
/gui/addButton viewer "Refresh viewer" "/vis/viewer/refresh"
/gui/addButton viewer "Update viewer (interaction or end-of-file)" "/vis/viewer/update"
/gui/addButton viewer "Flush viewer (= refresh + update)" "/vis/viewer/flush"
/gui/addButton viewer "Update scene" "/vis/scene/notifyHandlers"
#
/gps/hist/type theta
#/gps/hist/point -0.007400 0.000000
/gps/hist/point 0.000000 0.000059
/gps/hist/point 0.007400 0.000338
/gps/hist/point 0.014800 0.000512
/gps/hist/point 0.022200 0.000687
/gps/hist/point 0.029600 0.000990
/gps/hist/point 0.037000 0.001121
/gps/hist/point 0.044400 0.001404
/gps/hist/point 0.051800 0.001575
/gps/hist/point 0.059200 0.001921
/gps/hist/point 0.066600 0.002071
/gps/hist/point 0.074000 0.002209
/gps/hist/point 0.081400 0.002370
/gps/hist/point 0.088800 0.002663
/gps/hist/point 0.096200 0.002832
/gps/hist/point 0.103600 0.003022
/gps/hist/point 0.111000 0.003347
/gps/hist/point 0.118400 0.003500
/gps/hist/point 0.125800 0.003817
/gps/hist/point 0.133200 0.003972
/gps/hist/point 0.140600 0.004145
/gps/hist/point 0.148000 0.004303
/gps/hist/point 0.155400 0.004621
/gps/hist/point 0.162800 0.004762
/gps/hist/point 0.170200 0.005010
/gps/hist/point 0.177600 0.005308
/gps/hist/point 0.185000 0.005465
/gps/hist/point 0.192400 0.005574
/gps/hist/point 0.199800 0.005896
/gps/hist/point 0.207200 0.006192
/gps/hist/point 0.214600 0.006292
/gps/hist/point 0.222000 0.006516
/gps/hist/point 0.229400 0.006742
/gps/hist/point 0.236800 0.006942
/gps/hist/point 0.244200 0.007175
/gps/hist/point 0.251600 0.007442
/gps/hist/point 0.259000 0.007549
/gps/hist/point 0.266400 0.007859
/gps/hist/point 0.273800 0.007951
/gps/hist/point 0.281200 0.008102
/gps/hist/point 0.288600 0.008663
/gps/hist/point 0.296000 0.008789
/gps/hist/point 0.303400 0.009103
/gps/hist/point 0.310800 0.009285
/gps/hist/point 0.318200 0.009436
/gps/hist/point 0.325600 0.009630
/gps/hist/point 0.333000 0.009931
/gps/hist/point 0.340400 0.010256
/gps/hist/point 0.347800 0.010362
/gps/hist/point 0.355200 0.010797
/gps/hist/point 0.362600 0.010825
/gps/hist/point 0.370000 0.011403
/gps/hist/point 0.377400 0.011606
/gps/hist/point 0.384800 0.011730
/gps/hist/point 0.392200 0.011980
/gps/hist/point 0.399600 0.012238
/gps/hist/point 0.407000 0.012208
/gps/hist/point 0.414400 0.012737
/gps/hist/point 0.421800 0.013022
/gps/hist/point 0.429200 0.013560
/gps/hist/point 0.436600 0.013393
/gps/hist/point 0.444000 0.013733
/gps/hist/point 0.451400 0.014151
/gps/hist/point 0.458800 0.014394
/gps/hist/point 0.466200 0.014743
/gps/hist/point 0.473600 0.015354
/gps/hist/point 0.481000 0.015463
/gps/hist/point 0.488400 0.015805
/gps/hist/point 0.495800 0.016047
/gps/hist/point 0.503200 0.016040
/gps/hist/point 0.510600 0.016432
/gps/hist/point 0.518000 0.016911
/gps/hist/point 0.525400 0.017092
/gps/hist/point 0.532800 0.017341
/gps/hist/point 0.540200 0.017891
/gps/hist/point 0.547600 0.018050
/gps/hist/point 0.555000 0.018850
/gps/hist/point 0.562400 0.019253
/gps/hist/point 0.569800 0.019231
/gps/hist/point 0.577200 0.019886
/gps/hist/point 0.584600 0.020413
/gps/hist/point 0.592000 0.020505
/gps/hist/point 0.599400 0.021237
/gps/hist/point 0.606800 0.021726
/gps/hist/point 0.614200 0.022311
/gps/hist/point 0.621600 0.022637
/gps/hist/point 0.629000 0.023515
/gps/hist/point 0.636400 0.024492
/gps/hist/point 0.643800 0.025049
/gps/hist/point 0.651200 0.025821
/gps/hist/point 0.658600 0.026996
/gps/hist/point 0.666000 0.028316
/gps/hist/point 0.673400 0.007106
/gps/hist/point 0.680800 0.000000
/gps/hist/point 0.688200 0.000000
/gps/hist/point 0.695600 0.000000
/gps/hist/point 0.703000 0.000000
/gps/hist/point 0.710400 0.000000
/gps/hist/point 0.717800 0.000000
/gps/hist/point 0.725200 0.000000
# #OLD HIST.MAC
# /gps/hist/point 0.000000 0.000000
# /gps/hist/point 0.008726 0.001677
# /gps/hist/point 0.026179 0.002438
# /gps/hist/point 0.043632 0.002966
# /gps/hist/point 0.061085 0.003407
# /gps/hist/point 0.078538 0.003771
# /gps/hist/point 0.095990 0.004110
# /gps/hist/point 0.113443 0.004415
# /gps/hist/point 0.130896 0.004724
# /gps/hist/point 0.148349 0.005010
# /gps/hist/point 0.165801 0.005293
# /gps/hist/point 0.183254 0.005592
# /gps/hist/point 0.200707 0.005862
# /gps/hist/point 0.218160 0.006130
# /gps/hist/point 0.235613 0.006412
# /gps/hist/point 0.253065 0.006682
# /gps/hist/point 0.270518 0.006950
# /gps/hist/point 0.287971 0.007234
# /gps/hist/point 0.305424 0.007515
# /gps/hist/point 0.322876 0.007781
# /gps/hist/point 0.340329 0.008063
# /gps/hist/point 0.357782 0.008323
# /gps/hist/point 0.375235 0.008598
# /gps/hist/point 0.392687 0.008907
# /gps/hist/point 0.410140 0.009175
# /gps/hist/point 0.427593 0.009454
# /gps/hist/point 0.445046 0.009775
# /gps/hist/point 0.462499 0.010074
# /gps/hist/point 0.479951 0.010385
# /gps/hist/point 0.497404 0.010707
# /gps/hist/point 0.514857 0.011049
# /gps/hist/point 0.532310 0.011366
# /gps/hist/point 0.549762 0.011748
# /gps/hist/point 0.567215 0.012158
# /gps/hist/point 0.584668 0.012550
# /gps/hist/point 0.602121 0.012953
# /gps/hist/point 0.619574 0.013384
# /gps/hist/point 0.637026 0.013836
# /gps/hist/point 0.654479 0.014333
# /gps/hist/point 0.671932 0.014900
# /gps/hist/point 0.689385 0.015575
# /gps/hist/point 0.706837 0.016303
# /gps/hist/point 0.724290 0.017249
# /gps/hist/point 0.741743 0.018648
# /gps/hist/point 0.759196 0.019849
# /gps/hist/point 0.776649 0.020756
# /gps/hist/point 0.794101 0.021327
# /gps/hist/point 0.811554 0.019696
# /gps/hist/point 0.829007 0.018203
# /gps/hist/point 0.846460 0.017120
# /gps/hist/point 0.863912 0.016291
# /gps/hist/point 0.881365 0.015641
# /gps/hist/point 0.898818 0.015079
# /gps/hist/point 0.916271 0.014629
# /gps/hist/point 0.933724 0.014212
# /gps/hist/point 0.951176 0.013883
# /gps/hist/point 0.968629 0.013545
# /gps/hist/point 0.986082 0.013284
# /gps/hist/point 1.003535 0.013057
# /gps/hist/point 1.020988 0.012847
# /gps/hist/point 1.038440 0.012644
# /gps/hist/point 1.055893 0.012443
# /gps/hist/point 1.073346 0.012321
# /gps/hist/point 1.090799 0.012159
# /gps/hist/point 1.108251 0.012022
# /gps/hist/point 1.125704 0.011891
# /gps/hist/point 1.143157 0.011784
# /gps/hist/point 1.160610 0.011684
# /gps/hist/point 1.178063 0.011600
# /gps/hist/point 1.195515 0.011499
# /gps/hist/point 1.212968 0.011423
# /gps/hist/point 1.230421 0.011358
# /gps/hist/point 1.247874 0.011273
# /gps/hist/point 1.265326 0.011216
# /gps/hist/point 1.282779 0.011145
# /gps/hist/point 1.300232 0.011114
# /gps/hist/point 1.317685 0.011054
# /gps/hist/point 1.335137 0.011028
# /gps/hist/point 1.352590 0.010988
# /gps/hist/point 1.370043 0.010938
# /gps/hist/point 1.387496 0.010915
# /gps/hist/point 1.404949 0.010911
# /gps/hist/point 1.422401 0.010852
# /gps/hist/point 1.439854 0.010845
# /gps/hist/point 1.457307 0.010834
# /gps/hist/point 1.474760 0.010807
# /gps/hist/point 1.492212 0.010819
# /gps/hist/point 1.509665 0.010799
# /gps/hist/point 1.527118 0.010811
# /gps/hist/point 1.544571 0.009312
# /gps/hist/point 1.562024 0.008725
# /gps/hist/point 1.570700 0.000000
......@@ -23,43 +23,46 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file OpNovice/include/OpNovicePhysicsListMessenger.hh
/// \brief Definition of the OpNovicePhysicsListMessenger class
/// \file ASCIIPrimaryGenerator.hh
/// \brief Definition of the ASCIIPrimaryGenerator class
//
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef OpNovicePhysicsListMessenger_h
#define OpNovicePhysicsListMessenger_h 1
#ifndef ASCIIPrimaryGenerator_h
#define ASCIIPrimaryGenerator_h 1
#include "G4VPrimaryGenerator.hh"
#include "globals.hh"
#include "G4UImessenger.hh"
#include <fstream>
#include <vector>
class OpNovicePhysicsList;
class G4UIdirectory;
class G4UIcmdWithAnInteger;
class G4Event;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class OpNovicePhysicsListMessenger: public G4UImessenger
class ASCIIPrimaryGenerator : public G4VPrimaryGenerator
{
public:
OpNovicePhysicsListMessenger(OpNovicePhysicsList* );
virtual ~OpNovicePhysicsListMessenger();
virtual void SetNewValue(G4UIcommand*, G4String);
ASCIIPrimaryGenerator();
~ASCIIPrimaryGenerator();
virtual void SetInputFile(G4String _name);
virtual void GetNextEvent( );
inline G4int GetnEvents(){return fnEvents;}
public:
virtual void GeneratePrimaryVertex(G4Event*);
private:
OpNovicePhysicsList* fPhysicsList;
G4UIdirectory* fOpNoviceDir;
G4UIdirectory* fPhysDir;
G4UIcmdWithAnInteger* fVerboseCmd;
G4UIcmdWithAnInteger* fCerenkovCmd;
std::vector< G4ThreeVector >* fPositionVec;
std::vector< G4ThreeVector >* fMomentumVec;
std::vector< G4double >* fEnergyVec;
G4int fEventNo;
G4int fnEvents = 0;
std::ifstream fInputFile;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
......
......@@ -24,11 +24,11 @@
// ********************************************************************
//
//
/// \file OpNoviceActionInitialization.hh
/// \brief Definition of the OpNoviceActionInitialization class
/// \file ActionInitialization.hh
/// \brief Definition of the ActionInitialization class
#ifndef OpNoviceActionInitialization_h
#define OpNoviceActionInitialization_h 1
#ifndef ActionInitialization_h
#define ActionInitialization_h 1
#include "G4VUserActionInitialization.hh"
#include "G4String.hh"
......@@ -38,16 +38,15 @@ class B4DetectorConstruction;
/// Action initialization class.
///
class OpNoviceActionInitialization : public G4VUserActionInitialization
class ActionInitialization : public G4VUserActionInitialization
{
public:
OpNoviceActionInitialization(G4String);
virtual ~OpNoviceActionInitialization();
ActionInitialization(G4String);
virtual ~ActionInitialization();
virtual void BuildForMaster() const;
virtual void Build() const;
virtual G4VSteppingVerbose* InitializeSteppingVerbose() const;
G4String ffileName;
};
......
// The MIT License (MIT)
//
// Copyright (c) 2011-2020 Christopher M. Poole <mail@christopherpoole.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// CADMESH - Load CAD files into Geant4 quickly and easily.
//
// Read all about it at: https://github.com/christopherpoole/CADMesh
//
// Basic usage:
//
// #include "CADMesh.hh" // This file.
// ...
// auto mesh = CADMesh::TessellatedMesh::FromSTL("mesh.stl");
// G4VSolid* solid = mesh->GetSolid();
// ...
//
// !! THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DON'T EDIT IT DIRECTLY. !!
#pragma once
class BuiltInReader;
class CADMeshTemplate;
class Mesh;
class STLReader;
class ASSIMPReader;
class PLYReader;
class FileTypes;
class OBJReader;
class Exceptions;
class TetrahedralMesh;
class Reader;
class Lexer;
class LexerMacros;
class TessellatedMesh;
#include "G4String.hh"
#include <algorithm>
#include <map>
namespace CADMesh {
namespace File {
enum Type {
Unknown,
PLY,
STL,
DAE,
OBJ,
TET,
OFF,
};
static std::map<Type, G4String> Extension = {
{Unknown, "unknown"}, {PLY, "ply"}, {STL, "stl"}, {DAE, "dae"},
{OBJ, "obj"}, {TET, "tet"}, {OFF, "off"}};
static std::map<Type, G4String> TypeString = {
{Unknown, "UNKNOWN"}, {PLY, "PLY"}, {STL, "STL"}, {DAE, "DAE"},
{OBJ, "OBJ"}, {TET, "TET"}, {OFF, "OFF"}};
static std::map<Type, G4String> TypeName = {
{Unknown, "Unknown File Format"}, {PLY, "Stanford Triangle Format (PLY)"},
{STL, "Stereolithography (STL)"}, {DAE, "COLLADA (DAE)"},
{OBJ, "Wavefront (OBJ)"}, {TET, "TetGet (TET)"},
{OFF, "Object File Format (OFF)"}};
Type TypeFromExtension(G4String extension);
Type TypeFromName(G4String name);
}
}
#include "G4ThreeVector.hh"
#include "G4TriangularFacet.hh"
#include <memory>
#include <vector>
namespace CADMesh {
typedef std::vector<G4ThreeVector> Points;
typedef std::vector<G4TriangularFacet *> Triangles;
class Mesh {
public:
Mesh(Points points, Triangles triangles, G4String name = "");
static std::shared_ptr<Mesh> New(Points points, Triangles triangles,
G4String name = "");
static std::shared_ptr<Mesh> New(Triangles triangles, G4String name = "");
static std::shared_ptr<Mesh> New(std::shared_ptr<Mesh> mesh,
G4String name = "");
public:
G4String GetName();
Points GetPoints();
Triangles GetTriangles();
G4bool IsValidForNavigation();
private:
G4String name_ = "";
Points points_;
Triangles triangles_;
};
typedef std::vector<std::shared_ptr<Mesh>> Meshes;
}
namespace CADMesh {
namespace File {
class Reader {
public:
Reader(G4String reader_name);
~Reader();
virtual G4bool Read(G4String filepath) = 0;
virtual G4bool CanRead(Type file_type) = 0;
public:
G4String GetName();
std::shared_ptr<Mesh> GetMesh();
std::shared_ptr<Mesh> GetMesh(size_t index);
std::shared_ptr<Mesh> GetMesh(G4String name, G4bool exact = true);
size_t GetNumberOfMeshes();
Meshes GetMeshes();
protected:
size_t AddMesh(std::shared_ptr<Mesh> mesh);
void SetMeshes(Meshes meshs);
private:
Meshes meshes_;
G4String name_ = "";
};
}
}
#include <iostream>
#include <string>
namespace CADMesh {
namespace File {
struct Token {
std::string name;
bool operator==(Token other) { return name == other.name; };
bool operator!=(Token other) { return name != other.name; };
};
static Token ErrorToken{"ErrorToken"};
static Token EnfOfFileToken{"EndOfFileToken"};
static Token ParentToken{"Parent"};
static Token WordToken{"Word"};
static Token NumberToken{"Number"};
static Token ThreeVectorToken{"ThreeVector"};
static Token VertexToken{"Vertex"};
static Token VerticesToken{"Vertices"};
static Token FacetToken{"Facet"};
static Token LineToken{"Line"};
static Token NormalToken{"Normal"};
static Token TextureToken{"Texture"};
static Token SolidToken{"Solid"};
static Token ObjectToken{"Object"};
static Token CommentToken{"Comment"};
static Token BlankLineToken{"BlankLine"};
struct Item {
Token token;
size_t position;
size_t line;
std::string value;
std::string error;
Item *parent;
std::vector<Item> children;
};
typedef std::vector<Item> Items;
typedef Items::iterator ItemsIterator;
class Lexer;
struct State {
virtual State *operator()(Lexer *) const = 0;
};
struct __FinalState : public State {
State *operator()(Lexer *) const { return nullptr; }
};
class Lexer {
public:
Lexer(std::string filepath, State *initial_state = nullptr);
public:
std::string String();
void Run(State *initial_state, size_t lines = 0);
Items GetItems();
void Backup();
void BackupTo(int position);
std::string Next();
std::string Peek();
void Skip();
Item *ThisIsA(Token token, std::string error = "");
Item *StartOfA(Token token, std::string error = "");
Item *EndOfA(Token token, std::string error = "");
Item *MaybeEndOfA(Token token, std::string error = "");
bool OneOf(std::string possibles);
bool ManyOf(std::string possibles);
bool Until(std::string match);
bool MatchExactly(std::string match);
bool OneDigit();
bool ManyDigits();
bool OneLetter();
bool ManyLetters();
bool ManyCharacters();
bool Integer();
bool Float();
bool Number();
bool SkipWhiteSpace();
bool SkipLineBreak();
bool SkipLineBreaks();
bool SkipLine();
State *Error(std::string message);
State *LastError();
bool TestState(State *state);
bool IsDryRun();
void PrintMessage(std::string name, std::string message);
void PrintItem(Item item);
size_t LineNumber();
private:
State *state_;
Item *parent_item_ = nullptr;
Items items_;
std::string input_;
size_t position_ = 0;
size_t start_ = 0;
size_t width_ = 1;
size_t line_ = 1;
size_t end_line_ = 0;
bool dry_run_ = false;
int depth_ = 0;
std::string last_error_ = "";
};
}
}
#ifdef USE_CADMESH_ASSIMP_READER
#include "assimp/Importer.hpp"
#include "assimp/postprocess.h"
#include "assimp/scene.h"
namespace CADMesh {
namespace File {
class ASSIMPReader : public File::Reader {
public:
ASSIMPReader();
~ASSIMPReader();
public:
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
private:
Assimp::Importer *importer_;
};
std::shared_ptr<ASSIMPReader> ASSIMP();
}
}
#endif
namespace CADMesh {
namespace File {
class BuiltInReader : public Reader {
public:
BuiltInReader() : Reader("BuiltInReader"){};
public:
G4bool Read(G4String filepath);
G4bool CanRead(File::Type file_type);
};
std::shared_ptr<BuiltInReader> BuiltIn();
}
}
#ifndef CADMESH_DEFAULT_READER
#define CADMESH_DEFAULT_READER BuiltIn
#endif
#include "G4AssemblyVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4TessellatedSolid.hh"
#include "G4Tet.hh"
#include "G4UIcommand.hh"
namespace CADMesh {
template <typename T> class CADMeshTemplate {
public:
CADMeshTemplate();
CADMeshTemplate(G4String file_name);
CADMeshTemplate(G4String file_name, File::Type file_type);
CADMeshTemplate(std::shared_ptr<File::Reader> reader);
CADMeshTemplate(G4String file_name, std::shared_ptr<File::Reader> reader);
CADMeshTemplate(G4String file_name, File::Type file_type,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> From(G4String file_name);
static std::shared_ptr<T> From(G4String file_name,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> FromPLY(G4String file_name);
static std::shared_ptr<T> FromPLY(G4String file_name,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> FromSTL(G4String file_name);
static std::shared_ptr<T> FromSTL(G4String file_name,
std::shared_ptr<File::Reader> reader);
static std::shared_ptr<T> FromOBJ(G4String file_name);
static std::shared_ptr<T> FromOBJ(G4String file_name,
std::shared_ptr<File::Reader> reader);
~CADMeshTemplate();
public:
virtual G4VSolid *GetSolid() = 0;
virtual G4VSolid *GetSolid(G4int index) = 0;
virtual G4VSolid *GetSolid(G4String name, G4bool exact = true) = 0;
virtual std::vector<G4VSolid *> GetSolids() = 0;
virtual G4AssemblyVolume *GetAssembly() = 0;
bool IsValidForNavigation();
public:
G4String GetFileName();
File::Type GetFileType();
void SetVerbose(G4int verbose);
G4int GetVerbose();
void SetScale(G4double scale);
G4double GetScale();
void SetOffset(G4double x, G4double y, G4double z);
void SetOffset(G4ThreeVector offset);
G4ThreeVector GetOffset();
protected:
G4String file_name_;
File::Type file_type_;
G4int verbose_;
G4double scale_;
G4ThreeVector offset_;
G4AssemblyVolume *assembly_ = nullptr;
std::shared_ptr<File::Reader> reader_ = nullptr;
};
}
#include "globals.hh"
namespace CADMesh {
namespace Exceptions {
void FileNotFound(G4String origin, G4String filepath);
void LexerError(G4String origin, G4String message);
void ParserError(G4String origin, G4String message);
void ReaderCantReadError(G4String origin, File::Type file_type,
G4String filepath);
void MeshNotFound(G4String origin, size_t index);
void MeshNotFound(G4String origin, G4String name);
}
}
namespace CADMesh {
class TessellatedMesh : public CADMeshTemplate<TessellatedMesh> {
using CADMeshTemplate::CADMeshTemplate;
public:
G4VSolid *GetSolid();
G4VSolid *GetSolid(G4int index);
G4VSolid *GetSolid(G4String name, G4bool exact = true);
std::vector<G4VSolid *> GetSolids();
G4TessellatedSolid *GetTessellatedSolid();
G4TessellatedSolid *GetTessellatedSolid(G4int index);
G4TessellatedSolid *GetTessellatedSolid(G4String name, G4bool exact = true);
G4TessellatedSolid *GetTessellatedSolid(std::shared_ptr<Mesh> mesh);
G4AssemblyVolume *GetAssembly();
public:
void SetReverse(G4bool reverse) { this->reverse_ = reverse; };
G4bool GetReverse() { return this->reverse_; };
private:
G4bool reverse_;
};
}
#ifdef USE_CADMESH_TETGEN
#include "tetgen.h"
namespace CADMesh {
class TetrahedralMesh : public CADMeshTemplate<TetrahedralMesh> {
public:
using CADMeshTemplate::CADMeshTemplate;
TetrahedralMesh();
~TetrahedralMesh();
public:
G4VSolid *GetSolid();
G4VSolid *GetSolid(G4int index);
G4VSolid *GetSolid(G4String name, G4bool exact = true);
std::vector<G4VSolid *> GetSolids();
G4AssemblyVolume *GetAssembly();
public:
void SetMaterial(G4Material *material) { this->material_ = material; };
G4Material *GetMaterial() { return this->material_; };
void SetQuality(G4double quality) { this->quality_ = quality; };
G4double GetQuality() { return this->quality_; };
std::shared_ptr<tetgenio> GetTetgenInput() { return in_; };
std::shared_ptr<tetgenio> GetTetgenOutput() { return out_; };
private:
G4ThreeVector GetTetPoint(G4int index_offset);
private:
std::shared_ptr<tetgenio> in_ = nullptr;
std::shared_ptr<tetgenio> out_ = nullptr;
G4double quality_;
G4Material *material_;
};
}
#endif
namespace CADMesh {
namespace File {
inline Type TypeFromExtension(G4String extension) {
std::for_each(extension.begin(), extension.end(),
[](char &e) { e = ::tolower(e); });
for (auto e = Extension.begin(); e != Extension.end(); ++e) {
if (e->second == extension) {
return e->first;
}
}
return Unknown;
}
inline Type TypeFromName(G4String name) {
auto extension = name.substr(name.find_last_of(".") + 1);
return TypeFromExtension(extension);
}
}
}
namespace CADMesh {
inline Mesh::Mesh(Points points, Triangles triangles, G4String name)
: name_(name), points_(points), triangles_(triangles) {}
inline std::shared_ptr<Mesh> Mesh::New(Points points, Triangles triangles,
G4String name) {
return std::make_shared<Mesh>(points, triangles, name);
}
inline std::shared_ptr<Mesh> Mesh::New(Triangles triangles, G4String name) {
Points points;
return New(points, triangles, name);
}
inline std::shared_ptr<Mesh> Mesh::New(std::shared_ptr<Mesh> mesh,
G4String name) {
return New(mesh->GetPoints(), mesh->GetTriangles(), name);
}
inline G4String Mesh::GetName() { return name_; }
inline Points Mesh::GetPoints() { return points_; }
inline Triangles Mesh::GetTriangles() { return triangles_; }
inline G4bool Mesh::IsValidForNavigation() {
std::map<G4ThreeVector, size_t> point_index;
size_t index = 0;
for (auto point : points_) {
point_index[point] = index;
index++;
}
typedef std::pair<size_t, size_t> Edge;
std::map<Edge, G4int> edge_use_count;
for (size_t i = 0; i < triangles_.size(); i++) {
auto triangle = triangles_[i];
size_t a = point_index[triangle->GetVertex(0)];
size_t b = point_index[triangle->GetVertex(1)];
size_t c = point_index[triangle->GetVertex(2)];
if (a < b) {
edge_use_count[Edge(a, b)] += 1;
}
else if (a > b) {
edge_use_count[Edge(b, a)] += 1;
}
if (b < c) {
edge_use_count[Edge(b, c)] += 1;
}
else if (b > c) {
edge_use_count[Edge(c, b)] += 1;
}
if (c < a) {
edge_use_count[Edge(c, a)] += 1;
}
else if (c > a) {
edge_use_count[Edge(a, c)] += 1;
}
}
for (auto count : edge_use_count) {
if (count.second != 2) {
return false;
}
}
return true;
}
}
namespace CADMesh {
namespace File {
inline Reader::Reader(G4String reader_name) : name_(reader_name) {}
inline Reader::~Reader() {}
inline G4String Reader::GetName() { return name_; }
inline std::shared_ptr<Mesh> Reader::GetMesh() {
if (meshes_.size() > 0) {
return meshes_[0];
}
return nullptr;
}
inline std::shared_ptr<Mesh> Reader::GetMesh(size_t index) {
if (index < meshes_.size()) {
return meshes_[index];
}
Exceptions::MeshNotFound("Reader::GetMesh", index);
return nullptr;
}
inline std::shared_ptr<Mesh> Reader::GetMesh(G4String name, G4bool exact) {
for (auto mesh : meshes_) {
if (exact) {
if (mesh->GetName() == name)
return mesh;
}
else {
if (mesh->GetName().find(name) != std::string::npos)
return mesh;
}
}
Exceptions::MeshNotFound("Reader::GetMesh", name);
return nullptr;
}
inline Meshes Reader::GetMeshes() { return meshes_; }
inline size_t Reader::GetNumberOfMeshes() { return meshes_.size(); }
inline size_t Reader::AddMesh(std::shared_ptr<Mesh> mesh) {
meshes_.push_back(mesh);
return meshes_.size();
}
inline void Reader::SetMeshes(Meshes meshes) { meshes_ = meshes; }
}
}
#include <fstream>
#include <sstream>
#include <streambuf>
namespace CADMesh {
namespace File {
inline Lexer::Lexer(std::string filepath, State *initial_state) {
std::ifstream file(filepath);
input_ = std::string((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
if (initial_state) {
Run(initial_state);
}
}
inline std::string Lexer::String() {
return input_.substr(start_, position_ - start_);
}
inline void Lexer::Run(State *initial_state, size_t lines) {
parent_item_ = new Item{ParentToken, position_, line_, "", "",
nullptr, std::vector<Item>()};
state_ = initial_state;
end_line_ = 0;
if (lines > 0)
end_line_ = line_ + lines;
while (state_) {
state_ = (*state_)(this);
}
}
inline Items Lexer::GetItems() { return parent_item_->children; }
inline void Lexer::Backup() {
position_ -= width_;
auto next = input_.substr(position_, 1);
if (next == "\n") {
line_--;
}
}
inline void Lexer::BackupTo(int position) {
auto s = input_.substr(position, position_ - position);
line_ -= std::count(s.begin(), s.end(), '\n');
position_ = position;
}
inline std::string Lexer::Next() {
if (position_ >= input_.length()) {
return "";
}
auto next = input_.substr(position_, 1);
width_ = 1;
position_ += width_;
if (next == "\n")
line_++;
return next;
}
inline std::string Lexer::Peek() {
auto next = Next();
if (next != "")
Backup();
return next;
}
inline void Lexer::Skip() { start_ = position_; }
inline Item *Lexer::ThisIsA(Token token, std::string error) {
if (dry_run_)
return nullptr;
auto item =
Item{token, position_, line_, String(), error, parent_item_, Items()};
Skip();
if (parent_item_) {
PrintItem(item);
parent_item_->children.push_back(item);
return &(parent_item_->children.back());
}
else {
depth_++;
PrintItem(item);
items_.push_back(item);
return &(items_.back());
}
}
inline Item *Lexer::StartOfA(Token token, std::string error) {
if (dry_run_)
return nullptr;
parent_item_ = ThisIsA(token, error);
depth_++;
return parent_item_;
}
inline Item *Lexer::EndOfA(Token token, std::string /*error*/) {
if (dry_run_)
return nullptr;
depth_--;
PrintItem(*parent_item_);
if (parent_item_->token.name != token.name) {
Exceptions::LexerError("Lexer::EndOfA",
"Trying to end a '" + parent_item_->token.name +
"' with a '" + token.name + "' token.");
}
if (parent_item_) {
parent_item_ = parent_item_->parent;
}
return nullptr;
}
inline Item *Lexer::MaybeEndOfA(Token token, std::string error) {
if (parent_item_->token.name == token.name) {
return EndOfA(token, error);
}
else {
return nullptr;
}
}
inline bool Lexer::OneOf(std::string possibles) {
auto peek = Peek();
size_t position = possibles.find(Peek());
if (position != std::string::npos) {
auto next = Next();
return next != "";
}
return false;
}
inline bool Lexer::ManyOf(std::string possibles) {
bool has = false;
while (OneOf(possibles)) {
has = true;
}
return has;
}
inline bool Lexer::Until(std::string match) {
while (!OneOf(match)) {
if (Next() == "")
return false;
}
return true;
}
inline bool Lexer::MatchExactly(std::string match) {
auto start_position = position_;
for (auto m : match) {
if (!OneOf(std::string(1, m))) {
BackupTo(start_position);
return false;
}
}
return true;
}
inline bool Lexer::OneDigit() { return OneOf("0123456789"); }
inline bool Lexer::ManyDigits() { return ManyOf("0123456789"); }
inline bool Lexer::OneLetter() {
return OneOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
inline bool Lexer::ManyLetters() {
return ManyOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
inline bool Lexer::ManyCharacters() {
return ManyOf("!\"#$%&\\\'()*+,-./"
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[|]^_`"
"abcdefghijklmnopqrstuvwxyz{}~");
}
inline bool Lexer::Integer() {
auto start_position = position_;
OneOf("+-");
if (!ManyDigits()) {
BackupTo(start_position);
return false;
}
return true;
}
inline bool Lexer::Float() {
auto start_position = position_;
OneOf("+-");
bool has_integer = Integer();
if (!OneOf(".")) {
BackupTo(start_position);
return false;
}
bool has_decimal = ManyDigits();
if (!has_integer || !has_decimal) {
BackupTo(start_position);
return false;
}
return true;
}
inline bool Lexer::Number() {
if (!Float()) {
if (!Integer()) {
return false;
}
}
auto start_position = position_;
if (OneOf("eE")) {
if (!Float()) {
if (!Integer()) {
BackupTo(start_position);
}
}
}
return true;
}
inline bool Lexer::SkipWhiteSpace() {
if (!ManyOf(" \t\r")) {
Skip();
return false;
}
Skip();
return true;
}
inline bool Lexer::SkipLineBreak() {
if (!OneOf("\n")) {
return false;
}
Skip();
return true;
}
inline bool Lexer::SkipLineBreaks() {
if (!ManyOf("\n")) {
return false;
}
Skip();
return true;
}
inline bool Lexer::SkipLine() {
if (!Until("\n")) {
return false;
}
Skip();
return true;
}
inline State *Lexer::Error(std::string message) {
std::stringstream error;
error << "Error around line " << line_ << ": " << message << std::endl;
last_error_ = error.str();
if (dry_run_)
return nullptr;
Item item{ErrorToken, position_, line_, "",
error.str(), parent_item_, Items()};
items_.push_back(item);
Exceptions::LexerError("Lexer", error.str());
return nullptr;
}
inline State *Lexer::LastError() {
if (last_error_ == "") {
Exceptions::LexerError("Lexer", "Something went wrong.");
}
else {
Exceptions::LexerError("Lexer", last_error_);
}
return nullptr;
}
inline bool Lexer::TestState(State *state) {
if (dry_run_)
return false;
if (end_line_ > 0 && line_ > end_line_)
return false;
auto start_position = position_;
dry_run_ = true;
bool state_transition = ((*state)(this) != nullptr);
dry_run_ = false;
BackupTo(start_position);
return state_transition;
}
inline bool Lexer::IsDryRun() { return dry_run_; }
inline size_t Lexer::LineNumber() { return line_; }
#ifdef CADMESH_LEXER_VERBOSE
inline void Lexer::PrintMessage(std::string name, std::string message) {
std::cout << "Lexer::" << name << " : " << message << std::endl;
}
#else
inline void Lexer::PrintMessage(std::string, std::string) {}
#endif
#ifdef CADMESH_LEXER_VERBOSE
inline void Lexer::PrintItem(Item item) {
auto depth = std::max(0, depth_) * 2;
std::cout << std::string(depth, ' ') << item.token.name << ": " << item.value
<< std::endl;
}
#else
inline void Lexer::PrintItem(Item) {}
#endif
}
}
namespace CADMesh {
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate() : CADMeshTemplate<T>("") {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name)
: CADMeshTemplate<T>(file_name, File::Unknown) {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, File::Type file_type)
: CADMeshTemplate<T>(file_name, file_type, File::CADMESH_DEFAULT_READER()) {
}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(std::shared_ptr<File::Reader> reader)
: CADMeshTemplate<T>("", reader) {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name,
std::shared_ptr<File::Reader> reader)
: CADMeshTemplate<T>(file_name, File::Unknown, reader) {}
template <typename T>
CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, File::Type file_type,
std::shared_ptr<File::Reader> reader) {
if (!reader->CanRead(file_type)) {
Exceptions::ReaderCantReadError(reader->GetName(), file_type, file_name);
}
file_name_ = file_name;
file_type_ = file_type;
scale_ = 1.0;
offset_ = G4ThreeVector();
verbose_ = 0;
reader_ = reader;
reader_->Read(file_name_);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::From(G4String file_name) {
return std::make_shared<T>(file_name);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::From(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, reader);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::FromPLY(G4String file_name) {
return std::make_shared<T>(file_name, File::PLY);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::FromPLY(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, File::PLY, reader);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::FromSTL(G4String file_name) {
return std::make_shared<T>(file_name, File::STL);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::FromSTL(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, File::STL, reader);
}
template <typename T>
std::shared_ptr<T> CADMeshTemplate<T>::FromOBJ(G4String file_name) {
return std::make_shared<T>(file_name, File::OBJ);
}
template <typename T>
std::shared_ptr<T>
CADMeshTemplate<T>::FromOBJ(G4String file_name,
std::shared_ptr<File::Reader> reader) {
return std::make_shared<T>(file_name, File::OBJ, reader);
}
template <typename T> CADMeshTemplate<T>::~CADMeshTemplate() {}
template <typename T> bool CADMeshTemplate<T>::IsValidForNavigation() {
return reader_->GetMesh()->IsValidForNavigation();
}
template <typename T> G4String CADMeshTemplate<T>::GetFileName() {
return file_name_;
}
template <typename T> File::Type CADMeshTemplate<T>::GetFileType() {
return file_type_;
}
template <typename T> void CADMeshTemplate<T>::SetVerbose(G4int verbose) {
verbose_ = verbose;
}
template <typename T> G4int CADMeshTemplate<T>::GetVerbose() {
return verbose_;
}
template <typename T> void CADMeshTemplate<T>::SetScale(G4double scale) {
scale_ = scale;
}
template <typename T> G4double CADMeshTemplate<T>::GetScale() { return scale_; }
template <typename T>
void CADMeshTemplate<T>::SetOffset(G4double x, G4double y, G4double z) {
SetOffset(G4ThreeVector(x, y, z));
}
template <typename T> void CADMeshTemplate<T>::SetOffset(G4ThreeVector offset) {
offset_ = offset;
}
template <typename T> G4ThreeVector CADMeshTemplate<T>::GetOffset() {
return offset_;
}
}
namespace CADMesh {
namespace Exceptions {
inline void FileNotFound(G4String origin, G4String filepath) {
G4Exception(
("CADMesh in " + origin).c_str(), "FileNotFound", FatalException,
("\nThe file: \n\t" + filepath + "\ncould not be found.").c_str());
}
inline void LexerError(G4String origin, G4String message) {
G4Exception(
("CADMesh in " + origin).c_str(), "LexerError", FatalException,
("\nThe CAD file appears to contain incorrect syntax:\n\t" + message)
.c_str());
}
inline void ParserError(G4String origin, G4String message) {
G4Exception(("CADMesh in " + origin).c_str(), "ParserError", FatalException,
("\nThe CAD file appears to contain invalid data:\n\t" + message)
.c_str());
}
inline void ReaderCantReadError(G4String origin, File::Type file_type,
G4String filepath) {
G4Exception(
("CADMesh in " + origin).c_str(), "ReaderCantReadError", FatalException,
(G4String("\nThe the reader can't read files of type '") +
File::TypeString[file_type] +
".'\n\tSpecified the incorrect file type (?) for file:\n\t\t" + filepath)
.c_str());
}
inline void MeshNotFound(G4String origin, size_t index) {
std::stringstream message;
message << "\nThe mesh with index '" << index << "' could not be found.";
G4Exception(("CADMesh in " + origin).c_str(), "MeshNotFound", FatalException,
message.str().c_str());
}
inline void MeshNotFound(G4String origin, G4String name) {
G4Exception(
("CADMesh in " + origin).c_str(), "MeshNotFound", FatalException,
("\nThe mesh with name '" + name + "' could not be found.").c_str());
}
}
}
#include "Randomize.hh"
namespace CADMesh {
inline G4VSolid *TessellatedMesh::GetSolid() {
return (G4VSolid *)GetTessellatedSolid();
}
inline G4VSolid *TessellatedMesh::GetSolid(G4int index) {
return (G4VSolid *)GetTessellatedSolid(index);
}
inline G4VSolid *TessellatedMesh::GetSolid(G4String name, G4bool exact) {
return (G4VSolid *)GetTessellatedSolid(name, exact);
}
inline std::vector<G4VSolid *> TessellatedMesh::GetSolids() {
std::vector<G4VSolid *> solids;
for (auto mesh : reader_->GetMeshes()) {
solids.push_back(GetTessellatedSolid(mesh));
}
return solids;
}
inline G4AssemblyVolume *TessellatedMesh::GetAssembly() {
if (assembly_) {
return assembly_;
}
for (auto mesh : reader_->GetMeshes()) {
auto solid = GetTessellatedSolid(mesh);
G4Material *material = nullptr;
auto logical =
new G4LogicalVolume(solid, material, mesh->GetName() + "_logical");
G4ThreeVector position = G4ThreeVector();
G4RotationMatrix *rotation = new G4RotationMatrix();
assembly_->AddPlacedVolume(logical, position, rotation);
}
return assembly_;
}
inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid() {
return GetTessellatedSolid(0);
}
inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid(G4int index) {
return GetTessellatedSolid(reader_->GetMesh(index));
}
inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid(G4String name,
G4bool exact) {
return GetTessellatedSolid(reader_->GetMesh(name, exact));
}
inline G4TessellatedSolid *
TessellatedMesh::GetTessellatedSolid(std::shared_ptr<Mesh> mesh) {
auto volume_solid = new G4TessellatedSolid(mesh->GetName());
for (auto triangle : mesh->GetTriangles()) {
auto a = triangle->GetVertex(0) * scale_ + offset_;
auto b = triangle->GetVertex(1) * scale_ + offset_;
auto c = triangle->GetVertex(2) * scale_ + offset_;
auto t = new G4TriangularFacet(a, b, c, ABSOLUTE);
if (reverse_) {
volume_solid->AddFacet((G4VFacet *)t->GetFlippedFacet());
}
else {
volume_solid->AddFacet((G4VFacet *)t);
}
}
volume_solid->SetSolidClosed(true);
if (volume_solid->GetNumberOfFacets() == 0) {
G4Exception("TessellatedMesh::GetTessellatedSolid",
"The loaded mesh has 0 faces.", FatalException,
"The file may be empty.");
return nullptr;
}
return volume_solid;
}
}
#ifdef USE_CADMESH_TETGEN
namespace CADMesh {
inline TetrahedralMesh::TetrahedralMesh() {}
inline TetrahedralMesh::~TetrahedralMesh() {}
inline G4VSolid *TetrahedralMesh::GetSolid() { return GetSolid(0); }
inline G4VSolid *TetrahedralMesh::GetSolid(G4int /*index*/) { return nullptr; }
inline G4VSolid *TetrahedralMesh::GetSolid(G4String /*name*/,
G4bool /*exact*/) {
return nullptr;
}
inline std::vector<G4VSolid *> TetrahedralMesh::GetSolids() {
return std::vector<G4VSolid *>();
}
inline G4AssemblyVolume *TetrahedralMesh::GetAssembly() {
if (assembly_) {
return assembly_;
}
assembly_ = new G4AssemblyVolume();
in_ = std::make_shared<tetgenio>();
out_ = std::make_shared<tetgenio>();
char *fn = (char *)file_name_.c_str();
G4bool do_tet = true;
if (file_type_ == File::STL) {
in_->load_stl(fn);
}
else if (file_type_ == File::PLY) {
in_->load_ply(fn);
}
else if (file_type_ == File::TET) {
out_->load_tetmesh(fn, 0);
do_tet = false;
}
else if (file_type_ == File::OFF) {
out_->load_off(fn);
do_tet = false;
}
if (do_tet) {
tetgenbehavior *behavior = new tetgenbehavior();
behavior->nobisect = 1;
behavior->plc = 1;
behavior->quality = quality_;
tetrahedralize(behavior, in_.get(), out_.get());
}
G4RotationMatrix *element_rotation = new G4RotationMatrix();
G4ThreeVector element_position = G4ThreeVector();
G4Transform3D assembly_transform = G4Translate3D();
for (int i = 0; i < out_->numberoftetrahedra; i++) {
int index_offset = i * 4;
G4ThreeVector p1 = GetTetPoint(index_offset);
G4ThreeVector p2 = GetTetPoint(index_offset + 1);
G4ThreeVector p3 = GetTetPoint(index_offset + 2);
G4ThreeVector p4 = GetTetPoint(index_offset + 3);
G4String tet_name =
file_name_ + G4String("_tet_") + G4UIcommand::ConvertToString(i);
auto tet_solid =
new G4Tet(tet_name + G4String("_solid"), p1, p2, p3, p4, 0);
auto tet_logical = new G4LogicalVolume(
tet_solid, material_, tet_name + G4String("_logical"), 0, 0, 0);
assembly_->AddPlacedVolume(tet_logical, element_position, element_rotation);
}
return assembly_;
}
inline G4ThreeVector TetrahedralMesh::GetTetPoint(G4int index_offset) {
return G4ThreeVector(
out_->pointlist[out_->tetrahedronlist[index_offset] * 3] * scale_ -
offset_.x(),
out_->pointlist[out_->tetrahedronlist[index_offset] * 3 + 1] * scale_ -
offset_.y(),
out_->pointlist[out_->tetrahedronlist[index_offset] * 3 + 2] * scale_ -
offset_.z());
}
}
#endif
#define CADMeshLexerToken(name) \
static Token name##Token { #name }
#define CADMeshLexerStateDefinition(name) \
struct name##State : public State { \
State *operator()(Lexer *lexer) const; \
}
#define CADMeshLexerState(name) name##State::operator()(Lexer *lexer) const
#define ThisIsA(name) lexer->ThisIsA(name##Token)
#define StartOfA(name) lexer->StartOfA(name##Token)
#define EndOfA(name) lexer->EndOfA(name##Token)
#define MaybeEndOfA(name) lexer->MaybeEndOfA(name##Token)
#define Skip() lexer->Skip()
#define Next() lexer->Peek()
#define PrintNext() std::cout << lexer->Peek() << std::endl;
#define OneOf(possibles) lexer->OneOf(possibles)
#define NotOneOf(possibles) !OneOf(possibles)
#define ManyOf(possibles) lexer->ManyOf(possibles)
#define NotManyOf(possibles) !ManyOf(possibles)
#define Until(match) lexer->Until(match)
#define RestOfLine() \
if (Until("\n\r")) \
lexer->Backup()
#define MatchExactly(match) lexer->MatchExactly(match)
#define DoesNotMatchExactly(match) !MatchExactly(match)
#define OneDigit() lexer->OneDigit()
#define NotOneDigit() !OneDigit()
#define ManyDigits() lexer->ManyDigits()
#define NotManyDigits() !ManyDigits()
#define OneLetter() lexer->OneLetter()
#define NotOneLetter() !OneLetter()
#define ManyLetters() lexer->ManyLetters()
#define NotManyLetters() !ManyLetters()
#define ManyCharacters() lexer->ManyCharacters()
#define NotManyCharacters() !ManyCharacters()
#define Integer() lexer->Integer()
#define NotAnInteger() !Integer()
#define Float() lexer->Float()
#define NotAFloat() !Float()
#define Number() lexer->Number()
#define NotANumber() !Number()
#define SkipWhiteSpace() lexer->SkipWhiteSpace()
#define DidNotSkipWhiteSpace() !SkipWhiteSpace()
#define SkipLineBreak() lexer->SkipLineBreak()
#define DidNotSkipLineBreak() !SkipLineBreak()
#define SkipLineBreaks() lexer->SkipLineBreaks()
#define DidNotSkipLineBreaks() !SkipLineBreaks()
#define SkipLine() lexer->SkipLine()
#define DidNotSkipLine() !SkipLine()
#define AtEndOfLine() Next() == "\n" || Next() == "\r"
#define Error(message) \
{ \
lexer->Error(message); \
return nullptr; \
}
#define NextState(next) return new next##State()
#define TestState(next) lexer->TestState(new next##State())
#define TryState(next) \
if (TestState(next)) \
NextState(next)
#define FinalState() return new __FinalState();
#define RunLexer(filepath, start) Lexer(filepath, new start##State).GetItems()
namespace CADMesh {
namespace File {
class STLReader : public Reader {
public:
STLReader() : Reader("STLReader"){};
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
protected:
CADMeshLexerStateDefinition(StartSolid);
CADMeshLexerStateDefinition(EndSolid);
CADMeshLexerStateDefinition(StartFacet);
CADMeshLexerStateDefinition(EndFacet);
CADMeshLexerStateDefinition(StartVertices);
CADMeshLexerStateDefinition(EndVertices);
CADMeshLexerStateDefinition(Vertex);
CADMeshLexerStateDefinition(ThreeVector);
std::shared_ptr<Mesh> ParseMesh(Items items);
G4TriangularFacet *ParseFacet(Items items);
G4TriangularFacet *ParseVertices(Items items);
G4ThreeVector ParseThreeVector(Items items);
};
}
}
namespace CADMesh {
namespace File {
class OBJReader : public Reader {
public:
OBJReader() : Reader("OBJReader"){};
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
protected:
CADMeshLexerStateDefinition(StartSolid);
CADMeshLexerStateDefinition(EndSolid);
CADMeshLexerStateDefinition(Ignore);
CADMeshLexerStateDefinition(Vertex);
CADMeshLexerStateDefinition(Facet);
CADMeshLexerStateDefinition(Object);
std::shared_ptr<Mesh> ParseMesh(Items items);
G4ThreeVector ParseVertex(Items items);
G4TriangularFacet *ParseFacet(Items items, G4bool quad);
private:
Points vertices_;
};
}
}
namespace CADMesh {
namespace File {
CADMeshLexerToken(Header);
CADMeshLexerToken(Element);
CADMeshLexerToken(Property);
class PLYReader : public Reader {
public:
PLYReader() : Reader("PLYReader"){};
G4bool Read(G4String filepath);
G4bool CanRead(Type file_type);
protected:
CADMeshLexerStateDefinition(StartHeader);
CADMeshLexerStateDefinition(EndHeader);
CADMeshLexerStateDefinition(Element);
CADMeshLexerStateDefinition(Property);
CADMeshLexerStateDefinition(Ignore);
CADMeshLexerStateDefinition(Vertex);
CADMeshLexerStateDefinition(Facet);
void ParseHeader(Items items);
std::shared_ptr<Mesh> ParseMesh(Items vertex_items, Items face_items);
G4ThreeVector ParseVertex(Items items);
G4TriangularFacet *ParseFacet(Items items, Points vertices);
size_t vertex_count_ = 0;
size_t facet_count_ = 0;
size_t x_index_ = 0;
size_t y_index_ = 0;
size_t z_index_ = 0;
size_t facet_index_ = 0;
};
}
}
namespace CADMesh {
namespace File {
inline State *STLReader::CADMeshLexerState(StartSolid) {
if (DoesNotMatchExactly("solid"))
Error("STL files start with 'solid'. Make sure you are using an ASCII STL "
"file.");
SkipWhiteSpace();
RestOfLine();
StartOfA(Solid);
SkipLineBreak();
NextState(StartFacet);
}
inline State *STLReader::CADMeshLexerState(EndSolid) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("endsolid"))
Error("STL files end with 'endsolid'.");
Skip();
EndOfA(Solid);
FinalState();
}
inline State *STLReader::CADMeshLexerState(StartFacet) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("facet normal"))
Error("Facets are indicated by the tag 'facet normal'.");
SkipWhiteSpace();
StartOfA(Facet);
SkipLine();
NextState(StartVertices);
}
inline State *STLReader::CADMeshLexerState(EndFacet) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("endfacet"))
Error("The end of a facets is indicated by the tag 'endfacet'.");
SkipWhiteSpace();
SkipLineBreak();
EndOfA(Facet);
TryState(StartFacet);
NextState(EndSolid);
}
inline State *STLReader::CADMeshLexerState(StartVertices) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("outer loop"))
Error("The start of the vertices is indicated by the tag 'outer loop'.");
SkipWhiteSpace();
SkipLineBreak();
StartOfA(Vertices);
NextState(Vertex);
}
inline State *STLReader::CADMeshLexerState(EndVertices) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("endloop"))
Error("The end of the vertices is indicated by the tag 'endloop'.");
SkipWhiteSpace();
SkipLineBreak();
EndOfA(Vertices);
NextState(EndFacet);
}
inline State *STLReader::CADMeshLexerState(Vertex) {
SkipWhiteSpace();
SkipLineBreaks();
SkipWhiteSpace();
if (DoesNotMatchExactly("vertex"))
Error("A vertex is indicated by the tag 'vertex'.");
SkipWhiteSpace();
NextState(ThreeVector);
}
inline State *STLReader::CADMeshLexerState(ThreeVector) {
SkipWhiteSpace();
StartOfA(ThreeVector);
if (NotANumber())
Error("First number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Second number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Third number in three vector not found.");
ThisIsA(Number);
EndOfA(ThreeVector);
SkipWhiteSpace();
if (DidNotSkipLineBreak())
Error("Expecting a new line at the end of a three vector.");
TryState(StartVertices);
TryState(Vertex);
NextState(EndVertices);
}
inline G4bool STLReader::Read(G4String filepath) {
auto items = RunLexer(filepath, StartSolid);
if (items.size() == 0) {
Exceptions::ParserError("STLReader::Read",
"The STL file appears to be empty.");
}
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The mesh appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::Read", error.str());
}
auto mesh = ParseMesh(item.children);
auto name = G4String(item.value);
AddMesh(Mesh::New(mesh, name));
}
return true;
}
inline G4bool STLReader::CanRead(Type file_type) { return (file_type == STL); }
inline std::shared_ptr<Mesh> STLReader::ParseMesh(Items items) {
Triangles triangles;
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The facet appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::Mesh", error.str());
}
triangles.push_back(ParseFacet(item.children));
}
return Mesh::New(triangles);
}
inline G4TriangularFacet *STLReader::ParseFacet(Items items) {
Triangles triangles;
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::ParseFacet", error.str());
}
triangles.push_back(ParseVertices(item.children));
}
if (triangles.size() != 1) {
std::stringstream error;
error << "STL files expect exactly 1 triangle per facet.";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("STLReader::ParseFacet", error.str());
}
return triangles[0];
}
inline G4TriangularFacet *STLReader::ParseVertices(Items items) {
std::vector<G4ThreeVector> vertices;
for (auto item : items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("STLReader::ParseVertices", error.str());
}
vertices.push_back(ParseThreeVector(item.children));
}
if (vertices.size() != 3) {
std::stringstream error;
error << "STL files expect exactly 3 vertices for a triangular facet. ";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("STLReader::ParseVertices", error.str());
}
return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
}
inline G4ThreeVector STLReader::ParseThreeVector(Items items) {
std::vector<double> numbers;
for (auto item : items) {
numbers.push_back((double)atof(item.value.c_str()));
}
if (numbers.size() != 3) {
std::stringstream error;
error << "Three vectors in STL files require exactly 3 numbers";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("STLReader::ParseThreeVector", error.str());
}
return G4ThreeVector(numbers[0], numbers[1], numbers[2]);
}
}
}
namespace CADMesh {
namespace File {
inline State *OBJReader::CADMeshLexerState(StartSolid) {
StartOfA(Solid);
TryState(Object);
TryState(Vertex);
TryState(Ignore);
Error("Invalid element tag.");
}
inline State *OBJReader::CADMeshLexerState(EndSolid) {
if (Next() != "")
lexer->LastError();
EndOfA(Solid);
FinalState();
}
inline State *OBJReader::CADMeshLexerState(Ignore) {
if (DidNotSkipLine())
NextState(EndSolid);
TryState(Object);
TryState(Vertex);
TryState(Facet);
TryState(Ignore);
NextState(EndSolid);
}
inline State *OBJReader::CADMeshLexerState(Vertex) {
SkipLineBreaks();
if (DoesNotMatchExactly("v "))
Error("A vertex is indicated by the tag 'v'.");
SkipWhiteSpace();
StartOfA(Vertex);
if (NotANumber())
Error("First number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Second number in three vector not found.");
ThisIsA(Number);
SkipWhiteSpace();
if (NotANumber())
Error("Third number in three vector not found.");
ThisIsA(Number);
EndOfA(Vertex);
SkipLine();
TryState(Vertex);
TryState(Object);
TryState(Facet);
TryState(Ignore);
NextState(EndSolid);
}
inline State *OBJReader::CADMeshLexerState(Facet) {
SkipLineBreaks();
if (DoesNotMatchExactly("f "))
Error("A facet is indicated by the tag 'f'.");
SkipWhiteSpace();
StartOfA(Facet);
if (NotANumber())
Error("First number in three vector not found.");
ThisIsA(Number);
OneOf("/");
Number();
OneOf("/");
Number();
SkipWhiteSpace();
if (NotANumber())
Error("Second number in three vector not found.");
ThisIsA(Number);
OneOf("/");
Number();
OneOf("/");
Number();
SkipWhiteSpace();
if (NotANumber())
Error("Third number in three vector not found.");
ThisIsA(Number);
OneOf("/");
Number();
OneOf("/");
Number();
SkipWhiteSpace();
if (Number())
ThisIsA(Number);
EndOfA(Facet);
SkipLine();
TryState(Facet);
TryState(Vertex);
TryState(Object);
TryState(Ignore);
NextState(EndSolid);
}
inline State *OBJReader::CADMeshLexerState(Object) {
SkipLineBreaks();
if (DoesNotMatchExactly("o "))
Error("An object is indicated by the tag 'o'.");
EndOfA(Solid);
SkipWhiteSpace();
StartOfA(Solid);
ManyCharacters();
ThisIsA(Word);
SkipWhiteSpace();
TryState(Vertex);
TryState(Facet);
TryState(Object);
TryState(Ignore);
NextState(EndSolid);
}
inline G4bool OBJReader::Read(G4String filepath) {
auto items = RunLexer(filepath, StartSolid);
if (items.size() == 0) {
Exceptions::ParserError("OBJReader::Read",
"The OBJ file appears to be empty.");
}
for (auto item : items) {
if (item.children.size() == 0) {
continue;
}
auto mesh = ParseMesh(item.children);
if (mesh->GetTriangles().size() == 0) {
continue;
}
G4String name;
if (item.children[0].token == WordToken) {
name = item.children[0].value;
}
AddMesh(Mesh::New(mesh, name));
}
return true;
}
inline G4bool OBJReader::CanRead(Type file_type) { return (file_type == OBJ); }
inline std::shared_ptr<Mesh> OBJReader::ParseMesh(Items items) {
Triangles facets;
for (auto item : items) {
if (item.token != VertexToken) {
continue;
}
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("OBJReader::Mesh", error.str());
}
vertices_.push_back(ParseVertex(item.children));
}
for (auto item : items) {
if (item.token != FacetToken) {
continue;
}
if (item.children.size() == 0) {
std::stringstream error;
error << "The facet appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("OBJReader::Mesh", error.str());
}
facets.push_back(ParseFacet(item.children, false));
if (item.children.size() == 4) {
facets.push_back(ParseFacet(item.children, true));
}
}
return Mesh::New(facets);
}
inline G4ThreeVector OBJReader::ParseVertex(Items items) {
std::vector<double> numbers;
for (auto item : items) {
numbers.push_back((double)atof(item.value.c_str()));
}
if (numbers.size() != 3) {
std::stringstream error;
error << "Three vectors in OBJ files require exactly 3 numbers";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("OBJReader::ParseThreeVector", error.str());
}
return G4ThreeVector(numbers[0], numbers[1], numbers[2]);
}
inline G4TriangularFacet *OBJReader::ParseFacet(Items items, G4bool quad) {
std::vector<int> indices;
for (auto item : items) {
indices.push_back((int)atoi(item.value.c_str()));
}
if (indices.size() < 3) {
std::stringstream error;
error << "Facets in OBJ files require at least 3 indicies";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("OBJReader::ParseFacet", error.str());
}
if (quad && indices.size() != 4) {
std::stringstream error;
error << "Trying to triangle-ify a facet that isn't a quad";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("OBJReader::ParseFacet", error.str());
}
if (quad) {
return new G4TriangularFacet(vertices_[indices[0] - 1],
vertices_[indices[2] - 1],
vertices_[indices[3] - 1], ABSOLUTE);
}
else {
return new G4TriangularFacet(vertices_[indices[0] - 1],
vertices_[indices[1] - 1],
vertices_[indices[2] - 1], ABSOLUTE);
}
}
}
}
namespace CADMesh {
namespace File {
inline State *PLYReader::CADMeshLexerState(StartHeader) {
if (DoesNotMatchExactly("ply"))
Error("PLY files start with 'ply'.");
StartOfA(Header);
SkipLine();
TryState(Element);
TryState(Ignore);
Error("Invalid header tag.");
}
inline State *PLYReader::CADMeshLexerState(EndHeader) {
if (DoesNotMatchExactly("end_header"))
Error("PLY file headers end with 'end_header'.");
MaybeEndOfA(Element);
EndOfA(Header);
FinalState();
}
inline State *PLYReader::CADMeshLexerState(Element) {
if (DoesNotMatchExactly("element "))
Error("An element is indicated by the tag 'element'.");
MaybeEndOfA(Element);
SkipWhiteSpace();
StartOfA(Element);
if (NotManyCharacters())
Error("Element type not found.");
ThisIsA(Word);
SkipWhiteSpace();
if (NotANumber())
Error("Element count not found.");
ThisIsA(Number);
SkipLine();
TryState(Property);
TryState(Ignore);
NextState(EndHeader);
}
inline State *PLYReader::CADMeshLexerState(Property) {
if (DoesNotMatchExactly("property "))
Error("An property is indicated by the tag 'property'.");
SkipWhiteSpace();
StartOfA(Property);
if (NotManyCharacters())
Error("Element type not found.");
ThisIsA(Word);
SkipWhiteSpace();
RestOfLine();
ThisIsA(Word);
EndOfA(Property);
SkipLineBreak();
TryState(Property);
TryState(Element);
TryState(EndHeader);
TryState(Ignore);
NextState(EndHeader);
}
inline State *PLYReader::CADMeshLexerState(Ignore) {
if (DidNotSkipLine())
NextState(EndHeader);
TryState(Element);
TryState(Property);
TryState(EndHeader);
NextState(Ignore);
}
inline State *PLYReader::CADMeshLexerState(Vertex) {
SkipLineBreaks();
SkipWhiteSpace();
SkipLineBreaks();
StartOfA(Vertex);
size_t i = 0;
while (i < 32) {
if (AtEndOfLine())
break;
SkipWhiteSpace();
if (NotANumber())
Error("Expecting only numbers in the vertex specification.");
ThisIsA(Number);
SkipWhiteSpace();
i++;
}
EndOfA(Vertex);
SkipLine();
TryState(Vertex);
FinalState();
}
inline State *PLYReader::CADMeshLexerState(Facet) {
SkipLineBreaks();
SkipWhiteSpace();
SkipLineBreaks();
StartOfA(Facet);
size_t i = 0;
while (i < 32) {
if (AtEndOfLine())
break;
SkipWhiteSpace();
if (NotANumber())
Error("Expecting only numbers in the facet specification.");
ThisIsA(Number);
SkipWhiteSpace();
i++;
}
EndOfA(Facet);
SkipLine();
TryState(Facet);
FinalState();
}
inline G4bool PLYReader::Read(G4String filepath) {
auto lexer = Lexer(filepath, new StartHeaderState);
auto items = lexer.GetItems();
if (items.size() == 0) {
std::stringstream error;
error << "The header appears to be empty.";
Exceptions::ParserError("PLYReader::Read", error.str());
}
ParseHeader(items);
lexer.Run(new VertexState, vertex_count_);
auto vertex_items = lexer.GetItems();
if (vertex_items.size() == 0) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to have no vertices.");
}
if (vertex_items.size() != vertex_count_) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to be missing vertices.");
}
lexer.Run(new FacetState, facet_count_);
auto face_items = lexer.GetItems();
if (face_items.size() == 0) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to have no facets.");
}
if (face_items.size() != facet_count_) {
Exceptions::ParserError("PLYReader::Read",
"The PLY file appears to be missing facets");
}
auto mesh = ParseMesh(vertex_items, face_items);
AddMesh(Mesh::New(mesh));
return true;
}
inline G4bool PLYReader::CanRead(Type file_type) { return (file_type == PLY); }
inline void PLYReader::ParseHeader(Items items) {
if (items.size() != 1) {
std::stringstream error;
error << "The header appears to be invalid or missing."
<< "Error around line 1.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
for (auto item : items[0].children) {
if (item.token == ElementToken) {
if (item.children.size() < 2) {
std::stringstream error;
error << "Invalid element information in header. Expecting 'vertex' or "
"'face' and a number."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
if (item.children[0].token == WordToken &&
item.children[1].token == NumberToken) {
if (item.children[0].value == "vertex") {
vertex_count_ = atoi(item.children[1].value.c_str());
for (size_t i = 2; i < item.children.size(); i++) {
auto property = item.children[i];
if (property.children.size() > 1) {
if (property.children[1].token == WordToken) {
if (property.children[1].value == "x") {
x_index_ = i - 2;
}
if (property.children[1].value == "y") {
y_index_ = i - 2;
}
if (property.children[1].value == "z") {
z_index_ = i - 2;
}
}
}
}
}
else if (item.children[0].value == "face") {
facet_count_ = atoi(item.children[1].value.c_str());
for (size_t i = 2; i < item.children.size(); i++) {
auto property = item.children[i];
if (property.children.size() > 1) {
if (property.children[1].token == WordToken) {
if (property.children[1].value == "uchar int vertex_indices") {
facet_index_ = i - 2;
}
}
}
}
}
}
}
}
if (vertex_count_ == 0) {
std::stringstream error;
error << "The number of vertices was not found in the header.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
if (facet_count_ == 0) {
std::stringstream error;
error << "The number of faces was not found in the header.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
if ((x_index_ == y_index_) || (y_index_ == z_index_) ||
(x_index_ == z_index_)) {
std::stringstream error;
error << "The vertex x, y, z indices were not found in the header.";
Exceptions::ParserError("PLYReader::ParseHeader", error.str());
}
}
inline std::shared_ptr<Mesh> PLYReader::ParseMesh(Items vertex_items,
Items face_items) {
Points vertices;
Triangles facets;
for (auto item : vertex_items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The vertex appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("PLYReader::ParseMesh", error.str());
}
if (item.token == VertexToken) {
vertices.push_back(ParseVertex(item.children));
}
}
for (auto item : face_items) {
if (item.children.size() == 0) {
std::stringstream error;
error << "The facet appears to be empty."
<< "Error around line " << item.line << ".";
Exceptions::ParserError("PLYReader::Mesh", error.str());
}
if (item.token == FacetToken) {
facets.push_back(ParseFacet(item.children, vertices));
}
}
return Mesh::New(facets);
}
inline G4ThreeVector PLYReader::ParseVertex(Items items) {
std::vector<double> numbers;
for (auto item : items) {
numbers.push_back((double)atof(item.value.c_str()));
}
if (numbers.size() < 3) {
std::stringstream error;
error << "Vertices in PLY files require atleast 3 numbers. ";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("PLYReader::ParseVertex", error.str());
}
return G4ThreeVector(numbers[x_index_], numbers[y_index_], numbers[z_index_]);
}
inline G4TriangularFacet *PLYReader::ParseFacet(Items items, Points vertices) {
std::vector<int> indices;
for (auto item : items) {
indices.push_back((int)atoi(item.value.c_str()));
}
if (indices.size() < 4) {
std::stringstream error;
error << "Facets in PLY files require 3 indicies";
if (items.size() != 0) {
error << "Error around line " << items[0].line << ".";
}
Exceptions::ParserError("PLYReader::ParseFacet", error.str());
}
return new G4TriangularFacet(vertices[indices[1 + facet_index_]],
vertices[indices[2 + facet_index_]],
vertices[indices[3 + facet_index_]], ABSOLUTE);
}
}
}
#ifdef USE_CADMESH_ASSIMP_READER
namespace CADMesh {
namespace File {
inline ASSIMPReader::ASSIMPReader() : Reader("ASSIMPReader") {
importer_ = new Assimp::Importer();
}
inline ASSIMPReader::~ASSIMPReader() { delete importer_; }
inline G4bool ASSIMPReader::Read(G4String filepath) {
auto scene = importer_->ReadFile(filepath.c_str(),
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_CalcTangentSpace);
if (!scene) {
Exceptions::FileNotFound("ASSIMP::Read", filepath);
return false;
}
for (unsigned int index = 0; index < scene->mNumMeshes; index++) {
aiMesh *mesh = scene->mMeshes[index];
auto name = mesh->mName.C_Str();
Triangles triangles;
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
const aiFace &face = mesh->mFaces[i];
G4ThreeVector a(mesh->mVertices[face.mIndices[0]].x,
mesh->mVertices[face.mIndices[0]].y,
mesh->mVertices[face.mIndices[0]].z);
G4ThreeVector b(mesh->mVertices[face.mIndices[1]].x,
mesh->mVertices[face.mIndices[1]].y,
mesh->mVertices[face.mIndices[1]].z);
G4ThreeVector c(mesh->mVertices[face.mIndices[2]].x,
mesh->mVertices[face.mIndices[2]].y,
mesh->mVertices[face.mIndices[2]].z);
triangles.push_back(new G4TriangularFacet(a, b, c, ABSOLUTE));
}
AddMesh(Mesh::New(triangles, name));
}
return true;
}
inline G4bool ASSIMPReader::CanRead(Type /*file_type*/) { return true; }
std::shared_ptr<ASSIMPReader> ASSIMP() {
return std::make_shared<ASSIMPReader>();
}
}
}
#endif
namespace CADMesh {
namespace File {
inline G4bool BuiltInReader::Read(G4String filepath) {
File::Reader *reader = nullptr;
auto type = TypeFromName(filepath);
if (type == STL) {
reader = new File::STLReader();
}
else if (type == OBJ) {
reader = new File::OBJReader();
}
else if (type == PLY) {
reader = new File::PLYReader();
}
else {
Exceptions::ReaderCantReadError("BuildInReader::Read", type, filepath);
}
if (!reader->Read(filepath)) {
return false;
}
SetMeshes(reader->GetMeshes());
return true;
}
inline G4bool BuiltInReader::CanRead(Type type) {
return type == STL || type == OBJ || type == PLY;
}
inline std::shared_ptr<BuiltInReader> BuiltIn() {
return std::make_shared<BuiltInReader>();
}
}
}
......@@ -23,69 +23,102 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file OpNovice/include/OpNovicePhysicsList.hh
/// \brief Definition of the OpNovicePhysicsList class
/// \file /include/DetectorConstruction.hh
/// \brief Definition of the DetectorConstruction class
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef OpNovicePhysicsList_h
#define OpNovicePhysicsList_h 1
//
#ifndef DetectorConstruction_h
#define DetectorConstruction_h 1
#include "globals.hh"
#include "G4VUserPhysicsList.hh"
class OpNovicePhysicsListMessenger;
#include "G4Material.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VUserDetectorConstruction.hh"
#include "G4SubtractionSolid.hh"
// #include "G4GDMLParser.hh"
#include "G4RunManager.hh"
class G4Cerenkov;
class G4Scintillation;
class G4OpAbsorption;
class G4OpRayleigh;
class G4OpMieHG;
class G4OpBoundaryProcess;
#include "Materials.hh"
#include "DetectorMessenger.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class OpNovicePhysicsList : public G4VUserPhysicsList
class DetectorConstruction : public G4VUserDetectorConstruction
{
public:
OpNovicePhysicsList();
virtual ~OpNovicePhysicsList();
DetectorConstruction();
virtual ~DetectorConstruction();
public:
virtual G4VPhysicalVolume* Construct();
void ConstructSDandField();
void BuildWorld ();
void BuildTrapezoidLG ();
void BuildPMT ();
void PlaceGeometry ();
void SetWorldVolume (G4ThreeVector arg);
void SetEnvelope (G4ThreeVector arg);
void SetRotation (G4ThreeVector arg);
void SetTranslation (G4ThreeVector arg);
void SetPMTTranslation (G4ThreeVector arg);
void SetPMTDiameter (G4double arg);
void SetLGthickness (G4double arg);
void UseCADModel (G4String fileName);
void OutputToGDML (G4String name);
void SetNSegmentsX (G4int arg);
void SetNSegmentsZ (G4int arg);
void SetSurfaceModel (const G4OpticalSurfaceModel model);
void SetSurfaceFinish (const G4OpticalSurfaceFinish finish);
void SetSurfaceType (const G4SurfaceType type);
void SetSurfaceSigmaAlpha (G4double v);
void AddSurfaceMPV (const char* c, G4MaterialPropertyVector* mpv);
void AddGasMPV (const char* c, G4MaterialPropertyVector* mpv);
virtual void ConstructParticle();
virtual void ConstructProcess();
virtual void SetCuts();
//these methods Construct physics processes and register them
void ConstructDecay();
void ConstructEM();
void ConstructOp();
//for the Messenger
void SetVerbose(G4int);
void SetNbOfPhotonsCerenkov(G4int);
private:
OpNovicePhysicsListMessenger* fMessenger;
static G4ThreadLocal G4int fVerboseLevel;
static G4ThreadLocal G4int fMaxNumPhotonStep;
static G4ThreadLocal G4Cerenkov* fCerenkovProcess;
static G4ThreadLocal G4Scintillation* fScintillationProcess;
static G4ThreadLocal G4OpAbsorption* fAbsorptionProcess;
static G4ThreadLocal G4OpRayleigh* fRayleighScatteringProcess;
static G4ThreadLocal G4OpMieHG* fMieHGScatteringProcess;
static G4ThreadLocal G4OpBoundaryProcess* fBoundaryProcess;
G4ThreeVector* m_worldDim;
G4ThreeVector* m_LGenvelope;
G4ThreeVector* m_LGpos;
G4ThreeVector* m_pmtPos;
G4RotationMatrix* m_rotation;
G4double m_pmtDia;
G4double m_PMTthickness;
G4double m_thickness;
G4int m_nSegmentsX;
G4int m_nSegmentsZ;
G4bool m_ConstructionHasBeenDone;
G4bool m_UsingCADmodel;
G4Box* m_solidWorld;
G4LogicalVolume* m_logicWorld;
G4VPhysicalVolume* m_physWorld;
G4Box* m_solidHalfWorld;
G4LogicalVolume* m_logicHalfWorld;
G4VPhysicalVolume* m_physHalfWorld;
G4Trd* m_inner;
G4Trd* m_outter;
G4SubtractionSolid* m_LightGuide;
G4LogicalVolume* m_logicLightGuide;
std::vector< G4VPhysicalVolume* > m_physLightGuide;
G4Tubs* m_solidPMT;
G4LogicalVolume* m_logicPMT;
std::vector< G4VPhysicalVolume* > m_physPMT;
std::vector< G4LogicalBorderSurface* > m_Surfvec;
Materials* materials;
G4Material* m_filler;
G4MaterialPropertiesTable* m_GasMPT;
// G4GDMLParser m_Parser;
G4RunManager* m_runMan;
DetectorMessenger* m_DetectorMessenger;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif /* OpNovicePhysicsList_h */
#endif /*DetectorConstruction_h*/
// ********************************************************************
// * 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. *
// ********************************************************************
//
/// \file optical/OpNovice2/include/DetectorMessenger.hh
/// \brief Definition of the DetectorMessenger class
//
//
//
#ifndef DetectorMessenger_h
#define DetectorMessenger_h 1
#include "globals.hh"
#include "G4UImessenger.hh"
class DetectorConstruction;
class G4UIdirectory;
class G4UIcommand;
class G4UIcmdWithAString;
class G4UIcmdWithAnInteger;
class G4UIcmdWithADouble;
class G4UIcmdWithADoubleAndUnit;
class G4UIcmdWithoutParameter;
class G4UIcmdWith3VectorAndUnit;
class DetectorMessenger: public G4UImessenger{
public:
DetectorMessenger(DetectorConstruction* );
~DetectorMessenger();
virtual void SetNewValue(G4UIcommand*, G4String);
private:
DetectorConstruction* fDetector;
G4UIdirectory* flightGuideDir;
G4UIdirectory* fSurfaceDir;
G4UIdirectory* fModelDir;
// the model
G4UIcmdWithAString* fModelCmd;
G4UIcmdWith3VectorAndUnit* fWorldVolumeCmd;
G4UIcmdWith3VectorAndUnit* fEnvelopeCmd;
G4UIcmdWith3VectorAndUnit* fModelRotationCmd;
G4UIcmdWith3VectorAndUnit* fModelTranslationCmd;
G4UIcmdWith3VectorAndUnit* fPMTTranslationCmd;
G4UIcmdWithADoubleAndUnit* fPMTDiameterCmd;
G4UIcmdWithADoubleAndUnit* fLGThicknessCmd;
G4UIcmdWithAString* fOutputModelCmd;
G4UIcmdWithAnInteger* fNsegmentsXCmd;
G4UIcmdWithAnInteger* fNsegmentsZCmd;
// the surface
G4UIcmdWithAString* fSurfaceModelCmd;
G4UIcmdWithAString* fSurfaceFinishCmd;
G4UIcmdWithAString* fSurfaceTypeCmd;
G4UIcmdWithADouble* fSurfaceSigmaAlphaCmd;
G4UIcmdWithAString* fSurfaceMatPropVectorCmd;
// the gas
G4UIcmdWithAString* fGasPropVectorCmd;
};
#endif