Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog (revision 8336)
+++ trunk/ChangeLog (revision 8337)
@@ -1,1946 +1,1949 @@
ChangeLog -- Summary of changes to the WHIZARD package
Use svn log to see detailed changes.
Version 2.8.3
2020-01-09
RELEASE: version 2.8.3
+2019-11-06
+ Add squared matrix elements to the LCIO event header
+
2019-11-05
Do not include RNG state in MD5 sum for CIRCE1/2
2019-11-04
Full CIRCE2 ILC 250 and 500 GeV beam spectra added
Minor update on LCIO event header information
2019-10-30
NLO QCD for final states completed
When using Openloops, v2.1.1+ mandatory
2019-10-25
Binary grid files for VAMP2 integrator
##################################################################
2019-10-24
RELEASE: version 2.8.2
2019-10-20
Bug fix for HepMC linker flags
2019-10-19
Support for spin-2 particles from UFO files
2019-09-27
LCIO event format allows rescan and alternate weights
2019-09-24
Compatibility fix for OCaml v4.08.0+
##################################################################
2019-09-21
RELEASE: version 2.8.1
2019-09-19
Carriage return characters in UFO models can be parsed
Mathematica symbols in UFO models possible
Unused/undefined parameters in UFO models handled
2019-09-13
New extended NLO test suite for ee and pp processes
2019-09-09
Photon isolation (separation of perturbative and fragmentation
part a la Frixione)
2019-09-05
Major progress on NLO QCD for hadron collisions:
- correctly assign flavor structures for alpha regions
- fix crossing of particles for initial state splittings
- correct assignment for PDF factors for real subtractions
- fix kinematics for collinear splittings
- bug fix for integrated virtual subtraction terms
2019-09-03
b and c jet selection in cuts and analysis
2019-08-27
Support for Intel MPI
2019-08-20
Complete (preliminary) HepMC3 support (incl.
backwards HepMC2 write/read mode)
2019-08-08
Bug fix: handle carriage returns in UFO files (non-Unix OS)
##################################################################
2019-08-07
RELEASE: version 2.8.0
2019-07-31
Complete WHIZARD UFO interface:
- general Lorentz structures
- matrix element support for general color factors
- missing features: Majorana fermions and SLHA
2019-07-20
Make WHIZARD compatible with OCaml 4.08.0+
2019-07-19
Fix version testing for LHAPDF 6.2.3 and newer
Minimal required OCaml version is now 4.02.3.
2019-04-18
Correctly generate ordered FKS tuples for alpha regions
from all possible underlying Born processes
2019-04-08
Extended O'Mega/Recola matrix element test suite
2019-03-29
Correct identical particle symmetry factors for FKS subtraction
2019-03-28
Correct assertion of spin-correlated matrix
elements for hadron collisions
2019-03-27
Bug fix for cut-off parameter delta_i for
collinear plus/minus regions
##################################################################
2019-03-27
RELEASE: version 2.7.1
2019-02-19
Further infrastructure for HepMC3 interface (v3.01.00)
2019-02-07
Explicit configure option for using debugging options
Bug fix for performance by removing unnecessary debug operations
2019-01-29
Bug fix for DGLAP remnants with cut-off parameter delta_i
2019-01-24
Radiative decay neu2 -> neu1 A added to MSSM_Hgg model
##################################################################
2019-01-21
RELEASE: version 2.7.0
2018-12-18
Support RECOLA for integrated und unintegrated subtractions
2018-12-11
FCNC top-up sector in model SM_top_anom
2018-12-05
Use libtirpc instead of SunRPC on Arch Linux etc.
2018-11-30
Display rescaling factor for weighted event samples with cuts
2018-11-29
Reintroduce check against different masses in flavor sums
Bug fix for wrong couplings in the Littlest Higgs model(s)
2018-11-22
Bug fix for rescanning events with beam structure
2018-11-09
Major refactoring of internal process data
2018-11-02
PYTHIA8 interface
2018-10-29
Flat phase space parametrization with RAMBO (on diet) implemented
2018-10-17
Revise extended test suite
2018-09-27
Process container for RECOLA processes
2018-09-15
Fixes by M. Berggren for PYTHIA6 interface
2018-09-14
First fixes after HepForge modernization
##################################################################
2018-08-23
RELEASE: version 2.6.4
2018-08-09
Infrastructure to check colored subevents
2018-07-10
Infrastructure for running WHIZARD in batch mode
2018-07-04
MPI available from distribution tarball
2018-06-03
Support Intel Fortran Compiler under MAC OS X
2018-05-07
FKS slicing parameter delta_i (initial state) implementend
2018-05-03
Refactor structure function assignment for NLO
2018-05-02
FKS slicing parameter xi_cut, delta_0 implemented
2018-04-20
Workspace subdirectory for process integration (grid/phs files)
Packing/unpacking of files at job end/start
Exporting integration results from scan loops
2018-04-13
Extended QCD NLO test suite
2018-04-09
Bug fix for Higgs Singlet Extension model
2018-04-06
Workspace subdirectory for process generation and compilation
--job-id option for creating job-specific names
2018-03-20
Bug fix for color flow matching in hadron collisions
with identical initial state quarks
2018-03-08
Structure functions quantum numbers correctly assigned for NLO
2018-02-24
Configure setup includes 'pgfortran' and 'flang'
2018-02-21
Include spin-correlated matrix elements in interactions
2018-02-15
Separate module for QED ISR structure functions
##################################################################
2018-02-10
RELEASE: version 2.6.3
2018-02-08
Improvements in memory management for PS generation
2018-01-31
Partial refactoring: quantum number assigment NLO
Initial-state QCD splittings for hadron collisions
2018-01-25
Bug fix for weighted events with VAMP2
2018-01-17
Generalized interface for Recola versions 1.3+ and 2.1+
2018-01-15
Channel equivalences also for VAMP2 integrator
2018-01-12
Fix for OCaml compiler 4.06 (and newer)
2017-12-19
RECOLA matrix elements with flavor sums can be integrated
2017-12-18
Bug fix for segmentation fault in empty resonance histories
2017-12-16
Fixing a bug in PYTHIA6 PYHEPC routine by omitting CMShowers
from transferral between PYTHIA and WHIZARD event records
2017-12-15
Event index for multiple processes in event file correct
##################################################################
2017-12-13
RELEASE: version 2.6.2
2017-12-07
User can set offset in event numbers
2017-11-29
Possibility to have more than one RECOLA process in one file
2017-11-23
Transversal/mixed (and unitarized) dim-8 operators
2017-11-16
epa_q_max replaces epa_e_max (trivial factor 2)
2017-11-15
O'Mega matrix element compilation silent now
2017-11-14
Complete expanded P-wave form factor for top threshold
2017-11-10
Incoming particles can be accessed in SINDARIN
2017-11-08
Improved handling of resonance insertion, additional parameters
2017-11-04
Added Higgs-electron coupling (SM_Higgs)
##################################################################
2017-11-03
RELEASE: version 2.6.1
2017-10-20
More than 5 NLO components possible at same time
2017-10-19
Gaussian cutoff for shower resonance matching
2017-10-12
Alternative (more efficient) method to generate
phase space file
2017-10-11
Bug fix for shower resonance histories for processes
with multiple components
2017-09-25
Bugfix for process libraries in shower resonance histories
2017-09-21
Correctly generate pT distribution for EPA remnants
2017-09-20
Set branching ratios for unstable particles also by hand
2017-09-14
Correctly generate pT distribution for ISR photons
##################################################################
2017-09-08
RELEASE: version 2.6.0
2017-09-05
Bug fix for initial state NLO QCD flavor structures
Real and virtual NLO QCD hadron collider processes
work with internal interactions
2017-09-04
Fully validated MPI integration and event generation
2017-09-01
Resonance histories for shower: full support
Bug fix in O'Mega model constraints
O'Mega allows to output a parsable form of the DAG
2017-08-24
Resonance histories in events for transferral
to parton shower (e.g. in ee -> jjjj)
2017-08-01
Alpha version of HepMC v3 interface
(not yet really functional)
2017-07-31
Beta version for RECOLA OLP support
2017-07-06
Radiation generator fix for LHC processes
2017-06-30
Fix bug for NLO with structure
functions and/or polarization
2017-06-23
Collinear limit for QED corrections works
2017-06-17
POWHEG grids generated already during integration
2017-06-12
Soft limit for QED corrections works
2017-05-16
Beta version of full MPI parallelization (VAMP2)
Check consistency of POWHEG grid files
Logfile config-summary.log for configure summary
2017-05-12
Allow polarization in top threshold
2017-05-09
Minimal demand automake 1.12.2
Silent rules for make procedures
2017-05-07
Major fix for POWHEG damping
Correctly initialize FKS ISR phasespace
##################################################################
2017-05-06
RELEASE: version 2.5.0
2017-05-05
Full UFO support (SM-like models)
Fixed-beam ISR FKS phase space
2017-04-26
QED splittings in radiation generator
2017-04-10
Retire deprecated O'Mega vertex cache files
##################################################################
2017-03-24
RELEASE: version 2.4.1
2017-03-16
Distinguish resonance charge in phase space channels
Keep track of resonance histories in phase space
Complex mass scheme default for OpenLoops amplitudes
2017-03-13
Fix helicities for polarized OpenLoops calculations
2017-03-09
Possibility to advance RNG state in rng_stream
2017-03-04
General setup for partitioning real emission
phase space
2017-03-06
Bugfix on rescan command for converting event files
2017-02-27
Alternative multi-channel VEGAS implementation
VAMP2: serial backbone for MPI setup
Smoothstep top threshold matching
2017-02-25
Single-beam structure function with
s-channel mapping supported
Safeguard against invalid process libraries
2017-02-16
Radiation generator for photon emission
2017-02-10
Fixes for NLO QCD processes (color correlations)
2017-01-16
LCIO variable takes precedence over LCIO_DIR
2017-01-13
Alternative random number generator
rng_stream (cf. L'Ecuyer et al.)
2017-01-01
Fix for multi-flavor BLHA tree
matrix elements
2016-12-31
Grid path option for VAMP grids
2016-12-28
Alpha version of Recola OLP support
2016-12-27
Dalitz plots for FKS phase space
2016-12-14
NLO multi-flavor events possible
2016-12-09
LCIO event header information added
2016-12-02
Alpha version of RECOLA interface
Bugfix for generator status in LCIO
##################################################################
2016-11-28
RELEASE: version 2.4.0
2016-11-24
Bugfix for OpenLoops interface: EW scheme
is set by WHIZARD
Bugfixes for top threshold implementation
2016-11-11
Refactoring of dispatching
2016-10-18
Bug fix for LCIO output
2016-10-10
First implementation for collinear soft terms
2016-10-06
First full WHIZARD models from UFO files
2016-10-05
WHIZARD does not support legacy gcc 4.7.4 any longer
2016-09-30
Major refactoring of process core and NLO components
2016-09-23
WHIZARD homogeneous entity: discarding subconfigures
for CIRCE1/2, O'Mega, VAMP subpackages; these are
reconstructable by script projectors
2016-09-06
Introduce main configure summary
2016-08-26
Fix memory leak in event generation
##################################################################
2016-08-25
RELEASE: version 2.3.1
2016-08-19
Bug fix for EW-scheme dependence of gluino propagators
2016-08-01
Beta version of complex mass scheme support
2016-07-26
Fix bug in POWHEG damping for the matching
##################################################################
2016-07-21
RELEASE: version 2.3.0
2016-07-20
UFO file support (alpha version) in O'Mega
2016-07-13
New (more) stable of WHIZARD GUI
Support for EW schemes for OpenLoops
Factorized NLO top decays for threshold model
2016-06-15
Passing factorization scale to PYTHIA6
Adding charge and neutral observables
2016-06-14
Correcting angular distribution/tweaked kinematics in
non-collinear structure functions splittings
2016-05-10
Include (Fortran) TAUOLA/PHOTOS for tau decays via PYTHIA6
(backwards validation of LC CDR/TDR samples)
2016-04-27
Within OpenLoops virtuals: support for Collier library
2016-04-25
O'Mega vertex tables only loaded at first usage
2016-04-21
New CJ15 PDF parameterizations added
2016-04-21
Support for hadron collisions at NLO QCD
2016-04-05
Support for different (parameter) schemes in model files
2016-03-31
Correct transferral of lifetime/vertex from PYTHIA/TAUOLA
into the event record
2016-03-21
New internal implementation of polarization
via Bloch vectors, remove pointer constructions
2016-03-13
Extension of cascade syntax for processes:
exclude propagators/vertices etc. possible
2016-02-24
Full support for OpenLoops QCD NLO matrix
elements, inclusion in test suite
2016-02-12
Substantial progress on QCD NLO support
2016-02-02
Automated resonance mapping for FKS subtraction
2015-12-17
New BSM model WZW for diphoton resonances
##################################################################
2015-11-22
RELEASE: version 2.2.8
2015-11-21
Bugfix for fixed-order NLO events
2015-11-20
Anomalous FCNC top-charm vertices
2015-11-19
StdHEP output via HEPEVT/HEPEV4 supported
2015-11-18
Full set of electroweak dim-6 operators included
2015-10-22
Polarized one-loop amplitudes supported
2015-10-21
Fixes for event formats for showered events
2015-10-14
Callback mechanism for event output
2015-09-22
Bypass matrix elements in pure event sample rescans
StdHep frozen final version v5.06.01 included internally
2015-09-21
configure option --with-precision to
demand 64bit, 80bit, or 128bit Fortran
and bind C precision types
2015-09-07
More extensive tests of NLO
infrastructure and POWHEG matching
2015-09-01
NLO decay infrastructure
User-defined squared matrix elements
Inclusive FastJet algorithm plugin
Numerical improvement for small boosts
##################################################################
2015-08-11
RELEASE: version 2.2.7
2015-08-10
Infrastructure for damped POWHEG
Massive emitters in POWHEG
Born matrix elements via BLHA
GoSam filters via SINDARIN
Minor running coupling bug fixes
Fixed-order NLO events
2015-08-06
CT14 PDFs included (LO, NLO, NNLL)
2015-07-07
Revalidation of ILC WHIZARD-PYTHIA event chain
Extended test suite for showered events
Alpha version of massive FSR for POWHEG
2015-06-09
Fix memory leak in interaction for long cascades
Catch mismatch between beam definition and CIRCE2 spectrum
2015-06-08
Automated POWHEG matching: beta version
Infrastructure for GKS matching
Alpha version of fixed-order NLO events
CIRCE2 polarization averaged spectra with
explicitly polarized beams
2015-05-12
Abstract matching type: OO structure for matching/merging
2015-05-07
Bug fix in event record WHIZARD-PYTHIA6 transferral
Gaussian beam spectra for lepton colliders
##################################################################
2015-05-02
RELEASE: version 2.2.6
2015-05-01
Models for (unitarized) tensor resonances in VBS
2015-04-28
Bug fix in channel weights for event generation.
2015-04-18
Improved event record transfer WHIZARD/PYTHIA6
2015-03-19
POWHEG matching: alpha version
##################################################################
2015-02-27
RELEASE: version 2.2.5
2015-02-26
Abstract types for quantum numbers
2015-02-25
Read-in of StdHEP events, self-tests
2015-02-22
Bugfix for mother-daughter relations in
showered/hadronized events
2015-02-20
Projection on polarization in intermediate states
2015-02-13
Correct treatment of beam remnants in
event formats (also LC remnants)
##################################################################
2015-02-06
RELEASE: version 2.2.4
2015-02-06
Bugfix in event output
2015-02-05
LCIO event format supported
2015-01-30
Including state matrices in WHIZARD's internal IO
Versioning for WHIZARD's internal IO
Libtool update from 2.4.3 to 2.4.5
LCIO event output (beta version)
2015-01-27
Progress on NLO integration
Fixing a bug for multiple processes in a single
event file when using beam event files
2015-01-19
Bug fix for spin correlations evaluated in the rest
frame of the mother particle
2015-01-17
Regression fix for statically linked processes
from SARAH and FeynRules
2015-01-10
NLO: massive FKS emitters supported (experimental)
2015-01-06
MMHT2014 PDF sets included
2015-01-05
Handling mass degeneracies in auto_decays
2014-12-19
Fixing bug in rescan of event files
##################################################################
2014-11-30
RELEASE: version 2.2.3
2014-11-29
Beta version of LO continuum/NLL-threshold
matched top threshold model for e+e- physics
2014-11-28
More internal refactoring: disentanglement of module
dependencies
2014-11-21
OVM: O'Mega Virtual Machine, bytecode instructions
instead of compiled Fortran code
2014-11-01
Higgs Singlet extension model included
2014-10-18
Internal restructuring of code; half-way
WHIZARD main code file disassembled
2014-07-09
Alpha version of NLO infrastructure
##################################################################
2014-07-06
RELEASE: version 2.2.2
2014-07-05
CIRCE2: correlated LC beam spectra and
GuineaPig Interface to LC machine parameters
2014-07-01
Reading LHEF for decayed/factorized/showered/
hadronized events
2014-06-25
Configure support for GoSAM/Ninja/Form/QGraf
2014-06-22
LHAPDF6 interface
2014-06-18
Module for automatic generation of
radiation and loop infrastructure code
2014-06-11
Improved internal directory structure
##################################################################
2014-06-03
RELEASE: version 2.2.1
2014-05-30
Extensions of internal PDG arrays
2014-05-26
FastJet interface
2014-05-24
CJ12 PDFs included
2014-05-20
Regression fix for external models (via SARAH
or FeynRules)
##################################################################
2014-05-18
RELEASE: version 2.2.0
2014-04-11
Multiple components: inclusive process definitions,
syntax: process A + B + ...
2014-03-13
Improved PS mappings for e+e- ISR
ILC TDR and CLIC spectra included in CIRCE1
2014-02-23
New models: AltH w\ Higgs for exclusion purposes,
SM_rx for Dim 6-/Dim-8 operators, SSC for
general strong interactions (w/ Higgs), and
NoH_rx (w\ Higgs)
2014-02-14
Improved s-channel mapping, new on-shell
production mapping (e.g. Drell-Yan)
2014-02-03
PRE-RELEASE: version 2.2.0_beta
2014-01-26
O'Mega: Feynman diagram generation possible (again)
2013-12-16
HOPPET interface for b parton matching
2013-11-15
PRE-RELEASE: version 2.2.0_alpha-4
2013-10-27
LHEF standards 1.0/2.0/3.0 implemented
2013-10-15
PRE-RELEASE: version 2.2.0_alpha-3
2013-10-02
PRE-RELEASE: version 2.2.0_alpha-2
2013-09-25
PRE-RELEASE: version 2.2.0_alpha-1
2013-09-12
PRE-RELEASE: version 2.2.0_alpha
2013-09-03
General 2HDM implemented
2013-08-18
Rescanning/recalculating events
2013-06-07
Reconstruction of complete event
from 4-momenta possible
2013-05-06
Process library stacks
2013-05-02
Process stacks
2013-04-29
Single-particle phase space module
2013-04-26
Abstract interface for random
number generator
2013-04-24
More object-orientation on modules
Midpoint-rule integrator
2013-04-05
Object-oriented integration and
event generation
2013-03-12
Processes recasted object-oriented:
MEs, scales, structure functions
First infrastructure for general Lorentz
structures
2013-01-17
Object-orientated reworking of library and
process core, more variable internal structure,
unit tests
2012-12-14
Update Pythia version to 6.4.27
2012-12-04
Fix the phase in HAZ vertices
2012-11-21
First O'Mega unit tests, some infrastructure
2012-11-13
Bugfix in anom. HVV Lorentz structures
##################################################################
2012-09-18
RELEASE: version 2.1.1
2012-09-11
Model MSSM_Hgg with Hgg and HAA vertices
2012-09-10
First version of implementation of multiple
interactions in WHIZARD
2012-09-05
Infrastructure for internal CKKW matching
2012-09-02
C, C++, Python API
2012-07-19
Fixing particle numbering in HepMC format
##################################################################
2012-06-15
RELEASE: version 2.1.0
2012-06-14
Analytical and kT-ordered shower officially
released
PYTHIA interface officially released
2012-05-09
Intrisince PDFs can be used for showering
2012-05-04
Anomalous Higgs couplings a la hep-ph/9902321
##################################################################
2012-03-19
RELEASE: version 2.0.7
2012-03-15
Run IDs are available now
More event variables in analysis
Modified raw event format (compatibility mode exists)
2012-03-12
Bugfix in decay-integration order
MLM matching steered completely internally now
2012-03-09
Special phase space mapping for narrow resonances
decaying to 4-particle final states with far off-shell
intermediate states
Running alphas from PDF collaborations with
builtin PDFs
2012-02-16
Bug fix in cascades decay infrastructure
2012-02-04
WHIZARD documentation compatible with TeXLive 2011
2012-02-01
Bug fix in FeynRules interface with --prefix flag
2012-01-29
Bug fix with name clash of O'Mega variable names
2012-01-27
Update internal PYTHIA to version 6.4.26
Bug fix in LHEF output
2012-01-21
Catching stricter automake 1.11.2 rules
2011-12-23
Bug fix in decay cascade setup
2011-12-20
Bug fix in helicity selection rules
2011-12-16
Accuracy goal reimplemented
2011-12-14
WHIZARD compatible with TeXLive 2011
2011-12-09
Option --user-target added
##################################################################
2011-12-07
RELEASE: version 2.0.6
2011-12-07
Bug fixes in SM_top_anom
Added missing entries to HepMC format
2011-12-06
Allow to pass options to O'Mega
Bug fix for HEPEVT block for showered/hadronized events
2011-12-01
Reenabled user plug-in for external code for
cuts, structure functions, routines etc.
2011-11-29
Changed model SM_Higgs for Higgs phenomenology
2011-11-25
Supporting a Y, (B-L) Z' model
2011-11-23
Make WHIZARD compatible for MAC OS X Lion/XCode 4
2011-09-25
WHIZARD paper published: Eur.Phys.J. C71 (2011) 1742
2011-08-16
Model SM_QCD: QCD with one EW insertion
2011-07-19
Explicit output channel for dvips avoids printing
2011-07-10
Test suite for WHIZARD unit tests
2011-07-01
Commands for matrix element tests
More OpenMP parallelization of kinematics
Added unit tests
2011-06-23
Conversion of CIRCE2 from F77 to F90, major
clean-up
2011-06-14
Conversion of CIRCE1 from F77 to F90
2011-06-10
OpenMP parallelization of channel kinematics
(by Matthias Trudewind)
2011-05-31
RELEASE: version 1.97
2011-05-24
Minor bug fixes: update grids and elsif statement.
##################################################################
2011-05-10
RELEASE: version 2.0.5
2011-05-09
Fixed bug in final state flavor sums
Minor improvements on phase-space setup
2011-05-05
Minor bug fixes
2011-04-15
WHIZARD as a precompiled 64-bit binary available
2011-04-06
Wall clock instead of cpu time for time estimates
2011-04-05
Major improvement on the phase space setup
2011-04-02
OpenMP parallelization for helicity loop in O'Mega
matrix elements
2011-03-31
Tools for relocating WHIZARD and use in batch
environments
2011-03-29
Completely static builds possible, profiling options
2011-03-28
Visualization of integration history
2011-03-27
Fixed broken K-matrix implementation
2011-03-23
Including the GAMELAN manual in the distribution
2011-01-26
WHIZARD analysis can handle hadronized event files
2011-01-17
MSTW2008 and CT10 PDF sets included
2010-12-23
Inclusion of NMSSM with Hgg couplings
2010-12-21
Advanced options for integration passes
2010-11-16
WHIZARD supports CTEQ6 and possibly other PDFs
directly; data files included in the distribution
##################################################################
2010-10-26
RELEASE: version 2.0.4
2010-10-06
Bug fix in MSSM implementation
2010-10-01
Update to libtool 2.4
2010-09-29
Support for anomalous top couplings (form factors etc.)
Bug fix for running gauge Yukawa SUSY couplings
2010-09-28
RELEASE: version 1.96
2010-09-21
Beam remnants and pT spectra for lepton collider re-enabled
Restructuring subevt class
2010-09-16
Shower and matching are disabled by default
PYTHIA as a conditional on these two options
2010-09-14
Possibility to read in beam spectra re-enabled (e.g. Guinea
Pig)
2010-09-13
Energy scan as (pseudo-) structure functions re-implemented
2010-09-10
CIRCE2 included again in WHIZARD 2 and validated
2010-09-02
Re-implementation of asymmetric beam energies and collision
angles, e-p collisions work, inclusion of a HERA DIS test
case
##################################################################
2010-10-18
RELEASE: version 2.0.3
2010-08-08
Bug in CP-violating anomalous triple TGCs fixed
2010-08-06
Solving backwards compatibility problem with O'Caml 3.12.0
2010-07-12
Conserved quantum numbers speed up O'Mega code generation
2010-07-07
Attaching full ISR/FSR parton shower and MPI/ISR
module
Added SM model containing Hgg, HAA, HAZ vertices
2010-07-02
Matching output available as LHEF and STDHEP
2010-06-30
Various bug fixes, missing files, typos
2010-06-26
CIRCE1 completely re-enabled
Chaining structure functions supported
2010-06-25
Partial support for conserved quantum numbers in
O'Mega
2010-06-21
Major upgrade of the graphics package: error bars,
smarter SINDARIN steering, documentation, and all that...
2010-06-17
MLM matching with PYTHIA shower included
2010-06-16
Added full CIRCE1 and CIRCE2 versions including
full documentation and miscellanea to the trunk
2010-06-12
User file management supported, improved variable
and command structure
2010-05-24
Improved handling of variables in local command lists
2010-05-20
PYTHIA interface re-enabled
2010-05-19
ASCII file formats for interfacing ROOT and gnuplot in
data analysis
##################################################################
2010-05-18
RELEASE: version 2.0.2
2010-05-14
Reimplementation of visualization of phase space
channels
Minor bug fixes
2010-05-12
Improved phase space - elimination of redundancies
2010-05-08
Interface for polarization completed: polarized beams etc.
2010-05-06
Full quantum numbers appear in process log
Integration results are usable as user variables
Communication with external programs
2010-05-05
Split module commands into commands, integration,
simulation modules
2010-05-04
FSR+ISR for the first time connected to the WHIZARD 2 core
##################################################################
2010-04-25
RELEASE: version 2.0.1
2010-04-23
Automatic compile and integrate if simulate is called
Minor bug fixes in O'Mega
2010-04-21
Checkpointing for event generation
Flush statements to use WHIZARD inside a pipe
2010-04-20
Reimplementation of signal handling in WGIZARD 2.0
2010-04-19
VAMP is now a separately configurable and installable unit of
WHIZARD, included VAMP self-checks
Support again compilation in quadruple precision
2010-04-06
Allow for logarithmic plots in GAMELAN, reimplement the
possibility to set the number of bins
2010-04-15
Improvement on time estimates for event generation
##################################################################
2010-04-12
RELEASE: version 2.0.0
2010-04-09
Per default, the code for the amplitudes is subdivided to allow
faster compiler optimization
More advanced and unified and straightforward command language
syntax
Final bug fixes
2010-04-07
Improvement on SINDARIN syntax; printf, sprintf function
thorugh a C interface
2010-04-05
Colorizing DAGs instead of model vertices: speed boost
in colored code generation
2010-03-31
Generalized options for normalization of weighted and
unweighted events
Grid and weight histories added again to log files
Weights can be used in analyses
2010-03-28
Cascade decays completely implemented including color and
spin correlations
2010-03-07
Added new WHIZARD header with logo
2010-03-05
Removed conflict in O'Mega amplitudes between flavour sums
and cascades
StdHEP interface re-implemented
2010-03-03
RELEASE: version 2.0.0rc3
Several bug fixes for preventing abuse in input files
OpenMP support for amplitudes
Reimplementation of WHIZARD 1 HEPEVT ASCII event formats
FeynRules interface successfully passed MSSM test
2010-02-26
Eliminating ghost gluons from multi-gluon amplitudes
2010-02-25
RELEASE: version 1.95
HEPEVT format from WHIZARD 1 re-implemented in WHIZARD 2
2010-02-23
Running alpha_s implemented in the FeynRules interface
2010-02-19
MSSM (semi-) automatized self-tests finalized
2010-02-17
RELEASE: version 1.94
2010-02-16
Closed memory corruption in WHIZARD 1
Fixed problems of old MadGraph and CompHep drivers
with modern compilers
Uncolored vertex selection rules for colored amplitudes in
O'Mega
2010-02-15
Infrastructure for color correlation computation in O'Mega
finished
Forbidden processes are warned about, but treated as non-fatal
2010-02-14
Color correlation computation in O'Mega finalized
2010-02-10
Improving phase space mappings for identical particles in
initial and final states
Introduction of more extended multi-line error message
2010-02-08
First O'Caml code for computation of color correlations in
O'Mega
2010-02-07
First MLM matching with e+ e- -> jets
##################################################################
2010-02-06
RELEASE: version 2.0.0rc2
2010-02-05
Reconsidered the Makefile structure and more extended tests
Catch a crash between WHIZARD and O'Mega for forbidden processes
Tensor products of arbitrary color structures in jet definitions
2010-02-04
Color correlation computation in O'Mega finalized
##################################################################
2010-02-03
RELEASE: version 2.0.0rc1
##################################################################
2010-01-31
Reimplemented numerical helicity selection rules
Phase space functionality of version 1 restored and improved
2009-12-05
NMSSM validated with FeynRules in WHIZARD 1 (Felix Braam)
2009-12-04
RELEASE: version 2.0.0alpha
##################################################################
2009-04-16
RELEASE: version 1.93
2009-04-15
Clean-up of Makefiles and configure scripts
Reconfiguration of BSM model implementation
extended supersymmetric models
2008-12-23
New model NMSSM (Felix Braam)
SLHA2 added
Bug in LHAPDF interface fixed
2008-08-16
Bug fixed in K matrix implementation
Gravitino option in the MSSM added
2008-03-20
Improved color and flavor sums
##################################################################
2008-03-12
RELEASE: version 1.92
LHEF (Les Houches Event File) format added
Fortran 2003 command-line interface (if supported by the compiler)
Automated interface to colored models
More bug fixes and workarounds for compiler compatibility
##################################################################
2008-03-06
RELEASE: version 1.91
New model K-matrix (resonances and anom. couplings in WW scattering)
EWA spectrum
Energy-scan pseudo spectrum
Preliminary parton shower module (only from final-state quarks)
Cleanup and improvements of configure process
Improvements for O'Mega parameter files
Quadruple precision works again
More plotting options: lines, symbols, errors
Documentation with PDF bookmarks enabled
Various bug fixes
2007-11-29
New model UED
##################################################################
2007-11-23
RELEASE: version 1.90
O'Mega now part of the WHIZARD tree
Madgraph/CompHEP disabled by default (but still usable)
Support for LHAPDF (preliminary)
Added new models: SMZprime, SM_km, Template
Improved compiler recognition and compatibility
Minor bug fixes
##################################################################
2006-06-15
RELEASE: version 1.51
Support for anomaly-type Higgs couplings (to gluon and photon/Z)
Support for spin 3/2 and spin 2
New models: Little Higgs (4 versions), toy models for extra dimensions
and gravitinos
Fixes to the whizard.nw source documentation to run through LaTeX
Intel 9.0 bug workaround (deallocation of some arrays)
2006-05-15
O'Mega RELEASE: version 0.11
merged JRR's O'Mega extensions
##################################################################
2006-02-07
RELEASE: version 1.50
To avoid confusion: Mention outdated manual example in BUGS file
O'Mega becomes part of the WHIZARD generator
2006-02-02 [bug fix update]
Bug fix: spurious error when writing event files for weighted events
Bug fix: 'r' option for omega produced garbage for some particle names
Workaround for ifort90 bug (crash when compiling whizard_event)
Workaround for ifort90 bug (crash when compiling hepevt_common)
2006-01-27
Added process definition files for MSSM 2->2 processes
Included beam recoil for EPA (T.Barklow)
Updated STDHEP byte counts (for STDHEP 5.04.02)
Fixed STDHEP compatibility (avoid linking of incomplete .so libs)
Fixed issue with comphep requiring Xlibs on Opteron
Fixed issue with ifort 8.x on Opteron (compiling 'signal' interface)
Fixed color-flow code: was broken for omega with option 'c' and 'w'
Workaround hacks for g95 compatibility
2005-11-07
O'Mega RELEASE: version 0.10
O'Mega, merged JRR's and WK's color hack for WHiZard
O'Mega, EXPERIMENTAL: cache fusion tables (required for colors
a la JRR/WK)
O'Mega, make JRR's MSSM official
##################################################################
2005-10-25
RELEASE: version 1.43
Minor fixes in MSSM couplings (Higgs/3rd gen squarks).
This should be final, since the MSSM results agree now completely
with Madgraph and Sherpa
User-defined lower and upper limits for split event file count
Allow for counters (events, bytes) exceeding $2^{31}$
Revised checksum treatment and implementation (now MD5)
Bug fix: missing process energy scale in raw event file
##################################################################
2005-09-30
RELEASE: version 1.42
Graphical display of integration history ('make history')
Allow for switching off signals even if supported (configure option)
2005-09-29
Revised phase space generation code, in particular for flavor sums
Negative cut and histogram codes use initial beams instead of
initial parton momenta. This allows for computing, e.g., E_miss
Support constant-width and zero-width options for O'Mega
Width options now denoted by w:X (X=f,c,z). f option obsolescent
Bug fix: colorized code: flipped indices could screw up result
Bug fix: O'Mega with 'c' and 'w:f' option together (still some problem)
Bug fix: dvips on systems where dvips defaults to lpr
Bug fix: integer overflow if too many events are requested
2005-07-29
Allow for 2 -> 1 processes (if structure functions are on)
2005-07-26
Fixed and expanded the 'test' matrix element:
Unit matrix element with option 'u' / default: normalized phase space
##################################################################
2005-07-15
RELEASE: version 1.41
Bug fix: no result for particle decay processes with width=0
Bug fix: line breaks in O'Mega files with color decomposition
2005-06-02
New self-tests (make test-QED / test-QCD / test-SM)
check lists of 2->2 processes
Bug fix: HELAS calling convention for wwwwxx and jwwwxx (4W-Vertex)
2005-05-25
Revised Makefile structure
Eliminated obsolete references to ISAJET/SUSY (superseded by SLHA)
2005-05-19
Support for color in O'Mega (using color flow decomposition)
New model QCD
Parameter file changes that correspond to replaced SM module in O'Mega
Bug fixes in MSSM (O'Mega) parameter file
2005-05-18
New event file formats, useful for LHC applications:
ATHENA and Les Houches Accord (external fragmentation)
Naive (i.e., leading 1/N) color factor now implemented both for
incoming and outgoing partons
2005-01-26
include missing HELAS files for bundle
pgf90 compatibility issues [note: still internal error in pgf90]
##################################################################
2004-12-13
RELEASE: version 1.40
compatibility fix: preprocessor marks in helas code now commented out
minor bug fix: format string in madgraph source
2004-12-03
support for arbitray beam energies and directions
allow for pT kick in structure functions
bug fix: rounding error could result in zero cross section
(compiler-dependent)
2004-10-07
simulate decay processes
list fraction (of total width/cross section) instead of efficiency
in process summary
new cut/analysis parameters AA, AAD, CTA: absolute polar angle
2004-10-04
Replaced Madgraph I by Madgraph II. Main improvement: model no
longer hardcoded
introduced parameter reset_seed_each_process (useful for debugging)
bug fix: color initialization for some processes was undefined
2004-09-21
don't compile unix_args module if it is not required
##################################################################
2004-09-20
RELEASE: version 1.30
g95 compatibility issues resolved
some (irrelevant) memory leaks closed
removed obsolete warning in circe1
manual update (essentially) finished
2004-08-03
O'Mega RELEASE: version 0.9
O'Mega, src/trie.mli, src/trie.ml: make interface compatible with
the O'Caml 3.08 library (remains compatible with older
versions). Implementation of unused functions still
incomplete.
2004-07-26
minor fixes and improvements in make process
2004-06-29
workarounds for new Intel compiler bugs ...
no rebuild of madgraph/comphep executables after 'make clean'
bug fix in phase space routine:
wrong energy for massive initial particles
bug fix in (new) model interface: name checks for antiparticles
pre-run checks for comphep improved
ww-strong model file extended
Model files particle name fixes, chep SM vertices included
2004-06-22
O'Mega RELEASE: version 0.8
O'Mega MSSM: sign of W+/W-/A and W+/W-/Z couplings
2004-05-05
Fixed bug in PDFLIB interface: p+pbar was initialized as p+p (ThO)
NAG compiler: set number of continuation lines to 200 as default
Extended format for cross section summary; appears now in whizard.out
Fixed 'bundle' feature
2004-04-28
Fixed compatibility with revised O'Mega SM_ac model
Fixed problem with x=0 or x=1 when calling PDFLIB (ThO)
Fixed bug in comphep module: Vtb was overlooked
##################################################################
2004-04-15
RELEASE: version 1.28
Fixed bug: Color factor was missing for O'Mega processes with
four quarks and more
Manual partially updated
2004-04-08
Support for grid files in binary format
New default value show_histories=F (reduce output file size)
Revised phase space switches: removed annihilation_lines,
removed s_channel_resonance, changed meaning of
extra_off_shell_lines, added show_deleted_channels
Bug fixed which lead to omission of some phase space channels
Color flow guessed only if requested by guess_color_flow
2004-03-10
New model interface: Only one model name specified in whizard.prc
All model-dependent files reside in conf/models (modellib removed)
2004-03-03
Support for input/output in SUSY Les Houches Accord format
Split event files if requested
Support for overall time limit
Support for CIRCE and CIRCE2 generator mode
Support for reading beam events from file
2004-02-05
Fixed compiler problems with Intel Fortran 7.1 and 8.0
Support for catching signals
##################################################################
2003-08-06
RELEASE: version 1.27
User-defined PDF libraries as an alternative to the standard PDFLIB
2003-07-23
Revised phase space module: improved mappings for massless particles,
equivalences of phase space channels are exploited
Improved mapping for PDF (hadron colliders)
Madgraph module: increased max number of color flows from 250 to 1000
##################################################################
2003-06-23
RELEASE: version 1.26
CIRCE2 support
Fixed problem with 'TC' integer kind [Intel compiler complained]
2003-05-28
Support for drawing histograms of grids
Bug fixes for MSSM definitions
##################################################################
2003-05-22
RELEASE: version 1.25
Experimental MSSM support with ISAJET interface
Improved capabilities of generating/analyzing weighted events
Optional drawing phase space diagrams using FeynMF
##################################################################
2003-01-31
RELEASE: version 1.24
A few more fixes and workarounds (Intel and Lahey compiler)
2003-01-15
Fixes and workarounds needed for WHIZARD to run with Intel compiler
Command-line option interface for the Lahey compiler
Bug fix: problem with reading whizard.phs
##################################################################
2002-12-10
RELEASE: version 1.23
Command-line options (on some systems)
Allow for initial particles in the event record, ordered:
[beams, initials] - [remnants] - outgoing partons
Support for PYTHIA 6.2: Les Houches external process interface
String pythia_parameters can be up to 1000 characters long
Select color flow states in (internal) analysis
Bug fix in color flow content of raw event files
Support for transversal polarization of fermion beams
Cut codes: PHI now for absolute azimuthal angle, DPHI for distance
'Test' matrix elements optionally respect polarization
User-defined code can be inserted for spectra, structure functions
and fragmentation
Time limits can be specified for adaptation and simulation
User-defined file names and file directory
Initial weights in input file no longer supported
Bug fix in MadGraph (wave function counter could overflow)
Bug fix: Gamelan (graphical analysis) was not built if noweb absent
##################################################################
2002-03-16
RELEASE: version 1.22
Allow for beam remnants in the event record
2002-03-01
Handling of aliases in whizard.prc fixed (aliases are whole tokens)
2002-02-28
Optimized phase space handling routines
(total execution time reduced by 20-60%, depending on process)
##################################################################
2002-02-26
RELEASE: version 1.21
Fixed ISR formula (ISR was underestimated in previous versions).
New version includes ISR in leading-log approximation up to
third order. Parameter ISR_sqrts renamed to ISR_scale.
##################################################################
2002-02-19
RELEASE: version 1.20
New process-generating method 'test' (dummy matrix element)
Compatibility with autoconf 2.50 and current O'Mega version
2002-02-05
Prevent integration channels from being dropped (optionally)
New internal mapping for structure functions improves performance
Old whizard.phx file deleted after recompiling (could cause trouble)
2002-01-24
Support for user-defined cuts and matrix element reweighting
STDHEP output now written by write_events_format=20 (was 3)
2002-01-16
Improved structure function handling; small changes in user interface:
new parameter structured_beams in &process_input
parameter fixed_energy in &beam_input removed
Support for multiple initial states
Eta-phi (cone) cut possible (hadron collider applications)
Fixed bug: Whizard library was not always recompiled when necessary
Fixed bug: Default cuts were insufficient in some cases
Fixed bug: Unusable phase space mappings generated in some cases
2001-12-06
Reorganized document source
2001-12-05
Preliminary CIRCE2 support (no functionality yet)
2001-11-27
Intel compiler support (does not yet work because of compiler bugs)
New cut and analysis mode cos-theta* and related
Fixed circular jetset_interface dependency warning
Some broadcast routines removed (parallel support disabled anyway)
Minor shifts in cleanup targets (Makefiles)
Modified library search, check for pdflib8*
2001-08-06
Fixed bug: I/O unit number could be undefined when reading phase space
Fixed bug: Unitialized variable could cause segfault when
event generation was disabled
Fixed bug: Undefined subroutine in CIRCE replacement module
Enabled feature: TGCs in O'Mega (not yet CompHEP!) matrix elements
(CompHEP model sm-GF #5, O'Mega model SM_ac)
Fixed portability issue: Makefile did rely on PWD environment variable
Fixed portability issue: PYTHIA library search ambiguity resolved
2001-08-01
Default whizard.prc and whizard.in depend on activated modules
Fixed bug: TEX=latex was not properly enabled when making plots
2001-07-20
Fixed output settings in PERL script calls
Cache enabled in various configure checks
2001-07-13
Support for multiple processes in a single WHIZARD run. The
integrations are kept separate, but the generated events are mixed
The whizard.evx format has changed (incompatible), including now
the color flow information for PYTHIA fragmentation
Output files are now process-specific, except for the event file
Phase space file whizard.phs (if present) is used only as input,
program-generated phase space is now in whizard.phx
2001-07-10
Bug fix: Undefined parameters in parameters_SM_ac.f90 removed
2001-07-04
Bug fix: Compiler options for the case OMEGA is disabled
Small inconsistencies in whizard.out format fixed
2001-07-01
Workaround for missing PDFLIB dummy routines in PYTHIA library
##################################################################
2001-06-30
RELEASE: version 1.13
Default path /cern/pro/lib in configure script
2001-06-20
New fragmentation option: Interface for PYTHIA with full color flow
information, beam remnants etc.
2001-06-18
Severe bug fixed in madgraph interface: 3-gluon coupling was missing
Enabled color flow information in madgraph
2001-06-11
VAMP interface module rewritten
Revised output format: Multiple VAMP iterations count as one WHIZARD
iteration in integration passes 1 and 3
Improved message and error handling
Bug fix in VAMP: handle exceptional cases in rebinning_weights
2001-05-31
new parameters for grid adaptation: accuracy_goal and efficiency_goal
##################################################################
2001-05-29
RELEASE: version 1.12
bug fixes (compilation problems): deleted/modified unused functions
2001-05-16
diagram selection improved and documented
2001-05-06
allow for disabling packages during configuration
2001-05-03
slight changes in whizard.out format; manual extended
##################################################################
2001-04-20
RELEASE: version 1.11
fixed some configuration and compilation problems (PDFLIB etc.)
2001-04-18
linked PDFLIB: support for quark/gluon structure functions
2001-04-05
parameter interface written by PERL script
SM_ac model file: fixed error in continuation line
2001-03-13
O'Mega, O'Caml 3.01: incompatible changes
O'Mega, src/trie.mli: add covariance annotation to T.t
This breaks O'Caml 3.00, but is required for O'Caml 3.01.
O'Mega, many instances: replace `sig include Module.T end' by
`Module.T', since the bug is fixed in O'Caml 3.01
2001-02-28
O'Mega, src/model.mli:
new field Model.vertices required for model functors, will
retire Model.fuse2, Model.fuse3, Model.fusen soon.
##################################################################
2001-03-27
RELEASE: version 1.10
reorganized the modules as libraries
linked PYTHIA: support for parton fragmentation
2000-12-14
fixed some configuration problems (if noweb etc. are absent)
##################################################################
2000-12-01
RELEASE of first public version: version 1.00beta
Index: trunk/src/lcio/LCIOWrap.cpp
===================================================================
--- trunk/src/lcio/LCIOWrap.cpp (revision 8336)
+++ trunk/src/lcio/LCIOWrap.cpp (revision 8337)
@@ -1,567 +1,572 @@
//////////////////////////////////////////////////////////////////////////
// Interface for building LCIO events
//////////////////////////////////////////////////////////////////////////
#include<stdio.h>
#include<string>
#include<iostream>
#include<fstream>
#include "lcio.h"
#include "IO/LCWriter.h"
#include "IO/LCReader.h"
#include "EVENT/LCIO.h"
#include "EVENT/MCParticle.h"
#include "IMPL/LCEventImpl.h"
#include "IMPL/LCRunHeaderImpl.h"
#include "IMPL/LCCollectionVec.h"
#include "IMPL/MCParticleImpl.h"
#include "IMPL/LCTOOLS.h"
#include "UTIL/LCTime.h"
using namespace std;
using namespace lcio;
using namespace IMPL;
using namespace EVENT;
// Tell the caller that this is the true LCIO library
extern "C" bool lcio_available() {
return true;
}
//////////////////////////////////////////////////////////////////////////
// LCEventImpl functions
// The run number at the moment is set to the process ID. We add the process
// ID in addition as an event variable.
extern "C" LCEventImpl* new_lcio_event ( int proc_id, int event_id, int run_id ) {
LCEventImpl* evt = new LCEventImpl();
evt->setRunNumber ( run_id );
evt->parameters().setValue("Run ID", run_id );
evt->parameters().setValue("ProcessID", proc_id );
evt->setEventNumber ( event_id );
evt->parameters().setValue("Event Number", event_id );
LCTime now;
evt->setTimeStamp ( now.timeStamp() );
return evt;
}
extern "C" void lcio_event_delete( LCEventImpl* evt) {
delete evt;
}
extern "C" void lcio_set_weight( LCEventImpl* evt, double wgt ) {
evt->setWeight ( wgt );
}
+extern "C" void lcio_set_sqme( LCEventImpl* evt, double sqme ) {
+ float sqme_dble = sqme;
+ evt->parameters().setValue ( "sqme" , sqme_dble );
+}
+
extern "C" void lcio_set_alt_weight( LCEventImpl* evt, double wgt, int index ) {
float weight = wgt;
evt->parameters().setValue ( "alternateWeight"+to_string(index), weight );
}
extern "C" void lcio_set_alt_sqme( LCEventImpl* evt, double sqme, int index ) {
float sqme_dble = sqme;
evt->parameters().setValue ( "alternateSqme"+to_string(index) , sqme_dble );
}
extern "C" void lcio_set_alpha_qcd ( LCEventImpl* evt, double alphas ) {
float alpha_qcd = alphas;
evt->parameters().setValue ( "alphaQCD", alpha_qcd );
}
extern "C" void lcio_set_scale ( LCEventImpl* evt, double scale ) {
float scale_f = scale;
evt->parameters().setValue ( "scale", scale_f );
}
extern "C" void lcio_set_sqrts ( LCEventImpl* evt, double sqrts ) {
float sqrts_f = sqrts;
evt->parameters().setValue ( "Energy", sqrts_f );
}
extern "C" void lcio_set_xsec ( LCEventImpl* evt, double xsec, double xsec_err ) {
float xsec_f = xsec;
float xsec_err_f = xsec_err;
evt->parameters().setValue ( "crossSection", xsec_f );
evt->parameters().setValue ( "crossSectionError", xsec_err_f );
}
extern "C" void lcio_set_beam ( LCEventImpl* evt, int pdg, int beam ) {
if (beam == 1){
evt->parameters().setValue ( "beamPDG1", pdg );
}
else if (beam == 2){
evt->parameters().setValue ( "beamPDG2", pdg );
}
}
extern "C" void lcio_set_pol ( LCEventImpl* evt, double pol1, double pol2 ) {
float pol1_f = pol1;
float pol2_f = pol2;
evt->parameters().setValue ( "beamPol1", pol1_f );
evt->parameters().setValue ( "beamPol2", pol2_f );
}
extern "C" void lcio_set_beam_file ( LCEventImpl* evt, char* file ) {
evt->parameters().setValue ( "BeamSpectrum", file );
}
extern "C" void lcio_set_process_name ( LCEventImpl* evt, char* name ) {
evt->parameters().setValue ( "processName", name );
}
extern "C" LCEvent* read_lcio_event ( LCReader* lcRdr) {
LCEvent* evt;
if ((evt = lcRdr->readNextEvent ()) != 0) {
return evt;
}
else
{
return NULL;
}
}
// dump the event to the screen
extern "C" void dump_lcio_event ( LCEvent* evt) {
LCTOOLS::dumpEventDetailed ( evt );
}
extern "C" int lcio_event_get_event_number (LCEvent* evt) {
return evt->getEventNumber();
}
extern "C" int lcio_event_signal_process_id (LCEvent* evt) {
return evt->getParameters().getIntVal("ProcessID");
}
extern "C" int lcio_event_get_n_particles (LCEvent* evt) {
LCCollection* col = evt->getCollection( LCIO::MCPARTICLE );
int n = col->getNumberOfElements();
return n;
}
extern "C" double lcio_event_get_alpha_qcd (LCEvent* evt) {
double alphas;
return alphas = evt->parameters().getFloatVal( "alphaQCD" );
}
extern "C" double lcio_event_get_scale (LCEvent* evt) {
double scale;
return scale = evt->parameters().getFloatVal( "scale" );
}
// Write parameters in LCIO event in ASCII form to a stream
extern "C" std::ostream& printParameters
( const EVENT::LCParameters& params, std::ofstream &out){
StringVec intKeys ;
int nIntParameters = params.getIntKeys( intKeys ).size() ;
for(int i=0; i< nIntParameters ; i++ ){
IntVec intVec ;
params.getIntVals( intKeys[i], intVec ) ;
int nInt = intVec.size() ;
out << " parameter " << intKeys[i] << " [int]: " ;
if( nInt == 0 ){
out << " [empty] " << std::endl ;
}
for(int j=0; j< nInt ; j++ ){
out << intVec[j] << ", " ;
}
out << endl ;
}
StringVec floatKeys ;
int nFloatParameters = params.getFloatKeys( floatKeys ).size() ;
for(int i=0; i< nFloatParameters ; i++ ){
FloatVec floatVec ;
params.getFloatVals( floatKeys[i], floatVec ) ;
int nFloat = floatVec.size() ;
out << " parameter " << floatKeys[i] << " [float]: " ;
if( nFloat == 0 ){
out << " [empty] " << std::endl ;
}
for(int j=0; j< nFloat ; j++ ){
out << floatVec[j] << ", " ;
}
out << endl ;
}
StringVec stringKeys ;
int nStringParameters = params.getStringKeys( stringKeys ).size() ;
for(int i=0; i< nStringParameters ; i++ ){
StringVec stringVec ;
params.getStringVals( stringKeys[i], stringVec ) ;
int nString = stringVec.size() ;
out << " parameter " << stringKeys[i] << " [string]: " ;
if( nString == 0 ){
out << " [empty] " << std::endl ;
}
for(int j=0; j< nString ; j++ ){
out << stringVec[j] << ", " ;
}
out << endl ;
}
return out;
}
// Write MCParticles as ASCII to stream
extern "C" std::ostream& printMCParticles
(const EVENT::LCCollection* col, std::ofstream &out) {
out << endl
<< "--------------- " << "print out of " << LCIO::MCPARTICLE
<< " collection " << "--------------- " << endl ;
out << endl
<< " flag: 0x" << hex << col->getFlag() << dec << endl ;
printParameters( col->getParameters(), out ) ;
int nParticles = col->getNumberOfElements() ;
out << " " << LCTOOLS::getSimulatorStatusString() << std::endl ;
// fill map with particle pointers and collection indices
typedef std::map< MCParticle*, int > PointerToIndexMap ;
PointerToIndexMap p2i_map ;
for( int k=0; k<nParticles; k++){
MCParticle* part = static_cast<MCParticle*>( col->getElementAt( k ) ) ;
p2i_map[ part ] = k ;
}
out << endl
<< "[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | endpoint x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]"
<< endl
<< endl ;
// loop over collection - preserve order
for( int index = 0 ; index < nParticles ; index++){
char buff[215];
MCParticle* part = static_cast<MCParticle*>( col->getElementAt( index ) ) ;
sprintf(buff, "[%8.8d]%5d|%10d|% 1.2e,% 1.2e,% 1.2e|% 1.2e| %1d |%s|% 1.2e,% 1.2e,% 1.2e|% 1.2e,% 1.2e,% 1.2e|% 1.2e|% 1.2e|% 1.2e,% 1.2e,% 1.2e| (%d, %d) | [",
part->id(), index, part->getPDG(),
part->getMomentum()[0], part->getMomentum()[1],
part->getMomentum()[2], part->getEnergy(),
part->getGeneratorStatus(),
LCTOOLS::getSimulatorStatusString( part ).c_str(),
part->getVertex()[0], part->getVertex()[1], part->getVertex()[2],
part->getEndpoint()[0], part->getEndpoint()[1],
part->getEndpoint()[2], part->getMass(), part->getCharge(),
part->getSpin()[0], part->getSpin()[1], part->getSpin()[2],
part->getColorFlow()[0], part->getColorFlow()[1] );
out << buff;
for(unsigned int k=0;k<part->getParents().size();k++){
if(k>0) out << "," ;
out << p2i_map[ part->getParents()[k] ] ;
}
out << "] - [" ;
for(unsigned int k=0;k<part->getDaughters().size();k++){
if(k>0) out << "," ;
out << p2i_map[ part->getDaughters()[k] ] ;
}
out << "] " << endl ;
}
out << endl
<< "-------------------------------------------------------------------------------- "
<< endl ;
return out;
}
// Write LCIO event to ASCII file
extern "C" void lcio_event_to_file ( LCEvent* evt, char* filename ) {
ofstream myfile;
myfile.open ( filename );
myfile << endl
<< "=========================================" << endl;
myfile << " - Event : " << evt->getEventNumber() << endl;
myfile << " - run: " << evt->getRunNumber() << endl;
myfile << " - timestamp " << evt->getTimeStamp() << endl;
myfile << " - weight " << evt->getWeight() << endl;
myfile << "=========================================" << endl;
LCTime evtTime( evt->getTimeStamp() ) ;
myfile << " date: " << evtTime.getDateString() << endl ;
myfile << " detector : " << evt->getDetectorName() << endl ;
myfile << " event parameters: " << endl ;
printParameters (evt->getParameters(), myfile );
const std::vector< std::string >* strVec = evt->getCollectionNames() ;
// loop over all collections:
std::vector< std::string >::const_iterator name ;
for( name = strVec->begin() ; name != strVec->end() ; name++){
LCCollection* col = evt->getCollection( *name ) ;
myfile << endl
<< " collection name : " << *name
<< endl
<< " parameters: " << endl ;
// call the detailed print functions depending on type name
if( evt->getCollection( *name )->getTypeName() == LCIO::MCPARTICLE ){
if( col->getTypeName() != LCIO::MCPARTICLE ){
myfile << " collection not of type " << LCIO::MCPARTICLE << endl ;
return ;
}
printMCParticles (col, myfile);
}
myfile.close();
}
}
// add collection to LCIO event
extern "C" void lcio_event_add_collection
( LCEventImpl* evt, LCCollectionVec* mcVec ) {
evt->addCollection( mcVec, LCIO::MCPARTICLE );
}
extern "C" MCParticle* lcio_event_particle_k ( LCEventImpl* evt, int k ) {
LCCollection* col = evt->getCollection( LCIO::MCPARTICLE );
MCParticle* mcp = static_cast<MCParticle*>(col->getElementAt ( k ));
return mcp;
}
// returns the index of the parent / daughter with incoming index
extern "C" int lcio_event_parent_k
( LCEventImpl* evt, int num_part, int k_parent) {
LCCollection* col = evt->getCollection( LCIO::MCPARTICLE );
int nParticles = col->getNumberOfElements() ;
std::vector<int> p_parents[nParticles];
typedef std::map< MCParticle*, int > PointerToIndexMap ;
PointerToIndexMap p2i_map ;
for( int k=0; k<nParticles; k++){
MCParticle* part = static_cast<MCParticle*>( col->getElementAt ( k ) );
p2i_map[ part ] = k;
}
for( int index = 0; index < nParticles ; index++){
MCParticle* part = static_cast<MCParticle*>( col->getElementAt ( index ) );
for(unsigned int k =0;k<part->getParents().size();k++){
p_parents[index].push_back( p2i_map[ part -> getParents()[k] ]) ;
}
}
return p_parents[num_part-1][k_parent-1] + 1;
}
extern "C" int lcio_event_daughter_k
( LCEventImpl* evt, int num_part, int k_daughter) {
LCCollection* col = evt->getCollection( LCIO::MCPARTICLE );
int nParticles = col->getNumberOfElements() ;
std::vector<int> p_daughters[nParticles];
typedef std::map< MCParticle*, int > PointerToIndexMap ;
PointerToIndexMap p2i_map ;
for( int k=0; k<nParticles; k++){
MCParticle* part = static_cast<MCParticle*>( col->getElementAt ( k ) );
p2i_map[ part ] = k;
}
for( int index = 0; index < nParticles ; index++){
MCParticle* part = static_cast<MCParticle*>( col->getElementAt ( index ) );
for(unsigned int k =0;k<part->getDaughters().size();k++){
p_daughters[index].push_back( p2i_map[ part -> getDaughters()[k] ]) ;
}
}
return p_daughters[num_part-1][k_daughter-1] + 1;
}
//////////////////////////////////////////////////////////////////////////
// MCParticle and LCCollectionVec functions
extern "C" LCCollectionVec* new_lccollection() {
LCCollectionVec* mcVec = new LCCollectionVec(LCIO::MCPARTICLE);
return mcVec;
}
extern "C" void add_particle_to_collection
(MCParticleImpl* mcp, LCCollectionVec* mcVec) {
mcVec->push_back( mcp );
}
extern "C" MCParticleImpl* new_lcio_particle
(double px, double py, double pz, int pdg, double mass, double charge, int status) {
MCParticleImpl* mcp = new MCParticleImpl() ;
double p[3] = { px, py, pz };
mcp->setPDG ( pdg );
mcp->setMomentum ( p );
mcp->setMass ( mass );
mcp->setCharge ( charge );
mcp->setGeneratorStatus ( status );
mcp->setCreatedInSimulation (false);
return mcp;
}
extern "C" MCParticleImpl* lcio_set_color_flow
(MCParticleImpl* mcp, int cflow1, int cflow2) {
int cflow[2] = { cflow1, cflow2 };
mcp->setColorFlow ( cflow );
return mcp;
}
extern "C" MCParticleImpl* lcio_particle_set_spin
(MCParticleImpl* mcp, const double spin1, const double spin2, const double spin3) {
float spin1_fl = spin1;
float spin2_fl = spin2;
float spin3_fl = spin3;
float spin[3] = { spin1_fl, spin2_fl, spin3_fl };
mcp->setSpin( spin );
return mcp;
}
extern "C" MCParticleImpl* lcio_particle_set_time
(MCParticleImpl* mcp, const double t) {
mcp->setTime( t );
return mcp;
}
extern "C" MCParticleImpl* lcio_particle_set_vertex
(MCParticleImpl* mcp, const double vx, const double vy, const double vz) {
double vtx[3] = { vx, vy, vz };
mcp->setVertex( vtx );
return mcp;
}
extern "C" void lcio_particle_add_parent
( MCParticleImpl* daughter , MCParticleImpl* parent) {
daughter->addParent( parent );
}
extern "C" int lcio_particle_get_generator_status ( MCParticleImpl* mcp) {
return mcp->getGeneratorStatus();
}
extern "C" int lcio_particle_get_pdg_code ( MCParticleImpl* mcp) {
return mcp->getPDG();
}
extern "C" int lcio_particle_flow ( MCParticleImpl* mcp, int col_index ) {
return mcp->getColorFlow()[ col_index ];
}
extern "C" double lcio_polarization_degree ( MCParticleImpl* mcp) {
return mcp->getSpin()[ 0 ];
}
extern "C" double lcio_polarization_theta ( MCParticleImpl* mcp) {
return mcp->getSpin()[ 1 ];
}
extern "C" double lcio_polarization_phi ( MCParticleImpl* mcp) {
return mcp->getSpin()[ 2 ];
}
extern "C" double lcio_three_momentum ( MCParticleImpl* mcp, int p_index ) {
return mcp->getMomentum()[ p_index ];
}
extern "C" double lcio_energy ( MCParticleImpl* mcp ) {
return mcp->getEnergy();
}
extern "C" double lcio_mass ( MCParticleImpl* mcp ) {
return mcp->getMass();
}
extern "C" int lcio_n_parents ( MCParticleImpl* mcp) {
return mcp->getParents().size();
}
extern "C" int lcio_n_daughters ( MCParticleImpl* mcp) {
return mcp->getDaughters().size();
}
extern "C" double lcio_vtx_x (MCParticleImpl* mcp) {
return mcp->getVertex()[0];
}
extern "C" double lcio_vtx_y (MCParticleImpl* mcp) {
return mcp->getVertex()[1];
}
extern "C" double lcio_vtx_z (MCParticleImpl* mcp) {
return mcp->getVertex()[2];
}
extern "C" float lcio_prt_time (MCParticleImpl* mcp) {
return mcp->getTime();
}
//////////////////////////////////////////////////////////////////////////
// LCWriter functions
extern "C" LCWriter* open_lcio_writer_new
( char* filename, int complevel ) {
LCWriter* lcWrt = LCFactory::getInstance()->createLCWriter();
lcWrt->setCompressionLevel (complevel);
lcWrt->open( filename, LCIO::WRITE_NEW );
return lcWrt;
}
extern "C" LCWriter* open_lcio_writer_append
( char* filename ) {
LCWriter* lcWrt = LCFactory::getInstance()->createLCWriter();
lcWrt->open( filename, LCIO::WRITE_APPEND );
return lcWrt;
}
// write the event
extern "C" LCWriter* lcio_write_event
( LCWriter* lcWrt, LCEventImpl* evt) {
lcWrt->writeEvent( evt );
return lcWrt;
}
// destructor
extern "C" void lcio_writer_delete ( LCWriter* lcWrt ) {
lcWrt->close();
delete lcWrt;
}
//////////////////////////////////////////////////////////////////////////
// LCReader functions
extern "C" LCReader* open_lcio_reader ( char* filename) {
LCReader* lcRdr = LCFactory::getInstance()->createLCReader();
lcRdr->open ( filename );
return lcRdr;
}
extern "C" LCReader* open_lcio_reader_direct_access ( char* filename) {
LCReader* lcRdr = LCFactory::getInstance()->createLCReader(LCReader::directAccess);
lcRdr->open ( filename );
return lcRdr;
}
extern "C" int lcio_get_n_runs ( LCReader* lcRdr ) {
return lcRdr->getNumberOfRuns();
}
extern "C" int lcio_get_n_events ( LCReader* lcRdr ) {
return lcRdr->getNumberOfEvents();
}
extern "C" void lcio_reader_delete ( LCReader* lcRdr ) {
lcRdr->close();
}
//////////////////////////////////////////////////////////////////////////
// LCRunHeader functions
// We set the process ID equal to the run number, and at it also as an
// explicit parameter.
extern "C" LCRunHeaderImpl* new_lcio_run_header( int rn ) {
LCRunHeaderImpl* runHdr = new LCRunHeaderImpl;
runHdr->setRunNumber (rn);
return runHdr;
}
extern "C" void run_header_set_simstring
(LCRunHeaderImpl* runHdr, char* simstring) {
runHdr->parameters().setValue ( "SimulationProgram", simstring );
}
extern "C" bool read_run_header ( LCReader* lcRdr , LCRunHeader* runHdr ) {
return ((runHdr = lcRdr->readNextRunHeader ()) != 0);
}
extern "C" void dump_run_header ( LCRunHeaderImpl* runHdr ) {
LCTOOLS::dumpRunHeader( runHdr );
}
extern "C" void write_run_header
(LCWriter* lcWrt, const LCRunHeaderImpl* runHdr) {
lcWrt->writeRunHeader (runHdr);
}
Index: trunk/src/lcio/LCIOWrap_dummy.f90
===================================================================
--- trunk/src/lcio/LCIOWrap_dummy.f90 (revision 8336)
+++ trunk/src/lcio/LCIOWrap_dummy.f90 (revision 8337)
@@ -1,712 +1,723 @@
! WHIZARD <<Version>> <<Date>>
!
! Copyright (C) 1999-2019 by
! Wolfgang Kilian <kilian@physik.uni-siegen.de>
! Thorsten Ohl <ohl@physik.uni-wuerzburg.de>
! Juergen Reuter <juergen.reuter@desy.de>
!
! with contributions from
! cf. main AUTHORS file
!
! WHIZARD is free software; you can redistribute it and/or modify it
! under the terms of the GNU General Public License as published by
! the Free Software Foundation; either version 2, or (at your option)
! any later version.
!
! WHIZARD is distributed in the hope that it will be useful, but
! WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with this program; if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! Dummy interface for non-existent LCIO library
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! Tell the caller that this is not the true LCIO library
logical(c_bool) function lcio_available () bind(C)
use iso_c_binding
lcio_available = .false.
end function lcio_available
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! LCEventImpl functions
! extern "C" void* new_lcio_event( int proc_id, int event_id ) {}
type(c_ptr) function new_lcio_event (proc_id, event_id, run_id) bind(C)
use iso_c_binding
integer(c_int), value :: proc_id, event_id, run_id
new_lcio_event = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function new_lcio_event
! extern "C" void lcio_set_weight( LCEventImpl* evt, double wgt )
subroutine lcio_set_weight (evt_obj, weight) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: weight
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_weight
+! extern "C" void lcio_set_sqme( LCEventImpl* evt, double sqme ) {
+subroutine lcio_set_sqme (evt_obj, sqme) bind(C)
+ use iso_c_binding
+ type(c_ptr), value :: evt_obj
+ real(c_double), value :: sqme
+ write (0, "(A)") "***********************************************************"
+ write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
+ write (0, "(A)") "***********************************************************"
+ stop
+end subroutine lcio_set_sqme
+
! extern "C" void lcio_set_alt_weight( LCEventImpl* evt, double wgt, int index )
subroutine lcio_set_alt_weight (evt_obj, weight, index) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: weight
integer(c_int), value :: index
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_alt_weight
! extern "C" void lcio_set_alt_sqme( LCEventImpl* evt, double sqme, int index )
subroutine lcio_set_alt_sqme (evt_obj, sqme, index) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: sqme
integer(c_int), value :: index
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_alt_sqme
! extern "C" void lcio_set_alpha_qcd ( LCEventImpl* evt, double alphas )
subroutine lcio_set_alpha_qcd (evt_obj, alphas) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: alphas
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_alpha_qcd
! extern "C" void lcio_set_scale ( LCEventImpl* evt, double scale )
subroutine lcio_set_scale (evt_obj, scale) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: scale
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_scale
! extern "C" void lcio_set_sqrts ( LCEventImpl* evt, double sqrts )
subroutine lcio_set_sqrts (evt_obj, sqrts) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: sqrts
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_sqrts
! extern "C" void lcio_set_xsec ( LCEventImpl* evt, double xsec, double xsec_err )
subroutine lcio_set_xsec (evt_obj, xsec, xsec_err) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: xsec, xsec_err
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_xsec
! extern "C" void lcio_set_beam ( LCEventImpl* evt, int pdg, int beam )
subroutine lcio_set_beam (evt_obj, pdg, beam) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
integer(c_int), value :: pdg, beam
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_beam
! extern "C" void lcio_set_pol ( LCEventImpl* evt, double pol1, double pol2 )
subroutine lcio_set_pol (evt_obj, pol1, pol2) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
real(c_double), value :: pol1, pol2
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_pol
! extern "C" void lcio_set_beam_file ( LCEventImpl* evt, char* file ) {
subroutine lcio_set_beam_file (evt_obj, file) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
character(len=1, kind=c_char), dimension(*), intent(in) :: file
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_beam_file
! extern "C" void lcio_set_process_name ( LCEventImpl* evt, char* name ) {
subroutine lcio_set_process_name (evt_obj, name) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
character(len=1, kind=c_char), dimension(*), intent(in) :: name
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_process_name
! extern "C" void lcio_event_delete( void* evt) {}
subroutine lcio_event_delete (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_event_delete
! extern "C" LCEvent* read_lcio_event ( LCReader* lcRdr )
type (c_ptr) function read_lcio_event (io_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj
read_lcio_event = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function read_lcio_event
! extern "C" void dump_lcio_event ( LCEventImpl* evt )
subroutine dump_lcio_event (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine dump_lcio_event
! extern "C" int lcio_get_event_number (LCEvent* evt)
integer(c_int) function lcio_event_get_event_number (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
lcio_event_get_event_number = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_get_event_number
! extern "C" int lcio_event_signal_process_id (LCEvent* evt)
integer(c_int) function lcio_event_signal_process_id (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
lcio_event_signal_process_id = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_signal_process_id
! extern "C" int lcio_event_get_n_particles (LCEvent* evt)
integer(c_int) function lcio_event_get_n_particles (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
lcio_event_get_n_particles = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_get_n_particles
! extern "C" double lcio_event_get_alpha_qcd (LCEvent* evt)
real(c_double) function lcio_event_get_alpha_qcd (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
lcio_event_get_alpha_qcd = 0._c_double
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_get_alpha_qcd
! extern "C" double lcio_event_get_scale (LCEvent* evt)
real(c_double) function lcio_event_get_scale (evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
lcio_event_get_scale = 0._c_double
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_get_scale
! extern "C" void lcio_event_to_file ( LCEvent* evt, char* filename )
subroutine lcio_event_to_file (evt_obj, filename) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
character(c_char), dimension(*), intent(in) :: filename
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_event_to_file
! extern "C" void lcio_event_add_collection ( LCEventImpl* evt, LCCollectionVec* mcVec )
subroutine lcio_event_add_collection (evt_obj, lccoll_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj, lccoll_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_event_add_collection
! extern "C" MCParticleImpl* lcio_event_particle_k ( LCEventImpl* evt, int k )
type(c_ptr) function lcio_event_particle_k (evt_obj, k) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
integer(c_int), value :: k
lcio_event_particle_k = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_particle_k
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! MCParticleImpl and LCCollectionVec functions
! extern "C" LCCollectionVec* new_lccollection()
type(c_ptr) function new_lccollection () bind(C)
use iso_c_binding
new_lccollection = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function new_lccollection
! extern "C" void add_particle_to_collection (MCParticleImpl* mcp, LCCollectionVec* mcVec)
subroutine add_particle_to_collection (prt_obj, lccoll_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj, lccoll_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine add_particle_to_collection
! extern "C" MCParticleImpl* new_lcio_particle(void* momentum, int pdg_id, int status)
type(c_ptr) function new_lcio_particle &
(px, py, pz, pdg_id, mass, charge, status) bind(C)
use iso_c_binding
integer(c_int), value :: pdg_id, status
real(c_double), value :: px, py, pz, mass, charge
new_lcio_particle = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function new_lcio_particle
! extern "C" void lcio_particle_add_parent
subroutine lcio_particle_add_parent (io_obj1, io_obj2) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj1, io_obj2
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_particle_add_parent
! extern "C" MCParticleImpl* lcio_set_color_flow
subroutine lcio_set_color_flow (prt_obj, cflow1, cflow2) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
integer(c_int), value :: cflow1, cflow2
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_set_color_flow
! extern "C" MCParticleImpl* lcio_particle_set_spin
! (MCParticleImpl* mcp, int s1, int s2, int s3)
subroutine lcio_particle_set_spin (prt_obj, s1, s2, s3) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
real(c_double), value :: s1, s2, s3
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_particle_set_spin
! extern "C" MCParticleImpl* lcio_particle_set_time
subroutine lcio_particle_set_time (prt_obj, t) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
real(c_double), value :: t
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_particle_set_time
! extern "C" MCParticleImpl* lcio_particle_set_vertex
! (MCParticleImpl* mcp, const double vx, const double vy, const double vz)
subroutine lcio_particle_set_vertex (prt_obj, vx, vy, vz) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
real(c_double), value :: vx, vy, vz
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_particle_set_vertex
! extern "C" double lcio_polarization_degree ( MCParticleImpl* mcp)
real(c_double) function lcio_polarization_degree (prt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_polarization_degree = 0._c_double
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_polarization_degree
! extern "C" double lcio_polarization_theta ( MCParticleImpl* mcp)
real(c_double) function lcio_polarization_theta (prt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_polarization_theta = 0._c_double
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_polarization_theta
! extern "C" double lcio_polarization_phi ( MCParticleImpl* mcp)
real(c_double) function lcio_polarization_phi (prt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_polarization_phi = 0._c_double
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_polarization_phi
! extern "C" const int* lcio_particle_flow
integer(c_int) function lcio_particle_flow (evt_obj, col_index) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
integer(c_int) :: col_index
lcio_particle_flow = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_particle_flow
! extern "C" int lcio_particle_get_generator_status ( MCParticleImpl* mcp)
integer(c_int) function lcio_particle_get_generator_status (prt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_particle_get_generator_status = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_particle_get_generator_status
! extern "C" int lcio_particle_get_pdg_code ( MCParticleImpl* mcp)
integer(c_int) function lcio_particle_get_pdg_code (prt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_particle_get_pdg_code = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_particle_get_pdg_code
! extern "C" double lcio_three_momentum ( MCParticleImpl* mcp, int p_index ) {
real(c_double) function lcio_three_momentum (prt_obj, p_index) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
integer(c_int), value :: p_index
lcio_three_momentum = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_three_momentum
! extern "C" double lcio_energy ( MCParticleImpl* mcp) {
real(c_double) function lcio_energy (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_energy = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_energy
! extern "C" double lcio_mass ( MCParticleImpl* mcp) {
real(c_double) function lcio_mass (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_mass = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_mass
! extern "C" int lcio_n_parents ( MCParticleImpl* mcp)
integer(c_int) function lcio_n_parents (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_n_parents = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_n_parents
! extern "C" int lcio_n_daughters ( MCParticleImpl* mcp)
integer(c_int) function lcio_n_daughters (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_n_daughters = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_n_daughters
! extern "C" double lcio_vtx_x (MCParticleImpl* mcp)
real(c_double) function lcio_vtx_x (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_vtx_x = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_vtx_x
! extern "C" double lcio_vtx_y (MCParticleImpl* mcp)
real(c_double) function lcio_vtx_y (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_vtx_y = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_vtx_y
! extern "C" double lcio_vtx_z (MCParticleImpl* mcp)
real(c_double) function lcio_vtx_z (prt_obj) bind (C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_vtx_z = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_vtx_z
! extern "C" double lcio_prt_time (MCParticleImpl* mcp) {
real(c_float) function lcio_prt_time (prt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: prt_obj
lcio_prt_time = 0
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_prt_time
! extern "C" int lcio_event_daughter_k ( LCEventImpl* evt, int num_part, int k_daughter)
integer(c_int) function lcio_event_daughter_k &
(evt_obj, num_part, k_daughter) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
integer(c_int), value :: num_part, k_daughter
lcio_event_daughter_k = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_daughter_k
! extern "C" int lcio_event_parent_k ( LCEventImpl* evt, int num_part, int k_parent)
integer(c_int) function lcio_event_parent_k &
(evt_obj, num_part, k_parent) bind(C)
use iso_c_binding
type(c_ptr), value :: evt_obj
integer(c_int), value :: num_part, k_parent
lcio_event_parent_k = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_event_parent_k
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! LCWriter functions
! extern "C" LCWriter* open_lcio_writer_new
type (c_ptr) function open_lcio_writer_new (filename, complevel) bind(C)
use iso_c_binding
character(c_char), dimension(*), intent(in) :: filename
integer(c_int), value :: complevel
open_lcio_writer_new = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function open_lcio_writer_new
! extern "C" LCWriter* lcio_writer_delete
subroutine lcio_writer_delete (io_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_writer_delete
! extern "C" LCWriter* lcio_write_event
subroutine lcio_write_event (io_obj, evt_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj, evt_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_write_event
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! LCReader functions
! extern "C" LCReader* open_lcio_reader ()
type(c_ptr) function open_lcio_reader (filename) bind(C)
use iso_c_binding
character(c_char), dimension(*), intent(in) :: filename
open_lcio_reader = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function open_lcio_reader
! extern "C" LCReader* open_lcio_reader ()
type(c_ptr) function open_lcio_reader_direct_access (filename) bind(C)
use iso_c_binding
character(c_char), dimension(*), intent(in) :: filename
open_lcio_reader_direct_access = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function open_lcio_reader_direct_access
! extern "C" void lcio_get_n_runs ( LCReader* lcRdr )
integer(c_int) function lcio_get_n_runs (io_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj
lcio_get_n_runs = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_get_n_runs
! extern "C" void lcio_get_n_events ( LCReader* lcRdr )
integer(c_int) function lcio_get_n_events (io_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj
lcio_get_n_events = 0_c_int
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function lcio_get_n_events
! extern "C" void lcio_reader_delete ( LCReader* lcRdr )
subroutine lcio_reader_delete (io_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: io_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine lcio_reader_delete
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! LCRunHeader functions
! extern "C" LCRunHeaderImpl* new_lcio_run_header( int run_id ) {
type(c_ptr) function new_lcio_run_header (run_id) bind(C)
use iso_c_binding
integer(c_int), value :: run_id
new_lcio_run_header = c_null_ptr
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end function new_lcio_run_header
! extern "C" void run_header_set_simstring (LCRunHeaderImpl* runHdr, char* simstring)
subroutine run_header_set_simstring (runhdr_obj, simstring) bind(C)
use iso_c_binding
type(c_ptr), value :: runhdr_obj
character(c_char), dimension(*), intent(in) :: simstring
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine run_header_set_simstring
! extern "C" void dump_run_header ( LCRunHeaderImpl* runHdr )
subroutine dump_run_header (runhdr_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: runhdr_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine dump_run_header
! extern "C" void write_run_header (LCWriter* lcWrt, const LCRunHeaderImpl* runHdr)
subroutine write_run_header (lcwrt_obj, runhdr_obj) bind(C)
use iso_c_binding
type(c_ptr), value :: lcwrt_obj, runhdr_obj
write (0, "(A)") "***********************************************************"
write (0, "(A)") "*** LCIO: Error: library not linked, WHIZARD terminates ***"
write (0, "(A)") "***********************************************************"
stop
end subroutine write_run_header
Index: trunk/src/events/events.nw
===================================================================
--- trunk/src/events/events.nw (revision 8336)
+++ trunk/src/events/events.nw (revision 8337)
@@ -1,16883 +1,16902 @@
%% -*- ess-noweb-default-code-mode: f90-mode; noweb-default-code-mode: f90-mode; -*-
% WHIZARD code as NOWEB source: event handling objects
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Generic Event Handling}
\includemodulegraph{events}
Event records allow the MC to communicate with the outside world. The
event record should exhibit the observable contents of a physical
event. We should be able to read and write events. The actual
implementation of the event need not be defined yet, for that purpose.
We have the following basic modules:
\begin{description}
\item[event\_base]
Abstract base type for event records. The base type contains a
reference to a [[particle_set_t]] object as the event core, and it
holds some data that we should always expect, such as the squared
matrix element and event weight.
\item[eio\_data]
Transparent container for the metadata of an event sample.
\item[eio\_base]
Abstract base type for event-record input and output. The
implementations of this base type represent specific event I/O
formats.
\end{description}
These are the implementation modules:
\begin{description}
\item[eio\_checkpoints]
Auxiliary output format. The only purpose is to provide screen
diagnostics during event output.
\item[eio\_callback]
Auxiliary output format. The only purpose is to execute a callback
procedure, so we have a hook for external access during event output.
\item[eio\_weights]
Print some event summary data, no details. The main use if for
testing purposes.
\item[eio\_dump]
Dump the contents of WHIZARD's [[particle_set]] internal record,
using the [[write]] method of that record as-is. The main use if for
testing purposes.
\item[hep\_common]
Implements traditional HEP common blocks that are (still) used by
some of the event I/O formats below.
\item[hepmc\_interface]
Access particle objects of the HepMC package. Functional only if this
package is linked. The interface is working both for HepMC2 and HepMC3.
\item[lcio\_interface]
Access objects of the LCIO package. Functional only if this
package is linked.
\item[hep\_events]
Interface between the event record and the common blocks.
\item[eio\_ascii]
Collection of event output formats that write ASCII files.
\item[eio\_lhef]
LHEF for input and output.
\item[eio\_stdhep]
Support for the StdHEP format (binary, machine-independent).
\item[eio\_hepmc]
Support for the HepMC format (C++).
\item[eio\_lcio]
Support for the LCIO format (C++).
\end{description}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Generic Event Handling}
We introduce events first in form of an abstract type, together with
some utilities. Abstract events can be used by other modules, in
particular event I/O, without introducing an explicit dependency on
the event implementation.
<<[[event_base.f90]]>>=
<<File header>>
module event_base
<<Use kinds>>
use kinds, only: i64
<<Use strings>>
use io_units
use string_utils, only: lower_case
use diagnostics
use model_data
use particles
<<Standard module head>>
<<Event base: public>>
<<Event base: parameters>>
<<Event base: types>>
<<Event base: interfaces>>
contains
<<Event base: procedures>>
end module event_base
@ %def event_base
@
\subsection{generic event type}
<<Event base: public>>=
public :: generic_event_t
<<Event base: types>>=
type, abstract :: generic_event_t
!private
logical :: particle_set_is_valid = .false.
type(particle_set_t), pointer :: particle_set => null ()
logical :: sqme_ref_known = .false.
real(default) :: sqme_ref = 0
logical :: sqme_prc_known = .false.
real(default) :: sqme_prc = 0
logical :: weight_ref_known = .false.
real(default) :: weight_ref = 0
logical :: weight_prc_known = .false.
real(default) :: weight_prc = 0
logical :: excess_prc_known = .false.
real(default) :: excess_prc = 0
logical :: n_dropped_known = .false.
integer :: n_dropped = 0
integer :: n_alt = 0
logical :: sqme_alt_known = .false.
real(default), dimension(:), allocatable :: sqme_alt
logical :: weight_alt_known = .false.
real(default), dimension(:), allocatable :: weight_alt
contains
<<Event base: generic event: TBP>>
end type generic_event_t
@ %def generic_event_t
@
\subsection{Initialization}
This determines the number of alternate weights and sqme values.
<<Event base: generic event: TBP>>=
procedure :: base_init => generic_event_init
<<Event base: procedures>>=
subroutine generic_event_init (event, n_alt)
class(generic_event_t), intent(out) :: event
integer, intent(in) :: n_alt
event%n_alt = n_alt
allocate (event%sqme_alt (n_alt))
allocate (event%weight_alt (n_alt))
end subroutine generic_event_init
@ %def generic_event_init
@
\subsection{Access particle set}
The particle set is the core of the event. We allow access to it via
a pointer, and we maintain the information whether the particle set
is valid, i.e., has been filled with meaningful data.
<<Event base: generic event: TBP>>=
procedure :: has_valid_particle_set => generic_event_has_valid_particle_set
procedure :: accept_particle_set => generic_event_accept_particle_set
procedure :: discard_particle_set => generic_event_discard_particle_set
<<Event base: procedures>>=
function generic_event_has_valid_particle_set (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%particle_set_is_valid
end function generic_event_has_valid_particle_set
subroutine generic_event_accept_particle_set (event)
class(generic_event_t), intent(inout) :: event
event%particle_set_is_valid = .true.
end subroutine generic_event_accept_particle_set
subroutine generic_event_discard_particle_set (event)
class(generic_event_t), intent(inout) :: event
event%particle_set_is_valid = .false.
end subroutine generic_event_discard_particle_set
@ %def generic_event_has_valid_particle_set
@ %def generic_event_accept_particle_set
@ %def generic_event_discard_particle_set
@
These procedures deal with the particle set directly. Return the pointer:
<<Event base: generic event: TBP>>=
procedure :: get_particle_set_ptr => generic_event_get_particle_set_ptr
<<Event base: procedures>>=
function generic_event_get_particle_set_ptr (event) result (ptr)
class(generic_event_t), intent(in) :: event
type(particle_set_t), pointer :: ptr
ptr => event%particle_set
end function generic_event_get_particle_set_ptr
@ %def generic_event_get_particle_set_ptr
@
Let it point to some existing particle set:
<<Event base: generic event: TBP>>=
procedure :: link_particle_set => generic_event_link_particle_set
<<Event base: procedures>>=
subroutine generic_event_link_particle_set (event, particle_set)
class(generic_event_t), intent(inout) :: event
type(particle_set_t), intent(in), target :: particle_set
event%particle_set => particle_set
call event%accept_particle_set ()
end subroutine generic_event_link_particle_set
@ %def generic_event_link_particle_set
@
\subsection{Access sqme and weight}
There are several incarnations: the current value, a reference value,
alternate values.
<<Event base: generic event: TBP>>=
procedure :: sqme_prc_is_known => generic_event_sqme_prc_is_known
procedure :: sqme_ref_is_known => generic_event_sqme_ref_is_known
procedure :: sqme_alt_is_known => generic_event_sqme_alt_is_known
procedure :: weight_prc_is_known => generic_event_weight_prc_is_known
procedure :: weight_ref_is_known => generic_event_weight_ref_is_known
procedure :: weight_alt_is_known => generic_event_weight_alt_is_known
procedure :: excess_prc_is_known => generic_event_excess_prc_is_known
<<Event base: procedures>>=
function generic_event_sqme_prc_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%sqme_prc_known
end function generic_event_sqme_prc_is_known
function generic_event_sqme_ref_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%sqme_ref_known
end function generic_event_sqme_ref_is_known
function generic_event_sqme_alt_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%sqme_alt_known
end function generic_event_sqme_alt_is_known
function generic_event_weight_prc_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%weight_prc_known
end function generic_event_weight_prc_is_known
function generic_event_weight_ref_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%weight_ref_known
end function generic_event_weight_ref_is_known
function generic_event_weight_alt_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%weight_alt_known
end function generic_event_weight_alt_is_known
function generic_event_excess_prc_is_known (event) result (flag)
class(generic_event_t), intent(in) :: event
logical :: flag
flag = event%excess_prc_known
end function generic_event_excess_prc_is_known
@ %def generic_event_sqme_prc_is_known
@ %def generic_event_sqme_ref_is_known
@ %def generic_event_sqme_alt_is_known
@ %def generic_event_weight_prc_is_known
@ %def generic_event_weight_ref_is_known
@ %def generic_event_weight_alt_is_known
@ %def generic_event_excess_prc_is_known
@
<<Event base: generic event: TBP>>=
procedure :: get_n_alt => generic_event_get_n_alt
<<Event base: procedures>>=
function generic_event_get_n_alt (event) result (n)
class(generic_event_t), intent(in) :: event
integer :: n
n = event%n_alt
end function generic_event_get_n_alt
@ %def generic_event_get_n_alt
@
<<Event base: generic event: TBP>>=
procedure :: get_sqme_prc => generic_event_get_sqme_prc
procedure :: get_sqme_ref => generic_event_get_sqme_ref
generic :: get_sqme_alt => &
generic_event_get_sqme_alt_0, generic_event_get_sqme_alt_1
procedure :: generic_event_get_sqme_alt_0
procedure :: generic_event_get_sqme_alt_1
procedure :: get_weight_prc => generic_event_get_weight_prc
procedure :: get_weight_ref => generic_event_get_weight_ref
generic :: get_weight_alt => &
generic_event_get_weight_alt_0, generic_event_get_weight_alt_1
procedure :: generic_event_get_weight_alt_0
procedure :: generic_event_get_weight_alt_1
procedure :: get_n_dropped => generic_event_get_n_dropped
procedure :: get_excess_prc => generic_event_get_excess_prc
<<Event base: procedures>>=
function generic_event_get_sqme_prc (event) result (sqme)
class(generic_event_t), intent(in) :: event
real(default) :: sqme
if (event%sqme_prc_known) then
sqme = event%sqme_prc
else
sqme = 0
end if
end function generic_event_get_sqme_prc
function generic_event_get_sqme_ref (event) result (sqme)
class(generic_event_t), intent(in) :: event
real(default) :: sqme
if (event%sqme_ref_known) then
sqme = event%sqme_ref
else
sqme = 0
end if
end function generic_event_get_sqme_ref
function generic_event_get_sqme_alt_0 (event, i) result (sqme)
class(generic_event_t), intent(in) :: event
integer, intent(in) :: i
real(default) :: sqme
if (event%sqme_alt_known) then
sqme = event%sqme_alt(i)
else
sqme = 0
end if
end function generic_event_get_sqme_alt_0
function generic_event_get_sqme_alt_1 (event) result (sqme)
class(generic_event_t), intent(in) :: event
real(default), dimension(event%n_alt) :: sqme
sqme = event%sqme_alt
end function generic_event_get_sqme_alt_1
function generic_event_get_weight_prc (event) result (weight)
class(generic_event_t), intent(in) :: event
real(default) :: weight
if (event%weight_prc_known) then
weight = event%weight_prc
else
weight = 0
end if
end function generic_event_get_weight_prc
function generic_event_get_weight_ref (event) result (weight)
class(generic_event_t), intent(in) :: event
real(default) :: weight
if (event%weight_ref_known) then
weight = event%weight_ref
else
weight = 0
end if
end function generic_event_get_weight_ref
function generic_event_get_weight_alt_0 (event, i) result (weight)
class(generic_event_t), intent(in) :: event
integer, intent(in) :: i
real(default) :: weight
if (event%weight_alt_known) then
weight = event%weight_alt(i)
else
weight = 0
end if
end function generic_event_get_weight_alt_0
function generic_event_get_weight_alt_1 (event) result (weight)
class(generic_event_t), intent(in) :: event
real(default), dimension(event%n_alt) :: weight
weight = event%weight_alt
end function generic_event_get_weight_alt_1
function generic_event_get_excess_prc (event) result (excess)
class(generic_event_t), intent(in) :: event
real(default) :: excess
if (event%excess_prc_known) then
excess = event%excess_prc
else
excess = 0
end if
end function generic_event_get_excess_prc
function generic_event_get_n_dropped (event) result (n_dropped)
class(generic_event_t), intent(in) :: event
integer :: n_dropped
if (event%n_dropped_known) then
n_dropped = event%n_dropped
else
n_dropped = 0
end if
end function generic_event_get_n_dropped
@ %def generic_event_get_sqme_prc
@ %def generic_event_get_sqme_ref
@ %def generic_event_get_sqme_alt
@ %def generic_event_get_weight_prc
@ %def generic_event_get_weight_ref
@ %def generic_event_get_weight_alt
@ %def generic_event_get_n_dropped
@ %def generic_event_get_excess_prc
@
<<Event base: generic event: TBP>>=
procedure :: set_sqme_prc => generic_event_set_sqme_prc
procedure :: set_sqme_ref => generic_event_set_sqme_ref
procedure :: set_sqme_alt => generic_event_set_sqme_alt
procedure :: set_weight_prc => generic_event_set_weight_prc
procedure :: set_weight_ref => generic_event_set_weight_ref
procedure :: set_weight_alt => generic_event_set_weight_alt
procedure :: set_excess_prc => generic_event_set_excess_prc
procedure :: set_n_dropped => generic_event_set_n_dropped
<<Event base: procedures>>=
subroutine generic_event_set_sqme_prc (event, sqme)
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: sqme
event%sqme_prc = sqme
event%sqme_prc_known = .true.
end subroutine generic_event_set_sqme_prc
subroutine generic_event_set_sqme_ref (event, sqme)
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: sqme
event%sqme_ref = sqme
event%sqme_ref_known = .true.
end subroutine generic_event_set_sqme_ref
subroutine generic_event_set_sqme_alt (event, sqme)
class(generic_event_t), intent(inout) :: event
real(default), dimension(:), intent(in) :: sqme
event%sqme_alt = sqme
event%sqme_alt_known = .true.
end subroutine generic_event_set_sqme_alt
subroutine generic_event_set_weight_prc (event, weight)
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: weight
event%weight_prc = weight
event%weight_prc_known = .true.
end subroutine generic_event_set_weight_prc
subroutine generic_event_set_weight_ref (event, weight)
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: weight
event%weight_ref = weight
event%weight_ref_known = .true.
end subroutine generic_event_set_weight_ref
subroutine generic_event_set_weight_alt (event, weight)
class(generic_event_t), intent(inout) :: event
real(default), dimension(:), intent(in) :: weight
event%weight_alt = weight
event%weight_alt_known = .true.
end subroutine generic_event_set_weight_alt
subroutine generic_event_set_excess_prc (event, excess)
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: excess
event%excess_prc = excess
event%excess_prc_known = .true.
end subroutine generic_event_set_excess_prc
subroutine generic_event_set_n_dropped (event, n_dropped)
class(generic_event_t), intent(inout) :: event
integer, intent(in) :: n_dropped
event%n_dropped = n_dropped
event%n_dropped_known = .true.
end subroutine generic_event_set_n_dropped
@ %def generic_event_set_sqme_prc
@ %def generic_event_set_sqme_ref
@ %def generic_event_set_sqme_alt
@ %def generic_event_set_weight_prc
@ %def generic_event_set_weight_ref
@ %def generic_event_set_weight_alt
@ %def generic_event_set_n_dropped
@
Set the appropriate entry directly.
<<Event base: generic event: TBP>>=
procedure :: set => generic_event_set
<<Event base: procedures>>=
subroutine generic_event_set (event, &
weight_ref, weight_prc, weight_alt, &
excess_prc, n_dropped, &
sqme_ref, sqme_prc, sqme_alt)
class(generic_event_t), intent(inout) :: event
real(default), intent(in), optional :: weight_ref, weight_prc
real(default), intent(in), optional :: sqme_ref, sqme_prc
real(default), dimension(:), intent(in), optional :: sqme_alt, weight_alt
real(default), intent(in), optional :: excess_prc
integer, intent(in), optional :: n_dropped
if (present (sqme_prc)) then
call event%set_sqme_prc (sqme_prc)
end if
if (present (sqme_ref)) then
call event%set_sqme_ref (sqme_ref)
end if
if (present (sqme_alt)) then
call event%set_sqme_alt (sqme_alt)
end if
if (present (weight_prc)) then
call event%set_weight_prc (weight_prc)
end if
if (present (weight_ref)) then
call event%set_weight_ref (weight_ref)
end if
if (present (weight_alt)) then
call event%set_weight_alt (weight_alt)
end if
if (present (excess_prc)) then
call event%set_excess_prc (excess_prc)
end if
if (present (n_dropped)) then
call event%set_n_dropped (n_dropped)
end if
end subroutine generic_event_set
@ %def generic_event_set
@
\subsection{Pure Virtual Methods}
These procedures can only implemented in the concrete implementation.
Output (verbose, depending on parameters).
<<Event base: generic event: TBP>>=
procedure (generic_event_write), deferred :: write
<<Event base: interfaces>>=
abstract interface
subroutine generic_event_write (object, unit, &
show_process, show_transforms, &
show_decay, verbose, testflag)
import
class(generic_event_t), intent(in) :: object
integer, intent(in), optional :: unit
logical, intent(in), optional :: show_process
logical, intent(in), optional :: show_transforms
logical, intent(in), optional :: show_decay
logical, intent(in), optional :: verbose
logical, intent(in), optional :: testflag
end subroutine generic_event_write
end interface
@ %def generic_event_write
@
Generate an event, based on a selector index [[i_mci]], and optionally on an
extra set of random numbers [[r]]. For the main bunch of random numbers that
the generator needs, the event object should contain its own generator.
<<Event base: generic event: TBP>>=
procedure (generic_event_generate), deferred :: generate
<<Event base: interfaces>>=
abstract interface
subroutine generic_event_generate (event, i_mci, r, i_nlo)
import
class(generic_event_t), intent(inout) :: event
integer, intent(in) :: i_mci
real(default), dimension(:), intent(in), optional :: r
integer, intent(in), optional :: i_nlo
end subroutine generic_event_generate
end interface
@ %def event_generate
@
Alternative : inject a particle set that is supposed to represent the hard
process.
How this determines the event, is dependent on the event structure,
therefore this is a deferred method.
<<Event base: generic event: TBP>>=
procedure (generic_event_set_hard_particle_set), deferred :: &
set_hard_particle_set
<<Event base: interfaces>>=
abstract interface
subroutine generic_event_set_hard_particle_set (event, particle_set)
import
class(generic_event_t), intent(inout) :: event
type(particle_set_t), intent(in) :: particle_set
end subroutine generic_event_set_hard_particle_set
end interface
@ %def generic_event_set_hard_particle_set
@ Event index handlers.
<<Event base: generic event: TBP>>=
procedure (generic_event_set_index), deferred :: set_index
procedure (generic_event_handler), deferred :: reset_index
procedure (generic_event_increment_index), deferred :: increment_index
@
<<Event base: interfaces>>=
abstract interface
subroutine generic_event_set_index (event, index)
import
class(generic_event_t), intent(inout) :: event
integer, intent(in) :: index
end subroutine generic_event_set_index
end interface
abstract interface
subroutine generic_event_handler (event)
import
class(generic_event_t), intent(inout) :: event
end subroutine generic_event_handler
end interface
abstract interface
subroutine generic_event_increment_index (event, offset)
import
class(generic_event_t), intent(inout) :: event
integer, intent(in), optional :: offset
end subroutine generic_event_increment_index
end interface
@ %def generic_event_set_index
@ %def generic_event_increment_index
@ %def generic_event_handler
@ Evaluate any expressions associated with the event. No argument needed.
<<Event base: generic event: TBP>>=
procedure (generic_event_handler), deferred :: evaluate_expressions
@
Select internal parameters
<<Event base: generic event: TBP>>=
procedure (generic_event_select), deferred :: select
<<Event base: interfaces>>=
abstract interface
subroutine generic_event_select (event, i_mci, i_term, channel)
import
class(generic_event_t), intent(inout) :: event
integer, intent(in) :: i_mci, i_term, channel
end subroutine generic_event_select
end interface
@ %def generic_event_select
@ Return a pointer to the model for the currently active process.
<<Event base: generic event: TBP>>=
procedure (generic_event_get_model_ptr), deferred :: get_model_ptr
<<Event base: interfaces>>=
abstract interface
function generic_event_get_model_ptr (event) result (model)
import
class(generic_event_t), intent(in) :: event
class(model_data_t), pointer :: model
end function generic_event_get_model_ptr
end interface
@ %def generic_event_get_model_ptr
@ Return data used by external event formats.
<<Event base: generic event: TBP>>=
procedure (generic_event_has_index), deferred :: has_index
procedure (generic_event_get_index), deferred :: get_index
procedure (generic_event_get_fac_scale), deferred :: get_fac_scale
procedure (generic_event_get_alpha_s), deferred :: get_alpha_s
procedure (generic_event_get_sqrts), deferred :: get_sqrts
procedure (generic_event_get_polarization), deferred :: get_polarization
procedure (generic_event_get_beam_file), deferred :: get_beam_file
procedure (generic_event_get_process_name), deferred :: &
get_process_name
<<Event base: interfaces>>=
abstract interface
function generic_event_has_index (event) result (flag)
import
class(generic_event_t), intent(in) :: event
logical :: flag
end function generic_event_has_index
end interface
abstract interface
function generic_event_get_index (event) result (index)
import
class(generic_event_t), intent(in) :: event
integer :: index
end function generic_event_get_index
end interface
abstract interface
function generic_event_get_fac_scale (event) result (fac_scale)
import
class(generic_event_t), intent(in) :: event
real(default) :: fac_scale
end function generic_event_get_fac_scale
end interface
abstract interface
function generic_event_get_alpha_s (event) result (alpha_s)
import
class(generic_event_t), intent(in) :: event
real(default) :: alpha_s
end function generic_event_get_alpha_s
end interface
abstract interface
function generic_event_get_sqrts (event) result (sqrts)
import
class(generic_event_t), intent(in) :: event
real(default) :: sqrts
end function generic_event_get_sqrts
end interface
abstract interface
function generic_event_get_polarization (event) result (pol)
import
class(generic_event_t), intent(in) :: event
real(default), dimension(2) :: pol
end function generic_event_get_polarization
end interface
abstract interface
function generic_event_get_beam_file (event) result (file)
import
class(generic_event_t), intent(in) :: event
type(string_t) :: file
end function generic_event_get_beam_file
end interface
abstract interface
function generic_event_get_process_name (event) result (name)
import
class(generic_event_t), intent(in) :: event
type(string_t) :: name
end function generic_event_get_process_name
end interface
@ %def generic_event_get_index
@ %def generic_event_get_fac_scale
@ %def generic_event_get_alpha_s
@ %def generic_event_get_sqrts
@ %def generic_event_get_polarization
@ %def generic_event_get_beam_file
@ %def generic_event_get_process_name
@ Set data used by external event formats.
<<Event base: generic event: TBP>>=
procedure (generic_event_set_alpha_qcd_forced), deferred :: &
set_alpha_qcd_forced
procedure (generic_event_set_scale_forced), deferred :: &
set_scale_forced
<<Event base: interfaces>>=
abstract interface
subroutine generic_event_set_alpha_qcd_forced (event, alpha_qcd)
import
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: alpha_qcd
end subroutine generic_event_set_alpha_qcd_forced
end interface
abstract interface
subroutine generic_event_set_scale_forced (event, scale)
import
class(generic_event_t), intent(inout) :: event
real(default), intent(in) :: scale
end subroutine generic_event_set_scale_forced
end interface
@ %def generic_event_set_alpha_qcd_forced
@ %def generic_event_set_scale_forced
@
\subsection{Utilities}
Applying this, current event contents are marked as incomplete but
are not deleted. In particular, the initialization is kept.
<<Event base: generic event: TBP>>=
procedure :: reset_contents => generic_event_reset_contents
procedure :: base_reset_contents => generic_event_reset_contents
<<Event base: procedures>>=
subroutine generic_event_reset_contents (event)
class(generic_event_t), intent(inout) :: event
call event%discard_particle_set ()
event%sqme_ref_known = .false.
event%sqme_prc_known = .false.
event%sqme_alt_known = .false.
event%weight_ref_known = .false.
event%weight_prc_known = .false.
event%weight_alt_known = .false.
event%excess_prc_known = .false.
end subroutine generic_event_reset_contents
@ %def generic_event_reset_contents
@ Pacify particle set.
<<Event base: generic event: TBP>>=
procedure :: pacify_particle_set => generic_event_pacify_particle_set
<<Event base: procedures>>=
subroutine generic_event_pacify_particle_set (event)
class(generic_event_t), intent(inout) :: event
if (event%has_valid_particle_set ()) call pacify (event%particle_set)
end subroutine generic_event_pacify_particle_set
@ %def generic_event_pacify_particle_set
@
\subsection{Event normalization}
The parameters for event normalization. For unweighted events,
[[NORM_UNIT]] is intended as default, while for weighted events, it is
[[NORM_SIGMA]].
Note: the unit test for this is in [[eio_data_2]] below.
<<Event base: parameters>>=
integer, parameter, public :: NORM_UNDEFINED = 0
integer, parameter, public :: NORM_UNIT = 1
integer, parameter, public :: NORM_N_EVT = 2
integer, parameter, public :: NORM_SIGMA = 3
integer, parameter, public :: NORM_S_N = 4
@ %def NORM_UNDEFINED NORM_UNIT NORM_N_EVT NORM_SIGMA NORM_S_N
@ These functions translate between the user representation and the
internal one.
<<Event base: public>>=
public :: event_normalization_mode
public :: event_normalization_string
<<Event base: procedures>>=
function event_normalization_mode (string, unweighted) result (mode)
integer :: mode
type(string_t), intent(in) :: string
logical, intent(in) :: unweighted
select case (lower_case (char (string)))
case ("auto")
if (unweighted) then
mode = NORM_UNIT
else
mode = NORM_SIGMA
end if
case ("1")
mode = NORM_UNIT
case ("1/n")
mode = NORM_N_EVT
case ("sigma")
mode = NORM_SIGMA
case ("sigma/n")
mode = NORM_S_N
case default
call msg_fatal ("Event normalization: unknown value '" &
// char (string) // "'")
end select
end function event_normalization_mode
function event_normalization_string (norm_mode) result (string)
integer, intent(in) :: norm_mode
type(string_t) :: string
select case (norm_mode)
case (NORM_UNDEFINED); string = "[undefined]"
case (NORM_UNIT); string = "'1'"
case (NORM_N_EVT); string = "'1/n'"
case (NORM_SIGMA); string = "'sigma'"
case (NORM_S_N); string = "'sigma/n'"
case default; string = "???"
end select
end function event_normalization_string
@ %def event_normalization_mode
@ %def event_normalization_string
@ We place this here as a generic helper, so we can update event
weights whenever we need, not just in connection with an event sample
data object.
<<Event base: public>>=
public :: event_normalization_update
<<Event base: procedures>>=
subroutine event_normalization_update (weight, sigma, n, mode_new, mode_old)
real(default), intent(inout) :: weight
real(default), intent(in) :: sigma
integer, intent(in) :: n
integer, intent(in) :: mode_new, mode_old
if (mode_new /= mode_old) then
if (sigma > 0 .and. n > 0) then
weight = weight / factor (mode_old) * factor (mode_new)
else
call msg_fatal ("Event normalization update: null sample")
end if
end if
contains
function factor (mode)
real(default) :: factor
integer, intent(in) :: mode
select case (mode)
case (NORM_UNIT); factor = 1._default
case (NORM_N_EVT); factor = 1._default / n
case (NORM_SIGMA); factor = sigma
case (NORM_S_N); factor = sigma / n
case default
call msg_fatal ("Event normalization update: undefined mode")
end select
end function factor
end subroutine event_normalization_update
@ %def event_normalization_update
@
\subsection{Callback container}
This derived type contains a callback procedure that can
be executed during event I/O. The callback procedure is given the
event object (with class [[generic_event]]) and an event index.
This is a simple wrapper. The object is abstract, so the the actual
procedure is introduced by overriding the deferred one. We use the
PASS attribute, so we may supplement runtime data in the callback object
if desired.
<<Event base: public>>=
public :: event_callback_t
<<Event base: types>>=
type, abstract :: event_callback_t
private
contains
procedure(event_callback_write), deferred :: write
procedure(event_callback_proc), deferred :: proc
end type event_callback_t
@ %def event_callback_t
@ Identify the callback procedure in output
<<Event base: interfaces>>=
abstract interface
subroutine event_callback_write (event_callback, unit)
import
class(event_callback_t), intent(in) :: event_callback
integer, intent(in), optional :: unit
end subroutine event_callback_write
end interface
@ %def event_callback_write
@ This is the procedure interface.
<<Event base: interfaces>>=
abstract interface
subroutine event_callback_proc (event_callback, i, event)
import
class(event_callback_t), intent(in) :: event_callback
integer(i64), intent(in) :: i
class(generic_event_t), intent(in) :: event
end subroutine event_callback_proc
end interface
@ %def event_callback_proc
@ A dummy implementation for testing and fallback.
<<Event base: public>>=
public :: event_callback_nop_t
<<Event base: types>>=
type, extends (event_callback_t) :: event_callback_nop_t
private
contains
procedure :: write => event_callback_nop_write
procedure :: proc => event_callback_nop
end type event_callback_nop_t
@ %def event_callback_t
<<Event base: procedures>>=
subroutine event_callback_nop_write (event_callback, unit)
class(event_callback_nop_t), intent(in) :: event_callback
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
write (u, "(1x,A)") "NOP"
end subroutine event_callback_nop_write
subroutine event_callback_nop (event_callback, i, event)
class(event_callback_nop_t), intent(in) :: event_callback
integer(i64), intent(in) :: i
class(generic_event_t), intent(in) :: event
end subroutine event_callback_nop
@ %def event_callback_nop_write
@ %def event_callback_nop
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Event Sample Data}
We define a simple and transparent container for (meta)data that are
associated with an event sample.
<<[[eio_data.f90]]>>=
<<File header>>
module eio_data
<<Use kinds>>
<<Use strings>>
use io_units
use numeric_utils
use diagnostics
use event_base
<<Standard module head>>
<<EIO data: public>>
<<EIO data: types>>
contains
<<EIO data: procedures>>
end module eio_data
@ %def eio_data
@
\subsection{Event Sample Data}
These are data that apply to an event sample as a whole. They are
given in an easily portable form (no fancy structure) and are used for
initializing event formats.
There are two MD5 sums here. [[md5sum_proc]] depends only on the
definition of the contributing processes. A sample with matching
checksum can be rescanned with modified model parameters, beam
structure etc, to recalculate observables. [[md5sum_config]] includes
all relevant data. Rescanning a sample with matching checksum will
produce identical observables. (A third checksum might be added which
depends on the event sample itself. This is not needed, so far.)
If alternate weights are part of the event sample ([[n_alt]] nonzero),
there is a configuration MD5 sum for each of them.
<<EIO data: public>>=
public :: event_sample_data_t
<<EIO data: types>>=
type :: event_sample_data_t
character(32) :: md5sum_prc = ""
character(32) :: md5sum_cfg = ""
logical :: unweighted = .true.
logical :: negative_weights = .false.
integer :: norm_mode = NORM_UNDEFINED
integer :: n_beam = 0
integer, dimension(2) :: pdg_beam = 0
real(default), dimension(2) :: energy_beam = 0
integer :: n_proc = 0
integer :: n_evt = 0
integer :: nlo_multiplier = 1
integer :: split_n_evt = 0
integer :: split_n_kbytes = 0
integer :: split_index = 0
real(default) :: total_cross_section = 0
integer, dimension(:), allocatable :: proc_num_id
integer :: n_alt = 0
character(32), dimension(:), allocatable :: md5sum_alt
real(default), dimension(:), allocatable :: cross_section
real(default), dimension(:), allocatable :: error
contains
<<EIO data: event sample data: TBP>>
end type event_sample_data_t
@ %def event_sample_data_t
@ Initialize: allocate for the number of processes
<<EIO data: event sample data: TBP>>=
procedure :: init => event_sample_data_init
<<EIO data: procedures>>=
subroutine event_sample_data_init (data, n_proc, n_alt)
class(event_sample_data_t), intent(out) :: data
integer, intent(in) :: n_proc
integer, intent(in), optional :: n_alt
data%n_proc = n_proc
allocate (data%proc_num_id (n_proc), source = 0)
allocate (data%cross_section (n_proc), source = 0._default)
allocate (data%error (n_proc), source = 0._default)
if (present (n_alt)) then
data%n_alt = n_alt
allocate (data%md5sum_alt (n_alt))
data%md5sum_alt = ""
end if
end subroutine event_sample_data_init
@ %def event_sample_data_init
@ Output.
<<EIO data: event sample data: TBP>>=
procedure :: write => event_sample_data_write
<<EIO data: procedures>>=
subroutine event_sample_data_write (data, unit)
class(event_sample_data_t), intent(in) :: data
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit)
write (u, "(1x,A)") "Event sample properties:"
write (u, "(3x,A,A,A)") "MD5 sum (proc) = '", data%md5sum_prc, "'"
write (u, "(3x,A,A,A)") "MD5 sum (config) = '", data%md5sum_cfg, "'"
write (u, "(3x,A,L1)") "unweighted = ", data%unweighted
write (u, "(3x,A,L1)") "negative weights = ", data%negative_weights
write (u, "(3x,A,A)") "normalization = ", &
char (event_normalization_string (data%norm_mode))
write (u, "(3x,A,I0)") "number of beams = ", data%n_beam
write (u, "(5x,A,2(1x,I19))") "PDG = ", &
data%pdg_beam(:data%n_beam)
write (u, "(5x,A,2(1x,ES19.12))") "Energy = ", &
data%energy_beam(:data%n_beam)
if (data%n_evt > 0) then
write (u, "(3x,A,I0)") "number of events = ", data%n_evt
end if
if (.not. vanishes (data%total_cross_section)) then
write (u, "(3x,A,ES19.12)") "total cross sec. = ", &
data%total_cross_section
end if
write (u, "(3x,A,I0)") "num of processes = ", data%n_proc
do i = 1, data%n_proc
write (u, "(3x,A,I0)") "Process #", data%proc_num_id (i)
select case (data%n_beam)
case (1)
write (u, "(5x,A,ES19.12)") "Width = ", data%cross_section(i)
case (2)
write (u, "(5x,A,ES19.12)") "CSec = ", data%cross_section(i)
end select
write (u, "(5x,A,ES19.12)") "Error = ", data%error(i)
end do
if (data%n_alt > 0) then
write (u, "(3x,A,I0)") "num of alt wgt = ", data%n_alt
do i = 1, data%n_alt
write (u, "(5x,A,A,A,1x,I0)") "MD5 sum (cfg) = '", &
data%md5sum_alt(i), "'", i
end do
end if
end subroutine event_sample_data_write
@ %def event_sample_data_write
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_data_ut.f90]]>>=
<<File header>>
module eio_data_ut
use unit_tests
use eio_data_uti
<<Standard module head>>
<<EIO data: public test>>
contains
<<EIO data: test driver>>
end module eio_data_ut
@ %def eio_data_ut
@
<<[[eio_data_uti.f90]]>>=
<<File header>>
module eio_data_uti
<<Use kinds>>
<<Use strings>>
use event_base
use eio_data
<<Standard module head>>
<<EIO data: test declarations>>
contains
<<EIO data: tests>>
end module eio_data_uti
@ %def eio_data_ut
@ API: driver for the unit tests below.
<<EIO data: public test>>=
public :: eio_data_test
<<EIO data: test driver>>=
subroutine eio_data_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO data: execute tests>>
end subroutine eio_data_test
@ %def eio_data_test
@
\subsubsection{Event Sample Data}
Print the contents of a sample data block.
<<EIO data: execute tests>>=
call test (eio_data_1, "eio_data_1", &
"event sample data", &
u, results)
<<EIO data: test declarations>>=
public :: eio_data_1
<<EIO data: tests>>=
subroutine eio_data_1 (u)
integer, intent(in) :: u
type(event_sample_data_t) :: data
write (u, "(A)") "* Test output: eio_data_1"
write (u, "(A)") "* Purpose: display event sample data"
write (u, "(A)")
write (u, "(A)") "* Decay process, one component"
write (u, "(A)")
call data%init (1, 1)
data%n_beam = 1
data%pdg_beam(1) = 25
data%energy_beam(1) = 125
data%norm_mode = NORM_UNIT
data%proc_num_id = [42]
data%cross_section = [1.23e-4_default]
data%error = 5e-6_default
data%md5sum_prc = "abcdefghijklmnopabcdefghijklmnop"
data%md5sum_cfg = "12345678901234561234567890123456"
data%md5sum_alt(1) = "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu"
call data%write (u)
write (u, "(A)")
write (u, "(A)") "* Scattering process, two components"
write (u, "(A)")
call data%init (2)
data%n_beam = 2
data%pdg_beam = [2212, -2212]
data%energy_beam = [8._default, 10._default]
data%norm_mode = NORM_SIGMA
data%proc_num_id = [12, 34]
data%cross_section = [100._default, 88._default]
data%error = [1._default, 0.1_default]
call data%write (u)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_data_1"
end subroutine eio_data_1
@ %def eio_data_1
@
\subsubsection{Event Normalization}
Check the functions for translating modes and updating weights.
<<EIO data: execute tests>>=
call test (eio_data_2, "eio_data_2", &
"event normalization", &
u, results)
<<EIO data: test declarations>>=
public :: eio_data_2
<<EIO data: tests>>=
subroutine eio_data_2 (u)
integer, intent(in) :: u
type(string_t) :: s
logical :: unweighted
real(default) :: w, w0, sigma
integer :: n
write (u, "(A)") "* Test output: eio_data_2"
write (u, "(A)") "* Purpose: handle event normalization"
write (u, "(A)")
write (u, "(A)") "* Normalization strings"
write (u, "(A)")
s = "auto"
unweighted = .true.
write (u, "(1x,A,1x,L1,1x,A)") char (s), unweighted, &
char (event_normalization_string &
(event_normalization_mode (s, unweighted)))
s = "AUTO"
unweighted = .false.
write (u, "(1x,A,1x,L1,1x,A)") char (s), unweighted, &
char (event_normalization_string &
(event_normalization_mode (s, unweighted)))
unweighted = .true.
s = "1"
write (u, "(2(1x,A))") char (s), char (event_normalization_string &
(event_normalization_mode (s, unweighted)))
s = "1/n"
write (u, "(2(1x,A))") char (s), char (event_normalization_string &
(event_normalization_mode (s, unweighted)))
s = "Sigma"
write (u, "(2(1x,A))") char (s), char (event_normalization_string &
(event_normalization_mode (s, unweighted)))
s = "sigma/N"
write (u, "(2(1x,A))") char (s), char (event_normalization_string &
(event_normalization_mode (s, unweighted)))
write (u, "(A)")
write (u, "(A)") "* Normalization update"
write (u, "(A)")
sigma = 5
n = 2
w0 = 1
w = w0
call event_normalization_update (w, sigma, n, NORM_UNIT, NORM_UNIT)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_N_EVT, NORM_UNIT)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_SIGMA, NORM_UNIT)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_S_N, NORM_UNIT)
write (u, "(2(F6.3))") w0, w
write (u, *)
w0 = 0.5
w = w0
call event_normalization_update (w, sigma, n, NORM_UNIT, NORM_N_EVT)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_N_EVT, NORM_N_EVT)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_SIGMA, NORM_N_EVT)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_S_N, NORM_N_EVT)
write (u, "(2(F6.3))") w0, w
write (u, *)
w0 = 5.0
w = w0
call event_normalization_update (w, sigma, n, NORM_UNIT, NORM_SIGMA)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_N_EVT, NORM_SIGMA)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_SIGMA, NORM_SIGMA)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_S_N, NORM_SIGMA)
write (u, "(2(F6.3))") w0, w
write (u, *)
w0 = 2.5
w = w0
call event_normalization_update (w, sigma, n, NORM_UNIT, NORM_S_N)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_N_EVT, NORM_S_N)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_SIGMA, NORM_S_N)
write (u, "(2(F6.3))") w0, w
w = w0
call event_normalization_update (w, sigma, n, NORM_S_N, NORM_S_N)
write (u, "(2(F6.3))") w0, w
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_data_2"
end subroutine eio_data_2
@ %def eio_data_2
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Abstract I/O Handler}
This module defines an abstract object for event I/O and the
associated methods.
There are [[output]] and [[input]] methods which
write or read a single event from/to the I/O stream, respectively.
The I/O stream itself may be a file, a common block, or an externally
linked structure, depending on the concrete implementation.
A [[write]] method prints the current content of the
implementation-dependent event record in human-readable form.
The [[init_in]]/[[init_out]] and [[final]] prepare
and finalize the I/O stream, respectively. There is also a
[[switch_inout]] method which turns an input stream into an output
stream where events can be appended.
Optionally, output files can be split in chunks of well-defined size. The
[[split_out]] method takes care of this.
<<[[eio_base.f90]]>>=
<<File header>>
module eio_base
use kinds, only: i64
<<Use strings>>
use io_units
use diagnostics
use model_data
use event_base
use eio_data
<<Standard module head>>
<<EIO base: public>>
<<EIO base: types>>
<<EIO base: interfaces>>
contains
<<EIO base: procedures>>
end module eio_base
@ %def eio_base
@
\subsection{Type}
We can assume that most implementations will need the file extension as a
fixed string and, if they support file splitting, the current file index.
The fallback model is useful for implementations that are able to read
unknown files which may contain hadrons etc., not in the current
hard-interaction model.
<<EIO base: public>>=
public :: eio_t
<<EIO base: types>>=
type, abstract :: eio_t
type(string_t) :: sample
type(string_t) :: extension
type(string_t) :: filename
logical :: has_file = .false.
logical :: split = .false.
integer :: split_n_evt = 0
integer :: split_n_kbytes = 0
integer :: split_index = 0
integer :: split_count = 0
class(model_data_t), pointer :: fallback_model => null ()
contains
<<EIO base: eio: TBP>>
end type eio_t
@ %def eio_t
@ Write to screen. If possible, this should display the contents of the
current event, i.e., the last one that was written or read.
<<EIO base: eio: TBP>>=
procedure (eio_write), deferred :: write
<<EIO base: interfaces>>=
abstract interface
subroutine eio_write (object, unit)
import
class(eio_t), intent(in) :: object
integer, intent(in), optional :: unit
end subroutine eio_write
end interface
@ %def eio_write
@ Finalize. This should write/read footer data and close input/output
channels.
<<EIO base: eio: TBP>>=
procedure (eio_final), deferred :: final
<<EIO base: interfaces>>=
abstract interface
subroutine eio_final (object)
import
class(eio_t), intent(inout) :: object
end subroutine eio_final
end interface
@ %def eio_final
@ Determine splitting parameters from the event sample data.
<<EIO base: eio: TBP>>=
procedure :: set_splitting => eio_set_splitting
<<EIO base: procedures>>=
subroutine eio_set_splitting (eio, data)
class(eio_t), intent(inout) :: eio
type(event_sample_data_t), intent(in) :: data
eio%split = data%split_n_evt > 0 .or. data%split_n_kbytes > 0
if (eio%split) then
eio%split_n_evt = data%split_n_evt
eio%split_n_kbytes = data%split_n_kbytes
eio%split_index = data%split_index
eio%split_count = 0
end if
end subroutine eio_set_splitting
@ %def eio_set_splitting
@ Update the byte count and check if it has increased. We use integer
division to determine the number of [[n_kbytes]] blocks that are in
the event file.
<<EIO base: eio: TBP>>=
procedure :: update_split_count => eio_update_split_count
<<EIO base: procedures>>=
subroutine eio_update_split_count (eio, increased)
class(eio_t), intent(inout) :: eio
logical, intent(out) :: increased
integer :: split_count_old
if (eio%split_n_kbytes > 0) then
split_count_old = eio%split_count
eio%split_count = eio%file_size_kbytes () / eio%split_n_kbytes
increased = eio%split_count > split_count_old
end if
end subroutine eio_update_split_count
@ %def eio_update_split_count
@ Generate a filename, taking a possible split index into account.
<<EIO base: eio: TBP>>=
procedure :: set_filename => eio_set_filename
<<EIO base: procedures>>=
subroutine eio_set_filename (eio)
class(eio_t), intent(inout) :: eio
character(32) :: buffer
if (eio%split) then
write (buffer, "(I0,'.')") eio%split_index
eio%filename = eio%sample // "." // trim (buffer) // eio%extension
eio%has_file = .true.
else
eio%filename = eio%sample // "." // eio%extension
eio%has_file = .true.
end if
end subroutine eio_set_filename
@ %def eio_set_filename
@ Set the fallback model.
<<EIO base: eio: TBP>>=
procedure :: set_fallback_model => eio_set_fallback_model
<<EIO base: procedures>>=
subroutine eio_set_fallback_model (eio, model)
class(eio_t), intent(inout) :: eio
class(model_data_t), intent(in), target :: model
eio%fallback_model => model
end subroutine eio_set_fallback_model
@ %def eio_set_fallback_model
@ Initialize for output. We provide process names. This should
open an event file if appropriate and write header data. Some methods
may require event sample data.
<<EIO base: eio: TBP>>=
procedure (eio_init_out), deferred :: init_out
<<EIO base: interfaces>>=
abstract interface
subroutine eio_init_out (eio, sample, data, success, extension)
import
class(eio_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
type(string_t), intent(in), optional :: extension
end subroutine eio_init_out
end interface
@ %def eio_init_out
@ Initialize for input. We provide process names. This should open an event
file if appropriate and read header data. The [[md5sum]] can be used to check
the integrity of the configuration, it it provides a checksum to compare with.
In case the extension has changed the extension is also given as an argument.
The [[data]] argument is [[intent(inout)]]: we may read part of it and
keep other parts and/or check them against the data in the file.
<<EIO base: eio: TBP>>=
procedure (eio_init_in), deferred :: init_in
<<EIO base: interfaces>>=
abstract interface
subroutine eio_init_in (eio, sample, data, success, extension)
import
class(eio_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
type(string_t), intent(in), optional :: extension
end subroutine eio_init_in
end interface
@ %def eio_init_in
@ Re-initialize for output. This should change the status of any event file
from input to output and position it for appending new events.
<<EIO base: eio: TBP>>=
procedure (eio_switch_inout), deferred :: switch_inout
<<EIO base: interfaces>>=
abstract interface
subroutine eio_switch_inout (eio, success)
import
class(eio_t), intent(inout) :: eio
logical, intent(out), optional :: success
end subroutine eio_switch_inout
end interface
@ %def eio_switch_inout
@ This is similar: split the output, i.e., close the current file and open a
new one. The default implementation does nothing. For the feature to work,
an implementation must override this.
<<EIO base: eio: TBP>>=
procedure :: split_out => eio_split_out
<<EIO base: procedures>>=
subroutine eio_split_out (eio)
class(eio_t), intent(inout) :: eio
end subroutine eio_split_out
@ %def eio_split_out
@ Determine the file size in kilobytes. More exactly, determine the
size in units of 1024 storage units, as returned by the INQUIRE statement.
The implementation returns zero if there is no file. The
[[has_file]] flag is set by the [[set_filename]] method, so we can be
confident that the [[inquire]] call is meaningful. If this algorithm
doesn't apply for a particular format, we still can override the
procedure.
<<EIO base: eio: TBP>>=
procedure :: file_size_kbytes => eio_file_size_kbytes
<<EIO base: procedures>>=
function eio_file_size_kbytes (eio) result (kbytes)
class(eio_t), intent(in) :: eio
integer :: kbytes
integer(i64) :: bytes
if (eio%has_file) then
inquire (file = char (eio%filename), size = bytes)
if (bytes > 0) then
kbytes = bytes / 1024
else
kbytes = 0
end if
else
kbytes = 0
end if
end function eio_file_size_kbytes
@ %def eio_file_size_kbytes
@ Output an event. All data can be taken from the [[event]] record.
The index [[i_prc]] identifies the process among the processes that
are contained in the current sample. The [[reading]] flag, if present,
indicates that the event was read from file, not generated.
The [[passed]] flag tells us that this event has passed the selection
criteria. Depending on the event format, we may choose to skip events
that have not passed.
<<EIO base: eio: TBP>>=
procedure (eio_output), deferred :: output
<<EIO base: interfaces>>=
abstract interface
subroutine eio_output (eio, event, i_prc, reading, passed, pacify)
import
class(eio_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
end subroutine eio_output
end interface
@ %def eio_output
@ Input an event. This should fill all event data that cannot be inferred
from the associated process.
The input is broken down into two parts. First we read the [[i_prc]]
index. So we know which process to expect in the subsequent event.
If we have reached end of file, we also will know.
Then, we read the event itself.
The parameter [[iostat]] is supposed to be set as the Fortran standard
requires, negative for EOF and positive for error.
<<EIO base: eio: TBP>>=
procedure (eio_input_i_prc), deferred :: input_i_prc
procedure (eio_input_event), deferred :: input_event
<<EIO base: interfaces>>=
abstract interface
subroutine eio_input_i_prc (eio, i_prc, iostat)
import
class(eio_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
end subroutine eio_input_i_prc
end interface
abstract interface
subroutine eio_input_event (eio, event, iostat)
import
class(eio_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
end subroutine eio_input_event
end interface
@ %def eio_input
@
<<EIO base: eio: TBP>>=
procedure (eio_skip), deferred :: skip
<<EIO base: interfaces>>=
abstract interface
subroutine eio_skip (eio, iostat)
import
class(eio_t), intent(inout) :: eio
integer, intent(out) :: iostat
end subroutine eio_skip
end interface
@ %def eio_skip
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_base_ut.f90]]>>=
<<File header>>
module eio_base_ut
use unit_tests
use eio_base_uti
<<Standard module head>>
<<EIO base: public test>>
<<EIO base: public test auxiliary>>
contains
<<EIO base: test driver>>
end module eio_base_ut
@ %def eio_base_ut
@
<<[[eio_base_uti.f90]]>>=
<<File header>>
module eio_base_uti
<<Use kinds>>
<<Use strings>>
use io_units
use lorentz
use model_data
use particles
use event_base
use eio_data
use eio_base
<<Standard module head>>
<<EIO base: public test auxiliary>>
<<EIO base: test declarations>>
<<EIO base: test types>>
<<EIO base: test variables>>
contains
<<EIO base: tests>>
<<EIO base: test auxiliary>>
end module eio_base_uti
@ %def eio_base_ut
@ API: driver for the unit tests below.
<<EIO base: public test>>=
public :: eio_base_test
<<EIO base: test driver>>=
subroutine eio_base_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO base: execute tests>>
end subroutine eio_base_test
@ %def eio_base_test
@ The caller has to provide procedures that prepare and cleanup the test
environment. They depend on modules that are not available here.
<<EIO base: test types>>=
abstract interface
subroutine eio_prepare_event (event, unweighted, n_alt)
import
class(generic_event_t), intent(inout), pointer :: event
logical, intent(in), optional :: unweighted
integer, intent(in), optional :: n_alt
end subroutine eio_prepare_event
end interface
abstract interface
subroutine eio_cleanup_event (event)
import
class(generic_event_t), intent(inout), pointer :: event
end subroutine eio_cleanup_event
end interface
@ We store pointers to the test-environment handlers as module variables.
This allows us to call them from the test routines themselves, which don't
allow for extra arguments.
<<EIO base: public test auxiliary>>=
public :: eio_prepare_test, eio_cleanup_test
<<EIO base: test types>>=
procedure(eio_prepare_event), pointer :: eio_prepare_test => null ()
procedure(eio_cleanup_event), pointer :: eio_cleanup_test => null ()
@ %def eio_prepare_test eio_cleanup_test
@ Similarly, for the fallback (hadron) model that some eio tests require:
<<EIO base: test types>>=
abstract interface
subroutine eio_prepare_model (model)
import
class(model_data_t), intent(inout), pointer :: model
end subroutine eio_prepare_model
end interface
abstract interface
subroutine eio_cleanup_model (model)
import
class(model_data_t), intent(inout), target :: model
end subroutine eio_cleanup_model
end interface
<<EIO base: public test auxiliary>>=
public :: eio_prepare_fallback_model, eio_cleanup_fallback_model
<<EIO base: test variables>>=
procedure(eio_prepare_model), pointer :: eio_prepare_fallback_model => null ()
procedure(eio_cleanup_model), pointer :: eio_cleanup_fallback_model => null ()
@ %def eio_prepare_fallback_model eio_cleanup_fallback_model
@
\subsubsection{Test type for event I/O}
The contents simulate the contents of an external file. We have the
[[sample]] string as the file name and the array of momenta
[[event_p]] as the list of events. The
second index is the event index. The [[event_i]] component is the pointer
to the current event, [[event_n]] is the total number of stored events.
<<EIO base: test types>>=
type, extends (eio_t) :: eio_test_t
integer :: event_n = 0
integer :: event_i = 0
integer :: i_prc = 0
type(vector4_t), dimension(:,:), allocatable :: event_p
contains
<<EIO base: eio test: TBP>>
end type eio_test_t
@ %def eio_test_t
@ Write to screen. Pretend that this is an actual event format.
<<EIO base: eio test: TBP>>=
procedure :: write => eio_test_write
<<EIO base: test auxiliary>>=
subroutine eio_test_write (object, unit)
class(eio_test_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit)
write (u, "(1x,A)") "Test event stream"
if (object%event_i /= 0) then
write (u, "(1x,A,I0,A)") "Event #", object%event_i, ":"
do i = 1, size (object%event_p, 1)
call vector4_write (object%event_p(i, object%event_i), u)
end do
end if
end subroutine eio_test_write
@ %def eio_test_write
@ Finalizer. For the test case, we just reset the event count,
but keep the stored ``events''. For the real implementations, the events
would be stored on an external medium, so we would delete the object
contents.
<<EIO base: eio test: TBP>>=
procedure :: final => eio_test_final
<<EIO base: test auxiliary>>=
subroutine eio_test_final (object)
class(eio_test_t), intent(inout) :: object
object%event_i = 0
end subroutine eio_test_final
@ %def eio_test_final
@ Initialization: We store the process IDs and the energy from the beam-data
object. We also allocate the momenta (i.e., the simulated event record) for a
fixed maximum size of 10 events, 2 momenta each. There is only a single
process.
<<EIO base: eio test: TBP>>=
procedure :: init_out => eio_test_init_out
<<EIO base: test auxiliary>>=
subroutine eio_test_init_out (eio, sample, data, success, extension)
class(eio_test_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
type(string_t), intent(in), optional :: extension
eio%sample = sample
eio%event_n = 0
eio%event_i = 0
allocate (eio%event_p (2, 10))
if (present (success)) success = .true.
end subroutine eio_test_init_out
@ %def eio_test_init_out
@ Initialization for input. Nothing to do for the test type.
<<EIO base: eio test: TBP>>=
procedure :: init_in => eio_test_init_in
<<EIO base: test auxiliary>>=
subroutine eio_test_init_in (eio, sample, data, success, extension)
class(eio_test_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
type(string_t), intent(in), optional :: extension
if (present (success)) success = .true.
end subroutine eio_test_init_in
@ %def eio_test_init_in
@ Switch from output to input. Again, nothing to do for the test type.
<<EIO base: eio test: TBP>>=
procedure :: switch_inout => eio_test_switch_inout
<<EIO base: test auxiliary>>=
subroutine eio_test_switch_inout (eio, success)
class(eio_test_t), intent(inout) :: eio
logical, intent(out), optional :: success
if (present (success)) success = .true.
end subroutine eio_test_switch_inout
@ %def eio_test_switch_inout
@ Output. Increment the event counter and store the momenta of the current
event.
<<EIO base: eio test: TBP>>=
procedure :: output => eio_test_output
<<EIO base: test auxiliary>>=
subroutine eio_test_output (eio, event, i_prc, reading, passed, pacify)
class(eio_test_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
logical, intent(in), optional :: reading, passed, pacify
integer, intent(in) :: i_prc
type(particle_set_t), pointer :: pset
type(particle_t) :: prt
eio%event_n = eio%event_n + 1
eio%event_i = eio%event_n
eio%i_prc = i_prc
pset => event%get_particle_set_ptr ()
prt = pset%get_particle (3)
eio%event_p(1, eio%event_i) = prt%get_momentum ()
prt = pset%get_particle (4)
eio%event_p(2, eio%event_i) = prt%get_momentum ()
end subroutine eio_test_output
@ %def eio_test_output
@ Input. Increment the event counter and retrieve the momenta of the current
event. For the test case, we do not actually modify the current event.
<<EIO base: eio test: TBP>>=
procedure :: input_i_prc => eio_test_input_i_prc
procedure :: input_event => eio_test_input_event
<<EIO base: test auxiliary>>=
subroutine eio_test_input_i_prc (eio, i_prc, iostat)
class(eio_test_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
i_prc = eio%i_prc
iostat = 0
end subroutine eio_test_input_i_prc
subroutine eio_test_input_event (eio, event, iostat)
class(eio_test_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
eio%event_i = eio%event_i + 1
iostat = 0
end subroutine eio_test_input_event
@ %def eio_test_input_i_prc
@ %def eio_test_input_event
@
<<EIO base: eio test: TBP>>=
procedure :: skip => eio_test_skip
<<EIO base: test auxiliary>>=
subroutine eio_test_skip (eio, iostat)
class(eio_test_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_test_skip
@ %def eio_test_skip
@
\subsubsection{Test I/O methods}
<<EIO base: execute tests>>=
call test (eio_base_1, "eio_base_1", &
"read and write event contents", &
u, results)
<<EIO base: test declarations>>=
public :: eio_base_1
<<EIO base: tests>>=
subroutine eio_base_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
integer :: i_prc, iostat
type(string_t) :: sample
write (u, "(A)") "* Test output: eio_base_1"
write (u, "(A)") "* Purpose: generate and read/write an event"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_test1"
allocate (eio_test_t :: eio)
call eio%init_out (sample)
call event%generate (1, [0._default, 0._default])
call eio%output (event, 42)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* Re-read the event"
write (u, "(A)")
call eio%init_in (sample)
call eio%input_i_prc (i_prc, iostat)
call eio%input_event (event, iostat)
call eio%write (u)
write (u, "(A)")
write (u, "(1x,A,I0)") "i = ", i_prc
write (u, "(A)")
write (u, "(A)") "* Generate and append another event"
write (u, "(A)")
call eio%switch_inout ()
call event%generate (1, [0._default, 0._default])
call eio%output (event, 5)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* Re-read both events"
write (u, "(A)")
call eio%init_in (sample)
call eio%input_i_prc (i_prc, iostat)
call eio%input_event (event, iostat)
call eio%input_i_prc (i_prc, iostat)
call eio%input_event (event, iostat)
call eio%write (u)
write (u, "(A)")
write (u, "(1x,A,I0)") "i = ", i_prc
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
deallocate (eio)
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_base_1"
end subroutine eio_base_1
@ %def eio_base_1
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Direct Event Access}
As a convenient application of the base type, we construct an event
handler that allows us of setting and retrieving events just in the
same way as an file I/O format, but directly dealing with particle
data and momenta. This is an input and output format, but we do not
care about counting events.
<<[[eio_direct.f90]]>>=
<<File header>>
module eio_direct
<<Use kinds>>
<<Use strings>>
use io_units
use diagnostics
use cputime
use lorentz, only: vector4_t
use particles, only: particle_set_t
use model_data, only: model_data_t
use event_base
use eio_data
use eio_base
<<Standard module head>>
<<EIO direct: public>>
<<EIO direct: types>>
contains
<<EIO direct: procedures>>
end module eio_direct
@ %def eio_direct
@
\subsection{Type}
<<EIO direct: public>>=
public :: eio_direct_t
<<EIO direct: types>>=
type, extends (eio_t) :: eio_direct_t
private
logical :: i_evt_set = .false.
integer :: i_evt = 0
integer :: i_prc = 0
integer :: i_mci = 0
integer :: i_term = 0
integer :: channel = 0
logical :: passed_set = .false.
logical :: passed = .true.
type(particle_set_t) :: pset
contains
<<EIO direct: eio direct: TBP>>
end type eio_direct_t
@ %def eio_direct_t
@
\subsection{Common Methods}
Output.
<<EIO direct: eio direct: TBP>>=
procedure :: write => eio_direct_write
<<EIO direct: procedures>>=
subroutine eio_direct_write (object, unit)
class(eio_direct_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
write (u, "(1x,A)") "Event direct access:"
if (object%i_evt_set) then
write (u, "(3x,A,1x,I0)") "i_evt =", object%i_evt
else
write (u, "(3x,A)") "i_evt = [undefined]"
end if
write (u, "(3x,A,1x,I0)") "i_prc =", object%i_prc
write (u, "(3x,A,1x,I0)") "i_mci =", object%i_prc
write (u, "(3x,A,1x,I0)") "i_term =", object%i_prc
write (u, "(3x,A,1x,I0)") "channel =", object%i_prc
if (object%passed_set) then
write (u, "(3x,A,1x,L1)") "passed =", object%passed
else
write (u, "(3x,A)") "passed = [N/A]"
end if
call object%pset%write (u)
end subroutine eio_direct_write
@ %def eio_direct_write
@ Finalizer: trivial.
<<EIO direct: eio direct: TBP>>=
procedure :: final => eio_direct_final
<<EIO direct: procedures>>=
subroutine eio_direct_final (object)
class(eio_direct_t), intent(inout) :: object
call object%pset%final ()
end subroutine eio_direct_final
@ %def eio_direct_final
@ Initialize for input and/or output, both are identical
<<EIO direct: eio direct: TBP>>=
procedure :: init_out => eio_direct_init_out
<<EIO direct: procedures>>=
subroutine eio_direct_init_out (eio, sample, data, success, extension)
class(eio_direct_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
if (present (success)) success = .true.
end subroutine eio_direct_init_out
@ %def eio_direct_init_out
@
<<EIO direct: eio direct: TBP>>=
procedure :: init_in => eio_direct_init_in
<<EIO direct: procedures>>=
subroutine eio_direct_init_in (eio, sample, data, success, extension)
class(eio_direct_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
if (present (success)) success = .true.
end subroutine eio_direct_init_in
@ %def eio_direct_init_in
@ Switch from input to output: no-op
<<EIO direct: eio direct: TBP>>=
procedure :: switch_inout => eio_direct_switch_inout
<<EIO direct: procedures>>=
subroutine eio_direct_switch_inout (eio, success)
class(eio_direct_t), intent(inout) :: eio
logical, intent(out), optional :: success
if (present (success)) success = .true.
end subroutine eio_direct_switch_inout
@ %def eio_direct_switch_inout
@ Output: transfer event contents from the [[event]] object to the
[[eio]] object. Note that finalization of the particle set is not
(yet) automatic.
<<EIO direct: eio direct: TBP>>=
procedure :: output => eio_direct_output
<<EIO direct: procedures>>=
subroutine eio_direct_output (eio, event, i_prc, reading, passed, pacify)
class(eio_direct_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
type(particle_set_t), pointer :: pset_ptr
call eio%pset%final ()
if (event%has_index ()) then
call eio%set_event_index (event%get_index ())
else
call eio%reset_event_index ()
end if
if (present (passed)) then
eio%passed = passed
eio%passed_set = .true.
else
eio%passed_set = .false.
end if
pset_ptr => event%get_particle_set_ptr ()
if (associated (pset_ptr)) then
eio%i_prc = i_prc
eio%pset = pset_ptr
end if
end subroutine eio_direct_output
@ %def eio_direct_output
@ Input: transfer event contents from the [[eio]] object to the
[[event]] object. The [[i_prc]] parameter has been stored inside the
[[eio]] record before.
<<EIO direct: eio direct: TBP>>=
procedure :: input_i_prc => eio_direct_input_i_prc
procedure :: input_event => eio_direct_input_event
<<EIO direct: procedures>>=
subroutine eio_direct_input_i_prc (eio, i_prc, iostat)
class(eio_direct_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
i_prc = eio%i_prc
iostat = 0
end subroutine eio_direct_input_i_prc
subroutine eio_direct_input_event (eio, event, iostat)
class(eio_direct_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
call event%select (eio%i_mci, eio%i_term, eio%channel)
if (eio%has_event_index ()) then
call event%set_index (eio%get_event_index ())
else
call event%reset_index ()
end if
call event%set_hard_particle_set (eio%pset)
end subroutine eio_direct_input_event
@ %def eio_direct_input_i_prc
@ %def eio_direct_input_event
@ No-op.
<<EIO direct: eio direct: TBP>>=
procedure :: skip => eio_direct_skip
<<EIO direct: procedures>>=
subroutine eio_direct_skip (eio, iostat)
class(eio_direct_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_direct_skip
@ %def eio_direct_skip
@
\subsection{Retrieve individual contents}
<<EIO direct: eio direct: TBP>>=
procedure :: has_event_index => eio_direct_has_event_index
procedure :: get_event_index => eio_direct_get_event_index
procedure :: passed_known => eio_direct_passed_known
procedure :: has_passed => eio_direct_has_passed
procedure :: get_n_in => eio_direct_get_n_in
procedure :: get_n_out => eio_direct_get_n_out
procedure :: get_n_tot => eio_direct_get_n_tot
<<EIO direct: procedures>>=
function eio_direct_has_event_index (eio) result (flag)
class(eio_direct_t), intent(in) :: eio
logical :: flag
flag = eio%i_evt_set
end function eio_direct_has_event_index
function eio_direct_get_event_index (eio) result (index)
class(eio_direct_t), intent(in) :: eio
integer :: index
if (eio%has_event_index ()) then
index = eio%i_evt
else
index = 0
end if
end function eio_direct_get_event_index
function eio_direct_passed_known (eio) result (flag)
class(eio_direct_t), intent(in) :: eio
logical :: flag
flag = eio%passed_set
end function eio_direct_passed_known
function eio_direct_has_passed (eio) result (flag)
class(eio_direct_t), intent(in) :: eio
logical :: flag
if (eio%passed_known ()) then
flag = eio%passed
else
flag = .true.
end if
end function eio_direct_has_passed
function eio_direct_get_n_in (eio) result (n_in)
class(eio_direct_t), intent(in) :: eio
integer :: n_in
n_in = eio%pset%get_n_in ()
end function eio_direct_get_n_in
function eio_direct_get_n_out (eio) result (n_out)
class(eio_direct_t), intent(in) :: eio
integer :: n_out
n_out = eio%pset%get_n_out ()
end function eio_direct_get_n_out
function eio_direct_get_n_tot (eio) result (n_tot)
class(eio_direct_t), intent(in) :: eio
integer :: n_tot
n_tot = eio%pset%get_n_tot ()
end function eio_direct_get_n_tot
@ %def eio_direct_has_event_index
@ %def eio_direct_get_event_index
@ %def eio_direct_passed_known
@ %def eio_direct_has_passed
@ %def eio_direct_get_n_in
@ %def eio_direct_get_n_out
@ %def eio_direct_get_n_tot
@ All momenta as a single allocatable array.
<<EIO direct: eio direct: TBP>>=
procedure :: get_momentum_array => eio_direct_get_momentum_array
<<EIO direct: procedures>>=
subroutine eio_direct_get_momentum_array (eio, p)
class(eio_direct_t), intent(in) :: eio
type(vector4_t), dimension(:), allocatable, intent(out) :: p
integer :: n
n = eio%get_n_tot ()
allocate (p (n))
p(:) = eio%pset%get_momenta ()
end subroutine eio_direct_get_momentum_array
@ %def eio_direct_get_momentum_array
@
\subsection{Manual access}
Build the contained particle set from scratch.
<<EIO direct: eio direct: TBP>>=
procedure :: init_direct => eio_direct_init_direct
<<EIO direct: procedures>>=
subroutine eio_direct_init_direct &
(eio, n_beam, n_in, n_rem, n_vir, n_out, pdg, model)
class(eio_direct_t), intent(out) :: eio
integer, intent(in) :: n_beam
integer, intent(in) :: n_in
integer, intent(in) :: n_rem
integer, intent(in) :: n_vir
integer, intent(in) :: n_out
integer, dimension(:), intent(in) :: pdg
class(model_data_t), intent(in), target :: model
call eio%pset%init_direct (n_beam, n_in, n_rem, n_vir, n_out, pdg, model)
end subroutine eio_direct_init_direct
@ %def eio_direct_init_direct
@ Set/reset the event index, which is optional.
<<EIO direct: eio direct: TBP>>=
procedure :: set_event_index => eio_direct_set_event_index
procedure :: reset_event_index => eio_direct_reset_event_index
<<EIO direct: procedures>>=
subroutine eio_direct_set_event_index (eio, index)
class(eio_direct_t), intent(inout) :: eio
integer, intent(in) :: index
eio%i_evt = index
eio%i_evt_set = .true.
end subroutine eio_direct_set_event_index
subroutine eio_direct_reset_event_index (eio)
class(eio_direct_t), intent(inout) :: eio
eio%i_evt_set = .false.
end subroutine eio_direct_reset_event_index
@ %def eio_direct_set_event_index
@ %def eio_direct_reset_event_index
@ Set the selection indices. This is supposed to select the [[i_prc]],
[[i_mci]], [[i_term]], and [[channel]]
entries of the event where the momentum set has to be stored, respectively.
The selection indices determine the process, MCI set, calculation term, and
phase-space channel is to be used for recalculation. The index values must
not be zero, even if the do not apply.
<<EIO direct: eio direct: TBP>>=
procedure :: set_selection_indices => eio_direct_set_selection_indices
<<EIO direct: procedures>>=
subroutine eio_direct_set_selection_indices &
(eio, i_prc, i_mci, i_term, channel)
class(eio_direct_t), intent(inout) :: eio
integer, intent(in) :: i_prc
integer, intent(in) :: i_mci
integer, intent(in) :: i_term
integer, intent(in) :: channel
eio%i_prc = i_prc
eio%i_mci = i_mci
eio%i_term = i_term
eio%channel = channel
end subroutine eio_direct_set_selection_indices
@ %def eio_direct_set_i_prc
@ Set momentum (or momenta -- elemental).
<<EIO direct: eio direct: TBP>>=
generic :: set_momentum => set_momentum_single
generic :: set_momentum => set_momentum_all
procedure :: set_momentum_single => eio_direct_set_momentum_single
procedure :: set_momentum_all => eio_direct_set_momentum_all
<<EIO direct: procedures>>=
subroutine eio_direct_set_momentum_single (eio, i, p, p2, on_shell)
class(eio_direct_t), intent(inout) :: eio
integer, intent(in) :: i
type(vector4_t), intent(in) :: p
real(default), intent(in), optional :: p2
logical, intent(in), optional :: on_shell
call eio%pset%set_momentum (i, p, p2, on_shell)
end subroutine eio_direct_set_momentum_single
subroutine eio_direct_set_momentum_all (eio, p, p2, on_shell)
class(eio_direct_t), intent(inout) :: eio
type(vector4_t), dimension(:), intent(in) :: p
real(default), dimension(:), intent(in), optional :: p2
logical, intent(in), optional :: on_shell
call eio%pset%set_momentum (p, p2, on_shell)
end subroutine eio_direct_set_momentum_all
@ %def eio_direct_set_momentum
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_direct_ut.f90]]>>=
<<File header>>
module eio_direct_ut
use unit_tests
use eio_direct_uti
<<Standard module head>>
<<EIO direct: public test>>
contains
<<EIO direct: test driver>>
end module eio_direct_ut
@ %def eio_direct_ut
@
<<[[eio_direct_uti.f90]]>>=
<<File header>>
module eio_direct_uti
<<Use kinds>>
<<Use strings>>
use lorentz, only: vector4_t
use model_data, only: model_data_t
use event_base
use eio_data
use eio_base
use eio_direct
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
<<Standard module head>>
<<EIO direct: test declarations>>
contains
<<EIO direct: tests>>
end module eio_direct_uti
@ %def eio_direct_ut
@ API: driver for the unit tests below.
<<EIO direct: public test>>=
public :: eio_direct_test
<<EIO direct: test driver>>=
subroutine eio_direct_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO direct: execute tests>>
end subroutine eio_direct_test
@ %def eio_direct_test
@
\subsubsection{Test I/O methods}
We test the implementation of all I/O methods.
<<EIO direct: execute tests>>=
call test (eio_direct_1, "eio_direct_1", &
"read and write event contents", &
u, results)
<<EIO direct: test declarations>>=
public :: eio_direct_1
<<EIO direct: tests>>=
subroutine eio_direct_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
type(event_sample_data_t) :: data
type(string_t) :: sample
type(vector4_t), dimension(:), allocatable :: p
class(model_data_t), pointer :: model
integer :: i, n_events, iostat, i_prc
write (u, "(A)") "* Test output: eio_direct_1"
write (u, "(A)") "* Purpose: generate and read/write an event"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
write (u, "(A)")
write (u, "(A)") "* Initial state"
write (u, "(A)")
allocate (eio_direct_t :: eio)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Extract an empty event"
write (u, "(A)")
call eio%output (event, 1)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Retrieve contents"
write (u, "(A)")
select type (eio)
class is (eio_direct_t)
if (eio%has_event_index ()) write (u, "(A,1x,I0)") "index =", eio%get_event_index ()
if (eio%passed_known ()) write (u, "(A,1x,L1)") "passed =", eio%has_passed ()
write (u, "(A,1x,I0)") "n_in =", eio%get_n_in ()
write (u, "(A,1x,I0)") "n_out =", eio%get_n_out ()
end select
write (u, "(A)")
write (u, "(A)") "* Generate and extract an event"
write (u, "(A)")
call event%generate (1, [0._default, 0._default])
call event%set_index (42)
model => event%get_model_ptr ()
sample = ""
call eio%init_out (sample)
call eio%output (event, 1, passed = .true.)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Retrieve contents"
write (u, "(A)")
select type (eio)
class is (eio_direct_t)
if (eio%has_event_index ()) write (u, "(A,1x,I0)") "index =", eio%get_event_index ()
if (eio%passed_known ()) write (u, "(A,1x,L1)") "passed =", eio%has_passed ()
write (u, "(A,1x,I0)") "n_in =", eio%get_n_in ()
write (u, "(A,1x,I0)") "n_out =", eio%get_n_out ()
end select
select type (eio)
class is (eio_direct_t)
call eio%get_momentum_array (p)
if (allocated (p)) then
write (u, "(A)") "p[3] ="
call p(3)%write (u)
end if
end select
write (u, "(A)")
write (u, "(A)") "* Re-create an eio event record: initialization"
write (u, "(A)")
call eio%final ()
select type (eio)
class is (eio_direct_t)
call eio%init_direct ( &
n_beam = 0, n_in = 2, n_rem = 0, n_vir = 0, n_out = 2, &
pdg = [25, 25, 25, 25], model = model)
call eio%set_event_index (42)
call eio%set_selection_indices (1, 1, 1, 1)
call eio%write (u)
end select
write (u, "(A)")
write (u, "(A)") "* Re-create an eio event record: &
&set momenta, interchanged"
write (u, "(A)")
select type (eio)
class is (eio_direct_t)
call eio%set_momentum (p([1,2,4,3]), on_shell=.true.)
call eio%write (u)
end select
write (u, "(A)")
write (u, "(A)") "* 'read' i_prc"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(1x,A,1x,I0)") "i_prc =", i_prc
write (u, "(1x,A,1x,I0)") "iostat =", iostat
write (u, "(A)")
write (u, "(A)") "* 'read' (fill) event"
write (u, "(A)")
call eio%input_event (event, iostat)
write (u, "(1x,A,1x,I0)") "iostat =", iostat
write (u, "(A)")
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
deallocate (eio)
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_direct_1"
end subroutine eio_direct_1
@ %def eio_direct_1
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Event Generation Checkpoints}
This is an output-only format. Its only use is to write screen
messages every $n$ events, to inform the user about progress.
<<[[eio_checkpoints.f90]]>>=
<<File header>>
module eio_checkpoints
<<Use strings>>
use io_units
use diagnostics
use cputime
use event_base
use eio_data
use eio_base
<<Standard module head>>
<<EIO checkpoints: public>>
<<EIO checkpoints: parameters>>
<<EIO checkpoints: types>>
contains
<<EIO checkpoints: procedures>>
end module eio_checkpoints
@ %def eio_checkpoints
@
\subsection{Type}
<<EIO checkpoints: public>>=
public :: eio_checkpoints_t
<<EIO checkpoints: types>>=
type, extends (eio_t) :: eio_checkpoints_t
logical :: active = .false.
logical :: running = .false.
integer :: val = 0
integer :: n_events = 0
integer :: n_read = 0
integer :: i_evt = 0
logical :: blank = .false.
type(timer_t) :: timer
contains
<<EIO checkpoints: eio checkpoints: TBP>>
end type eio_checkpoints_t
@ %def eio_checkpoints_t
@
\subsection{Specific Methods}
Set parameters that are specifically used for checkpointing.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: set_parameters => eio_checkpoints_set_parameters
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_set_parameters (eio, checkpoint, blank)
class(eio_checkpoints_t), intent(inout) :: eio
integer, intent(in) :: checkpoint
logical, intent(in), optional :: blank
eio%val = checkpoint
if (present (blank)) eio%blank = blank
end subroutine eio_checkpoints_set_parameters
@ %def eio_checkpoints_set_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current status.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: write => eio_checkpoints_write
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_write (object, unit)
class(eio_checkpoints_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
if (object%active) then
write (u, "(1x,A)") "Event-sample checkpoints: active"
write (u, "(3x,A,I0)") "interval = ", object%val
write (u, "(3x,A,I0)") "n_events = ", object%n_events
write (u, "(3x,A,I0)") "n_read = ", object%n_read
write (u, "(3x,A,I0)") "n_current = ", object%i_evt
write (u, "(3x,A,L1)") "blanking = ", object%blank
call object%timer%write (u)
else
write (u, "(1x,A)") "Event-sample checkpoints: off"
end if
end subroutine eio_checkpoints_write
@ %def eio_checkpoints_write
@ Finalizer: trivial.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: final => eio_checkpoints_final
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_final (object)
class(eio_checkpoints_t), intent(inout) :: object
object%active = .false.
end subroutine eio_checkpoints_final
@ %def eio_checkpoints_final
@ Activate checkpointing for event generation or writing.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: init_out => eio_checkpoints_init_out
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_init_out (eio, sample, data, success, extension)
class(eio_checkpoints_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
if (present (data)) then
if (eio%val > 0) then
eio%active = .true.
eio%i_evt = 0
eio%n_read = 0
eio%n_events = data%n_evt * data%nlo_multiplier
end if
end if
if (present (success)) success = .true.
end subroutine eio_checkpoints_init_out
@ %def eio_checkpoints_init_out
@ No checkpointing for event reading.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: init_in => eio_checkpoints_init_in
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_init_in (eio, sample, data, success, extension)
class(eio_checkpoints_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
call msg_bug ("Event checkpoints: event input not supported")
if (present (success)) success = .false.
end subroutine eio_checkpoints_init_in
@ %def eio_checkpoints_init_in
@ Switch from input to output: also not supported.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: switch_inout => eio_checkpoints_switch_inout
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_switch_inout (eio, success)
class(eio_checkpoints_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("Event checkpoints: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_checkpoints_switch_inout
@ %def eio_checkpoints_switch_inout
@ Checkpoints: display progress for the current event, if applicable.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: output => eio_checkpoints_output
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_output (eio, event, i_prc, reading, passed, pacify)
class(eio_checkpoints_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
logical :: rd
rd = .false.; if (present (reading)) rd = reading
if (eio%active) then
if (.not. eio%running) call eio%startup ()
if (eio%running) then
eio%i_evt = eio%i_evt + 1
if (rd) then
eio%n_read = eio%n_read + 1
else if (mod (eio%i_evt, eio%val) == 0) then
call eio%message (eio%blank)
end if
if (eio%i_evt == eio%n_events) call eio%shutdown ()
end if
end if
end subroutine eio_checkpoints_output
@ %def eio_checkpoints_output
@ When the first event is called, we have to initialize the screen output.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: startup => eio_checkpoints_startup
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_startup (eio)
class(eio_checkpoints_t), intent(inout) :: eio
if (eio%active .and. eio%i_evt < eio%n_events) then
call msg_message ("")
call msg_message (checkpoint_bar)
call msg_message (checkpoint_head)
call msg_message (checkpoint_bar)
write (msg_buffer, checkpoint_fmt) 0., 0, eio%n_events - eio%i_evt, "???"
call msg_message ()
eio%running = .true.
call eio%timer%start ()
end if
end subroutine eio_checkpoints_startup
@ %def eio_checkpoints_startup
@ This message is printed at every checkpoint.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: message => eio_checkpoints_message
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_message (eio, testflag)
class(eio_checkpoints_t), intent(inout) :: eio
logical, intent(in), optional :: testflag
real :: t
type(time_t) :: time_remaining
type(string_t) :: time_string
call eio%timer%stop ()
t = eio%timer
call eio%timer%restart ()
time_remaining = &
nint (t / (eio%i_evt - eio%n_read) * (eio%n_events - eio%i_evt))
time_string = time_remaining%to_string_ms (blank = testflag)
write (msg_buffer, checkpoint_fmt) &
100 * (eio%i_evt - eio%n_read) / real (eio%n_events - eio%n_read), &
eio%i_evt - eio%n_read, &
eio%n_events - eio%i_evt, &
char (time_string)
call msg_message ()
end subroutine eio_checkpoints_message
@ %def eio_checkpoints_message
@ When the last event is called, wrap up.
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: shutdown => eio_checkpoints_shutdown
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_shutdown (eio)
class(eio_checkpoints_t), intent(inout) :: eio
if (mod (eio%i_evt, eio%val) /= 0) then
write (msg_buffer, checkpoint_fmt) &
100., eio%i_evt - eio%n_read, 0, "0m:00s"
call msg_message ()
end if
call msg_message (checkpoint_bar)
call msg_message ("")
eio%running = .false.
end subroutine eio_checkpoints_shutdown
@ %def eio_checkpoints_shutdown
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: input_i_prc => eio_checkpoints_input_i_prc
procedure :: input_event => eio_checkpoints_input_event
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_input_i_prc (eio, i_prc, iostat)
class(eio_checkpoints_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
call msg_bug ("Event checkpoints: event input not supported")
i_prc = 0
iostat = 1
end subroutine eio_checkpoints_input_i_prc
subroutine eio_checkpoints_input_event (eio, event, iostat)
class(eio_checkpoints_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
call msg_bug ("Event checkpoints: event input not supported")
iostat = 1
end subroutine eio_checkpoints_input_event
@ %def eio_checkpoints_input_i_prc
@ %def eio_checkpoints_input_event
@
<<EIO checkpoints: eio checkpoints: TBP>>=
procedure :: skip => eio_checkpoints_skip
<<EIO checkpoints: procedures>>=
subroutine eio_checkpoints_skip (eio, iostat)
class(eio_checkpoints_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_checkpoints_skip
@ %def eio_checkpoints_skip
@
\subsection{Message header}
<<EIO checkpoints: parameters>>=
character(*), parameter :: &
checkpoint_head = "| % complete | events generated | events remaining &
&| time remaining"
character(*), parameter :: &
checkpoint_bar = "|==================================================&
&=================|"
character(*), parameter :: &
checkpoint_fmt = "(' ',F5.1,T16,I9,T35,I9,T58,A)"
@ %def checkpoint_head
@ %def checkpoint_bar
@ %def checkpoint_fmt
@ %def checkpointing_t
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_checkpoints_ut.f90]]>>=
<<File header>>
module eio_checkpoints_ut
use unit_tests
use eio_checkpoints_uti
<<Standard module head>>
<<EIO checkpoints: public test>>
contains
<<EIO checkpoints: test driver>>
end module eio_checkpoints_ut
@ %def eio_checkpoints_ut
@
<<[[eio_checkpoints_uti.f90]]>>=
<<File header>>
module eio_checkpoints_uti
<<Use kinds>>
<<Use strings>>
use event_base
use eio_data
use eio_base
use eio_checkpoints
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
<<Standard module head>>
<<EIO checkpoints: test declarations>>
contains
<<EIO checkpoints: tests>>
end module eio_checkpoints_uti
@ %def eio_checkpoints_ut
@ API: driver for the unit tests below.
<<EIO checkpoints: public test>>=
public :: eio_checkpoints_test
<<EIO checkpoints: test driver>>=
subroutine eio_checkpoints_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO checkpoints: execute tests>>
end subroutine eio_checkpoints_test
@ %def eio_checkpoints_test
@
\subsubsection{Test I/O methods}
We test the implementation of all I/O methods.
<<EIO checkpoints: execute tests>>=
call test (eio_checkpoints_1, "eio_checkpoints_1", &
"read and write event contents", &
u, results)
<<EIO checkpoints: test declarations>>=
public :: eio_checkpoints_1
<<EIO checkpoints: tests>>=
subroutine eio_checkpoints_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
type(event_sample_data_t) :: data
type(string_t) :: sample
integer :: i, n_events
write (u, "(A)") "* Test output: eio_checkpoints_1"
write (u, "(A)") "* Purpose: generate a number of events &
&with screen output"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event)
write (u, "(A)")
write (u, "(A)") "* Generate events"
write (u, "(A)")
sample = "eio_checkpoints_1"
allocate (eio_checkpoints_t :: eio)
n_events = 10
call data%init (1, 0)
data%n_evt = n_events
select type (eio)
type is (eio_checkpoints_t)
call eio%set_parameters (checkpoint = 4)
end select
call eio%init_out (sample, data)
do i = 1, n_events
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = 0)
end do
write (u, "(A)") "* Checkpointing status"
write (u, "(A)")
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_checkpoints_1"
end subroutine eio_checkpoints_1
@ %def eio_checkpoints_1
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Event Generation Callback}
This is an output-only format. Its only use is to write screen
messages every $n$ events, to inform the user about progress.
<<[[eio_callback.f90]]>>=
<<File header>>
module eio_callback
use kinds, only: i64
<<Use strings>>
use io_units
use diagnostics
use cputime
use event_base
use eio_data
use eio_base
<<Standard module head>>
<<EIO callback: public>>
<<EIO callback: types>>
contains
<<EIO callback: procedures>>
end module eio_callback
@ %def eio_callback
@
\subsection{Type}
<<EIO callback: public>>=
public :: eio_callback_t
<<EIO callback: types>>=
type, extends (eio_t) :: eio_callback_t
class(event_callback_t), allocatable :: callback
integer(i64) :: i_evt = 0
integer :: i_interval = 0
integer :: n_interval = 0
! type(timer_t) :: timer
contains
<<EIO callback: eio callback: TBP>>
end type eio_callback_t
@ %def eio_callback_t
@
\subsection{Specific Methods}
Set parameters that are specifically used for callback: the procedure
and the number of events to wait until the procedure is called (again).
<<EIO callback: eio callback: TBP>>=
procedure :: set_parameters => eio_callback_set_parameters
<<EIO callback: procedures>>=
subroutine eio_callback_set_parameters (eio, callback, count_interval)
class(eio_callback_t), intent(inout) :: eio
class(event_callback_t), intent(in) :: callback
integer, intent(in) :: count_interval
allocate (eio%callback, source = callback)
eio%n_interval = count_interval
end subroutine eio_callback_set_parameters
@ %def eio_callback_set_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current status.
<<EIO callback: eio callback: TBP>>=
procedure :: write => eio_callback_write
<<EIO callback: procedures>>=
subroutine eio_callback_write (object, unit)
class(eio_callback_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
write (u, "(1x,A)") "Event-sample callback:"
write (u, "(3x,A,I0)") "interval = ", object%n_interval
write (u, "(3x,A,I0)") "evt count = ", object%i_evt
! call object%timer%write (u)
end subroutine eio_callback_write
@ %def eio_callback_write
@ Finalizer: trivial.
<<EIO callback: eio callback: TBP>>=
procedure :: final => eio_callback_final
<<EIO callback: procedures>>=
subroutine eio_callback_final (object)
class(eio_callback_t), intent(inout) :: object
end subroutine eio_callback_final
@ %def eio_callback_final
@ Activate checkpointing for event generation or writing.
<<EIO callback: eio callback: TBP>>=
procedure :: init_out => eio_callback_init_out
<<EIO callback: procedures>>=
subroutine eio_callback_init_out (eio, sample, data, success, extension)
class(eio_callback_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
eio%i_evt = 0
eiO%i_interval = 0
if (present (success)) success = .true.
end subroutine eio_callback_init_out
@ %def eio_callback_init_out
@ No callback for event reading.
<<EIO callback: eio callback: TBP>>=
procedure :: init_in => eio_callback_init_in
<<EIO callback: procedures>>=
subroutine eio_callback_init_in (eio, sample, data, success, extension)
class(eio_callback_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
call msg_bug ("Event callback: event input not supported")
if (present (success)) success = .false.
end subroutine eio_callback_init_in
@ %def eio_callback_init_in
@ Switch from input to output: also not supported.
<<EIO callback: eio callback: TBP>>=
procedure :: switch_inout => eio_callback_switch_inout
<<EIO callback: procedures>>=
subroutine eio_callback_switch_inout (eio, success)
class(eio_callback_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("Event callback: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_callback_switch_inout
@ %def eio_callback_switch_inout
@ The actual callback. First increment counters, then call the
procedure if the counter hits the interval.
<<EIO callback: eio callback: TBP>>=
procedure :: output => eio_callback_output
<<EIO callback: procedures>>=
subroutine eio_callback_output (eio, event, i_prc, reading, passed, pacify)
class(eio_callback_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
eio%i_evt = eio%i_evt + 1
if (eio%n_interval > 0) then
eio%i_interval = eio%i_interval + 1
if (eio%i_interval >= eio%n_interval) then
call eio%callback%proc (eio%i_evt, event)
eio%i_interval = 0
end if
end if
end subroutine eio_callback_output
@ %def eio_callback_output
@ No input.
<<EIO callback: eio callback: TBP>>=
procedure :: input_i_prc => eio_callback_input_i_prc
procedure :: input_event => eio_callback_input_event
<<EIO callback: procedures>>=
subroutine eio_callback_input_i_prc (eio, i_prc, iostat)
class(eio_callback_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
call msg_bug ("Event callback: event input not supported")
i_prc = 0
iostat = 1
end subroutine eio_callback_input_i_prc
subroutine eio_callback_input_event (eio, event, iostat)
class(eio_callback_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
call msg_bug ("Event callback: event input not supported")
iostat = 1
end subroutine eio_callback_input_event
@ %def eio_callback_input_i_prc
@ %def eio_callback_input_event
@
<<EIO callback: eio callback: TBP>>=
procedure :: skip => eio_callback_skip
<<EIO callback: procedures>>=
subroutine eio_callback_skip (eio, iostat)
class(eio_callback_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_callback_skip
@ %def eio_callback_skip
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Event Weight Output}
This is an output-only format. For each event, we print the indices
that identify process, process part (MCI group), and term. As
numerical information we print the squared matrix element (trace) and
the event weight.
<<[[eio_weights.f90]]>>=
<<File header>>
module eio_weights
<<Use kinds>>
<<Use strings>>
use io_units
use diagnostics
use event_base
use eio_data
use eio_base
<<Standard module head>>
<<EIO weights: public>>
<<EIO weights: types>>
contains
<<EIO weights: procedures>>
end module eio_weights
@ %def eio_weights
@
\subsection{Type}
<<EIO weights: public>>=
public :: eio_weights_t
<<EIO weights: types>>=
type, extends (eio_t) :: eio_weights_t
logical :: writing = .false.
integer :: unit = 0
logical :: pacify = .false.
contains
<<EIO weights: eio weights: TBP>>
end type eio_weights_t
@ %def eio_weights_t
@
\subsection{Specific Methods}
Set pacify flags.
<<EIO weights: eio weights: TBP>>=
procedure :: set_parameters => eio_weights_set_parameters
<<EIO weights: procedures>>=
subroutine eio_weights_set_parameters (eio, pacify)
class(eio_weights_t), intent(inout) :: eio
logical, intent(in), optional :: pacify
if (present (pacify)) eio%pacify = pacify
eio%extension = "weights.dat"
end subroutine eio_weights_set_parameters
@ %def eio_weights_set_parameters
@
\subsection{Common Methods}
@ Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO weights: eio weights: TBP>>=
procedure :: write => eio_weights_write
<<EIO weights: procedures>>=
subroutine eio_weights_write (object, unit)
class(eio_weights_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
write (u, "(1x,A)") "Weight stream:"
if (object%writing) then
write (u, "(3x,A,A)") "Writing to file = ", char (object%filename)
write (u, "(3x,A,L1)") "Reduced I/O prec. = ", object%pacify
else
write (u, "(3x,A)") "[closed]"
end if
end subroutine eio_weights_write
@ %def eio_weights_write
@ Finalizer: close any open file.
<<EIO weights: eio weights: TBP>>=
procedure :: final => eio_weights_final
<<EIO weights: procedures>>=
subroutine eio_weights_final (object)
class(eio_weights_t), intent(inout) :: object
if (object%writing) then
write (msg_buffer, "(A,A,A)") "Events: closing weight stream file '", &
char (object%filename), "'"
call msg_message ()
close (object%unit)
object%writing = .false.
end if
end subroutine eio_weights_final
@ %def eio_weights_final
@ Initialize event writing.
<<EIO weights: eio weights: TBP>>=
procedure :: init_out => eio_weights_init_out
<<EIO weights: procedures>>=
subroutine eio_weights_init_out (eio, sample, data, success, extension)
class(eio_weights_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
if (present(extension)) then
eio%extension = extension
else
eio%extension = "weights.dat"
end if
eio%filename = sample // "." // eio%extension
eio%unit = free_unit ()
write (msg_buffer, "(A,A,A)") "Events: writing to weight stream file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
open (eio%unit, file = char (eio%filename), &
action = "write", status = "replace")
if (present (success)) success = .true.
end subroutine eio_weights_init_out
@ %def eio_weights_init_out
@ Initialize event reading.
<<EIO weights: eio weights: TBP>>=
procedure :: init_in => eio_weights_init_in
<<EIO weights: procedures>>=
subroutine eio_weights_init_in (eio, sample, data, success, extension)
class(eio_weights_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
call msg_bug ("Weight stream: event input not supported")
if (present (success)) success = .false.
end subroutine eio_weights_init_in
@ %def eio_weights_init_in
@ Switch from input to output: reopen the file for reading.
<<EIO weights: eio weights: TBP>>=
procedure :: switch_inout => eio_weights_switch_inout
<<EIO weights: procedures>>=
subroutine eio_weights_switch_inout (eio, success)
class(eio_weights_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("Weight stream: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_weights_switch_inout
@ %def eio_weights_switch_inout
@ Output an event. Write first the event indices, then weight and two
values of the squared matrix element: [[sqme_ref]] is the value stored
in the event record, and [[sqme_prc]] is the one stored in the process
instance. (They can differ: when recalculating, the former is read
from file and the latter is the result of the new calculation.)
For the alternative entries, the [[sqme]] value is always obtained by
a new calculation, and thus qualifies as [[sqme_prc]].
Don't write the file if the [[passed]] flag is set and false.
<<EIO weights: eio weights: TBP>>=
procedure :: output => eio_weights_output
<<EIO weights: procedures>>=
subroutine eio_weights_output (eio, event, i_prc, reading, passed, pacify)
class(eio_weights_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
integer :: n_alt, i
real(default) :: weight, sqme_ref, sqme_prc
logical :: evt_pacify, evt_passed
evt_pacify = eio%pacify; if (present (pacify)) evt_pacify = pacify
evt_passed = .true.; if (present (passed)) evt_passed = passed
if (eio%writing) then
if (evt_passed) then
weight = event%get_weight_prc ()
sqme_ref = event%get_sqme_ref ()
sqme_prc = event%get_sqme_prc ()
n_alt = event%get_n_alt ()
1 format (I0,3(1x,ES17.10),3(1x,I0))
2 format (I0,3(1x,ES15.8),3(1x,I0))
if (evt_pacify) then
write (eio%unit, 2) 0, weight, sqme_prc, sqme_ref, &
i_prc
else
write (eio%unit, 1) 0, weight, sqme_prc, sqme_ref, &
i_prc
end if
do i = 1, n_alt
weight = event%get_weight_alt(i)
sqme_prc = event%get_sqme_alt(i)
if (evt_pacify) then
write (eio%unit, 2) i, weight, sqme_prc
else
write (eio%unit, 1) i, weight, sqme_prc
end if
end do
end if
else
call eio%write ()
call msg_fatal ("Weight stream file is not open for writing")
end if
end subroutine eio_weights_output
@ %def eio_weights_output
@ Input an event.
<<EIO weights: eio weights: TBP>>=
procedure :: input_i_prc => eio_weights_input_i_prc
procedure :: input_event => eio_weights_input_event
<<EIO weights: procedures>>=
subroutine eio_weights_input_i_prc (eio, i_prc, iostat)
class(eio_weights_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
call msg_bug ("Weight stream: event input not supported")
i_prc = 0
iostat = 1
end subroutine eio_weights_input_i_prc
subroutine eio_weights_input_event (eio, event, iostat)
class(eio_weights_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
call msg_bug ("Weight stream: event input not supported")
iostat = 1
end subroutine eio_weights_input_event
@ %def eio_weights_input_i_prc
@ %def eio_weights_input_event
@
<<EIO weights: eio weights: TBP>>=
procedure :: skip => eio_weights_skip
<<EIO weights: procedures>>=
subroutine eio_weights_skip (eio, iostat)
class(eio_weights_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_weights_skip
@ %def eio_weights_skip
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_weights_ut.f90]]>>=
<<File header>>
module eio_weights_ut
use unit_tests
use eio_weights_uti
<<Standard module head>>
<<EIO weights: public test>>
contains
<<EIO weights: test driver>>
end module eio_weights_ut
@ %def eio_weights_ut
@
<<[[eio_weights_uti.f90]]>>=
<<File header>>
module eio_weights_uti
<<Use kinds>>
<<Use strings>>
use io_units
use event_base
use eio_data
use eio_base
use eio_weights
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
<<Standard module head>>
<<EIO weights: test declarations>>
contains
<<EIO weights: tests>>
end module eio_weights_uti
@ %def eio_weights_ut
@ API: driver for the unit tests below.
<<EIO weights: public test>>=
public :: eio_weights_test
<<EIO weights: test driver>>=
subroutine eio_weights_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO weights: execute tests>>
end subroutine eio_weights_test
@ %def eio_weights_test
@
\subsubsection{Simple event}
We test the implementation of all I/O methods.
<<EIO weights: execute tests>>=
call test (eio_weights_1, "eio_weights_1", &
"read and write event contents", &
u, results)
<<EIO weights: test declarations>>=
public :: eio_weights_1
<<EIO weights: tests>>=
subroutine eio_weights_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file
character(80) :: buffer
write (u, "(A)") "* Test output: eio_weights_1"
write (u, "(A)") "* Purpose: generate an event and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_weights_1"
allocate (eio_weights_t :: eio)
call eio%init_out (sample)
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = 42)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents: &
&(weight, sqme(evt), sqme(prc), i_prc)"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "eio_weights_1.weights.dat", &
action = "read", status = "old")
read (u_file, "(A)") buffer
write (u, "(A)") trim (buffer)
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_weights_1"
end subroutine eio_weights_1
@ %def eio_weights_1
@
\subsubsection{Multiple weights}
Event with several weight entries set.
<<EIO weights: execute tests>>=
call test (eio_weights_2, "eio_weights_2", &
"multiple weights", &
u, results)
<<EIO weights: test declarations>>=
public :: eio_weights_2
<<EIO weights: tests>>=
subroutine eio_weights_2 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, i
character(80) :: buffer
write (u, "(A)") "* Test output: eio_weights_2"
write (u, "(A)") "* Purpose: generate an event and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false., n_alt = 2)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_weights_2"
allocate (eio_weights_t :: eio)
call eio%init_out (sample)
select type (eio)
type is (eio_weights_t)
call eio%set_parameters (pacify = .true.)
end select
call event%generate (1, [0._default, 0._default])
call event%set (sqme_alt = [2._default, 3._default])
call event%set (weight_alt = &
[2 * event%get_weight_prc (), 3 * event%get_weight_prc ()])
call eio%output (event, i_prc = 42)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents: &
&(weight, sqme(evt), sqme(prc), i_prc)"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "eio_weights_2.weights.dat", &
action = "read", status = "old")
do i = 1, 3
read (u_file, "(A)") buffer
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_weights_2"
end subroutine eio_weights_2
@ %def eio_weights_2
@
\subsubsection{Multiple events}
Events with [[passed]] flag switched on/off.
<<EIO weights: execute tests>>=
call test (eio_weights_3, "eio_weights_3", &
"check passed-flag", &
u, results)
<<EIO weights: test declarations>>=
public :: eio_weights_3
<<EIO weights: tests>>=
subroutine eio_weights_3 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_weights_3"
write (u, "(A)") "* Purpose: generate three events and write to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
write (u, "(A)")
write (u, "(A)") "* Generate and write events"
write (u, "(A)")
sample = "eio_weights_3"
allocate (eio_weights_t :: eio)
select type (eio)
type is (eio_weights_t)
call eio%set_parameters (pacify = .true.)
end select
call eio%init_out (sample)
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = 1)
call event%generate (1, [0.1_default, 0._default])
call eio%output (event, i_prc = 1, passed = .false.)
call event%generate (1, [0.2_default, 0._default])
call eio%output (event, i_prc = 1, passed = .true.)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents: &
&(weight, sqme(evt), sqme(prc), i_prc), should be just two entries"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "eio_weights_3.weights.dat", &
action = "read", status = "old")
do
read (u_file, "(A)", iostat=iostat) buffer
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_weights_3"
end subroutine eio_weights_3
@ %def eio_weights_3
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Event Dump Output}
This is an output-only format. We simply dump the contents of the
[[particle_set]], using the [[write]] method of that type. The
event-format options are the options of that procedure.
<<[[eio_dump.f90]]>>=
<<File header>>
module eio_dump
use, intrinsic :: iso_fortran_env, only: output_unit
use kinds, only: i64
<<Use strings>>
use format_utils, only: write_separator
use format_utils, only: pac_fmt
use format_defs, only: FMT_16, FMT_19
use io_units
use diagnostics
use event_base
use eio_data
use eio_base
<<Standard module head>>
<<EIO dump: public>>
<<EIO dump: types>>
contains
<<EIO dump: procedures>>
end module eio_dump
@ %def eio_dump
@
\subsection{Type}
<<EIO dump: public>>=
public :: eio_dump_t
<<EIO dump: types>>=
type, extends (eio_t) :: eio_dump_t
integer(i64) :: count = 0
integer :: unit = 0
logical :: writing = .false.
logical :: screen = .false.
logical :: pacify = .false.
logical :: weights = .false.
logical :: compressed = .false.
logical :: summary = .false.
contains
<<EIO dump: eio dump: TBP>>
end type eio_dump_t
@ %def eio_dump_t
@
\subsection{Specific Methods}
Set control parameters. We may provide a [[unit]] for input or output; this
will be taken if the sample file name is empty. In that case, the unit is
assumed to be open and will be kept open; no messages will be issued.
<<EIO dump: eio dump: TBP>>=
procedure :: set_parameters => eio_dump_set_parameters
<<EIO dump: procedures>>=
subroutine eio_dump_set_parameters (eio, extension, &
pacify, weights, compressed, summary, screen, unit)
class(eio_dump_t), intent(inout) :: eio
type(string_t), intent(in), optional :: extension
logical, intent(in), optional :: pacify
logical, intent(in), optional :: weights
logical, intent(in), optional :: compressed
logical, intent(in), optional :: summary
logical, intent(in), optional :: screen
integer, intent(in), optional :: unit
if (present (pacify)) eio%pacify = pacify
if (present (weights)) eio%weights = weights
if (present (compressed)) eio%compressed = compressed
if (present (summary)) eio%summary = summary
if (present (screen)) eio%screen = screen
if (present (unit)) eio%unit = unit
eio%extension = "pset.dat"
if (present (extension)) eio%extension = extension
end subroutine eio_dump_set_parameters
@ %def eio_dump_set_parameters
@
\subsection{Common Methods}
@ Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO dump: eio dump: TBP>>=
procedure :: write => eio_dump_write
<<EIO dump: procedures>>=
subroutine eio_dump_write (object, unit)
class(eio_dump_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
write (u, "(1x,A)") "Dump event stream:"
if (object%writing) then
write (u, "(3x,A,L1)") "Screen output = ", object%screen
write (u, "(3x,A,A,A)") "Writing to file = '", char (object%filename), "'"
write (u, "(3x,A,L1)") "Reduced I/O prec. = ", object%pacify
write (u, "(3x,A,L1)") "Show weights/sqme = ", object%weights
write (u, "(3x,A,L1)") "Compressed = ", object%compressed
write (u, "(3x,A,L1)") "Summary = ", object%summary
else
write (u, "(3x,A)") "[closed]"
end if
end subroutine eio_dump_write
@ %def eio_dump_write
@ Finalizer: close any open file.
<<EIO dump: eio dump: TBP>>=
procedure :: final => eio_dump_final
<<EIO dump: procedures>>=
subroutine eio_dump_final (object)
class(eio_dump_t), intent(inout) :: object
if (object%screen) then
write (msg_buffer, "(A,A,A)") "Events: display complete"
call msg_message ()
object%screen = .false.
end if
if (object%writing) then
if (object%filename /= "") then
write (msg_buffer, "(A,A,A)") "Events: closing event dump file '", &
char (object%filename), "'"
call msg_message ()
close (object%unit)
end if
object%writing = .false.
end if
end subroutine eio_dump_final
@ %def eio_dump_final
@ Initialize event writing.
<<EIO dump: eio dump: TBP>>=
procedure :: init_out => eio_dump_init_out
<<EIO dump: procedures>>=
subroutine eio_dump_init_out (eio, sample, data, success, extension)
class(eio_dump_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
if (present(extension)) then
eio%extension = extension
else
eio%extension = "pset.dat"
end if
if (sample == "" .and. eio%unit /= 0) then
eio%filename = ""
eio%writing = .true.
else if (sample /= "") then
eio%filename = sample // "." // eio%extension
eio%unit = free_unit ()
write (msg_buffer, "(A,A,A)") "Events: writing to event dump file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
open (eio%unit, file = char (eio%filename), &
action = "write", status = "replace")
end if
if (eio%screen) then
write (msg_buffer, "(A,A,A)") "Events: display on standard output"
call msg_message ()
end if
eio%count = 0
if (present (success)) success = .true.
end subroutine eio_dump_init_out
@ %def eio_dump_init_out
@ Initialize event reading.
<<EIO dump: eio dump: TBP>>=
procedure :: init_in => eio_dump_init_in
<<EIO dump: procedures>>=
subroutine eio_dump_init_in (eio, sample, data, success, extension)
class(eio_dump_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
call msg_bug ("Event dump: event input not supported")
if (present (success)) success = .false.
end subroutine eio_dump_init_in
@ %def eio_dump_init_in
@ Switch from input to output: reopen the file for reading.
<<EIO dump: eio dump: TBP>>=
procedure :: switch_inout => eio_dump_switch_inout
<<EIO dump: procedures>>=
subroutine eio_dump_switch_inout (eio, success)
class(eio_dump_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("Event dump: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_dump_switch_inout
@ %def eio_dump_switch_inout
@ Output an event. Delegate the output call to the [[write]] method
of the current particle set, if valid. Output both to file (if defined)
and to screen (if requested).
<<EIO dump: eio dump: TBP>>=
procedure :: output => eio_dump_output
<<EIO dump: procedures>>=
subroutine eio_dump_output (eio, event, i_prc, reading, passed, pacify)
class(eio_dump_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
character(len=7) :: fmt
eio%count = eio%count + 1
if (present (pacify)) then
call pac_fmt (fmt, FMT_19, FMT_16, pacify)
else
call pac_fmt (fmt, FMT_19, FMT_16, eio%pacify)
end if
if (eio%writing) call dump (eio%unit)
if (eio%screen) then
call dump (output_unit)
if (logfile_unit () > 0) call dump (logfile_unit ())
end if
contains
subroutine dump (u)
integer, intent(in) :: u
integer :: i
call write_separator (u, 2)
write (u, "(1x,A,I0)", advance="no") "Event"
if (event%has_index ()) then
write (u, "(1x,'#',I0)") event%get_index ()
else
write (u, *)
end if
call write_separator (u, 2)
write (u, "(1x,A,1x,I0)") "count =", eio%count
if (present (passed)) then
write (u, "(1x,A,1x,L1)") "passed =", passed
else
write (u, "(1x,A)") "passed = [N/A]"
end if
write (u, "(1x,A,1x,I0)") "prc id =", i_prc
if (eio%weights) then
call write_separator (u)
if (event%sqme_ref_known) then
write (u, "(1x,A," // fmt // ")") "sqme (ref) = ", &
event%sqme_ref
else
write (u, "(1x,A)") "sqme (ref) = [undefined]"
end if
if (event%sqme_prc_known) then
write (u, "(1x,A," // fmt // ")") "sqme (prc) = ", &
event%sqme_prc
else
write (u, "(1x,A)") "sqme (prc) = [undefined]"
end if
if (event%weight_ref_known) then
write (u, "(1x,A," // fmt // ")") "weight (ref) = ", &
event%weight_ref
else
write (u, "(1x,A)") "weight (ref) = [undefined]"
end if
if (event%weight_prc_known) then
write (u, "(1x,A," // fmt // ")") "weight (prc) = ", &
event%weight_prc
else
write (u, "(1x,A)") "weight (prc) = [undefined]"
end if
if (event%excess_prc_known) then
write (u, "(1x,A," // fmt // ")") "excess (prc) = ", &
event%excess_prc
else
write (u, "(1x,A)") "excess (prc) = [undefined]"
end if
do i = 1, event%n_alt
if (event%sqme_ref_known) then
write (u, "(1x,A,I0,A," // fmt // ")") "sqme (", i, ") = ",&
event%sqme_prc
else
write (u, "(1x,A,I0,A)") "sqme (", i, ") = [undefined]"
end if
if (event%weight_prc_known) then
write (u, "(1x,A,I0,A," // fmt // ")") "weight (", i, ") = ",&
event%weight_prc
else
write (u, "(1x,A,I0,A)") "weight (", i, ") = [undefined]"
end if
end do
end if
call write_separator (u)
if (event%particle_set_is_valid) then
call event%particle_set%write (unit = u, &
summary = eio%summary, compressed = eio%compressed, &
testflag = eio%pacify)
else
write (u, "(1x,A)") "Particle set: [invalid]"
end if
end subroutine dump
end subroutine eio_dump_output
@ %def eio_dump_output
@ Input an event.
<<EIO dump: eio dump: TBP>>=
procedure :: input_i_prc => eio_dump_input_i_prc
procedure :: input_event => eio_dump_input_event
<<EIO dump: procedures>>=
subroutine eio_dump_input_i_prc (eio, i_prc, iostat)
class(eio_dump_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
call msg_bug ("Dump stream: event input not supported")
i_prc = 0
iostat = 1
end subroutine eio_dump_input_i_prc
subroutine eio_dump_input_event (eio, event, iostat)
class(eio_dump_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
call msg_bug ("Dump stream: event input not supported")
iostat = 1
end subroutine eio_dump_input_event
@ %def eio_dump_input_i_prc
@ %def eio_dump_input_event
@
<<EIO dump: eio dump: TBP>>=
procedure :: skip => eio_dump_skip
<<EIO dump: procedures>>=
subroutine eio_dump_skip (eio, iostat)
class(eio_dump_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_dump_skip
@ %def eio_dump_skip
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_dump_ut.f90]]>>=
<<File header>>
module eio_dump_ut
use unit_tests
use eio_dump_uti
<<Standard module head>>
<<EIO dump: public test>>
contains
<<EIO dump: test driver>>
end module eio_dump_ut
@ %def eio_dump_ut
@
<<[[eio_dump_uti.f90]]>>=
<<File header>>
module eio_dump_uti
<<Use kinds>>
<<Use strings>>
use io_units
use event_base
use eio_data
use eio_base
use eio_dump
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
<<Standard module head>>
<<EIO dump: test declarations>>
contains
<<EIO dump: tests>>
end module eio_dump_uti
@ %def eio_dump_ut
@ API: driver for the unit tests below.
<<EIO dump: public test>>=
public :: eio_dump_test
<<EIO dump: test driver>>=
subroutine eio_dump_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO dump: execute tests>>
end subroutine eio_dump_test
@ %def eio_dump_test
@
\subsubsection{Test I/O methods}
We test the implementation of all I/O methods.
<<EIO dump: execute tests>>=
call test (eio_dump_1, "eio_dump_1", &
"write event contents", &
u, results)
<<EIO dump: test declarations>>=
public :: eio_dump_1
<<EIO dump: tests>>=
subroutine eio_dump_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
class(eio_t), allocatable :: eio
integer :: i_prc
integer :: u_file
write (u, "(A)") "* Test output: eio_dump_1"
write (u, "(A)") "* Purpose: generate events and write essentials to output"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
write (u, "(A)")
write (u, "(A)") "* Generate and write three events (two passed)"
write (u, "(A)")
allocate (eio_dump_t :: eio)
select type (eio)
type is (eio_dump_t)
call eio%set_parameters (unit = u, weights = .true., pacify = .true.)
end select
i_prc = 42
call eio%init_out (var_str (""))
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = i_prc)
call event%generate (1, [0.1_default, 0._default])
call event%set_index (99)
call eio%output (event, i_prc = i_prc, passed = .false.)
call event%generate (1, [0.2_default, 0._default])
call event%increment_index ()
call eio%output (event, i_prc = i_prc, passed = .true.)
write (u, "(A)")
write (u, "(A)") "* Contents of eio_dump object"
write (u, "(A)")
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
select type (eio)
type is (eio_dump_t)
eio%writing = .false.
end select
call eio%final ()
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_dump_1"
end subroutine eio_dump_1
@ %def eio_dump_1
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{ASCII File Formats}
Here, we implement several ASCII file formats. It is possible to
switch between them using flags.
<<[[eio_ascii.f90]]>>=
<<File header>>
module eio_ascii
<<Use strings>>
use io_units
use diagnostics
use event_base
use eio_data
use eio_base
use hep_common
use hep_events
<<Standard module head>>
<<EIO ascii: public>>
<<EIO ascii: types>>
contains
<<EIO ascii: procedures>>
end module eio_ascii
@ %def eio_ascii
@
\subsection{Type}
<<EIO ascii: public>>=
public :: eio_ascii_t
<<EIO ascii: types>>=
type, abstract, extends (eio_t) :: eio_ascii_t
logical :: writing = .false.
integer :: unit = 0
logical :: keep_beams = .false.
logical :: keep_remnants = .true.
logical :: ensure_order = .false.
contains
<<EIO ascii: eio ascii: TBP>>
end type eio_ascii_t
@ %def eio_ascii_t
@
<<EIO ascii: public>>=
public :: eio_ascii_ascii_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_ascii_t
end type eio_ascii_ascii_t
@ %def eio_ascii_ascii_t
@
<<EIO ascii: public>>=
public :: eio_ascii_athena_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_athena_t
end type eio_ascii_athena_t
@ %def eio_ascii_athena_t
@ The debug format has a few options that can be controlled by
Sindarin variables.
<<EIO ascii: public>>=
public :: eio_ascii_debug_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_debug_t
logical :: show_process = .true.
logical :: show_transforms = .true.
logical :: show_decay = .true.
logical :: verbose = .true.
end type eio_ascii_debug_t
@ %def eio_ascii_debug_t
@
<<EIO ascii: public>>=
public :: eio_ascii_hepevt_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_hepevt_t
end type eio_ascii_hepevt_t
@ %def eio_ascii_hepevt_t
@
<<EIO ascii: public>>=
public :: eio_ascii_hepevt_verb_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_hepevt_verb_t
end type eio_ascii_hepevt_verb_t
@ %def eio_ascii_hepevt_verb_t
@
<<EIO ascii: public>>=
public :: eio_ascii_lha_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_lha_t
end type eio_ascii_lha_t
@ %def eio_ascii_lha_t
@
<<EIO ascii: public>>=
public :: eio_ascii_lha_verb_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_lha_verb_t
end type eio_ascii_lha_verb_t
@ %def eio_ascii_lha_verb_t
@
<<EIO ascii: public>>=
public :: eio_ascii_long_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_long_t
end type eio_ascii_long_t
@ %def eio_ascii_long_t
@
<<EIO ascii: public>>=
public :: eio_ascii_mokka_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_mokka_t
end type eio_ascii_mokka_t
@ %def eio_ascii_mokka_t
@
<<EIO ascii: public>>=
public :: eio_ascii_short_t
<<EIO ascii: types>>=
type, extends (eio_ascii_t) :: eio_ascii_short_t
end type eio_ascii_short_t
@ %def eio_ascii_short_t
@
\subsection{Specific Methods}
Set parameters that are specifically used with ASCII file formats. In
particular, this is the file extension.
<<EIO ascii: eio ascii: TBP>>=
procedure :: set_parameters => eio_ascii_set_parameters
<<EIO ascii: procedures>>=
subroutine eio_ascii_set_parameters (eio, &
keep_beams, keep_remnants, ensure_order, extension, &
show_process, show_transforms, show_decay, verbose)
class(eio_ascii_t), intent(inout) :: eio
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
logical, intent(in), optional :: ensure_order
type(string_t), intent(in), optional :: extension
logical, intent(in), optional :: show_process, show_transforms, show_decay
logical, intent(in), optional :: verbose
if (present (keep_beams)) eio%keep_beams = keep_beams
if (present (keep_remnants)) eio%keep_remnants = keep_remnants
if (present (ensure_order)) eio%ensure_order = ensure_order
if (present (extension)) then
eio%extension = extension
else
select type (eio)
type is (eio_ascii_ascii_t)
eio%extension = "evt"
type is (eio_ascii_athena_t)
eio%extension = "athena.evt"
type is (eio_ascii_debug_t)
eio%extension = "debug"
type is (eio_ascii_hepevt_t)
eio%extension = "hepevt"
type is (eio_ascii_hepevt_verb_t)
eio%extension = "hepevt.verb"
type is (eio_ascii_lha_t)
eio%extension = "lha"
type is (eio_ascii_lha_verb_t)
eio%extension = "lha.verb"
type is (eio_ascii_long_t)
eio%extension = "long.evt"
type is (eio_ascii_mokka_t)
eio%extension = "mokka.evt"
type is (eio_ascii_short_t)
eio%extension = "short.evt"
end select
end if
select type (eio)
type is (eio_ascii_debug_t)
if (present (show_process)) eio%show_process = show_process
if (present (show_transforms)) eio%show_transforms = show_transforms
if (present (show_decay)) eio%show_decay = show_decay
if (present (verbose)) eio%verbose = verbose
end select
end subroutine eio_ascii_set_parameters
@ %def eio_ascii_set_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO ascii: eio ascii: TBP>>=
procedure :: write => eio_ascii_write
<<EIO ascii: procedures>>=
subroutine eio_ascii_write (object, unit)
class(eio_ascii_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u
u = given_output_unit (unit)
select type (object)
type is (eio_ascii_ascii_t)
write (u, "(1x,A)") "ASCII event stream (default format):"
type is (eio_ascii_athena_t)
write (u, "(1x,A)") "ASCII event stream (ATHENA format):"
type is (eio_ascii_debug_t)
write (u, "(1x,A)") "ASCII event stream (Debugging format):"
type is (eio_ascii_hepevt_t)
write (u, "(1x,A)") "ASCII event stream (HEPEVT format):"
type is (eio_ascii_hepevt_verb_t)
write (u, "(1x,A)") "ASCII event stream (verbose HEPEVT format):"
type is (eio_ascii_lha_t)
write (u, "(1x,A)") "ASCII event stream (LHA format):"
type is (eio_ascii_lha_verb_t)
write (u, "(1x,A)") "ASCII event stream (verbose LHA format):"
type is (eio_ascii_long_t)
write (u, "(1x,A)") "ASCII event stream (long format):"
type is (eio_ascii_mokka_t)
write (u, "(1x,A)") "ASCII event stream (MOKKA format):"
type is (eio_ascii_short_t)
write (u, "(1x,A)") "ASCII event stream (short format):"
end select
if (object%writing) then
write (u, "(3x,A,A)") "Writing to file = ", char (object%filename)
else
write (u, "(3x,A)") "[closed]"
end if
write (u, "(3x,A,L1)") "Keep beams = ", object%keep_beams
write (u, "(3x,A,L1)") "Keep remnants = ", object%keep_remnants
select type (object)
type is (eio_ascii_debug_t)
write (u, "(3x,A,L1)") "Show process = ", object%show_process
write (u, "(3x,A,L1)") "Show transforms = ", object%show_transforms
write (u, "(3x,A,L1)") "Show decay tree = ", object%show_decay
write (u, "(3x,A,L1)") "Verbose output = ", object%verbose
end select
end subroutine eio_ascii_write
@ %def eio_ascii_write
@ Finalizer: close any open file.
<<EIO ascii: eio ascii: TBP>>=
procedure :: final => eio_ascii_final
<<EIO ascii: procedures>>=
subroutine eio_ascii_final (object)
class(eio_ascii_t), intent(inout) :: object
if (object%writing) then
write (msg_buffer, "(A,A,A)") "Events: closing ASCII file '", &
char (object%filename), "'"
call msg_message ()
close (object%unit)
object%writing = .false.
end if
end subroutine eio_ascii_final
@ %def eio_ascii_final
@ Initialize event writing.
Check weight normalization. This applies to all ASCII-type files that
use the HEPRUP common block. We can't allow normalization conventions
that are not covered by the HEPRUP definition.
<<EIO ascii: eio ascii: TBP>>=
procedure :: init_out => eio_ascii_init_out
<<EIO ascii: procedures>>=
subroutine eio_ascii_init_out (eio, sample, data, success, extension)
class(eio_ascii_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
integer :: i
if (.not. present (data)) &
call msg_bug ("ASCII initialization: missing data")
if (data%n_beam /= 2) &
call msg_fatal ("ASCII: defined for scattering processes only")
eio%sample = sample
call eio%check_normalization (data)
call eio%set_splitting (data)
call eio%set_filename ()
eio%unit = free_unit ()
write (msg_buffer, "(A,A,A)") "Events: writing to ASCII file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
open (eio%unit, file = char (eio%filename), &
action = "write", status = "replace")
select type (eio)
type is (eio_ascii_lha_t)
call heprup_init &
(data%pdg_beam, &
data%energy_beam, &
n_processes = data%n_proc, &
unweighted = data%unweighted, &
negative_weights = data%negative_weights)
do i = 1, data%n_proc
call heprup_set_process_parameters (i = i, &
process_id = data%proc_num_id(i), &
cross_section = data%cross_section(i), &
error = data%error(i))
end do
call heprup_write_ascii (eio%unit)
type is (eio_ascii_lha_verb_t)
call heprup_init &
(data%pdg_beam, &
data%energy_beam, &
n_processes = data%n_proc, &
unweighted = data%unweighted, &
negative_weights = data%negative_weights)
do i = 1, data%n_proc
call heprup_set_process_parameters (i = i, &
process_id = data%proc_num_id(i), &
cross_section = data%cross_section(i), &
error = data%error(i))
end do
call heprup_write_verbose (eio%unit)
end select
if (present (success)) success = .true.
end subroutine eio_ascii_init_out
@ %def eio_ascii_init_out
@ Some event properties do not go well with some output formats. In
particular, many formats require unweighted events.
<<EIO ascii: eio ascii: TBP>>=
procedure :: check_normalization => eio_ascii_check_normalization
<<EIO ascii: procedures>>=
subroutine eio_ascii_check_normalization (eio, data)
class(eio_ascii_t), intent(in) :: eio
type(event_sample_data_t), intent(in) :: data
if (data%unweighted) then
else
select type (eio)
type is (eio_ascii_athena_t); call msg_fatal &
("Event output (Athena format): events must be unweighted.")
type is (eio_ascii_hepevt_t); call msg_fatal &
("Event output (HEPEVT format): events must be unweighted.")
type is (eio_ascii_hepevt_verb_t); call msg_fatal &
("Event output (HEPEVT format): events must be unweighted.")
end select
select case (data%norm_mode)
case (NORM_SIGMA)
case default
select type (eio)
type is (eio_ascii_lha_t)
call msg_fatal &
("Event output (LHA): normalization for weighted events &
&must be 'sigma'")
type is (eio_ascii_lha_verb_t)
call msg_fatal &
("Event output (LHA): normalization for weighted events &
&must be 'sigma'")
end select
end select
end if
end subroutine eio_ascii_check_normalization
@ %def check_normalization
@ Initialize event reading.
<<EIO ascii: eio ascii: TBP>>=
procedure :: init_in => eio_ascii_init_in
<<EIO ascii: procedures>>=
subroutine eio_ascii_init_in (eio, sample, data, success, extension)
class(eio_ascii_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
call msg_bug ("ASCII: event input not supported")
if (present (success)) success = .false.
end subroutine eio_ascii_init_in
@ %def eio_ascii_init_in
@ Switch from input to output: reopen the file for reading.
<<EIO ascii: eio ascii: TBP>>=
procedure :: switch_inout => eio_ascii_switch_inout
<<EIO ascii: procedures>>=
subroutine eio_ascii_switch_inout (eio, success)
class(eio_ascii_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("ASCII: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_ascii_switch_inout
@ %def eio_ascii_switch_inout
@ Split event file: increment the counter, close the current file, open a new
one. If the file needs a header, repeat it for the new file. (We assume that
the common block contents are still intact.)
<<EIO ascii: eio ascii: TBP>>=
procedure :: split_out => eio_ascii_split_out
<<EIO ascii: procedures>>=
subroutine eio_ascii_split_out (eio)
class(eio_ascii_t), intent(inout) :: eio
if (eio%split) then
eio%split_index = eio%split_index + 1
call eio%set_filename ()
write (msg_buffer, "(A,A,A)") "Events: writing to ASCII file '", &
char (eio%filename), "'"
call msg_message ()
close (eio%unit)
open (eio%unit, file = char (eio%filename), &
action = "write", status = "replace")
select type (eio)
type is (eio_ascii_lha_t)
call heprup_write_ascii (eio%unit)
type is (eio_ascii_lha_verb_t)
call heprup_write_verbose (eio%unit)
end select
end if
end subroutine eio_ascii_split_out
@ %def eio_ascii_split_out
@ Output an event. Write first the event indices, then weight and
squared matrix element, then the particle set.
Events that did not pass the selection are skipped. The exceptions are
the [[ascii]] and [[debug]] formats. These are the formats that
contain the [[passed]] flag in their output, and should be most useful
for debugging purposes.
<<EIO ascii: eio ascii: TBP>>=
procedure :: output => eio_ascii_output
<<EIO ascii: procedures>>=
subroutine eio_ascii_output (eio, event, i_prc, reading, passed, pacify)
class(eio_ascii_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
if (present (passed)) then
if (.not. passed) then
select type (eio)
type is (eio_ascii_debug_t)
type is (eio_ascii_ascii_t)
class default
return
end select
end if
end if
if (eio%writing) then
select type (eio)
type is (eio_ascii_lha_t)
call hepeup_from_event (event, &
process_index = i_prc, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants)
call hepeup_write_lha (eio%unit)
type is (eio_ascii_lha_verb_t)
call hepeup_from_event (event, &
process_index = i_prc, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants)
call hepeup_write_verbose (eio%unit)
type is (eio_ascii_ascii_t)
call event%write (eio%unit, &
show_process = .false., &
show_transforms = .false., &
show_decay = .false., &
verbose = .false., testflag = pacify)
type is (eio_ascii_athena_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call hepevt_write_athena (eio%unit)
type is (eio_ascii_debug_t)
call event%write (eio%unit, &
show_process = eio%show_process, &
show_transforms = eio%show_transforms, &
show_decay = eio%show_decay, &
verbose = eio%verbose, &
testflag = pacify)
type is (eio_ascii_hepevt_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call hepevt_write_hepevt (eio%unit)
type is (eio_ascii_hepevt_verb_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call hepevt_write_verbose (eio%unit)
type is (eio_ascii_long_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call hepevt_write_ascii (eio%unit, .true.)
type is (eio_ascii_mokka_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call hepevt_write_mokka (eio%unit)
type is (eio_ascii_short_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call hepevt_write_ascii (eio%unit, .false.)
end select
else
call eio%write ()
call msg_fatal ("ASCII file is not open for writing")
end if
end subroutine eio_ascii_output
@ %def eio_ascii_output
@ Input an event.
<<EIO ascii: eio ascii: TBP>>=
procedure :: input_i_prc => eio_ascii_input_i_prc
procedure :: input_event => eio_ascii_input_event
<<EIO ascii: procedures>>=
subroutine eio_ascii_input_i_prc (eio, i_prc, iostat)
class(eio_ascii_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
call msg_bug ("ASCII: event input not supported")
i_prc = 0
iostat = 1
end subroutine eio_ascii_input_i_prc
subroutine eio_ascii_input_event (eio, event, iostat)
class(eio_ascii_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
call msg_bug ("ASCII: event input not supported")
iostat = 1
end subroutine eio_ascii_input_event
@ %def eio_ascii_input_i_prc
@ %def eio_ascii_input_event
@
<<EIO ascii: eio ascii: TBP>>=
procedure :: skip => eio_ascii_skip
<<EIO ascii: procedures>>=
subroutine eio_ascii_skip (eio, iostat)
class(eio_ascii_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_ascii_skip
@ %def eio_asciii_skip
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_ascii_ut.f90]]>>=
<<File header>>
module eio_ascii_ut
use unit_tests
use eio_ascii_uti
<<Standard module head>>
<<EIO ascii: public test>>
contains
<<EIO ascii: test driver>>
end module eio_ascii_ut
@ %def eio_ascii_ut
@
<<[[eio_ascii_uti.f90]]>>=
<<File header>>
module eio_ascii_uti
<<Use kinds>>
<<Use strings>>
use io_units
use model_data
use event_base
use eio_data
use eio_base
use eio_ascii
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
<<Standard module head>>
<<EIO ascii: test declarations>>
contains
<<EIO ascii: tests>>
end module eio_ascii_uti
@ %def eio_ascii_uti
@ API: driver for the unit tests below.
<<EIO ascii: public test>>=
public :: eio_ascii_test
<<EIO ascii: test driver>>=
subroutine eio_ascii_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO ascii: execute tests>>
end subroutine eio_ascii_test
@ %def eio_ascii_test
@
\subsubsection{Test I/O methods}
We test the implementation of all I/O methods, method [[ascii]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_1, "eio_ascii_1", &
"read and write event contents, format [ascii]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_1
<<EIO ascii: tests>>=
subroutine eio_ascii_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_1"
write (u, "(A)") "* Purpose: generate an event in ASCII ascii format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_1"
allocate (eio_ascii_ascii_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (42)
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".evt"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_ascii_t :: eio)
select type (eio)
type is (eio_ascii_ascii_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_1"
end subroutine eio_ascii_1
@ %def eio_ascii_1
@
We test the implementation of all I/O methods, method [[athena]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_2, "eio_ascii_2", &
"read and write event contents, format [athena]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_2
<<EIO ascii: tests>>=
subroutine eio_ascii_2 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_2"
write (u, "(A)") "* Purpose: generate an event in ASCII athena format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_2"
allocate (eio_ascii_athena_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (42)
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char(sample // ".athena.evt"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_athena_t :: eio)
select type (eio)
type is (eio_ascii_athena_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_2"
end subroutine eio_ascii_2
@ %def eio_ascii_2
@
We test the implementation of all I/O methods, method [[debug]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_3, "eio_ascii_3", &
"read and write event contents, format [debug]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_3
<<EIO ascii: tests>>=
subroutine eio_ascii_3 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_3"
write (u, "(A)") "* Purpose: generate an event in ASCII debug format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_3"
allocate (eio_ascii_debug_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".debug"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_debug_t :: eio)
select type (eio)
type is (eio_ascii_debug_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_3"
end subroutine eio_ascii_3
@ %def eio_ascii_3
@
We test the implementation of all I/O methods, method [[hepevt]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_4, "eio_ascii_4", &
"read and write event contents, format [hepevt]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_4
<<EIO ascii: tests>>=
subroutine eio_ascii_4 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_4"
write (u, "(A)") "* Purpose: generate an event in ASCII hepevt format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_4"
allocate (eio_ascii_hepevt_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".hepevt"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_hepevt_t :: eio)
select type (eio)
type is (eio_ascii_hepevt_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_4"
end subroutine eio_ascii_4
@ %def eio_ascii_4
@
We test the implementation of all I/O methods, method [[lha]] (old LHA):
<<EIO ascii: execute tests>>=
call test (eio_ascii_5, "eio_ascii_5", &
"read and write event contents, format [lha]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_5
<<EIO ascii: tests>>=
subroutine eio_ascii_5 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_5"
write (u, "(A)") "* Purpose: generate an event in ASCII LHA format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_5"
allocate (eio_ascii_lha_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".lha"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_lha_t :: eio)
select type (eio)
type is (eio_ascii_lha_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_5"
end subroutine eio_ascii_5
@ %def eio_ascii_5
@
We test the implementation of all I/O methods, method [[long]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_6, "eio_ascii_6", &
"read and write event contents, format [long]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_6
<<EIO ascii: tests>>=
subroutine eio_ascii_6 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_6"
write (u, "(A)") "* Purpose: generate an event in ASCII long format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_6"
allocate (eio_ascii_long_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".long.evt"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_long_t :: eio)
select type (eio)
type is (eio_ascii_long_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_6"
end subroutine eio_ascii_6
@ %def eio_ascii_6
@
We test the implementation of all I/O methods, method [[mokka]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_7, "eio_ascii_7", &
"read and write event contents, format [mokka]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_7
<<EIO ascii: tests>>=
subroutine eio_ascii_7 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_7"
write (u, "(A)") "* Purpose: generate an event in ASCII mokka format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_7"
allocate (eio_ascii_mokka_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".mokka.evt"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_mokka_t :: eio)
select type (eio)
type is (eio_ascii_mokka_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_7"
end subroutine eio_ascii_7
@ %def eio_ascii_7
@
We test the implementation of all I/O methods, method [[short]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_8, "eio_ascii_8", &
"read and write event contents, format [short]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_8
<<EIO ascii: tests>>=
subroutine eio_ascii_8 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_8"
write (u, "(A)") "* Purpose: generate an event in ASCII short format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_8"
allocate (eio_ascii_short_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".short.evt"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_short_t :: eio)
select type (eio)
type is (eio_ascii_short_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_8"
end subroutine eio_ascii_8
@ %def eio_ascii_8
@
We test the implementation of all I/O methods, method [[lha]] (old
LHA) in verbose version:
<<EIO ascii: execute tests>>=
call test (eio_ascii_9, "eio_ascii_9", &
"read and write event contents, format [lha_verb]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_9
<<EIO ascii: tests>>=
subroutine eio_ascii_9 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_9"
write (u, "(A)") "* Purpose: generate an event in ASCII LHA verbose format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_9"
allocate (eio_ascii_lha_verb_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".lha.verb"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_lha_verb_t :: eio)
select type (eio)
type is (eio_ascii_lha_verb_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_9"
end subroutine eio_ascii_9
@ %def eio_ascii_9
@
We test the implementation of all I/O methods, method [[hepevt_verb]]:
<<EIO ascii: execute tests>>=
call test (eio_ascii_10, "eio_ascii_10", &
"read and write event contents, format [hepevt_verb]", &
u, results)
<<EIO ascii: test declarations>>=
public :: eio_ascii_10
<<EIO ascii: tests>>=
subroutine eio_ascii_10 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_ascii_10"
write (u, "(A)") "* Purpose: generate an event in ASCII hepevt verbose format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_ascii_10"
allocate (eio_ascii_hepevt_verb_t :: eio)
select type (eio)
class is (eio_ascii_t); call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%increment_index ()
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".hepevt.verb"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_ascii_hepevt_verb_t :: eio)
select type (eio)
type is (eio_ascii_hepevt_verb_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_ascii_10"
end subroutine eio_ascii_10
@ %def eio_ascii_10
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{HEP Common Blocks}
Long ago, to transfer data between programs one had to set up a common
block and link both programs as libraries to the main executable. The
HEP community standardizes several of those common blocks.
The modern way of data exchange uses data files with standard
formats. However, the LHEF standard data format derives from a common
block (actually, two).
\whizard\ used to support those common blocks, and LHEF was
implemented via writing/reading blocks. We still keep this
convention, but intend to eliminate common blocks (or any other static
storage) from the workflow in the future. This will gain flexibility
towards concurrent running of program images.
We encapsulate everything here in a module. The module holds the
variables which are part of the common block. To access the common
block variables, we just have to [[use]] this module. (They are
nevertheless in the common block, since external software may access
it in this way.)
Note: This code is taken essentially unchanged from \whizard\ 2.1 and
does not (yet) provide unit tests.
<<[[hep_common.f90]]>>=
<<File header>>
module hep_common
<<Use kinds>>
use kinds, only: double
use constants
<<Use strings>>
<<Use debug>>
use io_units
use diagnostics
use numeric_utils
use physics_defs, only: HADRON_REMNANT
use physics_defs, only: HADRON_REMNANT_SINGLET
use physics_defs, only: HADRON_REMNANT_TRIPLET
use physics_defs, only: HADRON_REMNANT_OCTET
use xml
use lorentz
use flavors
use colors
use polarizations
use model_data
use particles
use subevents, only: PRT_BEAM, PRT_INCOMING, PRT_OUTGOING
use subevents, only: PRT_UNDEFINED
use subevents, only: PRT_VIRTUAL, PRT_RESONANT, PRT_BEAM_REMNANT
<<Standard module head>>
<<HEP common: public>>
<<HEP common: interfaces>>
<<HEP common: parameters>>
<<HEP common: variables>>
<<HEP common: common blocks>>
contains
<<HEP common: procedures>>
end module hep_common
@ %def hep_common
@
\subsection{Event characteristics}
The maximal number of particles in an event record.
<<HEP common: parameters>>=
integer, parameter, public :: MAXNUP = 500
@ %def MAXNUP
@ The number of particles in this event.
<<HEP common: variables>>=
integer, public :: NUP
@ %def NUP
@ The process ID for this event.
<<HEP common: variables>>=
integer, public :: IDPRUP
@ %def IDPRUP
@ The weight of this event ($\pm 1$ for unweighted events).
<<HEP common: variables>>=
double precision, public :: XWGTUP
@ %def XWGTUP
@ The factorization scale that is used for PDF calculation ($-1$ if
undefined).
<<HEP common: variables>>=
double precision, public :: SCALUP
@ %def SCALUP
@ The QED and QCD couplings $\alpha$ used for this event ($-1$ if
undefined).
<<HEP common: variables>>=
double precision, public :: AQEDUP
double precision, public :: AQCDUP
@ %def AQEDUP AQCDUP
@
\subsection{Particle characteristics}
The PDG code:
<<HEP common: variables>>=
integer, dimension(MAXNUP), public :: IDUP
@ %def IDUP
@ The status code. Incoming: $-1$, outgoing: $+1$. Intermediate
t-channel propagator: $-2$ (currently not used by WHIZARD).
Intermediate resonance whose mass should be preserved: $2$.
Intermediate resonance for documentation: $3$ (currently not used).
Beam particles: $-9$.
<<HEP common: variables>>=
integer, dimension(MAXNUP), public :: ISTUP
@ %def ISTUP
@ Index of first and last mother.
<<HEP common: variables>>=
integer, dimension(2,MAXNUP), public :: MOTHUP
@ %def MOTHUP
@ Color line index of the color and anticolor entry for the particle.
The standard recommends using large numbers; we start from MAXNUP+1.
<<HEP common: variables>>=
integer, dimension(2,MAXNUP), public :: ICOLUP
@ %def ICOLUP
@ Momentum, energy, and invariant mass: $(p_x,p_y,p_z,E,M)$. For
space-like particles, $M$ is the negative square root of the absolute
value of the invariant mass.
<<HEP common: variables>>=
double precision, dimension(5,MAXNUP), public :: PUP
@ %def PUP
@ Invariant lifetime (distance) from production to decay in mm.
<<HEP common: variables>>=
double precision, dimension(MAXNUP), public :: VTIMUP
@ %def VTIMUP
@ Cosine of the angle between the spin-vector and a particle and the
3-momentum of its mother, given in the lab frame. If
undefined/unpolarized: $9$.
<<HEP common: variables>>=
double precision, dimension(MAXNUP), public :: SPINUP
@ %def SPINUP
@
\subsection{The HEPRUP common block}
This common block is filled once per run.
\subsubsection{Run characteristics}
The maximal number of different processes.
<<HEP common: parameters>>=
integer, parameter, public :: MAXPUP = 100
@ %def MAXPUP
@ The beam PDG codes.
<<HEP common: variables>>=
integer, dimension(2), public :: IDBMUP
@ %def IDBMUP
@ The beam energies in GeV.
<<HEP common: variables>>=
double precision, dimension(2), public :: EBMUP
@ %def EBMUP
@ The PDF group and set for the two beams. (Undefined: use $-1$;
LHAPDF: use group = $0$).
<<HEP common: variables>>=
integer, dimension(2), public :: PDFGUP
integer, dimension(2), public :: PDFSUP
@ %def PDFGUP PDFSUP
@ The (re)weighting model. 1: events are weighted, the shower
generator (SHG) selects processes according to the maximum weight (in
pb) and unweights events. 2: events are weighted, the SHG selects
processes according to their cross section (in pb) and unweights
events. 3: events are unweighted and simply run through the SHG. 4:
events are weighted, and the SHG keeps the weight. Negative numbers:
negative weights are allowed (and are reweighted to $\pm 1$ by the
SHG, if allowed).
\whizard\ only supports modes 3 and 4, as the SHG is not given control
over process selection. This is consistent with writing events to
file, for offline showering.
<<HEP common: variables>>=
integer, public :: IDWTUP
@ %def IDWTUP
@ The number of different processes.
<<HEP common: variables>>=
integer, public :: NPRUP
@ %def NPRUP
@
\subsubsection{Process characteristics}
Cross section and error in pb. (Cross section is needed only for
$[[IDWTUP]] = 2$, so here both values are given for informational
purposes only.)
<<HEP common: variables>>=
double precision, dimension(MAXPUP), public :: XSECUP
double precision, dimension(MAXPUP), public :: XERRUP
@ %def XSECUP XERRUP
@ Maximum weight, i.e., the maximum value that [[XWGTUP]] can take.
Also unused for the supported weighting models. It is $\pm 1$ for
unweighted events.
<<HEP common: variables>>=
double precision, dimension(MAXPUP), public :: XMAXUP
@ %def XMAXUP
@ Internal ID of the selected process, matches [[IDPRUP]] below.
<<HEP common: variables>>=
integer, dimension(MAXPUP), public :: LPRUP
@ %def LPRUP
@
\subsubsection{The common block}
<<HEP common: common blocks>>=
common /HEPRUP/ &
IDBMUP, EBMUP, PDFGUP, PDFSUP, IDWTUP, NPRUP, &
XSECUP, XERRUP, XMAXUP, LPRUP
save /HEPRUP/
@ %def HEPRUP
@ Fill the run characteristics of the common block. The
initialization sets the beam properties, number of processes, and
weighting model.
<<HEP common: public>>=
public :: heprup_init
<<HEP common: procedures>>=
subroutine heprup_init &
(beam_pdg, beam_energy, n_processes, unweighted, negative_weights)
integer, dimension(2), intent(in) :: beam_pdg
real(default), dimension(2), intent(in) :: beam_energy
integer, intent(in) :: n_processes
logical, intent(in) :: unweighted
logical, intent(in) :: negative_weights
IDBMUP = beam_pdg
EBMUP = beam_energy
PDFGUP = -1
PDFSUP = -1
if (unweighted) then
IDWTUP = 3
else
IDWTUP = 4
end if
if (negative_weights) IDWTUP = - IDWTUP
NPRUP = n_processes
end subroutine heprup_init
@ %def heprup_init
The HEPRUP (event) common block is needed for the interface to the shower.
Filling of it is triggered by some output file formats. If these are not
present, the common block is filled with some dummy information. Be generous
with the number of processes in HEPRUP so that PYTHIA only rarely needs to be
reinitialized in case events with higher process ids are generated.
<<HEP common: public>>=
public :: assure_heprup
<<HEP common: procedures>>=
subroutine assure_heprup (pset)
type(particle_set_t), intent(in) :: pset
integer :: i, num_id
integer, parameter :: min_processes = 10
num_id = 1
if (LPRUP (num_id) /= 0) return
call heprup_init ( &
[pset%prt(1)%get_pdg (), pset%prt(2)%get_pdg ()] , &
[pset%prt(1)%p%p(0), pset%prt(2)%p%p(0)], &
num_id, .false., .false.)
do i = 1, (num_id / min_processes + 1) * min_processes
call heprup_set_process_parameters (i = i, process_id = &
i, cross_section = 1._default, error = 1._default)
end do
end subroutine assure_heprup
@ %def assure_heprup
@ Read in the LHE file opened in unit [[u]] and add the final
particles to the [[particle_set]], the outgoing particles of the existing
[[particle_set]] are compared to the particles that are read in. When
they are equal in flavor and momenta, they are erased and their
mother-daughter relations are transferred to the existing particles.
<<HEP common: public>>=
public :: combine_lhef_with_particle_set
<<HEP common: procedures>>=
subroutine combine_lhef_with_particle_set &
(particle_set, u, model_in, model_hadrons)
type(particle_set_t), intent(inout) :: particle_set
integer, intent(in) :: u
class(model_data_t), intent(in), target :: model_in
class(model_data_t), intent(in), target :: model_hadrons
type(flavor_t) :: flv
type(color_t) :: col
class(model_data_t), pointer :: model
type(particle_t), dimension(:), allocatable :: prt_tmp, prt
integer :: i, j
type(vector4_t) :: mom, d_mom
integer, PARAMETER :: MAXLEN=200
character(len=maxlen) :: string
integer :: ibeg, n_tot, n_entries
integer, dimension(:), allocatable :: relations, mothers, tbd
INTEGER :: NUP,IDPRUP,IDUP,ISTUP
real(kind=double) :: XWGTUP,SCALUP,AQEDUP,AQCDUP,VTIMUP,SPINUP
integer :: MOTHUP(1:2), ICOLUP(1:2)
real(kind=double) :: PUP(1:5)
real(kind=default) :: pup_dum(1:5)
character(len=5) :: buffer
character(len=6) :: strfmt
logical :: not_found
logical :: debug_lhef = .false.
STRFMT='(A000)'
WRITE (STRFMT(3:5),'(I3)') MAXLEN
if (debug_lhef) call particle_set%write ()
rewind (u)
do
read (u,*, END=501, ERR=502) STRING
IBEG = 0
do
if (signal_is_pending ()) return
IBEG = IBEG + 1
! Allow indentation.
IF (STRING (IBEG:IBEG) .EQ. ' ' .and. IBEG < MAXLEN-6) cycle
exit
end do
IF (string(IBEG:IBEG+6) /= '<event>' .and. &
string(IBEG:IBEG+6) /= '<event ') cycle
exit
end do
!!! Read first line of event info -> number of entries
read (u, *, END=503, ERR=504) NUP, IDPRUP, XWGTUP, SCALUP, AQEDUP, AQCDUP
n_tot = particle_set%get_n_tot ()
allocate (prt_tmp (1:n_tot+NUP))
allocate (relations (1:NUP), mothers (1:NUP), tbd(1:NUP))
do i = 1, n_tot
if (signal_is_pending ()) return
prt_tmp (i) = particle_set%get_particle (i)
end do
!!! transfer particles from lhef to particle_set
!!!...Read NUP subsequent lines with information on each particle.
n_entries = 1
mothers = 0
relations = 0
PARTICLE_LOOP: do I = 1, NUP
read (u,*, END=200, ERR=505) IDUP, ISTUP, MOTHUP(1), MOTHUP(2), &
ICOLUP(1), ICOLUP(2), (PUP (J),J=1,5), VTIMUP, SPINUP
if (model_in%test_field (IDUP)) then
model => model_in
else if (model_hadrons%test_field (IDUP)) then
model => model_hadrons
else
write (buffer, "(I5)") IDUP
call msg_error ("Parton " // buffer // &
" found neither in given model file nor in SM_hadrons")
return
end if
if (debug_lhef) then
print *, "IDUP, ISTUP, MOTHUP, PUP = ", IDUP, ISTUP, MOTHUP(1), &
MOTHUP(2), PUP
end if
call flv%init (IDUP, model)
if (IABS(IDUP) == 2212 .or. IABS(IDUP) == 2112) then
! PYTHIA sometimes sets color indices for protons and neutrons (?)
ICOLUP (1) = 0
ICOLUP (2) = 0
end if
call col%init_col_acl (ICOLUP (1), ICOLUP (2))
!!! Settings for unpolarized particles
! particle_set%prt (oldsize+i)%hel = ??
! particle_set%prt (oldsize+i)%pol = ??
if (MOTHUP(1) /= 0) then
mothers(i) = MOTHUP(1)
end if
pup_dum = PUP
if (pup_dum(4) < 1E-10_default) cycle
mom = vector4_moving (pup_dum (4), &
vector3_moving ([pup_dum (1), pup_dum (2), pup_dum (3)]))
not_found = .true.
SCAN_PARTICLES: do j = 1, n_tot
d_mom = prt_tmp(j)%get_momentum ()
if (all (nearly_equal &
(mom%p, d_mom%p, abs_smallness = 1.E-4_default)) .and. &
(prt_tmp(j)%get_pdg () == IDUP)) then
if (.not. prt_tmp(j)%get_status () == PRT_BEAM .or. &
.not. prt_tmp(j)%get_status () == PRT_BEAM_REMNANT) &
relations(i) = j
not_found = .false.
end if
end do SCAN_PARTICLES
if (not_found) then
if (debug_lhef) &
print *, "Not found: adding particle"
call prt_tmp(n_tot+n_entries)%set_flavor (flv)
call prt_tmp(n_tot+n_entries)%set_color (col)
call prt_tmp(n_tot+n_entries)%set_momentum (mom)
if (MOTHUP(1) /= 0) then
if (relations(MOTHUP(1)) /= 0) then
call prt_tmp(n_tot+n_entries)%set_parents &
([relations(MOTHUP(1))])
call prt_tmp(relations(MOTHUP(1)))%add_child (n_tot+n_entries)
if (prt_tmp(relations(MOTHUP(1)))%get_status () &
== PRT_OUTGOING) &
call prt_tmp(relations(MOTHUP(1)))%reset_status &
(PRT_VIRTUAL)
end if
end if
call prt_tmp(n_tot+n_entries)%set_status (PRT_OUTGOING)
if (debug_lhef) call prt_tmp(n_tot+n_entries)%write ()
n_entries = n_entries + 1
end if
end do PARTICLE_LOOP
do i = 1, n_tot
if (prt_tmp(i)%get_status () == PRT_OUTGOING .and. &
prt_tmp(i)%get_n_children () /= 0) then
call prt_tmp(i)%reset_status (PRT_VIRTUAL)
end if
end do
allocate (prt (1:n_tot+n_entries-1))
prt = prt_tmp (1:n_tot+n_entries-1)
! transfer to particle_set
call particle_set%replace (prt)
deallocate (prt, prt_tmp)
if (debug_lhef) then
call particle_set%write ()
print *, "combine_lhef_with_particle_set"
! stop
end if
200 continue
return
501 write(*,*) "READING LHEF failed 501"
return
502 write(*,*) "READING LHEF failed 502"
return
503 write(*,*) "READING LHEF failed 503"
return
504 write(*,*) "READING LHEF failed 504"
return
505 write(*,*) "READING LHEF failed 505"
return
end subroutine combine_lhef_with_particle_set
@ %def combine_lhef_with_particle_set
@
<<HEP common: public>>=
public :: w2p_write_lhef_event
<<HEP common: procedures>>=
subroutine w2p_write_lhef_event (unit)
integer, intent(in) :: unit
type(xml_tag_t), allocatable :: tag_lhef, tag_head, tag_init, &
tag_event, tag_gen_n, tag_gen_v
if (debug_on) call msg_debug (D_EVENTS, "w2p_write_lhef_event")
allocate (tag_lhef, tag_head, tag_init, tag_event, &
tag_gen_n, tag_gen_v)
call tag_lhef%init (var_str ("LesHouchesEvents"), &
[xml_attribute (var_str ("version"), var_str ("1.0"))], .true.)
call tag_head%init (var_str ("header"), .true.)
call tag_init%init (var_str ("init"), .true.)
call tag_event%init (var_str ("event"), .true.)
call tag_gen_n%init (var_str ("generator_name"), .true.)
call tag_gen_v%init (var_str ("generator_version"), .true.)
call tag_lhef%write (unit); write (unit, *)
call tag_head%write (unit); write (unit, *)
write (unit, "(2x)", advance = "no")
call tag_gen_n%write (var_str ("WHIZARD"), unit)
write (unit, *)
write (unit, "(2x)", advance = "no")
call tag_gen_v%write (var_str ("<<Version>>"), unit)
write (unit, *)
call tag_head%close (unit); write (unit, *)
call tag_init%write (unit); write (unit, *)
call heprup_write_lhef (unit)
call tag_init%close (unit); write (unit, *)
call tag_event%write (unit); write (unit, *)
call hepeup_write_lhef (unit)
call tag_event%close (unit); write (unit, *)
call tag_lhef%close (unit); write (unit, *)
deallocate (tag_lhef, tag_head, tag_init, tag_event, &
tag_gen_n, tag_gen_v)
end subroutine w2p_write_lhef_event
@ %def w2p_write_lhef_event
@ Extract parameters from the common block. We leave it to the caller
to specify which parameters it actually needs.
[[PDFGUP]] and [[PDFSUP]] are not extracted. [[IDWTUP=1,2]] are not
supported by \whizard, but correspond to weighted events.
<<HEP common: public>>=
public :: heprup_get_run_parameters
<<HEP common: procedures>>=
subroutine heprup_get_run_parameters &
(beam_pdg, beam_energy, n_processes, unweighted, negative_weights)
integer, dimension(2), intent(out), optional :: beam_pdg
real(default), dimension(2), intent(out), optional :: beam_energy
integer, intent(out), optional :: n_processes
logical, intent(out), optional :: unweighted
logical, intent(out), optional :: negative_weights
if (present (beam_pdg)) beam_pdg = IDBMUP
if (present (beam_energy)) beam_energy = EBMUP
if (present (n_processes)) n_processes = NPRUP
if (present (unweighted)) then
select case (abs (IDWTUP))
case (3)
unweighted = .true.
case (4)
unweighted = .false.
case (1,2) !!! not supported by WHIZARD
unweighted = .false.
case default
call msg_fatal ("HEPRUP: unsupported IDWTUP value")
end select
end if
if (present (negative_weights)) then
negative_weights = IDWTUP < 0
end if
end subroutine heprup_get_run_parameters
@ %def heprup_get_run_parameters
@ Specify PDF set info. Since we support only LHAPDF, the group entry
is zero.
<<HEP common: public>>=
public :: heprup_set_lhapdf_id
<<HEP common: procedures>>=
subroutine heprup_set_lhapdf_id (i_beam, pdf_id)
integer, intent(in) :: i_beam, pdf_id
PDFGUP(i_beam) = 0
PDFSUP(i_beam) = pdf_id
end subroutine heprup_set_lhapdf_id
@ %def heprup_set_lhapdf_id
@ Fill the characteristics for a particular process. Only the process
ID is mandatory. Note that \whizard\ computes cross sections in fb,
so we have to rescale to pb. The maximum weight is meaningless for
unweighted events.
<<HEP common: public>>=
public :: heprup_set_process_parameters
<<HEP common: procedures>>=
subroutine heprup_set_process_parameters &
(i, process_id, cross_section, error, max_weight)
integer, intent(in) :: i, process_id
real(default), intent(in), optional :: cross_section, error, max_weight
real(default), parameter :: pb_per_fb = 1.e-3_default
LPRUP(i) = process_id
if (present (cross_section)) then
XSECUP(i) = cross_section * pb_per_fb
else
XSECUP(i) = 0
end if
if (present (error)) then
XERRUP(i) = error * pb_per_fb
else
XERRUP(i) = 0
end if
select case (IDWTUP)
case (3); XMAXUP(i) = 1
case (4)
if (present (max_weight)) then
XMAXUP(i) = max_weight * pb_per_fb
else
XMAXUP(i) = 0
end if
end select
end subroutine heprup_set_process_parameters
@ %def heprup_set_process_parameters
@ Extract the process parameters, as far as needed.
<<HEP common: public>>=
public :: heprup_get_process_parameters
<<HEP common: procedures>>=
subroutine heprup_get_process_parameters &
(i, process_id, cross_section, error, max_weight)
integer, intent(in) :: i
integer, intent(out), optional :: process_id
real(default), intent(out), optional :: cross_section, error, max_weight
real(default), parameter :: pb_per_fb = 1.e-3_default
if (present (process_id)) process_id = LPRUP(i)
if (present (cross_section)) then
cross_section = XSECUP(i) / pb_per_fb
end if
if (present (error)) then
error = XERRUP(i) / pb_per_fb
end if
if (present (max_weight)) then
select case (IDWTUP)
case (3)
max_weight = 1
case (4)
max_weight = XMAXUP(i) / pb_per_fb
case (1,2) !!! not supported by WHIZARD
max_weight = 0
case default
call msg_fatal ("HEPRUP: unsupported IDWTUP value")
end select
end if
end subroutine heprup_get_process_parameters
@ %def heprup_get_process_parameters
@
\subsection{Run parameter output (verbose)}
This is a verbose output of the HEPRUP block.
<<HEP common: public>>=
public :: heprup_write_verbose
<<HEP common: procedures>>=
subroutine heprup_write_verbose (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(A)") "HEPRUP Common Block"
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "IDBMUP", IDBMUP, &
"PDG code of beams"
write (u, "(3x,A6,' = ',G12.5,1x,G12.5,8x,A)") "EBMUP ", EBMUP, &
"Energy of beams in GeV"
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "PDFGUP", PDFGUP, &
"PDF author group [-1 = undefined]"
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "PDFSUP", PDFSUP, &
"PDF set ID [-1 = undefined]"
write (u, "(3x,A6,' = ',I9,3x,1x,9x,3x,8x,A)") "IDWTUP", IDWTUP, &
"LHA code for event weight mode"
write (u, "(3x,A6,' = ',I9,3x,1x,9x,3x,8x,A)") "NPRUP ", NPRUP, &
"Number of user subprocesses"
do i = 1, NPRUP
write (u, "(1x,A,I0)") "Subprocess #", i
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "XSECUP", XSECUP(i), &
"Cross section in pb"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "XERRUP", XERRUP(i), &
"Cross section error in pb"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "XMAXUP", XMAXUP(i), &
"Maximum event weight (cf. IDWTUP)"
write (u, "(3x,A6,' = ',I9,3x,1x,12x,8x,A)") "LPRUP ", LPRUP(i), &
"Subprocess ID"
end do
end subroutine heprup_write_verbose
@ %def heprup_write_verbose
@
\subsection{Run parameter output (other formats)}
This routine writes the initialization block according to the LHEF
standard. It uses the current contents of the HEPRUP block.
<<HEP common: public>>=
public :: heprup_write_lhef
<<HEP common: procedures>>=
subroutine heprup_write_lhef (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(2(1x,I0),2(1x,ES17.10),6(1x,I0))") &
IDBMUP, EBMUP, PDFGUP, PDFSUP, IDWTUP, NPRUP
do i = 1, NPRUP
write (u, "(3(1x,ES17.10),1x,I0)") &
XSECUP(i), XERRUP(i), XMAXUP(i), LPRUP(i)
end do
end subroutine heprup_write_lhef
@ %def heprup_write_lhef
@
This routine is a complete dummy at the moment. It uses the current
contents of the HEPRUP block. At the end, it should depend on certain
input flags for the different ASCII event formats.
<<HEP common: public>>=
public :: heprup_write_ascii
<<HEP common: procedures>>=
subroutine heprup_write_ascii (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(2(1x,I0),2(1x,ES17.10),6(1x,I0))") &
IDBMUP, EBMUP, PDFGUP, PDFSUP, IDWTUP, NPRUP
do i = 1, NPRUP
write (u, "(3(1x,ES17.10),1x,I0)") &
XSECUP(i), XERRUP(i), XMAXUP(i), LPRUP(i)
end do
end subroutine heprup_write_ascii
@ %def heprup_write_ascii
@
\subsubsection{Run parameter input (LHEF)}
In a LHEF file, the parameters are written in correct order on
separate lines, but we should not count on the precise format.
List-directed input should just work.
<<HEP common: public>>=
public :: heprup_read_lhef
<<HEP common: procedures>>=
subroutine heprup_read_lhef (u)
integer, intent(in) :: u
integer :: i
read (u, *) &
IDBMUP, EBMUP, PDFGUP, PDFSUP, IDWTUP, NPRUP
do i = 1, NPRUP
read (u, *) &
XSECUP(i), XERRUP(i), XMAXUP(i), LPRUP(i)
end do
end subroutine heprup_read_lhef
@ %def heprup_read_lhef
@
\subsection{The HEPEUP common block}
<<HEP common: common blocks>>=
common /HEPEUP/ &
NUP, IDPRUP, XWGTUP, SCALUP, AQEDUP, AQCDUP, &
IDUP, ISTUP, MOTHUP, ICOLUP, PUP, VTIMUP, SPINUP
save /HEPEUP/
@ %def HEPEUP
@
\subsubsection{Initialization}
Fill the event characteristics of the common block. The
initialization sets only the number of particles and initializes the
rest with default values. The other routine sets the optional
parameters.
<<HEP common: public>>=
public :: hepeup_init
public :: hepeup_set_event_parameters
<<HEP common: procedures>>=
subroutine hepeup_init (n_tot)
integer, intent(in) :: n_tot
NUP = n_tot
IDPRUP = 0
XWGTUP = 1
SCALUP = -1
AQEDUP = -1
AQCDUP = -1
end subroutine hepeup_init
subroutine hepeup_set_event_parameters &
(proc_id, weight, scale, alpha_qed, alpha_qcd)
integer, intent(in), optional :: proc_id
real(default), intent(in), optional :: weight, scale, alpha_qed, alpha_qcd
if (present (proc_id)) IDPRUP = proc_id
if (present (weight)) XWGTUP = weight
if (present (scale)) SCALUP = scale
if (present (alpha_qed)) AQEDUP = alpha_qed
if (present (alpha_qcd)) AQCDUP = alpha_qcd
end subroutine hepeup_set_event_parameters
@ %def hepeup_init hepeup_set_event_parameters
@ Extract event information. The caller determines the parameters.
<<HEP common: public>>=
public :: hepeup_get_event_parameters
<<HEP common: procedures>>=
subroutine hepeup_get_event_parameters &
(proc_id, weight, scale, alpha_qed, alpha_qcd)
integer, intent(out), optional :: proc_id
real(default), intent(out), optional :: weight, scale, alpha_qed, alpha_qcd
if (present (proc_id)) proc_id = IDPRUP
if (present (weight)) weight = XWGTUP
if (present (scale)) scale = SCALUP
if (present (alpha_qed)) alpha_qed = AQEDUP
if (present (alpha_qcd)) alpha_qcd = AQCDUP
end subroutine hepeup_get_event_parameters
@ %def hepeup_get_event_parameters
@
\subsubsection{Particle data}
Below we need the particle status codes which are actually defined
in the [[subevents]] module.
Set the entry for a specific particle. All parameters are set with
the exception of lifetime and spin, where default values are stored.
<<HEP common: public>>=
public :: hepeup_set_particle
<<HEP common: procedures>>=
subroutine hepeup_set_particle (i, pdg, status, parent, col, p, m2)
integer, intent(in) :: i
integer, intent(in) :: pdg, status
integer, dimension(:), intent(in) :: parent
type(vector4_t), intent(in) :: p
integer, dimension(2), intent(in) :: col
real(default), intent(in) :: m2
if (i > MAXNUP) then
call msg_error (arr=[ &
var_str ("Too many particles in HEPEUP common block. " // &
"If this happened "), &
var_str ("during event output, your events will be " // &
"invalid; please consider "), &
var_str ("switching to a modern event format like HEPMC. " // &
"If you are not "), &
var_str ("using an old, HEPEUP based format and " // &
"nevertheless get this error,"), &
var_str ("please notify the WHIZARD developers,") ])
return
end if
IDUP(i) = pdg
select case (status)
case (PRT_BEAM); ISTUP(i) = -9
case (PRT_INCOMING); ISTUP(i) = -1
case (PRT_BEAM_REMNANT); ISTUP(i) = 3
case (PRT_OUTGOING); ISTUP(i) = 1
case (PRT_RESONANT); ISTUP(i) = 2
case (PRT_VIRTUAL); ISTUP(i) = 3
case default; ISTUP(i) = 0
end select
select case (size (parent))
case (0); MOTHUP(:,i) = 0
case (1); MOTHUP(1,i) = parent(1); MOTHUP(2,i) = 0
case default; MOTHUP(:,i) = [ parent(1), parent(size (parent)) ]
end select
if (col(1) > 0) then
ICOLUP(1,i) = 500 + col(1)
else
ICOLUP(1,i) = 0
end if
if (col(2) > 0) then
ICOLUP(2,i) = 500 + col(2)
else
ICOLUP(2,i) = 0
end if
PUP(1:3,i) = vector3_get_components (space_part (p))
PUP(4,i) = energy (p)
PUP(5,i) = sign (sqrt (abs (m2)), m2)
VTIMUP(i) = 0
SPINUP(i) = 9
end subroutine hepeup_set_particle
@ %def hepeup_set_particle
@ Set the lifetime, actually $c\tau$ measured im mm, where $\tau$ is
the invariant lifetime.
<<HEP common: public>>=
public :: hepeup_set_particle_lifetime
<<HEP common: procedures>>=
subroutine hepeup_set_particle_lifetime (i, lifetime)
integer, intent(in) :: i
real(default), intent(in) :: lifetime
VTIMUP(i) = lifetime
end subroutine hepeup_set_particle_lifetime
@ %def hepeup_set_particle_lifetime
@ Set the particle spin entry. We need the cosine of the angle of the
spin axis with respect to the three-momentum of the parent particle.
If the particle has a full polarization density matrix given, we need
the particle momentum and polarization as well as the mother-particle
momentum. The polarization is transformed into a spin vector (which
is sensible only for spin-1/2 or massless particles), which then is
transformed into the lab frame (by a rotation of the 3-axis to the
particle momentum axis). Finally, we compute the scalar product of
this vector with the mother-particle three-momentum.
This puts severe restrictions on the applicability of this definition,
and Lorentz invariance is lost. Unfortunately, the Les Houches Accord
requires this computation.
<<HEP common: public>>=
public :: hepeup_set_particle_spin
<<HEP common: interfaces>>=
interface hepeup_set_particle_spin
module procedure hepeup_set_particle_spin_pol
end interface
<<HEP common: procedures>>=
subroutine hepeup_set_particle_spin_pol (i, p, pol, p_mother)
integer, intent(in) :: i
type(vector4_t), intent(in) :: p
type(polarization_t), intent(in) :: pol
type(vector4_t), intent(in) :: p_mother
type(vector3_t) :: s3, p3
type(vector4_t) :: s4
s3 = vector3_moving (pol%get_axis ())
p3 = space_part (p)
s4 = rotation_to_2nd (3, p3) * vector4_moving (0._default, s3)
SPINUP(i) = enclosed_angle_ct (s4, p_mother)
end subroutine hepeup_set_particle_spin_pol
@ %def hepeup_set_particle_spin
@
Extract particle data. The caller decides which ones to retrieve.
Status codes: beam remnants share the status code with virtual particles.
However, for the purpose of WHIZARD we should identify them. We
use the PDG code for this.
<<HEP common: public>>=
public :: hepeup_get_particle
<<HEP common: procedures>>=
subroutine hepeup_get_particle (i, pdg, status, parent, col, p, m2)
integer, intent(in) :: i
integer, intent(out), optional :: pdg, status
integer, dimension(:), intent(out), optional :: parent
type(vector4_t), intent(out), optional :: p
integer, dimension(2), intent(out), optional :: col
real(default), dimension(5,MAXNUP) :: pup_def
real(default), intent(out), optional :: m2
if (present (pdg)) pdg = IDUP(i)
if (present (status)) then
select case (ISTUP(i))
case (-9); status = PRT_BEAM
case (-1); status = PRT_INCOMING
case (1); status = PRT_OUTGOING
case (2); status = PRT_RESONANT
case (3);
select case (abs (IDUP(i)))
case (HADRON_REMNANT, HADRON_REMNANT_SINGLET, &
HADRON_REMNANT_TRIPLET, HADRON_REMNANT_OCTET)
status = PRT_BEAM_REMNANT
case default
status = PRT_VIRTUAL
end select
case default
status = PRT_UNDEFINED
end select
end if
if (present (parent)) then
select case (size (parent))
case (0)
case (1); parent(1) = MOTHUP(1,i)
case (2); parent = MOTHUP(:,i)
end select
end if
if (present (col)) then
col = ICOLUP(:,i)
end if
if (present (p)) then
pup_def = PUP
p = vector4_moving (pup_def(4,i), vector3_moving (pup_def(1:3,i)))
end if
if (present (m2)) then
m2 = sign (PUP(5,i) ** 2, PUP(5,i))
end if
end subroutine hepeup_get_particle
@ %def hepeup_get_particle
@
\subsection{The HEPEVT and HEPEV4 common block}
For the LEP Monte Carlos, a standard common block has been proposed
in AKV89. We strongly recommend its use. (The description is an
abbreviated transcription of AKV89, Vol. 3, pp. 327-330).
[[NMXHEP]] is the maximum number of entries:
<<HEP common: variables>>=
integer, parameter :: NMXHEP = 4000
@ %def NMXHEP
@ [[NEVHEP]] is normally the event number, but may take special
values as follows:
0 the program does not keep track of event numbers.
-1 a special initialization record.
-2 a special final record.
<<HEP common: variables>>=
integer :: NEVHEP
@ %def NEVHEP
@ [[NHEP]] holds the number of entries for this event.
<<HEP common: variables>>=
integer, public :: NHEP
@ %def NHEP
@ The entry [[ISTHEP(N)]] gives the status code for the [[N]]th entry,
with the following semantics:
0 a null entry.
1 an existing entry, which has not decayed or fragmented.
2 a decayed or fragmented entry, which is retained for
event history information.
3 documentation line.
4- 10 reserved for future standards.
11-200 at the disposal of each model builder.
201- at the disposal of users.
<<HEP common: variables>>=
integer, dimension(NMXHEP), public :: ISTHEP
@ %def ISTHEP
@
The Particle Data Group has proposed standard particle codes,
which are to be stored in [[IDHEP(N)]].
<<HEP common: variables>>=
integer, dimension(NMXHEP), public :: IDHEP
@ %def IDHEP
@ [[JMOHEP(1,N)]] points to the mother of the [[N]]th entry, if any.
It is set to zero for initial entries.
[[JMOHEP(2,N)]] points to the second mother, if any.
<<HEP common: variables>>=
integer, dimension(2, NMXHEP), public :: JMOHEP
@ %def JMOHEP
@ [[JDAHEP(1,N)]] and [[JDAHEP(2,N)]] point to the first and last daughter
of the [[N]]th entry, if any. These are zero for entries which have not
yet decayed. The other daughters are stored in between these two.
<<HEP common: variables>>=
integer, dimension(2, NMXHEP), public :: JDAHEP
@ %def JDAHEP
@ In [[PHEP]] we store the momentum of the particle, more specifically
this means that [[PHEP(1,N)]], [[PHEP(2,N)]], and [[PHEP(3,N)]] contain the
momentum in the $x$, $y$, and $z$ direction (as defined by the machine
people), measured in GeV/c. [[PHEP(4,N)]] contains the energy in GeV
and [[PHEP(5,N)]] the mass in GeV$/c^2$. The latter may be negative for
spacelike partons.
<<HEP common: variables>>=
double precision, dimension(5, NMXHEP), public :: PHEP
@ %def PHEP
@ Finally [[VHEP]] is the place to store the position of the production
vertex. [[VHEP(1,N)]], [[VHEP(2,N)]], and [[VHEP(3,N)]] contain the $x$, $y$,
and $z$ coordinate (as defined by the machine people), measured in mm.
[[VHEP(4,N)]] contains the production time in mm/c.
<<HEP common: variables>>=
double precision, dimension(4, NMXHEP) :: VHEP
@ %def VHEP
@ As an amendment to the proposed standard common block HEPEVT, we
also have a polarisation common block HEPSPN, as described in
AKV89. [[SHEP(1,N)]], [[SHEP(2,N)]], and [[SHEP(3,N)]] give the $x$, $y$, and $z$
component of the spinvector $s$ of a fermion in the fermions restframe.
Furthermore, we add the polarization of the corresponding outgoing
particles:
<<HEP common: variables>>=
integer, dimension(NMXHEP) :: hepevt_pol
@ %def hepevt_pol
@
By this variable the identity of the current process is given, defined
via the LPRUP codes.
<<HEP common: variables>>=
integer, public :: idruplh
@ %def idruplh
This is the event weight, i.e. the cross section divided by the total
number of generated events for the output of the parton shower programs.
<<HEP common: variables>>=
double precision, public :: eventweightlh
@ %def eventweightlh
@ There are the values for the electromagnetic and the strong coupling
constants, $\alpha_{em}$ and $\alpha_s$.
<<HEP common: variables>>=
double precision, public :: alphaqedlh, alphaqcdlh
@ %def alphaqedlh, alphaqcdlh
@ This is the squared scale $Q$ of the event.
<<HEP common: variables>>=
double precision, dimension(10), public :: scalelh
@ %def scalelh
@ Finally, these variables contain the spin information and the
color/anticolor flow of the particles.
<<HEP common: variables>>=
double precision, dimension (3,NMXHEP), public :: spinlh
integer, dimension (2,NMXHEP), public :: icolorflowlh
@ %def spinlh icolorflowlh
By convention, [[SHEP(4,N)]] is always 1. All this is taken from StdHep
4.06 manual and written using Fortran90 conventions.
<<HEP common: common blocks>>=
common /HEPEVT/ &
NEVHEP, NHEP, ISTHEP, IDHEP, &
JMOHEP, JDAHEP, PHEP, VHEP
save /HEPEVT/
@ %def HEPEVT
@ Here we store HEPEVT parameters of the WHIZARD 1 realization which
are not part of the HEPEVT common block.
<<HEP common: variables>>=
integer :: hepevt_n_out, hepevt_n_remnants
@ %def hepevt_n_out, hepevt_n_remnants
@
<<HEP common: variables>>=
double precision :: hepevt_weight, hepevt_function_value
double precision :: hepevt_function_ratio
@ %def hepevt_weight hepevt_function_value
@ The HEPEV4 common block is an extension of the HEPEVT common block
to allow for partonic colored events, including especially the color
flow etc.
<<HEP common: common blocks>>=
common /HEPEV4/ &
eventweightlh, alphaqedlh, alphaqcdlh, scalelh, &
spinlh, icolorflowlh, idruplh
save /HEPEV4/
@ %def HEPEV4
@ Filling HEPEVT: If the event count is not provided, set [[NEVHEP]]
to zero. If the event count is [[-1]] or [[-2]], the record
corresponds to initialization and finalization, and the event is
irrelevant.
Note that the event count may be larger than $2^{31}$ (2 GEvents). In
that case, cut off the upper bits since [[NEVHEP]] is probably limited
to default integer.
For the HEPEV4 common block, it is unclear why the [[scalelh]] variable
is 10-dimensional. We choose to only set the first value of the array.
<<HEP common: public>>=
public :: hepevt_init
public :: hepevt_set_event_parameters
<<HEP common: procedures>>=
subroutine hepevt_init (n_tot, n_out)
integer, intent(in) :: n_tot, n_out
NHEP = n_tot
NEVHEP = 0
idruplh = 0
hepevt_n_out = n_out
hepevt_n_remnants = 0
hepevt_weight = 1
eventweightlh = 1
hepevt_function_value = 0
hepevt_function_ratio = 1
alphaqcdlh = -1
alphaqedlh = -1
scalelh = -1
end subroutine hepevt_init
subroutine hepevt_set_event_parameters &
(proc_id, weight, function_value, function_ratio, &
alpha_qcd, alpha_qed, scale, i_evt)
integer, intent(in), optional :: proc_id
integer, intent(in), optional :: i_evt
real(default), intent(in), optional :: weight, function_value, &
function_ratio, alpha_qcd, alpha_qed, scale
if (present (proc_id)) idruplh = proc_id
if (present (i_evt)) NEVHEP = i_evt
if (present (weight)) then
hepevt_weight = weight
eventweightlh = weight
end if
if (present (function_value)) hepevt_function_value = &
function_value
if (present (function_ratio)) hepevt_function_ratio = &
function_ratio
if (present (alpha_qcd)) alphaqcdlh = alpha_qcd
if (present (alpha_qed)) alphaqedlh = alpha_qed
if (present (scale)) scalelh(1) = scale
if (present (i_evt)) NEVHEP = i_evt
end subroutine hepevt_set_event_parameters
@ %def hepevt_init hepevt_set_event_parameters
@ Set the entry for a specific particle. All parameters are set with
the exception of lifetime and spin, where default values are stored.
<<HEP common: public>>=
public :: hepevt_set_particle
<<HEP common: procedures>>=
subroutine hepevt_set_particle &
(i, pdg, status, parent, child, p, m2, hel, vtx, &
col, pol_status, pol, fill_hepev4)
integer, intent(in) :: i
integer, intent(in) :: pdg, status
integer, dimension(:), intent(in) :: parent
integer, dimension(:), intent(in) :: child
logical, intent(in), optional :: fill_hepev4
type(vector4_t), intent(in) :: p
real(default), intent(in) :: m2
integer, dimension(2), intent(in) :: col
integer, intent(in) :: pol_status
integer, intent(in) :: hel
type(polarization_t), intent(in), optional :: pol
type(vector4_t), intent(in) :: vtx
logical :: hepev4
hepev4 = .false.; if (present (fill_hepev4)) hepev4 = fill_hepev4
IDHEP(i) = pdg
select case (status)
case (PRT_BEAM); ISTHEP(i) = 2
case (PRT_INCOMING); ISTHEP(i) = 2
case (PRT_OUTGOING); ISTHEP(i) = 1
case (PRT_VIRTUAL); ISTHEP(i) = 2
case (PRT_RESONANT); ISTHEP(i) = 2
case default; ISTHEP(i) = 0
end select
select case (size (parent))
case (0); JMOHEP(:,i) = 0
case (1); JMOHEP(1,i) = parent(1); JMOHEP(2,i) = 0
case default; JMOHEP(:,i) = [ parent(1), parent(size (parent)) ]
end select
select case (size (child))
case (0); JDAHEP(:,i) = 0
case (1); JDAHEP(:,i) = child(1)
case default; JDAHEP(:,i) = [ child(1), child(size (child)) ]
end select
PHEP(1:3,i) = vector3_get_components (space_part (p))
PHEP(4,i) = energy (p)
PHEP(5,i) = sign (sqrt (abs (m2)), m2)
VHEP(1:3,i) = vtx%p(1:3)
VHEP(4,i) = vtx%p(0)
hepevt_pol(i) = hel
if (hepev4) then
if (col(1) > 0) then
icolorflowlh(1,i) = 500 + col(1)
else
icolorflowlh(1,i) = 0
end if
if (col(2) > 0) then
icolorflowlh(2,i) = 500 + col(2)
else
icolorflowlh(2,i) = 0
end if
if (present (pol) .and. &
pol_status == PRT_GENERIC_POLARIZATION) then
if (pol%is_polarized ()) &
spinlh(:,i) = pol%get_axis ()
else
spinlh(:,i) = zero
spinlh(3,i) = hel
end if
end if
end subroutine hepevt_set_particle
@ %def hepevt_set_particle
@
\subsection{Event output}
This is a verbose output of the HEPEVT block.
<<HEP common: public>>=
public :: hepevt_write_verbose
<<HEP common: procedures>>=
subroutine hepevt_write_verbose (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(A)") "HEPEVT Common Block"
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)") "NEVHEP", NEVHEP, &
"Event number"
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)") "NHEP ", NHEP, &
"Number of particles in event"
do i = 1, NHEP
write (u, "(1x,A,I0)") "Particle #", i
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)", advance="no") &
"ISTHEP", ISTHEP(i), "Status code: "
select case (ISTHEP(i))
case ( 0); write (u, "(A)") "null entry"
case ( 1); write (u, "(A)") "outgoing"
case ( 2); write (u, "(A)") "decayed"
case ( 3); write (u, "(A)") "documentation"
case (4:10); write (u, "(A)") "[unspecified]"
case (11:200); write (u, "(A)") "[model-specific]"
case (201:); write (u, "(A)") "[user-defined]"
case default; write (u, "(A)") "[undefined]"
end select
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)") "IDHEP ", IDHEP(i), &
"PDG code of particle"
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "JMOHEP", JMOHEP(:,i), &
"Index of first/second mother"
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "JDAHEP", JDAHEP(:,i), &
"Index of first/last daughter"
write (u, "(3x,A6,' = ',ES12.5,1x,ES12.5,8x,A)") "PHEP12", &
PHEP(1:2,i), "Transversal momentum (x/y) in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "PHEP3 ", PHEP(3,i), &
"Longitudinal momentum (z) in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "PHEP4 ", PHEP(4,i), &
"Energy in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "PHEP5 ", PHEP(5,i), &
"Invariant mass in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,ES12.5,8x,A)") "VHEP12", VHEP(1:2,i), &
"Transversal displacement (xy) in mm"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "VHEP3 ", VHEP(3,i), &
"Longitudinal displacement (z) in mm"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "VHEP4 ", VHEP(4,i), &
"Production time in mm"
end do
end subroutine hepevt_write_verbose
@ %def hepevt_write_verbose
@
This is a verbose output of the HEPEUP block.
<<HEP common: public>>=
public :: hepeup_write_verbose
<<HEP common: procedures>>=
subroutine hepeup_write_verbose (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(A)") "HEPEUP Common Block"
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)") "NUP ", NUP, &
"Number of particles in event"
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)") "IDPRUP", IDPRUP, &
"Subprocess ID"
write (u, "(3x,A6,' = ',ES12.5,1x,20x,A)") "XWGTUP", XWGTUP, &
"Event weight"
write (u, "(3x,A6,' = ',ES12.5,1x,20x,A)") "SCALUP", SCALUP, &
"Event energy scale in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,20x,A)") "AQEDUP", AQEDUP, &
"QED coupling [-1 = undefined]"
write (u, "(3x,A6,' = ',ES12.5,1x,20x,A)") "AQCDUP", AQCDUP, &
"QCD coupling [-1 = undefined]"
do i = 1, NUP
write (u, "(1x,A,I0)") "Particle #", i
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)") "IDUP ", IDUP(i), &
"PDG code of particle"
write (u, "(3x,A6,' = ',I9,3x,1x,20x,A)", advance="no") &
"ISTUP ", ISTUP(i), "Status code: "
select case (ISTUP(i))
case (-1); write (u, "(A)") "incoming"
case ( 1); write (u, "(A)") "outgoing"
case (-2); write (u, "(A)") "spacelike"
case ( 2); write (u, "(A)") "resonance"
case ( 3); write (u, "(A)") "resonance (doc)"
case (-9); write (u, "(A)") "beam"
case default; write (u, "(A)") "[undefined]"
end select
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "MOTHUP", MOTHUP(:,i), &
"Index of first/last mother"
write (u, "(3x,A6,' = ',I9,3x,1x,I9,3x,8x,A)") "ICOLUP", ICOLUP(:,i), &
"Color/anticolor flow index"
write (u, "(3x,A6,' = ',ES12.5,1x,ES12.5,8x,A)") "PUP1/2", PUP(1:2,i), &
"Transversal momentum (x/y) in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "PUP3 ", PUP(3,i), &
"Longitudinal momentum (z) in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "PUP4 ", PUP(4,i), &
"Energy in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "PUP5 ", PUP(5,i), &
"Invariant mass in GeV"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "VTIMUP", VTIMUP(i), &
"Invariant lifetime in mm"
write (u, "(3x,A6,' = ',ES12.5,1x,12x,8x,A)") "SPINUP", SPINUP(i), &
"cos(spin angle) [9 = undefined]"
end do
end subroutine hepeup_write_verbose
@ %def hepeup_write_verbose
@
\subsection{Event output in various formats}
This routine writes event output according to the LHEF standard. It
uses the current contents of the HEPEUP block.
<<HEP common: public>>=
public :: hepeup_write_lhef
public :: hepeup_write_lha
<<HEP common: procedures>>=
subroutine hepeup_write_lhef (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
if (debug_on) call msg_debug (D_EVENTS, "hepeup_write_lhef")
if (debug_on) call msg_debug2 (D_EVENTS, "ID IST MOTH ICOL P VTIM SPIN")
write (u, "(2(1x,I0),4(1x,ES17.10))") &
NUP, IDPRUP, XWGTUP, SCALUP, AQEDUP, AQCDUP
do i = 1, NUP
write (u, "(6(1x,I0),7(1x,ES17.10))") &
IDUP(i), ISTUP(i), MOTHUP(:,i), ICOLUP(:,i), &
PUP(:,i), VTIMUP(i), SPINUP(i)
if (debug2_active (D_EVENTS)) then
write (msg_buffer, "(6(1x,I0),7(1x,ES17.10))") &
IDUP(i), ISTUP(i), MOTHUP(:,i), ICOLUP(:,i), &
PUP(:,i), VTIMUP(i), SPINUP(i)
call msg_message ()
end if
end do
end subroutine hepeup_write_lhef
subroutine hepeup_write_lha (unit)
integer, intent(in), optional :: unit
integer :: u, i
integer, dimension(MAXNUP) :: spin_up
spin_up = int(SPINUP)
u = given_output_unit (unit); if (u < 0) return
write (u, "(2(1x,I5),1x,ES17.10,3(1x,ES13.6))") &
NUP, IDPRUP, XWGTUP, SCALUP, AQEDUP, AQCDUP
write (u, "(500(1x,I5))") IDUP(:NUP)
write (u, "(500(1x,I5))") MOTHUP(1,:NUP)
write (u, "(500(1x,I5))") MOTHUP(2,:NUP)
write (u, "(500(1x,I5))") ICOLUP(1,:NUP)
write (u, "(500(1x,I5))") ICOLUP(2,:NUP)
write (u, "(500(1x,I5))") ISTUP(:NUP)
write (u, "(500(1x,I5))") spin_up(:NUP)
do i = 1, NUP
write (u, "(1x,I5,4(1x,ES17.10))") i, PUP([ 4,1,2,3 ], i)
end do
end subroutine hepeup_write_lha
@ %def hepeup_write_lhef hepeup_write_lha
@ This routine writes event output according to the HEPEVT standard. It
uses the current contents of the HEPEVT block and some additional
parameters according to the standard in WHIZARD 1. For the long ASCII
format, the value of the sample function (i.e. the product of squared
matrix element, structure functions and phase space factor is printed out).
The option of reweighting matrix elements with respect to some
reference cross section is not implemented in WHIZARD 2 for this event
format, therefore the second entry in the long ASCII format (the
function ratio) is always one. The ATHENA format is an implementation
of the HEPEVT format that is readable by the ATLAS ATHENA software
framework. It is very similar to the WHIZARD 1 HEPEVT format, except
that it contains an event counter, a particle counter inside the
event, and has the HEPEVT [[ISTHEP]] status before the PDG code. The
MOKKA format is a special ASCII format that contains the information
to be parsed to the MOKKA LC fast simulation software.
<<HEP common: public>>=
public :: hepevt_write_hepevt
public :: hepevt_write_ascii
public :: hepevt_write_athena
public :: hepevt_write_mokka
<<HEP common: procedures>>=
subroutine hepevt_write_hepevt (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(3(1x,I0),(1x,ES17.10))") &
NHEP, hepevt_n_out, hepevt_n_remnants, hepevt_weight
do i = 1, NHEP
write (u, "(7(1x,I0))") &
ISTHEP(i), IDHEP(i), JMOHEP(:,i), JDAHEP(:,i), hepevt_pol(i)
write (u, "(5(1x,ES17.10))") PHEP(:,i)
write (u, "(5(1x,ES17.10))") VHEP(:,i), 0.d0
end do
end subroutine hepevt_write_hepevt
subroutine hepevt_write_ascii (unit, long)
integer, intent(in), optional :: unit
logical, intent(in) :: long
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(3(1x,I0),(1x,ES17.10))") &
NHEP, hepevt_n_out, hepevt_n_remnants, hepevt_weight
do i = 1, NHEP
if (ISTHEP(i) /= 1) cycle
write (u, "(2(1x,I0))") IDHEP(i), hepevt_pol(i)
write (u, "(5(1x,ES17.10))") PHEP(:,i)
end do
if (long) then
write (u, "(2(1x,ES17.10))") &
hepevt_function_value, hepevt_function_ratio
end if
end subroutine hepevt_write_ascii
subroutine hepevt_write_athena (unit)
integer, intent(in), optional :: unit
integer :: u, i, num_event
num_event = 0
u = given_output_unit (unit); if (u < 0) return
write (u, "(2(1x,I0))") NEVHEP, NHEP
do i = 1, NHEP
write (u, "(7(1x,I0))") &
i, ISTHEP(i), IDHEP(i), JMOHEP(:,i), JDAHEP(:,i)
write (u, "(5(1x,ES17.10))") PHEP(:,i)
write (u, "(5(1x,ES17.10))") VHEP(1:4,i)
end do
end subroutine hepevt_write_athena
subroutine hepevt_write_mokka (unit)
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit); if (u < 0) return
write (u, "(3(1x,I0),(1x,ES17.10))") &
NHEP, hepevt_n_out, hepevt_n_remnants, hepevt_weight
do i = 1, NHEP
write (u, "(4(1x,I0),4(1x,ES17.10))") &
ISTHEP(i), IDHEP(i), JDAHEP(1,i), JDAHEP(2,i), &
PHEP(1:3,i), PHEP(5,i)
end do
end subroutine hepevt_write_mokka
@ %def hepevt_write_hepevt hepevt_write_ascii
@ %def hepevt_write_athena
@
\subsection{Event input in various formats}
This routine writes event output according to the LHEF standard. It
uses the current contents of the HEPEUP block.
<<HEP common: public>>=
public :: hepeup_read_lhef
<<HEP common: procedures>>=
subroutine hepeup_read_lhef (u)
integer, intent(in) :: u
integer :: i
read (u, *) &
NUP, IDPRUP, XWGTUP, SCALUP, AQEDUP, AQCDUP
do i = 1, NUP
read (u, *) &
IDUP(i), ISTUP(i), MOTHUP(:,i), ICOLUP(:,i), &
PUP(:,i), VTIMUP(i), SPINUP(i)
end do
end subroutine hepeup_read_lhef
@ %def hepeup_read_lhef
@
\subsection{Data Transfer: particle sets}
The \whizard\ format for handling particle data in events is
[[particle_set_t]]. We have to interface this to the common blocks.
We first create a new particle set that contains only the particles
that are supported by the LHEF format. These are: beam, incoming,
resonant, outgoing. We drop particles with unknown, virtual or
beam-remnant status.
From this set we fill the common block. Event information such as
process ID and weight is not transferred here; this has to be done by
the caller. The spin information is set only if the particle has a
unique mother, and if its polarization is fully defined.
We use this routine also to hand over information to Pythia which lets
Tauola access SPINUP. Tauola expects in SPINUP the helicity and not the
LHA convention. We switch to this mode with [[tauola_convention]].
<<HEP common: public>>=
public :: hepeup_from_particle_set
<<HEP common: procedures>>=
subroutine hepeup_from_particle_set (pset_in, &
keep_beams, keep_remnants, tauola_convention)
type(particle_set_t), intent(in) :: pset_in
type(particle_set_t), target :: pset
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
logical, intent(in), optional :: tauola_convention
integer :: i, n_parents, status, n_tot
integer, dimension(1) :: i_mother
logical :: kr, tc
kr = .true.; if (present (keep_remnants)) kr = keep_remnants
tc = .false.; if (present (tauola_convention)) tc = tauola_convention
call pset_in%filter_particles (pset, real_parents = .true. , &
keep_beams = keep_beams, keep_virtuals = .false.)
n_tot = pset%get_n_tot ()
call hepeup_init (n_tot)
do i = 1, n_tot
associate (prt => pset%prt(i))
status = prt%get_status ()
if (kr .and. status == PRT_BEAM_REMNANT &
.and. prt%get_n_children () == 0) &
status = PRT_OUTGOING
call hepeup_set_particle (i, &
prt%get_pdg (), &
status, &
prt%get_parents (), &
prt%get_color (), &
prt%get_momentum (), &
prt%get_p2 ())
n_parents = prt%get_n_parents ()
call hepeup_set_particle_lifetime (i, &
prt%get_lifetime ())
if (.not. tc) then
if (n_parents == 1) then
i_mother = prt%get_parents ()
select case (prt%get_polarization_status ())
case (PRT_GENERIC_POLARIZATION)
call hepeup_set_particle_spin (i, &
prt%get_momentum (), &
prt%get_polarization (), &
pset%prt(i_mother(1))%get_momentum ())
end select
end if
else
select case (prt%get_polarization_status ())
case (PRT_DEFINITE_HELICITY)
SPINUP(i) = prt%get_helicity()
end select
end if
end associate
end do
end subroutine hepeup_from_particle_set
@ %def hepeup_from_particle_set
@ Input. The particle set should be allocated properly, but we
replace the particle contents.
If there are no beam particles in the event, we try to reconstruct beam
particles and beam remnants. We assume for simplicity that the beam
particles, if any, are the first two particles. If they are absent, the first
two particles should be the incoming partons.
<<HEP common: public>>=
public :: hepeup_to_particle_set
<<HEP common: procedures>>=
subroutine hepeup_to_particle_set &
(particle_set, recover_beams, model, alt_model)
type(particle_set_t), intent(inout), target :: particle_set
logical, intent(in), optional :: recover_beams
class(model_data_t), intent(in), target :: model, alt_model
type(particle_t), dimension(:), allocatable :: prt
integer, dimension(2) :: parent
integer, dimension(:), allocatable :: child
integer :: i, j, k, pdg, status
type(flavor_t) :: flv
type(color_t) :: col
integer, dimension(2) :: c
type(vector4_t) :: p
real(default) :: p2
logical :: reconstruct
integer :: off
if (present (recover_beams)) then
reconstruct = recover_beams .and. .not. all (ISTUP(1:2) == PRT_BEAM)
else
reconstruct = .false.
end if
if (reconstruct) then
off = 4
else
off = 0
end if
allocate (prt (NUP + off), child (NUP + off))
do i = 1, NUP
k = i + off
call hepeup_get_particle (i, pdg, status, col = c, p = p, m2 = p2)
call flv%init (pdg, model, alt_model)
call prt(k)%set_flavor (flv)
call prt(k)%reset_status (status)
call col%init (c)
call prt(k)%set_color (col)
call prt(k)%set_momentum (p, p2)
where (MOTHUP(:,i) /= 0)
parent = MOTHUP(:,i) + off
elsewhere
parent = 0
end where
call prt(k)%set_parents (parent)
child = [(j, j = 1 + off, NUP + off)]
where (MOTHUP(1,:NUP) /= i .and. MOTHUP(2,:NUP) /= i) child = 0
call prt(k)%set_children (child)
end do
if (reconstruct) then
do k = 1, 2
call prt(k)%reset_status (PRT_BEAM)
call prt(k)%set_children ([k+2,k+4])
end do
do k = 3, 4
call prt(k)%reset_status (PRT_BEAM_REMNANT)
call prt(k)%set_parents ([k-2])
end do
do k = 5, 6
call prt(k)%set_parents ([k-4])
end do
end if
call particle_set%replace (prt)
end subroutine hepeup_to_particle_set
@ %def hepeup_to_particle_set
@
The HEPEVT common block is quite similar, but does contain less
information, e.g. no color flows (it was LEP time). The spin
information is set only if the particle has a unique mother, and if
its polarization is fully defined.
<<HEP common: public>>=
public :: hepevt_from_particle_set
<<HEP common: procedures>>=
subroutine hepevt_from_particle_set &
(particle_set, keep_beams, keep_remnants, ensure_order, fill_hepev4)
type(particle_set_t), intent(in) :: particle_set
type(particle_set_t), target :: pset_hepevt, pset_tmp
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
logical, intent(in), optional :: ensure_order
logical, intent(in), optional :: fill_hepev4
integer :: i, status, n_tot
logical :: activate_remnants, ensure
activate_remnants = .true.
if (present (keep_remnants)) activate_remnants = keep_remnants
ensure = .false.
if (present (ensure_order)) ensure = ensure_order
call particle_set%filter_particles (pset_tmp, real_parents = .true., &
keep_virtuals = .false., keep_beams = keep_beams)
if (ensure) then
call pset_tmp%to_hepevt_form (pset_hepevt)
else
pset_hepevt = pset_tmp
end if
n_tot = pset_hepevt%get_n_tot ()
call hepevt_init (n_tot, pset_hepevt%get_n_out ())
do i = 1, n_tot
associate (prt => pset_hepevt%prt(i))
status = prt%get_status ()
if (activate_remnants &
.and. status == PRT_BEAM_REMNANT &
.and. prt%get_n_children () == 0) &
status = PRT_OUTGOING
select case (prt%get_polarization_status ())
case (PRT_GENERIC_POLARIZATION)
call hepevt_set_particle (i, &
prt%get_pdg (), status, &
prt%get_parents (), &
prt%get_children (), &
prt%get_momentum (), &
prt%get_p2 (), &
prt%get_helicity (), &
prt%get_vertex (), &
prt%get_color (), &
prt%get_polarization_status (), &
pol = prt%get_polarization (), &
fill_hepev4 = fill_hepev4)
case default
call hepevt_set_particle (i, &
prt%get_pdg (), status, &
prt%get_parents (), &
prt%get_children (), &
prt%get_momentum (), &
prt%get_p2 (), &
prt%get_helicity (), &
prt%get_vertex (), &
prt%get_color (), &
prt%get_polarization_status (), &
fill_hepev4 = fill_hepev4)
end select
end associate
end do
call pset_hepevt%final ()
end subroutine hepevt_from_particle_set
@ %def hepevt_from_particle_set
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{HepMC events}
This section provides the interface to the HepMC C++ library for handling
Monte-Carlo events.
Each C++ class of HepMC that we use is mirrored by a Fortran type,
which contains as its only component the C pointer to the C++ object.
Each C++ method of HepMC that we use has a C wrapper function. This
function takes a pointer to the host object as its first argument.
Further arguments are either C pointers, or in the case of simple
types (integer, real), interoperable C/Fortran objects.
The C wrapper functions have explicit interfaces in the Fortran
module. They are called by Fortran wrapper procedures. These are
treated as methods of the corresponding Fortran type.
<<[[hepmc_interface.f90]]>>=
<<File header>>
module hepmc_interface
use, intrinsic :: iso_c_binding !NODEP!
<<Use kinds>>
<<Use strings>>
use constants, only: PI
use system_dependencies, only: HEPMC2_AVAILABLE
use system_dependencies, only: HEPMC3_AVAILABLE
use diagnostics
use lorentz
use flavors
use colors
use helicities
use polarizations
<<Standard module head>>
<<HepMC interface: public>>
<<HepMC interface: types>>
<<HepMC interface: parameters>>
<<HepMC interface: interfaces>>
contains
<<HepMC interface: procedures>>
end module hepmc_interface
@ %def hepmc_interface
@
\subsection{Interface check}
This function can be called in order to verify that we are using the
actual HepMC library, and not the dummy version.
<<HepMC interface: interfaces>>=
interface
logical(c_bool) function hepmc_available () bind(C)
import
end function hepmc_available
end interface
<<HepMC interface: public>>=
public :: hepmc_is_available
<<HepMC interface: procedures>>=
function hepmc_is_available () result (flag)
logical :: flag
flag = hepmc_available ()
end function hepmc_is_available
@ %def hepmc_is_available
@
\subsection{FourVector}
The C version of four-vectors is often transferred by value, and the
associated procedures are all inlined. The wrapper needs to transfer
by reference, so we create FourVector objects on the heap which have
to be deleted explicitly. The input is a [[vector4_t]] or
[[vector3_t]] object from the [[lorentz]] module.
<<HepMC interface: public>>=
public :: hepmc_four_vector_t
<<HepMC interface: types>>=
type :: hepmc_four_vector_t
private
type(c_ptr) :: obj
end type hepmc_four_vector_t
@ %def hepmc_four_vector_t
@ In the C constructor, the zero-component (fourth argument) is
optional; if missing, it is set to zero. The Fortran version has
initializer form and takes either a three-vector or a four-vector.
A further version extracts the four-vector from a HepMC particle
object.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_four_vector_xyz (x, y, z) bind(C)
import
real(c_double), value :: x, y, z
end function new_four_vector_xyz
end interface
interface
type(c_ptr) function new_four_vector_xyzt (x, y, z, t) bind(C)
import
real(c_double), value :: x, y, z, t
end function new_four_vector_xyzt
end interface
@ %def new_four_vector_xyz new_four_vector_xyzt
<<HepMC interface: public>>=
public :: hepmc_four_vector_init
<<HepMC interface: interfaces>>=
interface hepmc_four_vector_init
module procedure hepmc_four_vector_init_v4
module procedure hepmc_four_vector_init_v3
module procedure hepmc_four_vector_init_hepmc_prt
end interface
<<HepMC interface: procedures>>=
subroutine hepmc_four_vector_init_v4 (pp, p)
type(hepmc_four_vector_t), intent(out) :: pp
type(vector4_t), intent(in) :: p
real(default), dimension(0:3) :: pa
pa = vector4_get_components (p)
pp%obj = new_four_vector_xyzt &
(real (pa(1), c_double), &
real (pa(2), c_double), &
real (pa(3), c_double), &
real (pa(0), c_double))
end subroutine hepmc_four_vector_init_v4
subroutine hepmc_four_vector_init_v3 (pp, p)
type(hepmc_four_vector_t), intent(out) :: pp
type(vector3_t), intent(in) :: p
real(default), dimension(3) :: pa
pa = vector3_get_components (p)
pp%obj = new_four_vector_xyz &
(real (pa(1), c_double), &
real (pa(2), c_double), &
real (pa(3), c_double))
end subroutine hepmc_four_vector_init_v3
subroutine hepmc_four_vector_init_hepmc_prt (pp, prt)
type(hepmc_four_vector_t), intent(out) :: pp
type(hepmc_particle_t), intent(in) :: prt
pp%obj = gen_particle_momentum (prt%obj)
end subroutine hepmc_four_vector_init_hepmc_prt
@ %def hepmc_four_vector_init
@ Here, the destructor is explicitly needed.
<<HepMC interface: interfaces>>=
interface
subroutine four_vector_delete (p_obj) bind(C)
import
type(c_ptr), value :: p_obj
end subroutine four_vector_delete
end interface
@ %def four_vector_delete
<<HepMC interface: public>>=
public :: hepmc_four_vector_final
<<HepMC interface: procedures>>=
subroutine hepmc_four_vector_final (p)
type(hepmc_four_vector_t), intent(inout) :: p
call four_vector_delete (p%obj)
end subroutine hepmc_four_vector_final
@ %def hepmc_four_vector_final
@ Convert to a Lorentz vector.
<<HepMC interface: interfaces>>=
interface
function four_vector_px (p_obj) result (px) bind(C)
import
real(c_double) :: px
type(c_ptr), value :: p_obj
end function four_vector_px
end interface
interface
function four_vector_py (p_obj) result (py) bind(C)
import
real(c_double) :: py
type(c_ptr), value :: p_obj
end function four_vector_py
end interface
interface
function four_vector_pz (p_obj) result (pz) bind(C)
import
real(c_double) :: pz
type(c_ptr), value :: p_obj
end function four_vector_pz
end interface
interface
function four_vector_e (p_obj) result (e) bind(C)
import
real(c_double) :: e
type(c_ptr), value :: p_obj
end function four_vector_e
end interface
@ %def four_vector_px four_vector_py four_vector_pz four_vector_e
<<HepMC interface: public>>=
public :: hepmc_four_vector_to_vector4
<<HepMC interface: procedures>>=
subroutine hepmc_four_vector_to_vector4 (pp, p)
type(hepmc_four_vector_t), intent(in) :: pp
type(vector4_t), intent(out) :: p
real(default) :: E
real(default), dimension(3) :: p3
E = four_vector_e (pp%obj)
p3(1) = four_vector_px (pp%obj)
p3(2) = four_vector_py (pp%obj)
p3(3) = four_vector_pz (pp%obj)
p = vector4_moving (E, vector3_moving (p3))
end subroutine hepmc_four_vector_to_vector4
@ %def hepmc_four_vector_to_vector4
@
\subsection{Polarization}
Polarization objects are temporarily used for assigning particle
polarization. We add a flag [[polarized]]. If this is false, the
polarization is not set and should not be transferred to
[[hepmc_particle]] objects.
<<HepMC interface: public>>=
public :: hepmc_polarization_t
<<HepMC interface: types>>=
type :: hepmc_polarization_t
private
logical :: polarized = .false.
type(c_ptr) :: obj
end type hepmc_polarization_t
@ %def hepmc_polarization_t
@ Constructor. The C wrapper takes polar and azimuthal angle as
arguments. The Fortran version allows for either a complete
polarization density matrix, or for a definite (diagonal) helicity.
\emph{HepMC does not allow to specify the degree of polarization,
therefore we have to map it to either 0 or 1. We choose 0 for
polarization less than $0.5$ and 1 for polarization greater than
$0.5$. Even this simplification works only for spin-1/2 and for
massless particles; massive vector bosons cannot be treated this
way. In particular, zero helicity is always translated as
unpolarized.}
\emph{For massive vector bosons, we arbitrarily choose the convention
that the longitudinal (zero) helicity state is mapped to the theta
angle $\pi/2$. This works under the condition that helicity is
projected onto one of the basis states.}
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_polarization (theta, phi) bind(C)
import
real(c_double), value :: theta, phi
end function new_polarization
end interface
@ %def new_polarization
<<HepMC interface: public>>=
public :: hepmc_polarization_init
<<HepMC interface: interfaces>>=
interface hepmc_polarization_init
module procedure hepmc_polarization_init_pol
module procedure hepmc_polarization_init_hel
module procedure hepmc_polarization_init_int
end interface
<<HepMC interface: procedures>>=
subroutine hepmc_polarization_init_pol (hpol, pol)
type(hepmc_polarization_t), intent(out) :: hpol
type(polarization_t), intent(in) :: pol
real(default) :: r, theta, phi
if (pol%is_polarized ()) then
call pol%to_angles (r, theta, phi)
if (r >= 0.5) then
hpol%polarized = .true.
hpol%obj = new_polarization &
(real (theta, c_double), real (phi, c_double))
end if
end if
end subroutine hepmc_polarization_init_pol
subroutine hepmc_polarization_init_hel (hpol, hel)
type(hepmc_polarization_t), intent(out) :: hpol
type(helicity_t), intent(in) :: hel
integer, dimension(2) :: h
if (hel%is_defined ()) then
h = hel%to_pair ()
select case (h(1))
case (1:)
hpol%polarized = .true.
hpol%obj = new_polarization (0._c_double, 0._c_double)
case (:-1)
hpol%polarized = .true.
hpol%obj = new_polarization (real (pi, c_double), 0._c_double)
case (0)
hpol%polarized = .true.
hpol%obj = new_polarization (real (pi/2, c_double), 0._c_double)
end select
end if
end subroutine hepmc_polarization_init_hel
subroutine hepmc_polarization_init_int (hpol, hel)
type(hepmc_polarization_t), intent(out) :: hpol
integer, intent(in) :: hel
select case (hel)
case (1:)
hpol%polarized = .true.
hpol%obj = new_polarization (0._c_double, 0._c_double)
case (:-1)
hpol%polarized = .true.
hpol%obj = new_polarization (real (pi, c_double), 0._c_double)
case (0)
hpol%polarized = .true.
hpol%obj = new_polarization (real (pi/2, c_double), 0._c_double)
end select
end subroutine hepmc_polarization_init_int
@ %def hepmc_polarization_init
@ Destructor. The C object is deallocated only if the [[polarized]]
flag is set.
<<HepMC interface: interfaces>>=
interface
subroutine polarization_delete (pol_obj) bind(C)
import
type(c_ptr), value :: pol_obj
end subroutine polarization_delete
end interface
@ %def polarization_delete
<<HepMC interface: public>>=
public :: hepmc_polarization_final
<<HepMC interface: procedures>>=
subroutine hepmc_polarization_final (hpol)
type(hepmc_polarization_t), intent(inout) :: hpol
if (hpol%polarized) call polarization_delete (hpol%obj)
end subroutine hepmc_polarization_final
@ %def hepmc_polarization_final
@ Recover polarization from HepMC polarization object (with the
abovementioned deficiencies).
<<HepMC interface: interfaces>>=
interface
function polarization_theta (pol_obj) result (theta) bind(C)
import
real(c_double) :: theta
type(c_ptr), value :: pol_obj
end function polarization_theta
end interface
interface
function polarization_phi (pol_obj) result (phi) bind(C)
import
real(c_double) :: phi
type(c_ptr), value :: pol_obj
end function polarization_phi
end interface
@ %def polarization_theta polarization_phi
<<HepMC interface: public>>=
public :: hepmc_polarization_to_pol
<<HepMC interface: procedures>>=
subroutine hepmc_polarization_to_pol (hpol, flv, pol)
type(hepmc_polarization_t), intent(in) :: hpol
type(flavor_t), intent(in) :: flv
type(polarization_t), intent(out) :: pol
real(default) :: theta, phi
theta = polarization_theta (hpol%obj)
phi = polarization_phi (hpol%obj)
call pol%init_angles (flv, 1._default, theta, phi)
end subroutine hepmc_polarization_to_pol
@ %def hepmc_polarization_to_pol
@ Recover helicity. Here, $\phi$ is ignored and only the sign of
$\cos\theta$ is relevant, mapped to positive/negative helicity.
<<HepMC interface: public>>=
public :: hepmc_polarization_to_hel
<<HepMC interface: procedures>>=
subroutine hepmc_polarization_to_hel (hpol, flv, hel)
type(hepmc_polarization_t), intent(in) :: hpol
type(flavor_t), intent(in) :: flv
type(helicity_t), intent(out) :: hel
real(default) :: theta
integer :: hmax
theta = polarization_theta (hpol%obj)
hmax = flv%get_spin_type () / 2
call hel%init (sign (hmax, nint (cos (theta))))
end subroutine hepmc_polarization_to_hel
@ %def hepmc_polarization_to_hel
@
\subsection{GenParticle}
Particle objects have the obvious meaning.
<<HepMC interface: public>>=
public :: hepmc_particle_t
<<HepMC interface: types>>=
type :: hepmc_particle_t
private
type(c_ptr) :: obj
end type hepmc_particle_t
@ %def hepmc_particle_t
@ Constructor. The C version takes a FourVector object, which in the
Fortran wrapper is created on the fly from a [[vector4]] Lorentz
vector.
No destructor is needed as long as all particles are entered into
vertex containers.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_gen_particle (prt_obj, pdg_id, status) bind(C)
import
type(c_ptr), value :: prt_obj
integer(c_int), value :: pdg_id, status
end function new_gen_particle
end interface
@ %def new_gen_particle
<<HepMC interface: public>>=
public :: hepmc_particle_init
<<HepMC interface: procedures>>=
subroutine hepmc_particle_init (prt, p, pdg, status)
type(hepmc_particle_t), intent(out) :: prt
type(vector4_t), intent(in) :: p
integer, intent(in) :: pdg, status
type(hepmc_four_vector_t) :: pp
call hepmc_four_vector_init (pp, p)
prt%obj = new_gen_particle (pp%obj, int (pdg, c_int), int (status, c_int))
call hepmc_four_vector_final (pp)
end subroutine hepmc_particle_init
@ %def hepmc_particle_init
@ Set the particle color flow.
<<HepMC interface: interfaces>>=
interface
subroutine gen_particle_set_flow (prt_obj, code_index, code) bind(C)
import
type(c_ptr), value :: prt_obj
integer(c_int), value :: code_index, code
end subroutine gen_particle_set_flow
end interface
@ %def gen_particle_set_flow
@ Set the particle color. Either from a [[color_t]] object or
directly from a pair of integers.
<<HepMC interface: interfaces>>=
interface hepmc_particle_set_color
module procedure hepmc_particle_set_color_col
module procedure hepmc_particle_set_color_int
end interface hepmc_particle_set_color
<<HepMC interface: public>>=
public :: hepmc_particle_set_color
<<HepMC interface: procedures>>=
subroutine hepmc_particle_set_color_col (prt, col)
type(hepmc_particle_t), intent(inout) :: prt
type(color_t), intent(in) :: col
integer(c_int) :: c
c = col%get_col ()
if (c /= 0) call gen_particle_set_flow (prt%obj, 1_c_int, c)
c = col%get_acl ()
if (c /= 0) call gen_particle_set_flow (prt%obj, 2_c_int, c)
end subroutine hepmc_particle_set_color_col
subroutine hepmc_particle_set_color_int (prt, col)
type(hepmc_particle_t), intent(inout) :: prt
integer, dimension(2), intent(in) :: col
integer(c_int) :: c
c = col(1)
if (c /= 0) call gen_particle_set_flow (prt%obj, 1_c_int, c)
c = col(2)
if (c /= 0) call gen_particle_set_flow (prt%obj, 2_c_int, c)
end subroutine hepmc_particle_set_color_int
@ %def hepmc_particle_set_color
@ Set the particle polarization. For the restrictions on particle
polarization in HepMC, see above [[hepmc_polarization_init]].
<<HepMC interface: interfaces>>=
interface
subroutine gen_particle_set_polarization (prt_obj, pol_obj) bind(C)
import
type(c_ptr), value :: prt_obj, pol_obj
end subroutine gen_particle_set_polarization
end interface
@ %def gen_particle_set_polarization
<<HepMC interface: public>>=
public :: hepmc_particle_set_polarization
<<HepMC interface: interfaces>>=
interface hepmc_particle_set_polarization
module procedure hepmc_particle_set_polarization_pol
module procedure hepmc_particle_set_polarization_hel
module procedure hepmc_particle_set_polarization_int
end interface
<<HepMC interface: procedures>>=
subroutine hepmc_particle_set_polarization_pol (prt, pol)
type(hepmc_particle_t), intent(inout) :: prt
type(polarization_t), intent(in) :: pol
type(hepmc_polarization_t) :: hpol
call hepmc_polarization_init (hpol, pol)
if (hpol%polarized) call gen_particle_set_polarization (prt%obj, hpol%obj)
call hepmc_polarization_final (hpol)
end subroutine hepmc_particle_set_polarization_pol
subroutine hepmc_particle_set_polarization_hel (prt, hel)
type(hepmc_particle_t), intent(inout) :: prt
type(helicity_t), intent(in) :: hel
type(hepmc_polarization_t) :: hpol
call hepmc_polarization_init (hpol, hel)
if (hpol%polarized) call gen_particle_set_polarization (prt%obj, hpol%obj)
call hepmc_polarization_final (hpol)
end subroutine hepmc_particle_set_polarization_hel
subroutine hepmc_particle_set_polarization_int (prt, hel)
type(hepmc_particle_t), intent(inout) :: prt
integer, intent(in) :: hel
type(hepmc_polarization_t) :: hpol
call hepmc_polarization_init (hpol, hel)
if (hpol%polarized) call gen_particle_set_polarization (prt%obj, hpol%obj)
call hepmc_polarization_final (hpol)
end subroutine hepmc_particle_set_polarization_int
@ %def hepmc_particle_set_polarization
@ Return the HepMC barcode (unique integer ID) of the particle.
<<HepMC interface: interfaces>>=
interface
function gen_particle_barcode (prt_obj) result (barcode) bind(C)
import
integer(c_int) :: barcode
type(c_ptr), value :: prt_obj
end function gen_particle_barcode
end interface
@ %def gen_particle_barcode
<<HepMC interface: public>>=
public :: hepmc_particle_get_barcode
<<HepMC interface: procedures>>=
function hepmc_particle_get_barcode (prt) result (barcode)
integer :: barcode
type(hepmc_particle_t), intent(in) :: prt
barcode = gen_particle_barcode (prt%obj)
end function hepmc_particle_get_barcode
@ %def hepmc_particle_get_barcode
@ Return the four-vector component of the particle object as a [[vector4_t]] Lorentz vector.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function gen_particle_momentum (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function gen_particle_momentum
end interface
@ %def gen_particle_momentum
<<HepMC interface: public>>=
public :: hepmc_particle_get_momentum
<<HepMC interface: procedures>>=
function hepmc_particle_get_momentum (prt) result (p)
type(vector4_t) :: p
type(hepmc_particle_t), intent(in) :: prt
type(hepmc_four_vector_t) :: pp
call hepmc_four_vector_init (pp, prt)
call hepmc_four_vector_to_vector4 (pp, p)
call hepmc_four_vector_final (pp)
end function hepmc_particle_get_momentum
@ %def hepmc_particle_get_momentum
@ Return the invariant mass squared of the particle object. HepMC
stores the signed invariant mass (no squaring).
<<HepMC interface: interfaces>>=
interface
function gen_particle_generated_mass (prt_obj) result (mass) bind(C)
import
real(c_double) :: mass
type(c_ptr), value :: prt_obj
end function gen_particle_generated_mass
end interface
@ %def gen_particle_generated_mass
<<HepMC interface: public>>=
public :: hepmc_particle_get_mass_squared
<<HepMC interface: procedures>>=
function hepmc_particle_get_mass_squared (prt) result (m2)
real(default) :: m2
type(hepmc_particle_t), intent(in) :: prt
real(default) :: m
m = gen_particle_generated_mass (prt%obj)
m2 = sign (m**2, m)
end function hepmc_particle_get_mass_squared
@ %def hepmc_particle_get_mass_squared
@ Return the PDG ID:
<<HepMC interface: interfaces>>=
interface
function gen_particle_pdg_id (prt_obj) result (pdg_id) bind(C)
import
integer(c_int) :: pdg_id
type(c_ptr), value :: prt_obj
end function gen_particle_pdg_id
end interface
@ %def gen_particle_pdg_id
<<HepMC interface: public>>=
public :: hepmc_particle_get_pdg
<<HepMC interface: procedures>>=
function hepmc_particle_get_pdg (prt) result (pdg)
integer :: pdg
type(hepmc_particle_t), intent(in) :: prt
pdg = gen_particle_pdg_id (prt%obj)
end function hepmc_particle_get_pdg
@ %def hepmc_particle_get_pdg
@ Return the status code:
<<HepMC interface: interfaces>>=
interface
function gen_particle_status (prt_obj) result (status) bind(C)
import
integer(c_int) :: status
type(c_ptr), value :: prt_obj
end function gen_particle_status
end interface
@ %def gen_particle_status
<<HepMC interface: public>>=
public :: hepmc_particle_get_status
<<HepMC interface: procedures>>=
function hepmc_particle_get_status (prt) result (status)
integer :: status
type(hepmc_particle_t), intent(in) :: prt
status = gen_particle_status (prt%obj)
end function hepmc_particle_get_status
@ %def hepmc_particle_get_status
<<HepMC interface: interfaces>>=
interface
function gen_particle_is_beam (prt_obj) result (is_beam) bind(C)
import
logical(c_bool) :: is_beam
type(c_ptr), value :: prt_obj
end function gen_particle_is_beam
end interface
@ %def gen_particle_is_beam
@ Determine whether a particle is a beam particle.
<<HepMC interface: public>>=
public :: hepmc_particle_is_beam
<<HepMC interface: procedures>>=
function hepmc_particle_is_beam (prt) result (is_beam)
logical :: is_beam
type(hepmc_particle_t), intent(in) :: prt
is_beam = gen_particle_is_beam (prt%obj)
end function hepmc_particle_is_beam
@ %def hepmc_particle_is_beam
@ Return the production/decay vertex (as a pointer, no finalization
necessary).
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function gen_particle_production_vertex (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function gen_particle_production_vertex
end interface
interface
type(c_ptr) function gen_particle_end_vertex (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function gen_particle_end_vertex
end interface
@ %def gen_particle_production_vertex gen_particle_end_vertex
<<HepMC interface: public>>=
public :: hepmc_particle_get_production_vertex
public :: hepmc_particle_get_decay_vertex
<<HepMC interface: procedures>>=
function hepmc_particle_get_production_vertex (prt) result (v)
type(hepmc_vertex_t) :: v
type(hepmc_particle_t), intent(in) :: prt
v%obj = gen_particle_production_vertex (prt%obj)
end function hepmc_particle_get_production_vertex
function hepmc_particle_get_decay_vertex (prt) result (v)
type(hepmc_vertex_t) :: v
type(hepmc_particle_t), intent(in) :: prt
v%obj = gen_particle_end_vertex (prt%obj)
end function hepmc_particle_get_decay_vertex
@ %def hepmc_particle_get_production_vertex hepmc_particle_get_decay_vertex
@ Convenience function: Return the array of parent particles for a
given HepMC particle. The contents are HepMC barcodes that still have
to be mapped to the particle indices.
<<HepMC interface: public>>=
public :: hepmc_particle_get_parent_barcodes
public :: hepmc_particle_get_child_barcodes
<<HepMC interface: procedures>>=
function hepmc_particle_get_parent_barcodes (prt) result (parent_barcode)
type(hepmc_particle_t), intent(in) :: prt
integer, dimension(:), allocatable :: parent_barcode
type(hepmc_vertex_t) :: v
type(hepmc_vertex_particle_in_iterator_t) :: it
integer :: i
v = hepmc_particle_get_production_vertex (prt)
if (hepmc_vertex_is_valid (v)) then
allocate (parent_barcode (hepmc_vertex_get_n_in (v)))
if (size (parent_barcode) /= 0) then
if (HEPMC2_AVAILABLE) then
call hepmc_vertex_particle_in_iterator_init (it, v)
do i = 1, size (parent_barcode)
parent_barcode(i) = hepmc_particle_get_barcode &
(hepmc_vertex_particle_in_iterator_get (it))
call hepmc_vertex_particle_in_iterator_advance (it)
end do
call hepmc_vertex_particle_in_iterator_final (it)
else if (HEPMC3_AVAILABLE) then
do i = 1, size (parent_barcode)
parent_barcode(i) = hepmc_particle_get_barcode &
(hepmc_vertex_get_nth_particle_in (v, i))
end do
end if
end if
else
allocate (parent_barcode (0))
end if
end function hepmc_particle_get_parent_barcodes
function hepmc_particle_get_child_barcodes (prt) result (child_barcode)
type(hepmc_particle_t), intent(in) :: prt
integer, dimension(:), allocatable :: child_barcode
type(hepmc_vertex_t) :: v
type(hepmc_vertex_particle_out_iterator_t) :: it
integer :: i
v = hepmc_particle_get_decay_vertex (prt)
if (hepmc_vertex_is_valid (v)) then
allocate (child_barcode (hepmc_vertex_get_n_out (v)))
if (size (child_barcode) /= 0) then
if (HEPMC2_AVAILABLE) then
call hepmc_vertex_particle_out_iterator_init (it, v)
do i = 1, size (child_barcode)
child_barcode(i) = hepmc_particle_get_barcode &
(hepmc_vertex_particle_out_iterator_get (it))
call hepmc_vertex_particle_out_iterator_advance (it)
end do
call hepmc_vertex_particle_out_iterator_final (it)
else if (HEPMC3_AVAILABLE) then
do i = 1, size (child_barcode)
child_barcode(i) = hepmc_particle_get_barcode &
(hepmc_vertex_get_nth_particle_out (v, i))
end do
end if
end if
else
allocate (child_barcode (0))
end if
end function hepmc_particle_get_child_barcodes
@ %def hepmc_particle_get_parent_barcodes hepmc_particle_get_child_barcodes
@ Return the polarization (assuming that the particle is completely
polarized). Note that the generated polarization object needs finalization.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function gen_particle_polarization (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function gen_particle_polarization
end interface
@ %def gen_particle_polarization
<<HepMC interface: public>>=
public :: hepmc_particle_get_polarization
<<HepMC interface: procedures>>=
function hepmc_particle_get_polarization (prt) result (pol)
type(hepmc_polarization_t) :: pol
type(hepmc_particle_t), intent(in) :: prt
pol%obj = gen_particle_polarization (prt%obj)
end function hepmc_particle_get_polarization
@ %def hepmc_particle_get_polarization
@ Return the particle color as a two-dimensional array (color, anticolor).
<<HepMC interface: interfaces>>=
interface
function gen_particle_flow (prt_obj, code_index) result (code) bind(C)
import
integer(c_int) :: code
type(c_ptr), value :: prt_obj
integer(c_int), value :: code_index
end function gen_particle_flow
end interface
@ %def gen_particle_flow
<<HepMC interface: public>>=
public :: hepmc_particle_get_color
<<HepMC interface: procedures>>=
function hepmc_particle_get_color (prt) result (col)
integer, dimension(2) :: col
type(hepmc_particle_t), intent(in) :: prt
col(1) = gen_particle_flow (prt%obj, 1)
col(2) = - gen_particle_flow (prt%obj, 2)
end function hepmc_particle_get_color
@ %def hepmc_particle_get_color
@
<<HepMC interface: interfaces>>=
interface
function gen_vertex_pos_x (v_obj) result (x) bind(C)
import
type(c_ptr), value :: v_obj
real(c_double) :: x
end function gen_vertex_pos_x
end interface
interface
function gen_vertex_pos_y (v_obj) result (y) bind(C)
import
type(c_ptr), value :: v_obj
real(c_double) :: y
end function gen_vertex_pos_y
end interface
interface
function gen_vertex_pos_z (v_obj) result (z) bind(C)
import
type(c_ptr), value :: v_obj
real(c_double) :: z
end function gen_vertex_pos_z
end interface
interface
function gen_vertex_time (v_obj) result (t) bind(C)
import
type(c_ptr), value :: v_obj
real(c_double) :: t
end function gen_vertex_time
end interface
@
<<HepMC interface: public>>=
public :: hepmc_vertex_to_vertex
<<HepMC interface: procedures>>=
function hepmc_vertex_to_vertex (vtx) result (v)
type(hepmc_vertex_t), intent(in) :: vtx
type(vector4_t) :: v
real(default) :: t, vx, vy, vz
if (hepmc_vertex_is_valid (vtx)) then
t = gen_vertex_time (vtx%obj)
vx = gen_vertex_pos_x (vtx%obj)
vy = gen_vertex_pos_y (vtx%obj)
vz = gen_vertex_pos_z (vtx%obj)
v = vector4_moving (t, &
vector3_moving ([vx, vy, vz]))
end if
end function hepmc_vertex_to_vertex
@ %def hepmc_vertex_to_vertex
@
\subsection{GenVertex}
Vertices are made of particles (incoming and outgoing).
<<HepMC interface: public>>=
public :: hepmc_vertex_t
<<HepMC interface: types>>=
type :: hepmc_vertex_t
private
type(c_ptr) :: obj
end type hepmc_vertex_t
@ %def hepmc_vertex_t
@ Constructor. Two versions, one plain, one with the position in
space and time (measured in mm) as argument. The Fortran version has
initializer form, and the vertex position is an optional argument.
A destructor is unnecessary as long as all vertices are entered into
an event container.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_gen_vertex () bind(C)
import
end function new_gen_vertex
end interface
interface
type(c_ptr) function new_gen_vertex_pos (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function new_gen_vertex_pos
end interface
@ %def new_gen_vertex new_gen_vertex_pos
<<HepMC interface: public>>=
public :: hepmc_vertex_init
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_init (v, x)
type(hepmc_vertex_t), intent(out) :: v
type(vector4_t), intent(in), optional :: x
type(hepmc_four_vector_t) :: pos
if (present (x)) then
call hepmc_four_vector_init (pos, x)
v%obj = new_gen_vertex_pos (pos%obj)
call hepmc_four_vector_final (pos)
else
v%obj = new_gen_vertex ()
end if
end subroutine hepmc_vertex_init
@ %def hepmc_vertex_init
@ Return true if the vertex pointer is non-null:
<<HepMC interface: interfaces>>=
interface
function gen_vertex_is_valid (v_obj) result (flag) bind(C)
import
logical(c_bool) :: flag
type(c_ptr), value :: v_obj
end function gen_vertex_is_valid
end interface
@ %def gen_vertex_is_valid
<<HepMC interface: public>>=
public :: hepmc_vertex_is_valid
<<HepMC interface: procedures>>=
function hepmc_vertex_is_valid (v) result (flag)
logical :: flag
type(hepmc_vertex_t), intent(in) :: v
flag = gen_vertex_is_valid (v%obj)
end function hepmc_vertex_is_valid
@ %def hepmc_vertex_is_valid
@ Add a particle to a vertex, incoming or outgoing.
<<HepMC interface: interfaces>>=
interface
subroutine gen_vertex_add_particle_in (v_obj, prt_obj) bind(C)
import
type(c_ptr), value :: v_obj, prt_obj
end subroutine gen_vertex_add_particle_in
end interface
interface
subroutine gen_vertex_add_particle_out (v_obj, prt_obj) bind(C)
import
type(c_ptr), value :: v_obj, prt_obj
end subroutine gen_vertex_add_particle_out
end interface
<<HepMC interface: public>>=
public :: hepmc_vertex_add_particle_in
public :: hepmc_vertex_add_particle_out
@ %def gen_vertex_add_particle_in gen_vertex_add_particle_out
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_add_particle_in (v, prt)
type(hepmc_vertex_t), intent(inout) :: v
type(hepmc_particle_t), intent(in) :: prt
call gen_vertex_add_particle_in (v%obj, prt%obj)
end subroutine hepmc_vertex_add_particle_in
subroutine hepmc_vertex_add_particle_out (v, prt)
type(hepmc_vertex_t), intent(inout) :: v
type(hepmc_particle_t), intent(in) :: prt
call gen_vertex_add_particle_out (v%obj, prt%obj)
end subroutine hepmc_vertex_add_particle_out
@ %def hepmc_vertex_add_particle_in hepmc_vertex_add_particle_out
@ Return the number of incoming/outgoing particles.
<<HepMC interface: interfaces>>=
interface
function gen_vertex_particles_in_size (v_obj) result (size) bind(C)
import
integer(c_int) :: size
type(c_ptr), value :: v_obj
end function gen_vertex_particles_in_size
end interface
interface
function gen_vertex_particles_out_size (v_obj) result (size) bind(C)
import
integer(c_int) :: size
type(c_ptr), value :: v_obj
end function gen_vertex_particles_out_size
end interface
interface
function gen_particle_get_n_parents (p_obj) result (size) bind(C)
import
integer(c_int) :: size
type(c_ptr), value :: p_obj
end function gen_particle_get_n_parents
end interface
interface
function gen_particle_get_n_children (p_obj) result (size) bind(C)
import
integer(c_int) :: size
type(c_ptr), value :: p_obj
end function gen_particle_get_n_children
end interface
@ %def gen_vertex_particles_in_size gen_vertex_particles_out_size
@ %def gen_particle_get_n_parents get_particle_get_n_children
<<HepMC interface: public>>=
public :: hepmc_vertex_get_n_in
public :: hepmc_vertex_get_n_out
public :: hepmc_particle_get_parents
public :: hepmc_particle_get_children
<<HepMC interface: procedures>>=
function hepmc_vertex_get_n_in (v) result (n_in)
integer :: n_in
type(hepmc_vertex_t), intent(in) :: v
n_in = gen_vertex_particles_in_size (v%obj)
end function hepmc_vertex_get_n_in
function hepmc_vertex_get_n_out (v) result (n_out)
integer :: n_out
type(hepmc_vertex_t), intent(in) :: v
n_out = gen_vertex_particles_out_size (v%obj)
end function hepmc_vertex_get_n_out
function hepmc_particle_get_parents (p) result (n_p)
integer :: n_p
type(hepmc_particle_t), intent(in) :: p
n_p = gen_particle_get_n_parents (p%obj)
end function hepmc_particle_get_parents
function hepmc_particle_get_children (p) result (n_ch)
integer :: n_ch
type(hepmc_particle_t), intent(in) :: p
n_ch = gen_particle_get_n_children (p%obj)
end function hepmc_particle_get_children
@ %def hepmc_vertex_n_in hepmc_vertex_n_out
@ %def hepmc_particle_get_parents hepmc_particle_get_children
@ Return the number of parents/children.
<<HepMC interface: public>>=
public :: hepmc_particle_get_n_parents
public :: hepmc_particle_get_n_children
<<HepMC interface: procedures>>=
function hepmc_particle_get_n_parents (prt) result (n_parents)
integer :: n_parents
type(hepmc_particle_t), intent(in) :: prt
type(hepmc_vertex_t) :: v
if (HEPMC2_AVAILABLE) then
v = hepmc_particle_get_production_vertex (prt)
if (hepmc_vertex_is_valid (v)) then
n_parents = hepmc_vertex_get_n_in (v)
else
n_parents = 0
end if
else if (HEPMC3_AVAILABLE) then
n_parents = hepmc_particle_get_parents (prt)
end if
end function hepmc_particle_get_n_parents
function hepmc_particle_get_n_children (prt) result (n_children)
integer :: n_children
type(hepmc_particle_t), intent(in) :: prt
type(hepmc_vertex_t) :: v
if (HEPMC2_AVAILABLE) then
v = hepmc_particle_get_decay_vertex (prt)
if (hepmc_vertex_is_valid (v)) then
n_children = hepmc_vertex_get_n_out (v)
else
n_children = 0
end if
else if (HEPMC3_AVAILABLE) then
n_children = hepmc_particle_get_children (prt)
end if
end function hepmc_particle_get_n_children
@ %def hepmc_particle_get_n_parents
@ %def hepmc_particle_get_n_children
\subsection{Vertex-particle-in iterator}
This iterator iterates over all incoming particles in an vertex. We store a
pointer to the vertex in addition to the iterator. This allows for
simple end checking.
The iterator is actually a constant iterator; it can only read.
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_t
<<HepMC interface: types>>=
type :: hepmc_vertex_particle_in_iterator_t
private
type(c_ptr) :: obj
type(c_ptr) :: v_obj
end type hepmc_vertex_particle_in_iterator_t
@ %def hepmc_vertex_particle_in_iterator_t
@ Constructor. The iterator is initialized at the first particle in
the vertex.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function &
new_vertex_particles_in_const_iterator (v_obj) bind(C)
import
type(c_ptr), value :: v_obj
end function new_vertex_particles_in_const_iterator
end interface
@ %def new_vertex_particles_in_const_iterator
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_init
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_in_iterator_init (it, v)
type(hepmc_vertex_particle_in_iterator_t), intent(out) :: it
type(hepmc_vertex_t), intent(in) :: v
it%obj = new_vertex_particles_in_const_iterator (v%obj)
it%v_obj = v%obj
end subroutine hepmc_vertex_particle_in_iterator_init
@ %def hepmc_vertex_particle_in_iterator_init
@ Destructor. Necessary because the iterator is allocated on the
heap.
<<HepMC interface: interfaces>>=
interface
subroutine vertex_particles_in_const_iterator_delete (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end subroutine vertex_particles_in_const_iterator_delete
end interface
@ %def vertex_particles_in_const_iterator_delete
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_final
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_in_iterator_final (it)
type(hepmc_vertex_particle_in_iterator_t), intent(inout) :: it
call vertex_particles_in_const_iterator_delete (it%obj)
end subroutine hepmc_vertex_particle_in_iterator_final
@ %def hepmc_vertex_particle_in_iterator_final
@ Increment
<<HepMC interface: interfaces>>=
interface
subroutine vertex_particles_in_const_iterator_advance (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end subroutine vertex_particles_in_const_iterator_advance
end interface
@ %def vertex_particles_in_const_iterator_advance
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_advance
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_in_iterator_advance (it)
type(hepmc_vertex_particle_in_iterator_t), intent(inout) :: it
call vertex_particles_in_const_iterator_advance (it%obj)
end subroutine hepmc_vertex_particle_in_iterator_advance
@ %def hepmc_vertex_particle_in_iterator_advance
@ Reset to the beginning
<<HepMC interface: interfaces>>=
interface
subroutine vertex_particles_in_const_iterator_reset &
(it_obj, v_obj) bind(C)
import
type(c_ptr), value :: it_obj, v_obj
end subroutine vertex_particles_in_const_iterator_reset
end interface
@ %def vertex_particles_in_const_iterator_reset
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_reset
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_in_iterator_reset (it)
type(hepmc_vertex_particle_in_iterator_t), intent(inout) :: it
call vertex_particles_in_const_iterator_reset (it%obj, it%v_obj)
end subroutine hepmc_vertex_particle_in_iterator_reset
@ %def hepmc_vertex_particle_in_iterator_reset
@ Test: return true as long as we are not past the end.
<<HepMC interface: interfaces>>=
interface
function vertex_particles_in_const_iterator_is_valid &
(it_obj, v_obj) result (flag) bind(C)
import
logical(c_bool) :: flag
type(c_ptr), value :: it_obj, v_obj
end function vertex_particles_in_const_iterator_is_valid
end interface
@ %def vertex_particles_in_const_iterator_is_valid
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_is_valid
<<HepMC interface: procedures>>=
function hepmc_vertex_particle_in_iterator_is_valid (it) result (flag)
logical :: flag
type(hepmc_vertex_particle_in_iterator_t), intent(in) :: it
flag = vertex_particles_in_const_iterator_is_valid (it%obj, it%v_obj)
end function hepmc_vertex_particle_in_iterator_is_valid
@ %def hepmc_vertex_particle_in_iterator_is_valid
@ Return the particle pointed to by the iterator. (The particle
object should not be finalized, since it contains merely a pointer to
the particle which is owned by the vertex.)
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function &
vertex_particles_in_const_iterator_get (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end function vertex_particles_in_const_iterator_get
end interface
@ %def vertex_particles_in_const_iterator_get
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_in_iterator_get
<<HepMC interface: procedures>>=
function hepmc_vertex_particle_in_iterator_get (it) result (prt)
type(hepmc_particle_t) :: prt
type(hepmc_vertex_particle_in_iterator_t), intent(in) :: it
prt%obj = vertex_particles_in_const_iterator_get (it%obj)
end function hepmc_vertex_particle_in_iterator_get
@ %def hepmc_vertex_particle_in_iterator_get
@
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function vertex_get_nth_particle_in (vtx_obj, n) bind(C)
import
type(c_ptr), value :: vtx_obj
integer(c_int), value :: n
end function vertex_get_nth_particle_in
end interface
interface
type(c_ptr) function vertex_get_nth_particle_out (vtx_obj, n) bind(C)
import
type(c_ptr), value :: vtx_obj
integer(c_int), value :: n
end function vertex_get_nth_particle_out
end interface
@ %def vertex_get_nth_particle_in
<<HepMC interface: public>>=
public :: hepmc_vertex_get_nth_particle_in
public :: hepmc_vertex_get_nth_particle_out
<<HepMC interface: procedures>>=
function hepmc_vertex_get_nth_particle_in (vtx, n) result (prt)
type(hepmc_particle_t) :: prt
type(hepmc_vertex_t), intent(in) :: vtx
integer, intent(in) :: n
integer(c_int) :: nth
nth = n
prt%obj = vertex_get_nth_particle_in (vtx%obj, nth)
end function hepmc_vertex_get_nth_particle_in
function hepmc_vertex_get_nth_particle_out (vtx, n) result (prt)
type(hepmc_particle_t) :: prt
type(hepmc_vertex_t), intent(in) :: vtx
integer, intent(in) :: n
integer(c_int) :: nth
nth = n
prt%obj = vertex_get_nth_particle_out (vtx%obj, nth)
end function hepmc_vertex_get_nth_particle_out
@ %def hepmc_vertex_get_nth_particle_in
@ %def hepmc_vertex_get_nth_particle_out
@
\subsection{Vertex-particle-out iterator}
This iterator iterates over all incoming particles in an vertex. We store a
pointer to the vertex in addition to the iterator. This allows for
simple end checking.
The iterator is actually a constant iterator; it can only read.
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_t
<<HepMC interface: types>>=
type :: hepmc_vertex_particle_out_iterator_t
private
type(c_ptr) :: obj
type(c_ptr) :: v_obj
end type hepmc_vertex_particle_out_iterator_t
@ %def hepmc_vertex_particle_out_iterator_t
@ Constructor. The iterator is initialized at the first particle in
the vertex.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function &
new_vertex_particles_out_const_iterator (v_obj) bind(C)
import
type(c_ptr), value :: v_obj
end function new_vertex_particles_out_const_iterator
end interface
@ %def new_vertex_particles_out_const_iterator
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_init
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_out_iterator_init (it, v)
type(hepmc_vertex_particle_out_iterator_t), intent(out) :: it
type(hepmc_vertex_t), intent(in) :: v
it%obj = new_vertex_particles_out_const_iterator (v%obj)
it%v_obj = v%obj
end subroutine hepmc_vertex_particle_out_iterator_init
@ %def hepmc_vertex_particle_out_iterator_init
@ Destructor. Necessary because the iterator is allocated on the
heap.
<<HepMC interface: interfaces>>=
interface
subroutine vertex_particles_out_const_iterator_delete (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end subroutine vertex_particles_out_const_iterator_delete
end interface
@ %def vertex_particles_out_const_iterator_delete
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_final
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_out_iterator_final (it)
type(hepmc_vertex_particle_out_iterator_t), intent(inout) :: it
call vertex_particles_out_const_iterator_delete (it%obj)
end subroutine hepmc_vertex_particle_out_iterator_final
@ %def hepmc_vertex_particle_out_iterator_final
@ Increment
<<HepMC interface: interfaces>>=
interface
subroutine vertex_particles_out_const_iterator_advance (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end subroutine vertex_particles_out_const_iterator_advance
end interface
@ %def vertex_particles_out_const_iterator_advance
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_advance
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_out_iterator_advance (it)
type(hepmc_vertex_particle_out_iterator_t), intent(inout) :: it
call vertex_particles_out_const_iterator_advance (it%obj)
end subroutine hepmc_vertex_particle_out_iterator_advance
@ %def hepmc_vertex_particle_out_iterator_advance
@ Reset to the beginning
<<HepMC interface: interfaces>>=
interface
subroutine vertex_particles_out_const_iterator_reset &
(it_obj, v_obj) bind(C)
import
type(c_ptr), value :: it_obj, v_obj
end subroutine vertex_particles_out_const_iterator_reset
end interface
@ %def vertex_particles_out_const_iterator_reset
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_reset
<<HepMC interface: procedures>>=
subroutine hepmc_vertex_particle_out_iterator_reset (it)
type(hepmc_vertex_particle_out_iterator_t), intent(inout) :: it
call vertex_particles_out_const_iterator_reset (it%obj, it%v_obj)
end subroutine hepmc_vertex_particle_out_iterator_reset
@ %def hepmc_vertex_particle_out_iterator_reset
@ Test: return true as long as we are not past the end.
<<HepMC interface: interfaces>>=
interface
function vertex_particles_out_const_iterator_is_valid &
(it_obj, v_obj) result (flag) bind(C)
import
logical(c_bool) :: flag
type(c_ptr), value :: it_obj, v_obj
end function vertex_particles_out_const_iterator_is_valid
end interface
@ %def vertex_particles_out_const_iterator_is_valid
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_is_valid
<<HepMC interface: procedures>>=
function hepmc_vertex_particle_out_iterator_is_valid (it) result (flag)
logical :: flag
type(hepmc_vertex_particle_out_iterator_t), intent(in) :: it
flag = vertex_particles_out_const_iterator_is_valid (it%obj, it%v_obj)
end function hepmc_vertex_particle_out_iterator_is_valid
@ %def hepmc_vertex_particle_out_iterator_is_valid
@ Return the particle pointed to by the iterator. (The particle
object should not be finalized, since it contains merely a pointer to
the particle which is owned by the vertex.)
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function &
vertex_particles_out_const_iterator_get (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end function vertex_particles_out_const_iterator_get
end interface
@ %def vertex_particles_out_const_iterator_get
<<HepMC interface: public>>=
public :: hepmc_vertex_particle_out_iterator_get
<<HepMC interface: procedures>>=
function hepmc_vertex_particle_out_iterator_get (it) result (prt)
type(hepmc_particle_t) :: prt
type(hepmc_vertex_particle_out_iterator_t), intent(in) :: it
prt%obj = vertex_particles_out_const_iterator_get (it%obj)
end function hepmc_vertex_particle_out_iterator_get
@ %def hepmc_vertex_particle_out_iterator_get
@
\subsection{GenEvent}
The main object of HepMC is a GenEvent. The object is filled by
GenVertex objects, which in turn contain GenParticle objects.
<<HepMC interface: public>>=
public :: hepmc_event_t
<<HepMC interface: types>>=
type :: hepmc_event_t
private
type(c_ptr) :: obj
end type hepmc_event_t
@ %def hepmc_event_t
@ Constructor. Arguments are process ID (integer) and event ID
(integer).
The Fortran version has initializer form.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_gen_event (proc_id, event_id) bind(C)
import
integer(c_int), value :: proc_id, event_id
end function new_gen_event
end interface
@ %def new_gen_event
<<HepMC interface: public>>=
public :: hepmc_event_init
<<HepMC interface: procedures>>=
subroutine hepmc_event_init (evt, proc_id, event_id)
type(hepmc_event_t), intent(out) :: evt
integer, intent(in), optional :: proc_id, event_id
integer(c_int) :: pid, eid
pid = 0; if (present (proc_id)) pid = proc_id
eid = 0; if (present (event_id)) eid = event_id
evt%obj = new_gen_event (pid, eid)
end subroutine hepmc_event_init
@ %def hepmc_event_init
@ Destructor.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_delete (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end subroutine gen_event_delete
end interface
@ %def gen_event_delete
<<HepMC interface: public>>=
public :: hepmc_event_final
<<HepMC interface: procedures>>=
subroutine hepmc_event_final (evt)
type(hepmc_event_t), intent(inout) :: evt
call gen_event_delete (evt%obj)
end subroutine hepmc_event_final
@ %def hepmc_event_final
@ Screen output. Printing to file is possible in principle (using a
C++ output channel), by allowing an argument. Printing to an open
Fortran unit is obviously not possible.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_print (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end subroutine gen_event_print
end interface
@ %def gen_event_print
<<HepMC interface: public>>=
public :: hepmc_event_print
<<HepMC interface: procedures>>=
subroutine hepmc_event_print (evt)
type(hepmc_event_t), intent(in) :: evt
call gen_event_print (evt%obj)
end subroutine hepmc_event_print
@ %def hepmc_event_print
@ Get the event number.
<<HepMC interface: interfaces>>=
interface
integer(c_int) function gen_event_event_number (evt_obj) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
end function gen_event_event_number
end interface
@ %def gen_event_event_number
<<HepMC interface: public>>=
public :: hepmc_event_get_event_index
<<HepMC interface: procedures>>=
function hepmc_event_get_event_index (evt) result (i_proc)
integer :: i_proc
type(hepmc_event_t), intent(in) :: evt
i_proc = gen_event_event_number (evt%obj)
end function hepmc_event_get_event_index
@ %def hepmc_event_get_event_index
<<HepMC interface: interfaces>>=
interface
integer(c_int) function gen_event_get_n_particles &
(evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function gen_event_get_n_particles
end interface
interface
integer(c_int) function gen_event_get_n_beams &
(evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function gen_event_get_n_beams
end interface
@ %def gen_event_get_n_particles gen_event_get_n_beams
<<HepMC interface: public>>=
public :: hepmc_event_get_n_particles
public :: hepmc_event_get_n_beams
<<HepMC interface: procedures>>=
function hepmc_event_get_n_particles (evt) result (n_tot)
integer :: n_tot
type(hepmc_event_t), intent(in) :: evt
n_tot = gen_event_get_n_particles (evt%obj)
end function hepmc_event_get_n_particles
function hepmc_event_get_n_beams (evt) result (n_tot)
integer :: n_tot
type(hepmc_event_t), intent(in) :: evt
n_tot = gen_event_get_n_beams (evt%obj)
end function hepmc_event_get_n_beams
@ %def hepmc_event_get_n_particles
@ %def hepmc_event_get_n_beams
@ Set the numeric signal process ID
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_set_signal_process_id (evt_obj, proc_id) bind(C)
import
type(c_ptr), value :: evt_obj
integer(c_int), value :: proc_id
end subroutine gen_event_set_signal_process_id
end interface
@ %def gen_event_set_signal_process_id
<<HepMC interface: public>>=
public :: hepmc_event_set_process_id
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_process_id (evt, proc)
type(hepmc_event_t), intent(in) :: evt
integer, intent(in) :: proc
integer(c_int) :: i_proc
i_proc = proc
call gen_event_set_signal_process_id (evt%obj, i_proc)
end subroutine hepmc_event_set_process_id
@ %def hepmc_event_set_process_id
@ Get the numeric signal process ID
<<HepMC interface: interfaces>>=
interface
integer(c_int) function gen_event_signal_process_id (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function gen_event_signal_process_id
end interface
@ %def gen_event_signal_process_id
<<HepMC interface: public>>=
public :: hepmc_event_get_process_id
<<HepMC interface: procedures>>=
function hepmc_event_get_process_id (evt) result (i_proc)
integer :: i_proc
type(hepmc_event_t), intent(in) :: evt
i_proc = gen_event_signal_process_id (evt%obj)
end function hepmc_event_get_process_id
@ %def hepmc_event_get_process_id
@ Set the event energy scale
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_set_event_scale (evt_obj, scale) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: scale
end subroutine gen_event_set_event_scale
end interface
@ %def gen_event_set_event_scale
<<HepMC interface: public>>=
public :: hepmc_event_set_scale
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_scale (evt, scale)
type(hepmc_event_t), intent(in) :: evt
real(default), intent(in) :: scale
real(c_double) :: cscale
cscale = scale
call gen_event_set_event_scale (evt%obj, cscale)
end subroutine hepmc_event_set_scale
@ %def hepmc_event_set_scale
@ Get the event energy scale
<<HepMC interface: interfaces>>=
interface
real(c_double) function gen_event_event_scale (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function gen_event_event_scale
end interface
@ %def gen_event_event_scale
<<HepMC interface: public>>=
public :: hepmc_event_get_scale
<<HepMC interface: procedures>>=
function hepmc_event_get_scale (evt) result (scale)
real(default) :: scale
type(hepmc_event_t), intent(in) :: evt
scale = gen_event_event_scale (evt%obj)
end function hepmc_event_get_scale
@ %def hepmc_event_set_scale
@ Set the value of $\alpha_{\rm QCD}$.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_set_alpha_qcd (evt_obj, a) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: a
end subroutine gen_event_set_alpha_qcd
end interface
@ %def gen_event_set_alpha_qcd
<<HepMC interface: public>>=
public :: hepmc_event_set_alpha_qcd
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_alpha_qcd (evt, alpha)
type(hepmc_event_t), intent(in) :: evt
real(default), intent(in) :: alpha
real(c_double) :: a
a = alpha
call gen_event_set_alpha_qcd (evt%obj, a)
end subroutine hepmc_event_set_alpha_qcd
@ %def hepmc_event_set_alpha_qcd
@ Get the value of $\alpha_{\rm QCD}$.
<<HepMC interface: interfaces>>=
interface
real(c_double) function gen_event_alpha_qcd (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function gen_event_alpha_qcd
end interface
@ %def gen_event_get_alpha_qcd
<<HepMC interface: public>>=
public :: hepmc_event_get_alpha_qcd
<<HepMC interface: procedures>>=
function hepmc_event_get_alpha_qcd (evt) result (alpha)
real(default) :: alpha
type(hepmc_event_t), intent(in) :: evt
alpha = gen_event_alpha_qcd (evt%obj)
end function hepmc_event_get_alpha_qcd
@ %def hepmc_event_get_alpha_qcd
@ Set the value of $\alpha_{\rm QED}$.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_set_alpha_qed (evt_obj, a) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: a
end subroutine gen_event_set_alpha_qed
end interface
@ %def gen_event_set_alpha_qed
<<HepMC interface: public>>=
public :: hepmc_event_set_alpha_qed
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_alpha_qed (evt, alpha)
type(hepmc_event_t), intent(in) :: evt
real(default), intent(in) :: alpha
real(c_double) :: a
a = alpha
call gen_event_set_alpha_qed (evt%obj, a)
end subroutine hepmc_event_set_alpha_qed
@ %def hepmc_event_set_alpha_qed
@ Get the value of $\alpha_{\rm QED}$.
<<HepMC interface: interfaces>>=
interface
real(c_double) function gen_event_alpha_qed (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function gen_event_alpha_qed
end interface
@ %def gen_event_get_alpha_qed
<<HepMC interface: public>>=
public :: hepmc_event_get_alpha_qed
<<HepMC interface: procedures>>=
function hepmc_event_get_alpha_qed (evt) result (alpha)
real(default) :: alpha
type(hepmc_event_t), intent(in) :: evt
alpha = gen_event_alpha_qed (evt%obj)
end function hepmc_event_get_alpha_qed
@ %def hepmc_event_get_alpha_qed
@ Clear a weight value to the end of the weight container.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_clear_weights (evt_obj) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
end subroutine gen_event_clear_weights
end interface
@ %def gen_event_set_alpha_qed
@ The HepMC weights are measured in pb.
<<HepMC interface: parameters>>=
real(default), parameter :: pb_per_fb = 1.e-3_default
@ %def pb_per_fb
@
<<HepMC interface: public>>=
public :: hepmc_event_clear_weights
<<HepMC interface: procedures>>=
subroutine hepmc_event_clear_weights (evt)
type(hepmc_event_t), intent(in) :: evt
call gen_event_clear_weights (evt%obj)
end subroutine hepmc_event_clear_weights
@ %def hepmc_event_clear_weights
@ Add a weight value to the end of the weight container.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_add_weight (evt_obj, w) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
real(c_double), value :: w
end subroutine gen_event_add_weight
end interface
@ %def gen_event_add_weight
@
<<HepMC interface: public>>=
public :: hepmc_event_add_weight
<<HepMC interface: procedures>>=
subroutine hepmc_event_add_weight (evt, weight)
type(hepmc_event_t), intent(in) :: evt
real(default), intent(in) :: weight
real(c_double) :: w
w = weight * pb_per_fb
call gen_event_add_weight (evt%obj, w)
end subroutine hepmc_event_add_weight
@ %def hepmc_event_add_weight
@ Get the size of the weight container (the number of valid elements).
<<HepMC interface: interfaces>>=
interface
integer(c_int) function gen_event_weights_size (evt_obj) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
end function gen_event_weights_size
end interface
@ %def gen_event_get_weight
<<HepMC interface: public>>=
public :: hepmc_event_get_weights_size
<<HepMC interface: procedures>>=
function hepmc_event_get_weights_size (evt) result (n)
integer :: n
type(hepmc_event_t), intent(in) :: evt
n = gen_event_weights_size (evt%obj)
end function hepmc_event_get_weights_size
@ %def hepmc_event_get_weights_size
@ Get the value of the weight with index [[i]]. (Count from 1, while C counts
from zero.)
<<HepMC interface: interfaces>>=
interface
real(c_double) function gen_event_weight (evt_obj, i) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
integer(c_int), value :: i
end function gen_event_weight
end interface
@ %def gen_event_get_weight
<<HepMC interface: public>>=
public :: hepmc_event_get_weight
<<HepMC interface: procedures>>=
function hepmc_event_get_weight (evt, index) result (weight)
real(default) :: weight
type(hepmc_event_t), intent(in) :: evt
integer, intent(in) :: index
integer(c_int) :: i
i = index - 1
weight = gen_event_weight (evt%obj, i) / pb_per_fb
end function hepmc_event_get_weight
@ %def hepmc_event_get_weight
@ Add a vertex to the event container.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_add_vertex (evt_obj, v_obj) bind(C)
import
type(c_ptr), value :: evt_obj
type(c_ptr), value :: v_obj
end subroutine gen_event_add_vertex
end interface
@ %def gen_event_add_vertex
<<HepMC interface: public>>=
public :: hepmc_event_add_vertex
<<HepMC interface: procedures>>=
subroutine hepmc_event_add_vertex (evt, v)
type(hepmc_event_t), intent(inout) :: evt
type(hepmc_vertex_t), intent(in) :: v
call gen_event_add_vertex (evt%obj, v%obj)
end subroutine hepmc_event_add_vertex
@ %def hepmc_event_add_vertex
@ Mark a particular vertex as the signal process (hard interaction).
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_set_signal_process_vertex (evt_obj, v_obj) bind(C)
import
type(c_ptr), value :: evt_obj
type(c_ptr), value :: v_obj
end subroutine gen_event_set_signal_process_vertex
end interface
@ %def gen_event_set_signal_process_vertex
<<HepMC interface: public>>=
public :: hepmc_event_set_signal_process_vertex
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_signal_process_vertex (evt, v)
type(hepmc_event_t), intent(inout) :: evt
type(hepmc_vertex_t), intent(in) :: v
call gen_event_set_signal_process_vertex (evt%obj, v%obj)
end subroutine hepmc_event_set_signal_process_vertex
@ %def hepmc_event_set_signal_process_vertex
@ Return the the signal process (hard interaction).
<<HepMC interface: interfaces>>=
interface
function gen_event_get_signal_process_vertex (evt_obj) &
result (v_obj) bind(C)
import
type(c_ptr), value :: evt_obj
type(c_ptr) :: v_obj
end function gen_event_get_signal_process_vertex
end interface
@ %def gen_event_get_signal_process_vertex
<<HepMC interface: public>>=
public :: hepmc_event_get_signal_process_vertex
<<HepMC interface: procedures>>=
function hepmc_event_get_signal_process_vertex (evt) result (v)
type(hepmc_event_t), intent(in) :: evt
type(hepmc_vertex_t) :: v
v%obj = gen_event_get_signal_process_vertex (evt%obj)
end function hepmc_event_get_signal_process_vertex
@ %def hepmc_event_get_signal_process_vertex
@ Set the beam particles explicitly.
<<HepMC interface: public>>=
public :: hepmc_event_set_beam_particles
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_beam_particles (evt, prt1, prt2)
type(hepmc_event_t), intent(inout) :: evt
type(hepmc_particle_t), intent(in) :: prt1, prt2
logical(c_bool) :: flag
flag = gen_event_set_beam_particles (evt%obj, prt1%obj, prt2%obj)
end subroutine hepmc_event_set_beam_particles
@ %def hepmc_event_set_beam_particles
@ The C function returns a boolean which we do not use.
<<HepMC interface: interfaces>>=
interface
logical(c_bool) function gen_event_set_beam_particles &
(evt_obj, prt1_obj, prt2_obj) bind(C)
import
type(c_ptr), value :: evt_obj, prt1_obj, prt2_obj
end function gen_event_set_beam_particles
end interface
@ %def gen_event_set_beam_particles
@ Set the cross section and error explicitly. Note that HepMC uses
pb, while WHIZARD uses fb.
<<HepMC interface: public>>=
public :: hepmc_event_set_cross_section
<<HepMC interface: procedures>>=
subroutine hepmc_event_set_cross_section (evt, xsec, xsec_err)
type(hepmc_event_t), intent(inout) :: evt
real(default), intent(in) :: xsec, xsec_err
call gen_event_set_cross_section &
(evt%obj, &
real (xsec * 1e-3_default, c_double), &
real (xsec_err * 1e-3_default, c_double))
end subroutine hepmc_event_set_cross_section
@ %def hepmc_event_set_cross_section
@ The C function returns a boolean which we do not use.
<<HepMC interface: interfaces>>=
interface
subroutine gen_event_set_cross_section (evt_obj, xs, xs_err) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: xs, xs_err
end subroutine gen_event_set_cross_section
end interface
@ %def gen_event_set_cross_section
@
\subsection{Event-particle iterator}
This iterator iterates over all particles in an event. We store a
pointer to the event in addition to the iterator. This allows for
simple end checking.
The iterator is actually a constant iterator; it can only read.
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_t
<<HepMC interface: types>>=
type :: hepmc_event_particle_iterator_t
private
type(c_ptr) :: obj
type(c_ptr) :: evt_obj
end type hepmc_event_particle_iterator_t
@ %def hepmc_event_particle_iterator_t
@ Constructor. The iterator is initialized at the first particle in
the event.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_event_particle_const_iterator (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function new_event_particle_const_iterator
end interface
@ %def new_event_particle_const_iterator
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_init
<<HepMC interface: procedures>>=
subroutine hepmc_event_particle_iterator_init (it, evt)
type(hepmc_event_particle_iterator_t), intent(out) :: it
type(hepmc_event_t), intent(in) :: evt
it%obj = new_event_particle_const_iterator (evt%obj)
it%evt_obj = evt%obj
end subroutine hepmc_event_particle_iterator_init
@ %def hepmc_event_particle_iterator_init
@ Destructor. Necessary because the iterator is allocated on the
heap.
<<HepMC interface: interfaces>>=
interface
subroutine event_particle_const_iterator_delete (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end subroutine event_particle_const_iterator_delete
end interface
@ %def event_particle_const_iterator_delete
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_final
<<HepMC interface: procedures>>=
subroutine hepmc_event_particle_iterator_final (it)
type(hepmc_event_particle_iterator_t), intent(inout) :: it
call event_particle_const_iterator_delete (it%obj)
end subroutine hepmc_event_particle_iterator_final
@ %def hepmc_event_particle_iterator_final
@ Increment
<<HepMC interface: interfaces>>=
interface
subroutine event_particle_const_iterator_advance (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end subroutine event_particle_const_iterator_advance
end interface
@ %def event_particle_const_iterator_advance
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_advance
<<HepMC interface: procedures>>=
subroutine hepmc_event_particle_iterator_advance (it)
type(hepmc_event_particle_iterator_t), intent(inout) :: it
call event_particle_const_iterator_advance (it%obj)
end subroutine hepmc_event_particle_iterator_advance
@ %def hepmc_event_particle_iterator_advance
@ Reset to the beginning
<<HepMC interface: interfaces>>=
interface
subroutine event_particle_const_iterator_reset (it_obj, evt_obj) bind(C)
import
type(c_ptr), value :: it_obj, evt_obj
end subroutine event_particle_const_iterator_reset
end interface
@ %def event_particle_const_iterator_reset
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_reset
<<HepMC interface: procedures>>=
subroutine hepmc_event_particle_iterator_reset (it)
type(hepmc_event_particle_iterator_t), intent(inout) :: it
call event_particle_const_iterator_reset (it%obj, it%evt_obj)
end subroutine hepmc_event_particle_iterator_reset
@ %def hepmc_event_particle_iterator_reset
@ Test: return true as long as we are not past the end.
<<HepMC interface: interfaces>>=
interface
function event_particle_const_iterator_is_valid &
(it_obj, evt_obj) result (flag) bind(C)
import
logical(c_bool) :: flag
type(c_ptr), value :: it_obj, evt_obj
end function event_particle_const_iterator_is_valid
end interface
@ %def event_particle_const_iterator_is_valid
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_is_valid
<<HepMC interface: procedures>>=
function hepmc_event_particle_iterator_is_valid (it) result (flag)
logical :: flag
type(hepmc_event_particle_iterator_t), intent(in) :: it
flag = event_particle_const_iterator_is_valid (it%obj, it%evt_obj)
end function hepmc_event_particle_iterator_is_valid
@ %def hepmc_event_particle_iterator_is_valid
@ Return the particle pointed to by the iterator. (The particle
object should not be finalized, since it contains merely a pointer to
the particle which is owned by the vertex.)
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function event_particle_const_iterator_get (it_obj) bind(C)
import
type(c_ptr), value :: it_obj
end function event_particle_const_iterator_get
end interface
@ %def event_particle_const_iterator_get
<<HepMC interface: public>>=
public :: hepmc_event_particle_iterator_get
<<HepMC interface: procedures>>=
function hepmc_event_particle_iterator_get (it) result (prt)
type(hepmc_particle_t) :: prt
type(hepmc_event_particle_iterator_t), intent(in) :: it
prt%obj = event_particle_const_iterator_get (it%obj)
end function hepmc_event_particle_iterator_get
@ %def hepmc_event_particle_iterator_get
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function gen_event_get_nth_particle (evt_obj, n) bind(C)
import
type(c_ptr), value :: evt_obj
integer(c_int), value :: n
end function gen_event_get_nth_particle
end interface
interface
integer(c_int) function gen_event_get_nth_beam (evt_obj, n) bind(C)
import
type(c_ptr), value :: evt_obj
integer(c_int), value :: n
end function gen_event_get_nth_beam
end interface
@ %def gen_event_get_nth_particle
@ %def gen_event_get_nth_beam
<<HepMC interface: public>>=
public :: hepmc_event_get_nth_particle
public :: hepmc_event_get_nth_beam
<<HepMC interface: procedures>>=
function hepmc_event_get_nth_particle (evt, n) result (prt)
type(hepmc_particle_t) :: prt
type(hepmc_event_t), intent(in) :: evt
integer, intent(in) :: n
integer :: n_tot
integer(c_int) :: nth
nth = n
n_tot = gen_event_get_n_particles (evt%obj)
if (n > n_tot .or. n < 1) then
prt%obj = c_null_ptr
call msg_error ("HepMC interface called for wrong particle ID.")
else
prt%obj = gen_event_get_nth_particle (evt%obj, nth)
end if
end function hepmc_event_get_nth_particle
function hepmc_event_get_nth_beam (evt, n) result (beam_barcode)
integer :: beam_barcode
type(hepmc_event_t), intent(in) :: evt
integer, intent(in) :: n
integer(c_int) :: bc
bc = gen_event_get_nth_beam (evt%obj, n)
beam_barcode = bc
end function hepmc_event_get_nth_beam
@ %def hepmc_event_get_nth_particle
@ %def hepmc_event_get_nth_beam
@
\subsection{I/O streams}
There is a specific I/O stream type for handling the output of
GenEvent objects (i.e., Monte Carlo event samples) to file. Opening
the file is done by the constructor, closing by the destructor.
<<HepMC interface: public>>=
public :: hepmc_iostream_t
<<HepMC interface: types>>=
type :: hepmc_iostream_t
private
type(c_ptr) :: obj
end type hepmc_iostream_t
@ %def hepmc_iostream_t
@ Constructor for an output stream associated to a file.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_io_gen_event_out (filename) bind(C)
import
character(c_char), dimension(*), intent(in) :: filename
end function new_io_gen_event_out
end interface
interface
type(c_ptr) function new_io_gen_event_out_hepmc2 (filename) bind(C)
import
character(c_char), dimension(*), intent(in) :: filename
end function new_io_gen_event_out_hepmc2
end interface
@ %def new_io_gen_event_out new_io_gen_event_out_hepmc2
<<HepMC interface: public>>=
public :: hepmc_iostream_open_out
<<HepMC interface: procedures>>=
subroutine hepmc_iostream_open_out (iostream, filename, hepmc2)
type(hepmc_iostream_t), intent(out) :: iostream
type(string_t), intent(in) :: filename
logical, intent(in), optional :: hepmc2
logical :: hepmc2_mode
hepmc2_mode = .false.
if (present (hepmc2)) hepmc2_mode = hepmc2
if (hepmc2_mode) then
iostream%obj = &
new_io_gen_event_out_hepmc2 (char (filename) // c_null_char)
else
iostream%obj = &
new_io_gen_event_out (char (filename) // c_null_char)
end if
end subroutine hepmc_iostream_open_out
@ %def hepmc_iostream_open_out
@ Constructor for an input stream associated to a file.
<<HepMC interface: interfaces>>=
interface
type(c_ptr) function new_io_gen_event_in (filename) bind(C)
import
character(c_char), dimension(*), intent(in) :: filename
end function new_io_gen_event_in
end interface
interface
type(c_ptr) function new_io_gen_event_in_hepmc2 (filename) bind(C)
import
character(c_char), dimension(*), intent(in) :: filename
end function new_io_gen_event_in_hepmc2
end interface
@ %def new_io_gen_event_in new_io_gen_event_in_hepmc
<<HepMC interface: public>>=
public :: hepmc_iostream_open_in
<<HepMC interface: procedures>>=
subroutine hepmc_iostream_open_in (iostream, filename, hepmc2)
type(hepmc_iostream_t), intent(out) :: iostream
type(string_t), intent(in) :: filename
logical, intent(in), optional :: hepmc2
logical :: hepmc2_mode
hepmc2_mode = .false.
if (present (hepmc2)) hepmc2_mode = hepmc2
if (hepmc2_mode) then
iostream%obj = &
new_io_gen_event_in_hepmc2 (char (filename) // c_null_char)
else
iostream%obj = &
new_io_gen_event_in (char (filename) // c_null_char)
end if
end subroutine hepmc_iostream_open_in
@ %def hepmc_iostream_open_in
@ Destructor:
<<HepMC interface: interfaces>>=
interface
subroutine io_gen_event_delete (io_obj) bind(C)
import
type(c_ptr), value :: io_obj
end subroutine io_gen_event_delete
end interface
interface
subroutine io_gen_event_delete_hepmc2 (io_obj) bind(C)
import
type(c_ptr), value :: io_obj
end subroutine io_gen_event_delete_hepmc2
end interface
@ %def io_gen_event_delete io_gen_event_delete
<<HepMC interface: public>>=
public :: hepmc_iostream_close
<<HepMC interface: procedures>>=
subroutine hepmc_iostream_close (iostream, hepmc2)
type(hepmc_iostream_t), intent(inout) :: iostream
logical, intent(in), optional :: hepmc2
logical :: hepmc2_mode
hepmc2_mode = .false.
if (present (hepmc2)) hepmc2_mode = hepmc2
if (hepmc2_mode) then
call io_gen_event_delete_hepmc2 (iostream%obj)
else
call io_gen_event_delete (iostream%obj)
end if
end subroutine hepmc_iostream_close
@ %def hepmc_iostream_close
@ Write a single event to the I/O stream.
<<HepMC interface: interfaces>>=
interface
subroutine io_gen_event_write_event (io_obj, evt_obj) bind(C)
import
type(c_ptr), value :: io_obj, evt_obj
end subroutine io_gen_event_write_event
end interface
interface
subroutine io_gen_event_write_event_hepmc2 (io_obj, evt_obj) bind(C)
import
type(c_ptr), value :: io_obj, evt_obj
end subroutine io_gen_event_write_event_hepmc2
end interface
@ %def io_gen_event_write_event io_gen_event_write_event_hepmc2
<<HepMC interface: public>>=
public :: hepmc_iostream_write_event
<<HepMC interface: procedures>>=
subroutine hepmc_iostream_write_event (iostream, evt, hepmc2)
type(hepmc_iostream_t), intent(inout) :: iostream
type(hepmc_event_t), intent(in) :: evt
logical, intent(in), optional :: hepmc2
logical :: hepmc2_mode
hepmc2_mode = .false.
if (present (hepmc2)) hepmc2_mode = hepmc2
if (hepmc2_mode) then
call io_gen_event_write_event_hepmc2 (iostream%obj, evt%obj)
else
call io_gen_event_write_event (iostream%obj, evt%obj)
end if
end subroutine hepmc_iostream_write_event
@ %def hepmc_iostream_write_event
@ Read a single event from the I/O stream. Return true if successful.
<<HepMC interface: interfaces>>=
interface
logical(c_bool) function io_gen_event_read_event (io_obj, evt_obj) bind(C)
import
type(c_ptr), value :: io_obj, evt_obj
end function io_gen_event_read_event
end interface
interface
logical(c_bool) function io_gen_event_read_event_hepmc2 (io_obj, evt_obj) bind(C)
import
type(c_ptr), value :: io_obj, evt_obj
end function io_gen_event_read_event_hepmc2
end interface
@ %def io_gen_event_read_event io_gen_event_read_event_hepmc2
<<HepMC interface: public>>=
public :: hepmc_iostream_read_event
<<HepMC interface: procedures>>=
subroutine hepmc_iostream_read_event (iostream, evt, ok, hepmc2)
type(hepmc_iostream_t), intent(inout) :: iostream
type(hepmc_event_t), intent(inout) :: evt
logical, intent(out) :: ok
logical, intent(in), optional :: hepmc2
logical :: hepmc2_mode
hepmc2_mode = .false.
if (present (hepmc2)) hepmc2_mode = hepmc2
if (hepmc2_mode) then
ok = io_gen_event_read_event_hepmc2 (iostream%obj, evt%obj)
else
ok = io_gen_event_read_event (iostream%obj, evt%obj)
end if
end subroutine hepmc_iostream_read_event
@ %def hepmc_iostream_read_event
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[hepmc_interface_ut.f90]]>>=
<<File header>>
module hepmc_interface_ut
use unit_tests
use system_dependencies, only: HEPMC2_AVAILABLE
use system_dependencies, only: HEPMC3_AVAILABLE
use hepmc_interface_uti
<<Standard module head>>
<<HepMC interface: public test>>
contains
<<HepMC interface: test driver>>
end module hepmc_interface_ut
@ %def hepmc_interface_ut
@
<<[[hepmc_interface_uti.f90]]>>=
<<File header>>
module hepmc_interface_uti
<<Use kinds>>
<<Use strings>>
use io_units
use lorentz
use flavors
use colors
use polarizations
use hepmc_interface
<<Standard module head>>
<<HepMC interface: test declarations>>
contains
<<HepMC interface: tests>>
end module hepmc_interface_uti
@ %def hepmc_interface_ut
@ API: driver for the unit tests below.
<<HepMC interface: public test>>=
public :: hepmc_interface_test
<<HepMC interface: test driver>>=
subroutine hepmc_interface_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<HepMC interface: execute tests>>
end subroutine hepmc_interface_test
@ %def hepmc_test
@
This test example is an abridged version from the build-from-scratch
example in the HepMC distribution. We create two vertices for $p\to
q$ PDF splitting, then a vertex for a $qq\to W^-g$ hard-interaction
process, and finally a vertex for $W^-\to qq$ decay. The setup is for
LHC kinematics.
Extending the original example, we set color flow for the incoming
quarks and polarization for the outgoing photon. For the latter, we
have to define a particle-data object for the photon, so a flavor
object can be correctly initialized.
<<HepMC interface: execute tests>>=
if (HEPMC2_AVAILABLE) then
call test (hepmc_interface_1, "hepmc2_interface_1", &
"check HepMC2 interface", &
u, results)
else if (HEPMC3_AVAILABLE) then
call test (hepmc_interface_1, "hepmc3_interface_1", &
"check HepMC3 interface", &
u, results)
end if
<<HepMC interface: test declarations>>=
public :: hepmc_interface_1
<<HepMC interface: tests>>=
subroutine hepmc_interface_1 (u)
use physics_defs, only: VECTOR
use model_data, only: field_data_t
integer, intent(in) :: u
integer :: u_file, iostat
type(hepmc_event_t) :: evt
type(hepmc_vertex_t) :: v1, v2, v3, v4
type(hepmc_particle_t) :: prt1, prt2, prt3, prt4, prt5, prt6, prt7, prt8
type(hepmc_iostream_t) :: iostream
type(flavor_t) :: flv
type(color_t) :: col
type(polarization_t) :: pol
type(field_data_t), target :: photon_data
character(80) :: buffer
write (u, "(A)") "* Test output: HepMC interface"
write (u, "(A)") "* Purpose: test HepMC interface"
write (u, "(A)")
write (u, "(A)") "* Initialization"
write (u, "(A)")
! Initialize a photon flavor object and some polarization
call photon_data%init (var_str ("PHOTON"), 22)
call photon_data%set (spin_type=VECTOR)
call photon_data%freeze ()
call flv%init (photon_data)
call pol%init_angles &
(flv, 0.6_default, 1._default, 0.5_default)
! Event initialization
call hepmc_event_init (evt, 20, 1)
write (u, "(A)") "* p -> q splitting"
write (u, "(A)")
! $p\to q$ splittings
call hepmc_vertex_init (v1)
call hepmc_event_add_vertex (evt, v1)
call hepmc_vertex_init (v2)
call hepmc_event_add_vertex (evt, v2)
call particle_init (prt1, &
0._default, 0._default, 7000._default, 7000._default, &
2212, 3)
call hepmc_vertex_add_particle_in (v1, prt1)
call particle_init (prt2, &
0._default, 0._default,-7000._default, 7000._default, &
2212, 3)
call hepmc_vertex_add_particle_in (v2, prt2)
call particle_init (prt3, &
.750_default, -1.569_default, 32.191_default, 32.238_default, &
1, 3)
call color_init_from_array (col, [501])
call hepmc_particle_set_color (prt3, col)
call hepmc_vertex_add_particle_out (v1, prt3)
call particle_init (prt4, &
-3.047_default, -19._default, -54.629_default, 57.920_default, &
-2, 3)
call color_init_from_array (col, [-501])
call hepmc_particle_set_color (prt4, col)
call hepmc_vertex_add_particle_out (v2, prt4)
write (u, "(A)") "* Hard interaction"
write (u, "(A)")
! Hard interaction
call hepmc_vertex_init (v3)
call hepmc_event_add_vertex (evt, v3)
call hepmc_vertex_add_particle_in (v3, prt3)
call hepmc_vertex_add_particle_in (v3, prt4)
call particle_init (prt6, &
-3.813_default, 0.113_default, -1.833_default, 4.233_default, &
22, 1)
call hepmc_particle_set_polarization (prt6, pol)
call hepmc_vertex_add_particle_out (v3, prt6)
call particle_init (prt5, &
1.517_default, -20.68_default, -20.605_default, 85.925_default, &
-24, 3)
call hepmc_vertex_add_particle_out (v3, prt5)
call hepmc_event_set_signal_process_vertex (evt, v3)
! $W^-$ decay
call vertex_init_pos (v4, &
0.12_default, -0.3_default, 0.05_default, 0.004_default)
call hepmc_event_add_vertex (evt, v4)
call hepmc_vertex_add_particle_in (v4, prt5)
call particle_init (prt7, &
-2.445_default, 28.816_default, 6.082_default, 29.552_default, &
1, 1)
call hepmc_vertex_add_particle_out (v4, prt7)
call particle_init (prt8, &
3.962_default, -49.498_default, -26.687_default, 56.373_default, &
-2, 1)
call hepmc_vertex_add_particle_out (v4, prt8)
! Event output
call hepmc_event_print (evt)
write (u, "(A)") "Writing to file 'hepmc_test.hepmc'"
write (u, "(A)")
call hepmc_iostream_open_out (iostream , var_str ("hepmc_test.hepmc"))
call hepmc_iostream_write_event (iostream, evt)
call hepmc_iostream_close (iostream)
write (u, "(A)") "Writing completed"
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "hepmc_test.hepmc", &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:14) == "HepMC::Version") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
write (u, "(A)")
! Wrapup
! call pol%final ()
call hepmc_event_final (evt)
write (u, "(A)")
write (u, "(A)") "* Test output end: hepmc_interface_1"
contains
subroutine vertex_init_pos (v, x, y, z, t)
type(hepmc_vertex_t), intent(out) :: v
real(default), intent(in) :: x, y, z, t
type(vector4_t) :: xx
xx = vector4_moving (t, vector3_moving ([x, y, z]))
call hepmc_vertex_init (v, xx)
end subroutine vertex_init_pos
subroutine particle_init (prt, px, py, pz, E, pdg, status)
type(hepmc_particle_t), intent(out) :: prt
real(default), intent(in) :: px, py, pz, E
integer, intent(in) :: pdg, status
type(vector4_t) :: p
p = vector4_moving (E, vector3_moving ([px, py, pz]))
call hepmc_particle_init (prt, p, pdg, status)
end subroutine particle_init
end subroutine hepmc_interface_1
@ %def hepmc_interface_1
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{LCIO events}
This section provides the interface to the LCIO C++ library for handling
Monte-Carlo events.
Each C++ class of LCIO that we use is mirrored by a Fortran type,
which contains as its only component the C pointer to the C++ object.
Each C++ method of LCIO that we use has a C wrapper function. This
function takes a pointer to the host object as its first argument.
Further arguments are either C pointers, or in the case of simple
types (integer, real), interoperable C/Fortran objects.
The C wrapper functions have explicit interfaces in the Fortran
module. They are called by Fortran wrapper procedures. These are
treated as methods of the corresponding Fortran type.
<<[[lcio_interface.f90]]>>=
<<File header>>
module lcio_interface
use, intrinsic :: iso_c_binding !NODEP!
<<Use kinds>>
<<Use strings>>
use constants, only: PI
use physics_defs, only: ns_per_mm
use diagnostics
use lorentz
use flavors
use colors
use helicities
use polarizations
<<Standard module head>>
<<LCIO interface: public>>
<<LCIO interface: types>>
<<LCIO interface: interfaces>>
contains
<<LCIO interface: procedures>>
end module lcio_interface
@ %def lcio_interface
@
\subsection{Interface check}
This function can be called in order to verify that we are using the
actual LCIO library, and not the dummy version.
<<LCIO interface: interfaces>>=
interface
logical(c_bool) function lcio_available () bind(C)
import
end function lcio_available
end interface
<<LCIO interface: public>>=
public :: lcio_is_available
<<LCIO interface: procedures>>=
function lcio_is_available () result (flag)
logical :: flag
flag = lcio_available ()
end function lcio_is_available
@ %def lcio_is_available
@
\subsection{LCIO Run Header}
This is a type for the run header of the LCIO file.
<<LCIO interface: public>>=
public :: lcio_run_header_t
<<LCIO interface: types>>=
type :: lcio_run_header_t
private
type(c_ptr) :: obj
end type lcio_run_header_t
@ %def lcio_run_header_t
The Fortran version has initializer form.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function new_lcio_run_header (proc_id) bind(C)
import
integer(c_int), value :: proc_id
end function new_lcio_run_header
end interface
@ %def new_lcio_run_header
<<LCIO interface: interfaces>>=
interface
subroutine run_header_set_simstring &
(runhdr_obj, simstring) bind(C)
import
type(c_ptr), value :: runhdr_obj
character(c_char), dimension(*), intent(in) :: simstring
end subroutine run_header_set_simstring
end interface
@ %def run_header_set_simstring
<<LCIO interface: public>>=
public :: lcio_run_header_init
<<LCIO interface: procedures>>=
subroutine lcio_run_header_init (runhdr, proc_id, run_id)
type(lcio_run_header_t), intent(out) :: runhdr
integer, intent(in), optional :: proc_id, run_id
integer(c_int) :: rid
rid = 0; if (present (run_id)) rid = run_id
runhdr%obj = new_lcio_run_header (rid)
call run_header_set_simstring (runhdr%obj, &
"WHIZARD version:" // "<<Version>>")
end subroutine lcio_run_header_init
@ %def lcio_run_header_init
@
<<LCIO interface: interfaces>>=
interface
subroutine write_run_header (lcwrt_obj, runhdr_obj) bind(C)
import
type(c_ptr), value :: lcwrt_obj
type(c_ptr), value :: runhdr_obj
end subroutine write_run_header
end interface
@ %def write_run_header
<<LCIO interface: public>>=
public :: lcio_run_header_write
<<LCIO interface: procedures>>=
subroutine lcio_run_header_write (wrt, hdr)
type(lcio_writer_t), intent(inout) :: wrt
type(lcio_run_header_t), intent(inout) :: hdr
call write_run_header (wrt%obj, hdr%obj)
end subroutine lcio_run_header_write
@ %def lcio_run_header_write
@
\subsection{LCIO Event and LC Collection}
The main object of LCIO is a LCEventImpl. The object is filled by
MCParticle objects, which are set as LCCollection.
<<LCIO interface: public>>=
public :: lccollection_t
<<LCIO interface: types>>=
type :: lccollection_t
private
type(c_ptr) :: obj
end type lccollection_t
@ %def lccollection_t
@ Initializer.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function new_lccollection () bind(C)
import
end function new_lccollection
end interface
@ %def new_lccollection
<<LCIO interface: public>>=
public :: lcio_event_t
<<LCIO interface: types>>=
type :: lcio_event_t
private
type(c_ptr) :: obj
type(lccollection_t) :: lccoll
end type lcio_event_t
@ %def lcio_event_t
@ Constructor. Arguments are process ID (integer) and event ID
(integer).
The Fortran version has initializer form.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function new_lcio_event (proc_id, event_id, run_id) bind(C)
import
integer(c_int), value :: proc_id, event_id, run_id
end function new_lcio_event
end interface
@ %def new_lcio_event
@
<<LCIO interface: public>>=
public :: lcio_event_init
<<LCIO interface: procedures>>=
subroutine lcio_event_init (evt, proc_id, event_id, run_id)
type(lcio_event_t), intent(out) :: evt
integer, intent(in), optional :: proc_id, event_id, run_id
integer(c_int) :: pid, eid, rid
pid = 0; if (present (proc_id)) pid = proc_id
eid = 0; if (present (event_id)) eid = event_id
rid = 0; if (present (run_id)) rid = run_id
evt%obj = new_lcio_event (pid, eid, rid)
evt%lccoll%obj = new_lccollection ()
end subroutine lcio_event_init
@ %def lcio_event_init
@ Destructor.
<<LCIO interface: interfaces>>=
interface
subroutine lcio_event_delete (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end subroutine lcio_event_delete
end interface
@ %def lcio_event_delete
@ Show event on screen.
<<LCIO interface: interfaces>>=
interface
subroutine dump_lcio_event (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end subroutine dump_lcio_event
end interface
@ %def dump_lcio_event
<<LCIO interface: public>>=
public :: show_lcio_event
<<LCIO interface: procedures>>=
subroutine show_lcio_event (evt)
type(lcio_event_t), intent(in) :: evt
if (c_associated (evt%obj)) then
call dump_lcio_event (evt%obj)
else
call msg_error ("LCIO event is not allocated.")
end if
end subroutine show_lcio_event
@ %def show_lcio_event
@ Put a single event to file.
<<LCIO interface: interfaces>>=
interface
subroutine lcio_event_to_file (evt_obj, filename) bind(C)
import
type(c_ptr), value :: evt_obj
character(c_char), dimension(*), intent(in) :: filename
end subroutine lcio_event_to_file
end interface
@ %def lcio_event_to_file
<<LCIO interface: public>>=
public :: write_lcio_event
<<LCIO interface: procedures>>=
subroutine write_lcio_event (evt, filename)
type(lcio_event_t), intent(in) :: evt
type(string_t), intent(in) :: filename
call lcio_event_to_file (evt%obj, char (filename) // c_null_char)
end subroutine write_lcio_event
@ %def write_lcio_event
@
<<LCIO interface: public>>=
public :: lcio_event_final
<<LCIO interface: procedures>>=
subroutine lcio_event_final (evt)
type(lcio_event_t), intent(inout) :: evt
call lcio_event_delete (evt%obj)
end subroutine lcio_event_final
@ %def lcio_event_final
@
<<LCIO interface: interfaces>>=
interface
subroutine lcio_set_weight (evt_obj, weight) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: weight
end subroutine lcio_set_weight
end interface
interface
subroutine lcio_set_alpha_qcd (evt_obj, alphas) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: alphas
end subroutine lcio_set_alpha_qcd
end interface
interface
subroutine lcio_set_scale (evt_obj, scale) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: scale
end subroutine lcio_set_scale
end interface
interface
subroutine lcio_set_sqrts (evt_obj, sqrts) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: sqrts
end subroutine lcio_set_sqrts
end interface
interface
subroutine lcio_set_xsec (evt_obj, xsec, xsec_err) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: xsec, xsec_err
end subroutine lcio_set_xsec
end interface
interface
subroutine lcio_set_beam (evt_obj, pdg, beam) bind(C)
import
type(c_ptr), value :: evt_obj
integer(c_int), value :: pdg, beam
end subroutine lcio_set_beam
end interface
interface
subroutine lcio_set_pol (evt_obj, pol1, pol2) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: pol1, pol2
end subroutine lcio_set_pol
end interface
interface
subroutine lcio_set_beam_file (evt_obj, file) bind(C)
import
type(c_ptr), value :: evt_obj
character(len=1, kind=c_char), dimension(*), intent(in) :: file
end subroutine lcio_set_beam_file
end interface
interface
subroutine lcio_set_process_name (evt_obj, name) bind(C)
import
type(c_ptr), value :: evt_obj
character(len=1, kind=c_char), dimension(*), intent(in) :: name
end subroutine lcio_set_process_name
end interface
interface
+ subroutine lcio_set_sqme (evt_obj, sqme) bind(C)
+ import
+ type(c_ptr), value :: evt_obj
+ real(c_double), value :: sqme
+ end subroutine lcio_set_sqme
+ end interface
+ interface
subroutine lcio_set_alt_sqme (evt_obj, sqme, index) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: sqme
integer(c_int), value :: index
end subroutine lcio_set_alt_sqme
end interface
interface
subroutine lcio_set_alt_weight (evt_obj, weight, index) bind(C)
import
type(c_ptr), value :: evt_obj
real(c_double), value :: weight
integer(c_int), value :: index
end subroutine lcio_set_alt_weight
end interface
@ %def lcio_set_weight lcio_set_alpha_qcd lcio_set_scale lcio_set_sqrts
@ %def lcio_set_xsec lcio_set_beam lcio_set_pol
@ %def lcio_set_beam_file lcio_set_process_name
-@ %def lcio_set_alt_sqme lcio_set_alt_weight
+@ %def lcio_set_sqme lcio_set_alt_sqme lcio_set_alt_weight
@
<<LCIO interface: public>>=
public :: lcio_event_set_weight
<<LCIO interface: procedures>>=
subroutine lcio_event_set_weight (evt, weight)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: weight
call lcio_set_weight (evt%obj, real (weight, c_double))
end subroutine lcio_event_set_weight
@ %def lcio_event_set_weight
@
<<LCIO interface: public>>=
public :: lcio_event_set_alpha_qcd
<<LCIO interface: procedures>>=
subroutine lcio_event_set_alpha_qcd (evt, alphas)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: alphas
call lcio_set_alpha_qcd (evt%obj, real (alphas, c_double))
end subroutine lcio_event_set_alpha_qcd
@ %def lcio_event_set_alpha_qcd
@
<<LCIO interface: public>>=
public :: lcio_event_set_scale
<<LCIO interface: procedures>>=
subroutine lcio_event_set_scale (evt, scale)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: scale
call lcio_set_scale (evt%obj, real (scale, c_double))
end subroutine lcio_event_set_scale
@ %def lcio_event_set_scale
@
<<LCIO interface: public>>=
public :: lcio_event_set_sqrts
<<LCIO interface: procedures>>=
subroutine lcio_event_set_sqrts (evt, sqrts)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: sqrts
call lcio_set_sqrts (evt%obj, real (sqrts, c_double))
end subroutine lcio_event_set_sqrts
@ %def lcio_event_set_sqrts
@
<<LCIO interface: public>>=
public :: lcio_event_set_xsec
<<LCIO interface: procedures>>=
subroutine lcio_event_set_xsec (evt, xsec, xsec_err)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: xsec, xsec_err
call lcio_set_xsec (evt%obj, &
real (xsec, c_double), real (xsec_err, c_double))
end subroutine lcio_event_set_xsec
@ %def lcio_event_set_xsec
@
<<LCIO interface: public>>=
public :: lcio_event_set_beam
<<LCIO interface: procedures>>=
subroutine lcio_event_set_beam (evt, pdg, beam)
type(lcio_event_t), intent(inout) :: evt
integer, intent(in) :: pdg, beam
call lcio_set_beam (evt%obj, &
int (pdg, c_int), int (beam, c_int))
end subroutine lcio_event_set_beam
@ %def lcio_event_set_beam
@
<<LCIO interface: public>>=
public :: lcio_event_set_polarization
<<LCIO interface: procedures>>=
subroutine lcio_event_set_polarization (evt, pol)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in), dimension(2) :: pol
call lcio_set_pol (evt%obj, &
real (pol(1), c_double), real (pol(2), c_double))
end subroutine lcio_event_set_polarization
@ %def lcio_event_set_polarization
@
<<LCIO interface: public>>=
public :: lcio_event_set_beam_file
<<LCIO interface: procedures>>=
subroutine lcio_event_set_beam_file (evt, file)
type(lcio_event_t), intent(inout) :: evt
type(string_t), intent(in) :: file
call lcio_set_beam_file (evt%obj, &
char (file) // c_null_char)
end subroutine lcio_event_set_beam_file
@ %def lcio_event_set_beam_file
@
<<LCIO interface: public>>=
public :: lcio_event_set_process_name
<<LCIO interface: procedures>>=
subroutine lcio_event_set_process_name (evt, name)
type(lcio_event_t), intent(inout) :: evt
type(string_t), intent(in) :: name
call lcio_set_process_name (evt%obj, &
char (name) // c_null_char)
end subroutine lcio_event_set_process_name
@ %def lcio_event_set_process_name
@
<<LCIO interface: public>>=
public :: lcio_event_set_alt_sqme
<<LCIO interface: procedures>>=
subroutine lcio_event_set_alt_sqme (evt, sqme, index)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: sqme
integer, intent(in) :: index
call lcio_set_alt_sqme (evt%obj, real (sqme, c_double), &
int (index, c_int))
end subroutine lcio_event_set_alt_sqme
@ %def lcio_event_set_alt_sqme
@
<<LCIO interface: public>>=
+ public :: lcio_event_set_sqme
+<<LCIO interface: procedures>>=
+ subroutine lcio_event_set_sqme (evt, sqme)
+ type(lcio_event_t), intent(inout) :: evt
+ real(default), intent(in) :: sqme
+ call lcio_set_sqme (evt%obj, real (sqme, c_double))
+ end subroutine lcio_event_set_sqme
+
+@ %def lcio_event_set_sqme
+@
+<<LCIO interface: public>>=
public :: lcio_event_set_alt_weight
<<LCIO interface: procedures>>=
subroutine lcio_event_set_alt_weight (evt, weight, index)
type(lcio_event_t), intent(inout) :: evt
real(default), intent(in) :: weight
integer, intent(in) :: index
call lcio_set_alt_weight (evt%obj, real (weight, c_double), &
int (index, c_int))
end subroutine lcio_event_set_alt_weight
@ %def lcio_event_set_alt_weight
@
<<LCIO interface: interfaces>>=
interface
subroutine lcio_event_add_collection &
(evt_obj, lccoll_obj) bind(C)
import
type(c_ptr), value :: evt_obj, lccoll_obj
end subroutine lcio_event_add_collection
end interface
@ %def lcio_event_add_collection
<<LCIO interface: public>>=
public :: lcio_event_add_coll
<<LCIO interface: procedures>>=
subroutine lcio_event_add_coll (evt)
type(lcio_event_t), intent(inout) :: evt
call lcio_event_add_collection (evt%obj, &
evt%lccoll%obj)
end subroutine lcio_event_add_coll
@ %def lcio_event_add_coll
@
\subsection{LCIO Particle}
Particle objects have the obvious meaning.
<<LCIO interface: public>>=
public :: lcio_particle_t
<<LCIO interface: types>>=
type :: lcio_particle_t
private
type(c_ptr) :: obj
end type lcio_particle_t
@ %def lcio_particle_t
@ Constructor.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function new_lcio_particle &
(px, py, pz, pdg_id, mass, charge, status) bind(C)
import
integer(c_int), value :: pdg_id, status
real(c_double), value :: px, py, pz, mass, charge
end function new_lcio_particle
end interface
@ %def new_lcio_particle
@
<<LCIO interface: interfaces>>=
interface
subroutine add_particle_to_collection &
(prt_obj, lccoll_obj) bind(C)
import
type(c_ptr), value :: prt_obj, lccoll_obj
end subroutine add_particle_to_collection
end interface
@ %def add_particle_to_collection
<<LCIO interface: public>>=
public :: lcio_particle_add_to_evt_coll
<<LCIO interface: procedures>>=
subroutine lcio_particle_add_to_evt_coll &
(lprt, evt)
type(lcio_particle_t), intent(in) :: lprt
type(lcio_event_t), intent(inout) :: evt
call add_particle_to_collection (lprt%obj, evt%lccoll%obj)
end subroutine lcio_particle_add_to_evt_coll
@ %def lcio_particle_to_collection
@
<<LCIO interface: public>>=
public :: lcio_particle_init
<<LCIO interface: procedures>>=
subroutine lcio_particle_init (prt, p, pdg, charge, status)
type(lcio_particle_t), intent(out) :: prt
type(vector4_t), intent(in) :: p
real(default), intent(in) :: charge
real(default) :: mass
real(default) :: px, py, pz
integer, intent(in) :: pdg, status
px = vector4_get_component (p, 1)
py = vector4_get_component (p, 2)
pz = vector4_get_component (p, 3)
mass = p**1
prt%obj = new_lcio_particle (real (px, c_double), real (py, c_double), &
real (pz, c_double), int (pdg, c_int), &
real (mass, c_double), real (charge, c_double), int (status, c_int))
end subroutine lcio_particle_init
@ %def lcio_particle_init
@ Set the particle color flow.
<<LCIO interface: interfaces>>=
interface
subroutine lcio_set_color_flow (prt_obj, col1, col2) bind(C)
import
type(c_ptr), value :: prt_obj
integer(c_int), value :: col1, col2
end subroutine lcio_set_color_flow
end interface
@ %def lcio_set_color_flow
@ Set the particle color. Either from a [[color_t]] object or
directly from a pair of integers.
<<LCIO interface: interfaces>>=
interface lcio_particle_set_color
module procedure lcio_particle_set_color_col
module procedure lcio_particle_set_color_int
end interface lcio_particle_set_color
<<LCIO interface: public>>=
public :: lcio_particle_set_color
<<LCIO interface: procedures>>=
subroutine lcio_particle_set_color_col (prt, col)
type(lcio_particle_t), intent(inout) :: prt
type(color_t), intent(in) :: col
integer(c_int), dimension(2) :: c
c(1) = col%get_col ()
c(2) = col%get_acl ()
if (c(1) /= 0 .or. c(2) /= 0) then
call lcio_set_color_flow (prt%obj, c(1), c(2))
end if
end subroutine lcio_particle_set_color_col
subroutine lcio_particle_set_color_int (prt, col)
type(lcio_particle_t), intent(inout) :: prt
integer, dimension(2), intent(in) :: col
integer(c_int), dimension(2) :: c
c = col
if (c(1) /= 0 .or. c(2) /= 0) then
call lcio_set_color_flow (prt%obj, c(1), c(2))
end if
end subroutine lcio_particle_set_color_int
@ %def lcio_particle_set_color
@ Return the particle color as a two-dimensional array (color, anticolor).
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_particle_flow (prt_obj, col_index) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: prt_obj
integer(c_int), value :: col_index
end function lcio_particle_flow
end interface
@ %def lcio_particle_flow
<<LCIO interface: public>>=
public :: lcio_particle_get_flow
<<LCIO interface: procedures>>=
function lcio_particle_get_flow (prt) result (col)
integer, dimension(2) :: col
type(lcio_particle_t), intent(in) :: prt
col(1) = lcio_particle_flow (prt%obj, 0_c_int)
col(2) = - lcio_particle_flow (prt%obj, 1_c_int)
end function lcio_particle_get_flow
@ %def lcio_particle_get_flow
@ Return the four-momentum of a LCIO particle.
<<LCIO interface: interfaces>>=
interface
real(c_double) function lcio_three_momentum (prt_obj, p_index) bind(C)
use iso_c_binding !NODEP!
type(c_ptr), value :: prt_obj
integer(c_int), value :: p_index
end function lcio_three_momentum
end interface
@ %def lcio_three_momentum
<<LCIO interface: interfaces>>=
interface
real(c_double) function lcio_energy (prt_obj) bind(C)
import
type(c_ptr), intent(in), value :: prt_obj
end function lcio_energy
end interface
@ %def lcio_energy
<<LCIO interface: public>>=
public :: lcio_particle_get_momentum
<<LCIO interface: procedures>>=
function lcio_particle_get_momentum (prt) result (p)
type(vector4_t) :: p
type(lcio_particle_t), intent(in) :: prt
real(default) :: E, px, py, pz
E = lcio_energy (prt%obj)
px = lcio_three_momentum (prt%obj, 0_c_int)
py = lcio_three_momentum (prt%obj, 1_c_int)
pz = lcio_three_momentum (prt%obj, 2_c_int)
p = vector4_moving ( E, vector3_moving ([ px, py, pz ]))
end function lcio_particle_get_momentum
@ %def lcio_particle_get_momentum
@ Return the invariant mass squared of the particle object. LCIO
stores the signed invariant mass (no squaring).
<<LCIO interface: interfaces>>=
interface
function lcio_mass (prt_obj) result (mass) bind(C)
import
real(c_double) :: mass
type(c_ptr), value :: prt_obj
end function lcio_mass
end interface
@ %def lcio_mass
<<LCIO interface: public>>=
public :: lcio_particle_get_mass_squared
<<LCIO interface: procedures>>=
function lcio_particle_get_mass_squared (prt) result (m2)
real(default) :: m2
type(lcio_particle_t), intent(in) :: prt
real(default) :: m
m = lcio_mass (prt%obj)
m2 = sign (m**2, m)
end function lcio_particle_get_mass_squared
@ %def lcio_particle_get_mass_squared
@ Return vertex and production time of a LCIO particle.
<<LCIO interface: interfaces>>=
interface
real(c_double) function lcio_vtx_x (prt) bind(C)
import
type(c_ptr), value :: prt
end function lcio_vtx_x
end interface
interface
real(c_double) function lcio_vtx_y (prt) bind(C)
import
type(c_ptr), value :: prt
end function lcio_vtx_y
end interface
interface
real(c_double) function lcio_vtx_z (prt) bind(C)
import
type(c_ptr), value :: prt
end function lcio_vtx_z
end interface
interface
real(c_float) function lcio_prt_time (prt) bind(C)
import
type(c_ptr), value :: prt
end function lcio_prt_time
end interface
@
@
(Decay) times in LCIO are in nanoseconds, so they need to get
converted to mm for the internal format.
<<LCIO interface: public>>=
public :: lcio_particle_get_vertex
public :: lcio_particle_get_time
<<LCIO interface: procedures>>=
function lcio_particle_get_vertex (prt) result (vtx)
type(vector3_t) :: vtx
type(lcio_particle_t), intent(in) :: prt
real(default) :: vx, vy, vz
vx = lcio_vtx_x (prt%obj)
vy = lcio_vtx_y (prt%obj)
vz = lcio_vtx_z (prt%obj)
vtx = vector3_moving ([vx, vy, vz])
end function lcio_particle_get_vertex
function lcio_particle_get_time (prt) result (time)
real(default) :: time
type(lcio_particle_t), intent(in) :: prt
time = lcio_prt_time (prt%obj)
time = time / ns_per_mm
end function lcio_particle_get_time
@ %def lcio_particle_get_vertex lcio_particle_get_time
@
\subsection{Polarization}
For polarization there is a three-component float entry foreseen in the LCIO
format. Completely generic density matrices can in principle be attached to
events as float vectors added to [[LCCollection]] of the [[LCEvent]]. This is
not yet implemented currently. Here, we restrict ourselves to the same
implementation as in HepMC format: we use two entries as the polarization
angles, while the first entry gives the degree of polarization (something
not specified in the HepMC format).
\emph{For massive vector bosons, we arbitrarily choose the convention
that the longitudinal (zero) helicity state is mapped to the theta
angle $\pi/2$. This works under the condition that helicity is
projected onto one of the basis states.}
<<LCIO interface: interfaces>>=
interface
subroutine lcio_particle_set_spin (prt_obj, s1, s2, s3) bind(C)
import
type(c_ptr), value :: prt_obj
real(c_double), value :: s1, s2, s3
end subroutine lcio_particle_set_spin
end interface
@ %def lcio_particle_set_spin
@
<<LCIO interface: public>>=
public :: lcio_polarization_init
<<LCIO interface: interfaces>>=
interface lcio_polarization_init
module procedure lcio_polarization_init_pol
module procedure lcio_polarization_init_hel
module procedure lcio_polarization_init_int
end interface
<<LCIO interface: procedures>>=
subroutine lcio_polarization_init_pol (prt, pol)
type(lcio_particle_t), intent(inout) :: prt
type(polarization_t), intent(in) :: pol
real(default) :: r, theta, phi
if (pol%is_polarized ()) then
call pol%to_angles (r, theta, phi)
call lcio_particle_set_spin (prt%obj, &
real(r, c_double), real (theta, c_double), real (phi, c_double))
end if
end subroutine lcio_polarization_init_pol
subroutine lcio_polarization_init_hel (prt, hel)
type(lcio_particle_t), intent(inout) :: prt
type(helicity_t), intent(in) :: hel
integer, dimension(2) :: h
if (hel%is_defined ()) then
h = hel%to_pair ()
select case (h(1))
case (1:)
call lcio_particle_set_spin (prt%obj, 1._c_double, &
0._c_double, 0._c_double)
case (:-1)
call lcio_particle_set_spin (prt%obj, 1._c_double, &
real (pi, c_double), 0._c_double)
case (0)
call lcio_particle_set_spin (prt%obj, 1._c_double, &
real (pi/2, c_double), 0._c_double)
end select
end if
end subroutine lcio_polarization_init_hel
subroutine lcio_polarization_init_int (prt, hel)
type(lcio_particle_t), intent(inout) :: prt
integer, intent(in) :: hel
call lcio_particle_set_spin (prt%obj, 0._c_double, &
0._c_double, real (hel, c_double))
end subroutine lcio_polarization_init_int
@ %def lcio_polarization_init
@ Recover polarization from LCIO particle (with the
abovementioned deficiencies).
<<LCIO interface: interfaces>>=
interface
function lcio_polarization_degree (prt_obj) result (degree) bind(C)
import
real(c_double) :: degree
type(c_ptr), value :: prt_obj
end function lcio_polarization_degree
end interface
interface
function lcio_polarization_theta (prt_obj) result (theta) bind(C)
import
real(c_double) :: theta
type(c_ptr), value :: prt_obj
end function lcio_polarization_theta
end interface
interface
function lcio_polarization_phi (prt_obj) result (phi) bind(C)
import
real(c_double) :: phi
type(c_ptr), value :: prt_obj
end function lcio_polarization_phi
end interface
@ %def lcio_polarization_degree lcio_polarization_theta lcio_polarization_phi
<<LCIO interface: public>>=
public :: lcio_particle_to_pol
<<LCIO interface: procedures>>=
subroutine lcio_particle_to_pol (prt, flv, pol)
type(lcio_particle_t), intent(in) :: prt
type(flavor_t), intent(in) :: flv
type(polarization_t), intent(out) :: pol
real(default) :: degree, theta, phi
degree = lcio_polarization_degree (prt%obj)
theta = lcio_polarization_theta (prt%obj)
phi = lcio_polarization_phi (prt%obj)
call pol%init_angles (flv, degree, theta, phi)
end subroutine lcio_particle_to_pol
@ %def lcio_polarization_to_pol
@ Recover helicity. Here, $\phi$ and [[degree]] is ignored and only the sign of
$\cos\theta$ is relevant, mapped to positive/negative helicity.
<<LCIO interface: public>>=
public :: lcio_particle_to_hel
<<LCIO interface: procedures>>=
subroutine lcio_particle_to_hel (prt, flv, hel)
type(lcio_particle_t), intent(in) :: prt
type(flavor_t), intent(in) :: flv
type(helicity_t), intent(out) :: hel
real(default) :: theta
integer :: hmax
theta = lcio_polarization_theta (prt%obj)
hmax = flv%get_spin_type () / 2
call hel%init (sign (hmax, nint (cos (theta))))
end subroutine lcio_particle_to_hel
@ %def lcio_particle_to_hel
@ Set the vertex of a particle.
<<LCIO interface: interfaces>>=
interface
subroutine lcio_particle_set_vertex (prt_obj, vx, vy, vz) bind(C)
import
type(c_ptr), value :: prt_obj
real(c_double), value :: vx, vy, vz
end subroutine lcio_particle_set_vertex
end interface
interface
subroutine lcio_particle_set_time (prt_obj, t) bind(C)
import
type(c_ptr), value :: prt_obj
real(c_float), value :: t
end subroutine lcio_particle_set_time
end interface
@ %def lcio_particle_set_vertex lcio_particle_set_time
@
<<LCIO interface: public>>=
public :: lcio_particle_set_vtx
<<LCIO interface: procedures>>=
subroutine lcio_particle_set_vtx (prt, vtx)
type(lcio_particle_t), intent(inout) :: prt
type(vector3_t), intent(in) :: vtx
call lcio_particle_set_vertex (prt%obj, real(vtx%p(1), c_double), &
real(vtx%p(2), c_double), real(vtx%p(3), c_double))
end subroutine lcio_particle_set_vtx
@ %def lcio_particle_set_vtx
@
Times in LCIO are in nanoseconds, not in mm, so need to be converted.
<<LCIO interface: public>>=
public :: lcio_particle_set_t
<<LCIO interface: procedures>>=
subroutine lcio_particle_set_t (prt, t)
type(lcio_particle_t), intent(inout) :: prt
real(default), intent(in) :: t
real(default) :: ns_from_t_mm
ns_from_t_mm = ns_per_mm * t
call lcio_particle_set_time (prt%obj, real(ns_from_t_mm, c_float))
end subroutine lcio_particle_set_t
@ %def lcio_particle_set_t
@
<<LCIO interface: interfaces>>=
interface
subroutine lcio_particle_add_parent (prt_obj1, prt_obj2) bind(C)
import
type(c_ptr), value :: prt_obj1, prt_obj2
end subroutine lcio_particle_add_parent
end interface
@ %def lcio_particle_add_parent
<<LCIO interface: public>>=
public :: lcio_particle_set_parent
<<LCIO interface: procedures>>=
subroutine lcio_particle_set_parent (daughter, parent)
type(lcio_particle_t), intent(inout) :: daughter, parent
call lcio_particle_add_parent (daughter%obj, parent%obj)
end subroutine lcio_particle_set_parent
@ %def lcio_particle_set_parent
@
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_particle_get_generator_status &
(prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function lcio_particle_get_generator_status
end interface
@ %def lcio_particle_get_generator_status
<<LCIO interface: public>>=
public :: lcio_particle_get_status
<<LCIO interface: procedures>>=
function lcio_particle_get_status (lptr) result (status)
integer :: status
type(lcio_particle_t), intent(in) :: lptr
status = lcio_particle_get_generator_status (lptr%obj)
end function lcio_particle_get_status
@ %def lcio_particle_get_status
@ Getting the PDG code.
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_particle_get_pdg_code (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function lcio_particle_get_pdg_code
end interface
@ %def lcio_particle_get_pdg_code
@
<<LCIO interface: public>>=
public :: lcio_particle_get_pdg
<<LCIO interface: procedures>>=
function lcio_particle_get_pdg (lptr) result (pdg)
integer :: pdg
type(lcio_particle_t), intent(in) :: lptr
pdg = lcio_particle_get_pdg_code (lptr%obj)
end function lcio_particle_get_pdg
@ %def lcio_particle_get_pdg
@ Obtaining the number of parents and daughters of an LCIO particle.
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_n_parents (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function lcio_n_parents
end interface
@ %def lcio_n_parents
@
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_n_daughters (prt_obj) bind(C)
import
type(c_ptr), value :: prt_obj
end function lcio_n_daughters
end interface
@ %def lcio_n_daughters
@
<<LCIO interface: public>>=
public :: lcio_particle_get_n_parents
<<LCIO interface: procedures>>=
function lcio_particle_get_n_parents (lptr) result (n_parents)
integer :: n_parents
type(lcio_particle_t), intent(in) :: lptr
n_parents = lcio_n_parents (lptr%obj)
end function lcio_particle_get_n_parents
@ %def lcio_particle_get_n_parents
@
<<LCIO interface: public>>=
public :: lcio_particle_get_n_children
<<LCIO interface: procedures>>=
function lcio_particle_get_n_children (lptr) result (n_children)
integer :: n_children
type(lcio_particle_t), intent(in) :: lptr
n_children = lcio_n_daughters (lptr%obj)
end function lcio_particle_get_n_children
@ %def lcio_particle_get_n_children
@ This provides access from the LCIO event [[lcio_event_t]] to the array entries
of the parent and daughter arrays of the LCIO particles.
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_event_parent_k &
(evt_obj, num_part, k_parent) bind (C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
integer(c_int), value :: num_part, k_parent
end function lcio_event_parent_k
end interface
@ %def lcio_event_parent_k
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_event_daughter_k &
(evt_obj, num_part, k_daughter) bind (C)
use iso_c_binding !NODEP!
type(c_ptr), value :: evt_obj
integer(c_int), value :: num_part, k_daughter
end function lcio_event_daughter_k
end interface
@ %def lcio_event_daughter_k
@
<<LCIO interface: public>>=
public :: lcio_get_n_parents
<<LCIO interface: procedures>>=
function lcio_get_n_parents (evt, num_part, k_parent) result (index_parent)
type(lcio_event_t), intent(in) :: evt
integer, intent(in) :: num_part, k_parent
integer :: index_parent
index_parent = lcio_event_parent_k (evt%obj, int (num_part, c_int), &
int (k_parent, c_int))
end function lcio_get_n_parents
@ %def lcio_get_n_parents
@
<<LCIO interface: public>>=
public :: lcio_get_n_children
<<LCIO interface: procedures>>=
function lcio_get_n_children (evt, num_part, k_daughter) result (index_daughter)
type(lcio_event_t), intent(in) :: evt
integer, intent(in) :: num_part, k_daughter
integer :: index_daughter
index_daughter = lcio_event_daughter_k (evt%obj, int (num_part, c_int), &
int (k_daughter, c_int))
end function lcio_get_n_children
@ %def lcio_get_n_children
@
\subsection{LCIO Writer type}
There is a specific LCIO Writer type for handling the output of
LCEventImpl objects (i.e., Monte Carlo event samples) to file. Opening
the file is done by the constructor, closing by the destructor.
<<LCIO interface: public>>=
public :: lcio_writer_t
<<LCIO interface: types>>=
type :: lcio_writer_t
private
type(c_ptr) :: obj
end type lcio_writer_t
@ %def lcio_writer_t
@ Constructor for an output associated to a file.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function open_lcio_writer_new (filename, complevel) bind(C)
import
character(c_char), dimension(*), intent(in) :: filename
integer(c_int), intent(in) :: complevel
end function open_lcio_writer_new
end interface
@ %def open_lcio_writer_now
<<LCIO interface: public>>=
public :: lcio_writer_open_out
<<LCIO interface: procedures>>=
subroutine lcio_writer_open_out (lcio_writer, filename)
type(lcio_writer_t), intent(out) :: lcio_writer
type(string_t), intent(in) :: filename
lcio_writer%obj = open_lcio_writer_new (char (filename) // &
c_null_char, 9_c_int)
end subroutine lcio_writer_open_out
@ %def lcio_writer_open_out
@ Destructor:
<<LCIO interface: interfaces>>=
interface
subroutine lcio_writer_delete (io_obj) bind(C)
import
type(c_ptr), value :: io_obj
end subroutine lcio_writer_delete
end interface
@ %def lcio_writer_delete
<<LCIO interface: public>>=
public :: lcio_writer_close
<<LCIO interface: procedures>>=
subroutine lcio_writer_close (lciowriter)
type(lcio_writer_t), intent(inout) :: lciowriter
call lcio_writer_delete (lciowriter%obj)
end subroutine lcio_writer_close
@ %def lcio_writer_close
@ Write a single event to the LCIO writer.
<<LCIO interface: interfaces>>=
interface
subroutine lcio_write_event (io_obj, evt_obj) bind(C)
import
type(c_ptr), value :: io_obj, evt_obj
end subroutine lcio_write_event
end interface
@ %def lcio_write_event
<<LCIO interface: public>>=
public :: lcio_event_write
<<LCIO interface: procedures>>=
subroutine lcio_event_write (wrt, evt)
type(lcio_writer_t), intent(inout) :: wrt
type(lcio_event_t), intent(in) :: evt
call lcio_write_event (wrt%obj, evt%obj)
end subroutine lcio_event_write
@ %def lcio_event_write
@
\subsection{LCIO Reader type}
There is a specific LCIO Reader type for handling the input of
LCEventImpl objects (i.e., Monte Carlo event samples) from file. Opening
the file is done by the constructor, closing by the destructor.
<<LCIO interface: public>>=
public :: lcio_reader_t
<<LCIO interface: types>>=
type :: lcio_reader_t
private
type(c_ptr) :: obj
end type lcio_reader_t
@ %def lcio_reader_t
@ Constructor for an output associated to a file.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function open_lcio_reader (filename) bind(C)
import
character(c_char), dimension(*), intent(in) :: filename
end function open_lcio_reader
end interface
@ %def open_lcio_reader
<<LCIO interface: public>>=
public :: lcio_open_file
<<LCIO interface: procedures>>=
subroutine lcio_open_file (lcio_reader, filename)
type(lcio_reader_t), intent(out) :: lcio_reader
type(string_t), intent(in) :: filename
lcio_reader%obj = open_lcio_reader (char (filename) // c_null_char)
end subroutine lcio_open_file
@ %def lcio_open_file
@ Destructor:
<<LCIO interface: interfaces>>=
interface
subroutine lcio_reader_delete (io_obj) bind(C)
import
type(c_ptr), value :: io_obj
end subroutine lcio_reader_delete
end interface
@ %def lcio_reader_delete
<<LCIO interface: public>>=
public :: lcio_reader_close
<<LCIO interface: procedures>>=
subroutine lcio_reader_close (lcioreader)
type(lcio_reader_t), intent(inout) :: lcioreader
call lcio_reader_delete (lcioreader%obj)
end subroutine lcio_reader_close
@ %def lcio_reader_close
@
@ Read a single event from the event file. Return true if successful.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function read_lcio_event (io_obj) bind(C)
import
type(c_ptr), value :: io_obj
end function read_lcio_event
end interface
@ %def read_lcio_event
<<LCIO interface: public>>=
public :: lcio_read_event
<<LCIO interface: procedures>>=
subroutine lcio_read_event (lcrdr, evt, ok)
type(lcio_reader_t), intent(inout) :: lcrdr
type(lcio_event_t), intent(out) :: evt
logical, intent(out) :: ok
evt%obj = read_lcio_event (lcrdr%obj)
ok = c_associated (evt%obj)
end subroutine lcio_read_event
@ %def lcio_read_event
@ Get the event index.
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_event_get_event_number (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function lcio_event_get_event_number
end interface
@ %def lcio_event_get_event_number
<<LCIO interface: public>>=
public :: lcio_event_get_event_index
<<LCIO interface: procedures>>=
function lcio_event_get_event_index (evt) result (i_evt)
integer :: i_evt
type(lcio_event_t), intent(in) :: evt
i_evt = lcio_event_get_event_number (evt%obj)
end function lcio_event_get_event_index
@ %def lcio_event_get_event_index
@ Extract the process ID. This is stored (at the moment abusively) in the
RUN ID as well as in an additional event parameter.
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_event_signal_process_id (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function lcio_event_signal_process_id
end interface
@ %def lcio_event_signal_process_id
<<LCIO interface: public>>=
public :: lcio_event_get_process_id
<<LCIO interface: procedures>>=
function lcio_event_get_process_id (evt) result (i_proc)
integer :: i_proc
type(lcio_event_t), intent(in) :: evt
i_proc = lcio_event_signal_process_id (evt%obj)
end function lcio_event_get_process_id
@ %def lcio_event_get_process_id
@ Number of particles in an LCIO event.
<<LCIO interface: interfaces>>=
interface
integer(c_int) function lcio_event_get_n_particles (evt_obj) bind(C)
import
type(c_ptr), value :: evt_obj
end function lcio_event_get_n_particles
end interface
@ %def lcio_event_get_n_particles
<<LCIO interface:>>=
@
<<LCIO interface: public>>=
public :: lcio_event_get_n_tot
<<LCIO interface: procedures>>=
function lcio_event_get_n_tot (evt) result (n_tot)
integer :: n_tot
type(lcio_event_t), intent(in) :: evt
n_tot = lcio_event_get_n_particles (evt%obj)
end function lcio_event_get_n_tot
@ %def lcio_event_get_n_tot
@ Extracting $\alpha_s$ and the scale.
<<LCIO interface: interfaces>>=
interface
function lcio_event_get_alpha_qcd (evt_obj) result (as) bind(C)
import
real(c_double) :: as
type(c_ptr), value :: evt_obj
end function lcio_event_get_alpha_qcd
end interface
interface
function lcio_event_get_scale (evt_obj) result (scale) bind(C)
import
real(c_double) :: scale
type(c_ptr), value :: evt_obj
end function lcio_event_get_scale
end interface
@ %def lcio_event_get_alpha_qcd lcio_event_get_scale
@
<<LCIO interface: public>>=
public :: lcio_event_get_alphas
<<LCIO interface: procedures>>=
function lcio_event_get_alphas (evt) result (as)
type(lcio_event_t), intent(in) :: evt
real(default) :: as
as = lcio_event_get_alpha_qcd (evt%obj)
end function lcio_event_get_alphas
@ %def lcio_event_get_alphas
@
<<LCIO interface: public>>=
public :: lcio_event_get_scaleval
<<LCIO interface: procedures>>=
function lcio_event_get_scaleval (evt) result (scale)
type(lcio_event_t), intent(in) :: evt
real(default) :: scale
scale = lcio_event_get_scale (evt%obj)
end function lcio_event_get_scaleval
@ %def lcio_event_get_scaleval
@ Extracting particles by index from an LCIO event.
<<LCIO interface: interfaces>>=
interface
type(c_ptr) function lcio_event_particle_k (evt_obj, k) bind(C)
import
type(c_ptr), value :: evt_obj
integer(c_int), value :: k
end function lcio_event_particle_k
end interface
@ %def lcio_event_particle_k
@
<<LCIO interface: public>>=
public :: lcio_event_get_particle
<<LCIO interface: procedures>>=
function lcio_event_get_particle (evt, n) result (prt)
type(lcio_event_t), intent(in) :: evt
integer, intent(in) :: n
type(lcio_particle_t) :: prt
prt%obj = lcio_event_particle_k (evt%obj, int (n, c_int))
end function lcio_event_get_particle
@ %def lcio_event_get_particle
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[lcio_interface_ut.f90]]>>=
<<File header>>
module lcio_interface_ut
use unit_tests
use lcio_interface_uti
<<Standard module head>>
<<LCIO interface: public test>>
contains
<<LCIO interface: test driver>>
end module lcio_interface_ut
@ %def lcio_interface_ut
@
<<[[lcio_interface_uti.f90]]>>=
<<File header>>
module lcio_interface_uti
<<Use kinds>>
<<Use strings>>
use io_units
use lorentz
use flavors
use colors
use polarizations
use lcio_interface
<<Standard module head>>
<<LCIO interface: test declarations>>
contains
<<LCIO interface: tests>>
end module lcio_interface_uti
@ %def lcio_interface_ut
@ API: driver for the unit tests below.
<<LCIO interface: public test>>=
public :: lcio_interface_test
<<LCIO interface: test driver>>=
subroutine lcio_interface_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<LCIO interface: execute tests>>
end subroutine lcio_interface_test
@ %def lcio_interface_test
@
<<LCIO interface: execute tests>>=
call test (lcio_interface_1, "lcio_interface_1", &
"check LCIO interface", &
u, results)
<<LCIO interface: test declarations>>=
public :: lcio_interface_1
<<LCIO interface: tests>>=
subroutine lcio_interface_1 (u)
use physics_defs, only: VECTOR
use model_data, only: field_data_t
integer, intent(in) :: u
integer :: u_file, iostat
type(lcio_event_t) :: evt
type(lcio_particle_t) :: prt1, prt2, prt3, prt4, prt5, prt6, prt7, prt8
type(flavor_t) :: flv
type(color_t) :: col
type(polarization_t) :: pol
type(field_data_t), target :: photon_data
character(220) :: buffer
write (u, "(A)") "* Test output: LCIO interface"
write (u, "(A)") "* Purpose: test LCIO interface"
write (u, "(A)")
write (u, "(A)") "* Initialization"
write (u, "(A)")
! Initialize a photon flavor object and some polarization
call photon_data%init (var_str ("PHOTON"), 22)
call photon_data%set (spin_type=VECTOR)
call photon_data%freeze ()
call flv%init (photon_data)
call pol%init_angles &
(flv, 0.6_default, 1._default, 0.5_default)
! Event initialization
call lcio_event_init (evt, 20, 1, 42)
write (u, "(A)") "* p -> q splitting"
write (u, "(A)")
! $p\to q$ splittings
call particle_init (prt1, &
0._default, 0._default, 7000._default, 7000._default, &
2212, 1._default, 3)
call particle_init (prt2, &
0._default, 0._default,-7000._default, 7000._default, &
2212, 1._default, 3)
call particle_init (prt3, &
.750_default, -1.569_default, 32.191_default, 32.238_default, &
1, -1._default/3._default, 3)
call color_init_from_array (col, [501])
call lcio_particle_set_color (prt3, col)
call lcio_particle_set_parent (prt3, prt1)
call lcio_particle_set_parent (prt3, prt2)
call particle_init (prt4, &
-3.047_default, -19._default, -54.629_default, 57.920_default, &
-2, -2._default/3._default, 3)
call color_init_from_array (col, [-501])
call lcio_particle_set_color (prt4, col)
call lcio_particle_set_parent (prt4, prt1)
call lcio_particle_set_parent (prt4, prt2)
write (u, "(A)") "* Hard interaction"
write (u, "(A)")
! Hard interaction
call particle_init (prt6, &
-3.813_default, 0.113_default, -1.833_default, 4.233_default, &
22, 0._default, 1)
call lcio_polarization_init (prt6, pol)
call particle_init (prt5, &
1.517_default, -20.68_default, -20.605_default, 85.925_default, &
-24, -1._default, 3)
call lcio_particle_set_parent (prt5, prt3)
call lcio_particle_set_parent (prt5, prt4)
call lcio_particle_set_parent (prt6, prt3)
call lcio_particle_set_parent (prt6, prt4)
! $W^-$ decay
call particle_init (prt7, &
-2.445_default, 28.816_default, 6.082_default, 29.552_default, &
1, -1._default/3._default, 1)
call particle_init (prt8, &
3.962_default, -49.498_default, -26.687_default, 56.373_default, &
-2, -2._default/3._default, 1)
call lcio_particle_set_t (prt7, 0.12_default)
call lcio_particle_set_t (prt8, 0.12_default)
call lcio_particle_set_vtx &
(prt7, vector3_moving ([-0.3_default, 0.05_default, 0.004_default]))
call lcio_particle_set_vtx &
(prt8, vector3_moving ([-0.3_default, 0.05_default, 0.004_default]))
call lcio_particle_set_parent (prt7, prt5)
call lcio_particle_set_parent (prt8, prt5)
call lcio_particle_add_to_evt_coll (prt1, evt)
call lcio_particle_add_to_evt_coll (prt2, evt)
call lcio_particle_add_to_evt_coll (prt3, evt)
call lcio_particle_add_to_evt_coll (prt4, evt)
call lcio_particle_add_to_evt_coll (prt5, evt)
call lcio_particle_add_to_evt_coll (prt6, evt)
call lcio_particle_add_to_evt_coll (prt7, evt)
call lcio_particle_add_to_evt_coll (prt8, evt)
call lcio_event_add_coll (evt)
! Event output
write (u, "(A)") "Writing in ASCII form to file 'lcio_test.slcio'"
write (u, "(A)")
call write_lcio_event (evt, var_str ("lcio_test.slcio"))
write (u, "(A)") "Writing completed"
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "lcio_test.slcio", &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (trim (buffer) == "") cycle
if (buffer(1:12) == " - timestamp") buffer = "[...]"
if (buffer(1:6) == " date:") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
write (u, "(A)")
! Wrapup
! call pol%final ()
call lcio_event_final (evt)
write (u, "(A)")
write (u, "(A)") "* Test output end: lcio_interface_1"
contains
subroutine particle_init &
(prt, px, py, pz, E, pdg, charge, status)
type(lcio_particle_t), intent(out) :: prt
real(default), intent(in) :: px, py, pz, E, charge
integer, intent(in) :: pdg, status
type(vector4_t) :: p
p = vector4_moving (E, vector3_moving ([px, py, pz]))
call lcio_particle_init (prt, p, pdg, charge, status)
end subroutine particle_init
end subroutine lcio_interface_1
@ %def lcio_interface_1
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{HEP Common and Events}
This is a separate module that manages data exchange between the common blocks
and [[event_t]] objects. We separate this from the previous module in order
to avoid a circular module dependency. It also contains the functions
necessary for communication between [[hepmc_event_t]] and
[[event_t]] or [[lcio_event_t]] and [[event_t]] as well as
[[particle_set_t]] and [[particle_t]] objects.
<<[[hep_events.f90]]>>=
<<File header>>
module hep_events
<<Use kinds>>
<<Use strings>>
use system_dependencies, only: HEPMC2_AVAILABLE
use system_dependencies, only: HEPMC3_AVAILABLE
use diagnostics
use lorentz
use numeric_utils
use flavors
use colors
use helicities
use polarizations
use model_data
use subevents, only: PRT_BEAM, PRT_INCOMING, PRT_OUTGOING
use subevents, only: PRT_UNDEFINED
use subevents, only: PRT_VIRTUAL, PRT_RESONANT, PRT_BEAM_REMNANT
use particles
use hep_common
use hepmc_interface
use lcio_interface
use event_base
<<Standard module head>>
<<HEP events: public>>
contains
<<HEP events: procedures>>
end module hep_events
@ %def hep_events
@
\subsection{Data Transfer: events}
Fill the HEPEUP block, given a \whizard\ event object.
<<HEP events: public>>=
public :: hepeup_from_event
<<HEP events: procedures>>=
subroutine hepeup_from_event &
(event, keep_beams, keep_remnants, process_index)
class(generic_event_t), intent(in), target :: event
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
integer, intent(in), optional :: process_index
type(particle_set_t), pointer :: particle_set
real(default) :: scale, alpha_qcd
if (event%has_valid_particle_set ()) then
particle_set => event%get_particle_set_ptr ()
call hepeup_from_particle_set (particle_set, keep_beams, keep_remnants)
if (present (process_index)) then
call hepeup_set_event_parameters (proc_id = process_index)
end if
scale = event%get_fac_scale ()
if (.not. vanishes (scale)) then
call hepeup_set_event_parameters (scale = scale)
end if
alpha_qcd = event%get_alpha_s ()
if (.not. vanishes (alpha_qcd)) then
call hepeup_set_event_parameters (alpha_qcd = alpha_qcd)
end if
if (event%weight_prc_is_known ()) then
call hepeup_set_event_parameters (weight = event%get_weight_prc ())
end if
else
call msg_bug ("HEPEUP: event incomplete")
end if
end subroutine hepeup_from_event
@ %def hepeup_from_event
@ Reverse.
Note: The current implementation sets the particle set of the hard
process and is therefore not useful if the event on file is dressed.
This should be reconsidered.
Note: setting of scale or alpha is not yet supported by the
[[event_t]] object. Ticket \#628.
<<HEP events: public>>=
public :: hepeup_to_event
<<HEP events: procedures>>=
subroutine hepeup_to_event &
(event, fallback_model, process_index, recover_beams, &
use_alpha_s, use_scale)
class(generic_event_t), intent(inout), target :: event
class(model_data_t), intent(in), target :: fallback_model
integer, intent(out), optional :: process_index
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alpha_s
logical, intent(in), optional :: use_scale
class(model_data_t), pointer :: model
real(default) :: weight, scale, alpha_qcd
type(particle_set_t) :: particle_set
model => event%get_model_ptr ()
call hepeup_to_particle_set &
(particle_set, recover_beams, model, fallback_model)
call event%set_hard_particle_set (particle_set)
call particle_set%final ()
if (present (process_index)) then
call hepeup_get_event_parameters (proc_id = process_index)
end if
call hepeup_get_event_parameters (weight = weight, &
scale = scale, alpha_qcd = alpha_qcd)
call event%set_weight_ref (weight)
if (present (use_alpha_s)) then
if (use_alpha_s .and. alpha_qcd > 0) &
call event%set_alpha_qcd_forced (alpha_qcd)
end if
if (present (use_scale)) then
if (use_scale .and. scale > 0) &
call event%set_scale_forced (scale)
end if
end subroutine hepeup_to_event
@ %def hepeup_to_event
@ Fill the HEPEVT (event) common block.
The [[i_evt]] argument overrides the index stored in the [[event]] object.
<<HEP events: public>>=
public :: hepevt_from_event
<<HEP events: procedures>>=
subroutine hepevt_from_event &
(event, process_index, i_evt, keep_beams, keep_remnants, &
ensure_order, fill_hepev4)
class(generic_event_t), intent(in), target :: event
integer, intent(in), optional :: i_evt, process_index
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
logical, intent(in), optional :: ensure_order
logical, intent(in), optional :: fill_hepev4
type(particle_set_t), pointer :: particle_set
real(default) :: alpha_qcd, scale
if (event%has_valid_particle_set ()) then
particle_set => event%get_particle_set_ptr ()
call hepevt_from_particle_set (particle_set, keep_beams, &
keep_remnants, ensure_order, fill_hepev4)
if (present (process_index)) then
call hepevt_set_event_parameters (proc_id = process_index)
end if
if (event%weight_prc_is_known ()) then
call hepevt_set_event_parameters (weight = event%get_weight_prc ())
end if
if (event%sqme_prc_is_known ()) then
call hepevt_set_event_parameters &
(function_value = event%get_sqme_prc ())
end if
scale = event%get_fac_scale ()
if (.not. vanishes (scale)) then
call hepevt_set_event_parameters (scale = scale)
end if
alpha_qcd = event%get_alpha_s ()
if (.not. vanishes (alpha_qcd)) then
call hepevt_set_event_parameters (alpha_qcd = alpha_qcd)
end if
if (present (i_evt)) then
call hepevt_set_event_parameters (i_evt = i_evt)
else if (event%has_index ()) then
call hepevt_set_event_parameters (i_evt = event%get_index ())
else
call hepevt_set_event_parameters (i_evt = 0)
end if
else
call msg_bug ("HEPEVT: event incomplete")
end if
end subroutine hepevt_from_event
@ %def hepevt_from_event
@
\subsubsection{HepMC format}
The master output function fills a HepMC GenEvent object that is
already initialized, but has no vertices in it.
We first set up the vertex lists and enter the vertices into the HepMC
event. Then, we assign first all incoming particles and then all
outgoing particles to their associated vertices. Particles which have
neither parent nor children entries (this should not happen) are
dropped.
Finally, we insert the beam particles. If there are none, use the incoming
particles instead.
@ Transform a particle into a [[hepmc_particle]] object, including
color and polarization. The HepMC status is equivalent to the HEPEVT
status, in particular: 0 = null entry, 1 = physical particle, 2 =
decayed/fragmented SM hadron, tau or muon, 3 = other unphysical particle
entry, 4 = incoming particles, 11 = intermediate resonance such as squarks.
The use of 11 for intermediate resonances is as done by HERWIG, see
http://herwig.hepforge.org/trac/wiki/FaQs.
<<HEP events: procedures>>=
subroutine particle_to_hepmc (prt, hprt)
type(particle_t), intent(in) :: prt
type(hepmc_particle_t), intent(out) :: hprt
integer :: hepmc_status
select case (prt%get_status ())
case (PRT_UNDEFINED)
hepmc_status = 0
case (PRT_OUTGOING)
hepmc_status = 1
case (PRT_BEAM)
hepmc_status = 4
case (PRT_RESONANT)
if (abs(prt%get_pdg()) == 13 .or. &
abs(prt%get_pdg()) == 15) then
hepmc_status = 2
else
hepmc_status = 11
end if
case default
hepmc_status = 3
end select
call hepmc_particle_init (hprt, &
prt%get_momentum (), prt%get_pdg (), &
hepmc_status)
if (HEPMC2_AVAILABLE) then
call hepmc_particle_set_color (hprt, prt%get_color ())
select case (prt%get_polarization_status ())
case (PRT_DEFINITE_HELICITY)
call hepmc_particle_set_polarization (hprt, &
prt%get_helicity ())
case (PRT_GENERIC_POLARIZATION)
call hepmc_particle_set_polarization (hprt, &
prt%get_polarization ())
end select
end if
end subroutine particle_to_hepmc
@ %def particle_to_hepmc
@ For HepMC3, a HepMC particle needs first to be attached to a vertex
and an event before non-intrinsic particle properties (color flow and
helicity) could be set.
<<HEP events: public>>=
public :: hepmc_event_from_particle_set
<<HEP events: procedures>>=
subroutine hepmc_event_from_particle_set &
(evt, particle_set, cross_section, error)
type(hepmc_event_t), intent(inout) :: evt
type(particle_set_t), intent(in) :: particle_set
real(default), intent(in), optional :: cross_section, error
type(hepmc_vertex_t), dimension(:), allocatable :: v
type(hepmc_particle_t), dimension(:), allocatable :: hprt
type(hepmc_particle_t), dimension(2) :: hbeam
type(vector4_t), dimension(:), allocatable :: vtx
logical, dimension(:), allocatable :: is_beam
integer, dimension(:), allocatable :: v_from, v_to
integer :: n_vertices, n_tot, i
n_tot = particle_set%get_n_tot ()
allocate (v_from (n_tot), v_to (n_tot))
call particle_set%assign_vertices (v_from, v_to, n_vertices)
allocate (hprt (n_tot))
allocate (vtx (n_vertices))
vtx = vector4_null
do i = 1, n_tot
if (v_to(i) /= 0 .or. v_from(i) /= 0) then
call particle_to_hepmc (particle_set%prt(i), hprt(i))
if (v_to(i) /= 0) then
vtx(v_to(i)) = particle_set%prt(i)%get_vertex ()
end if
end if
end do
if (present (cross_section) .and. present(error)) &
call hepmc_event_set_cross_section (evt, cross_section, error)
allocate (v (n_vertices))
do i = 1, n_vertices
call hepmc_vertex_init (v(i), vtx(i))
call hepmc_event_add_vertex (evt, v(i))
end do
allocate (is_beam (n_tot))
is_beam = particle_set%prt(1:n_tot)%get_status () == PRT_BEAM
if (.not. any (is_beam)) then
is_beam = particle_set%prt(1:n_tot)%get_status () == PRT_INCOMING
end if
if (count (is_beam) == 2) then
hbeam = pack (hprt, is_beam)
call hepmc_event_set_beam_particles (evt, hbeam(1), hbeam(2))
end if
do i = 1, n_tot
if (v_to(i) /= 0) then
call hepmc_vertex_add_particle_in (v(v_to(i)), hprt(i))
end if
end do
do i = 1, n_tot
if (v_from(i) /= 0) then
call hepmc_vertex_add_particle_out (v(v_from(i)), hprt(i))
end if
end do
FIND_SIGNAL_PROCESS: do i = 1, n_tot
if (particle_set%prt(i)%get_status () == PRT_INCOMING) then
call hepmc_event_set_signal_process_vertex (evt, v(v_to(i)))
exit FIND_SIGNAL_PROCESS
end if
end do FIND_SIGNAL_PROCESS
if (HEPMC3_AVAILABLE) then
do i = 1, n_tot
call hepmc_particle_set_color (hprt(i), &
particle_set%prt(i)%get_color ())
select case (particle_set%prt(i)%get_polarization_status ())
case (PRT_DEFINITE_HELICITY)
call hepmc_particle_set_polarization (hprt(i), &
particle_set%prt(i)%get_helicity ())
case (PRT_GENERIC_POLARIZATION)
call hepmc_particle_set_polarization (hprt(i), &
particle_set%prt(i)%get_polarization ())
end select
end do
end if
end subroutine hepmc_event_from_particle_set
@ %def hepmc_event_from_particle_set
@ Initialize a particle from a HepMC particle object. The model is
necessary for making a fully qualified flavor component. We have the
additional flag [[polarized]] which tells whether the polarization
information should be interpreted or ignored, and the lookup array of
barcodes. Note that the lookup array is searched linearly, a possible
bottleneck for large particle arrays. If necessary, the barcode array
could be replaced by a hash table.
<<HEP events: procedures>>=
subroutine particle_from_hepmc_particle &
(prt, hprt, model, fallback_model, polarization, barcode)
type(particle_t), intent(out) :: prt
type(hepmc_particle_t), intent(in) :: hprt
type(model_data_t), intent(in), target :: model
type(model_data_t), intent(in), target :: fallback_model
type(hepmc_vertex_t) :: vtx
integer, intent(in) :: polarization
integer, dimension(:), intent(in) :: barcode
type(hepmc_polarization_t) :: hpol
type(flavor_t) :: flv
type(color_t) :: col
type(helicity_t) :: hel
type(polarization_t) :: pol
type(vector4_t) :: vertex
integer :: n_parents, n_children
integer, dimension(:), allocatable :: &
parent_barcode, child_barcode, parent, child
integer :: i
select case (hepmc_particle_get_status (hprt))
case (1); call prt%set_status (PRT_OUTGOING)
case (2); call prt%set_status (PRT_RESONANT)
case (3); call prt%set_status (PRT_VIRTUAL)
end select
if (hepmc_particle_is_beam (hprt)) call prt%set_status (PRT_BEAM)
call flv%init (hepmc_particle_get_pdg (hprt), model, fallback_model)
call col%init (hepmc_particle_get_color (hprt))
call prt%set_flavor (flv)
call prt%set_color (col)
call prt%set_polarization (polarization)
select case (polarization)
case (PRT_DEFINITE_HELICITY)
hpol = hepmc_particle_get_polarization (hprt)
call hepmc_polarization_to_hel (hpol, prt%get_flv (), hel)
call prt%set_helicity (hel)
call hepmc_polarization_final (hpol)
case (PRT_GENERIC_POLARIZATION)
hpol = hepmc_particle_get_polarization (hprt)
call hepmc_polarization_to_pol (hpol, prt%get_flv (), pol)
call prt%set_pol (pol)
call hepmc_polarization_final (hpol)
end select
call prt%set_momentum (hepmc_particle_get_momentum (hprt), &
hepmc_particle_get_mass_squared (hprt))
n_parents = hepmc_particle_get_n_parents (hprt)
n_children = hepmc_particle_get_n_children (hprt)
if (HEPMC2_AVAILABLE) then
allocate (parent_barcode (n_parents), parent (n_parents))
allocate (child_barcode (n_children), child (n_children))
parent_barcode = hepmc_particle_get_parent_barcodes (hprt)
child_barcode = hepmc_particle_get_child_barcodes (hprt)
do i = 1, size (barcode)
where (parent_barcode == barcode(i)) parent = i
where (child_barcode == barcode(i)) child = i
end do
call prt%set_parents (parent)
call prt%set_children (child)
else if (HEPMC3_AVAILABLE) then
allocate (parent_barcode (n_parents), parent (n_parents))
allocate (child_barcode (n_children), child (n_children))
parent_barcode = hepmc_particle_get_parent_barcodes (hprt)
child_barcode = hepmc_particle_get_child_barcodes (hprt)
do i = 1, size (barcode)
where (parent_barcode == barcode(i)) parent = i
where (child_barcode == barcode(i)) child = i
end do
call prt%set_parents (parent)
call prt%set_children (child)
end if
if (prt%get_status () == PRT_VIRTUAL .and. n_parents == 0) &
call prt%set_status (PRT_INCOMING)
if (HEPMC2_AVAILABLE) then
vtx = hepmc_particle_get_decay_vertex (hprt)
if (hepmc_vertex_is_valid (vtx)) then
vertex = hepmc_vertex_to_vertex (vtx)
if (vertex /= vector4_null) call prt%set_vertex (vertex)
end if
end if
end subroutine particle_from_hepmc_particle
@ %def particle_from_hepmc_particle
@ If a particle set is initialized from a HepMC event record, we have
to specify the treatment of polarization (unpolarized or density
matrix) which is common to all particles. Correlated polarization
information is not available.
There is some complication in reconstructing incoming particles and
beam remnants. First of all, they all will be tagged as virtual. We
then define an incoming particle as
<<HEP events: public>>=
public :: hepmc_event_to_particle_set
<<HEP events: procedures>>=
subroutine hepmc_event_to_particle_set &
(particle_set, evt, model, fallback_model, polarization)
type(particle_set_t), intent(inout), target :: particle_set
type(hepmc_event_t), intent(in) :: evt
class(model_data_t), intent(in), target :: model, fallback_model
integer, intent(in) :: polarization
type(hepmc_event_particle_iterator_t) :: it
type(hepmc_vertex_t) :: v
type(hepmc_vertex_particle_in_iterator_t) :: v_it
type(hepmc_particle_t) :: prt
integer, dimension(:), allocatable :: barcode, n_parents
integer :: n_tot, n_beam, i, bc
n_tot = hepmc_event_get_n_particles(evt)
allocate (barcode (n_tot))
if (HEPMC2_AVAILABLE) then
call hepmc_event_particle_iterator_init (it, evt)
do i = 1, n_tot
barcode(i) = hepmc_particle_get_barcode &
(hepmc_event_particle_iterator_get (it))
call hepmc_event_particle_iterator_advance (it)
end do
allocate (particle_set%prt (n_tot))
call hepmc_event_particle_iterator_reset (it)
do i = 1, n_tot
prt = hepmc_event_particle_iterator_get (it)
call particle_from_hepmc_particle (particle_set%prt(i), &
prt, model, fallback_model, polarization, barcode)
call hepmc_event_particle_iterator_advance (it)
end do
call hepmc_event_particle_iterator_final (it)
v = hepmc_event_get_signal_process_vertex (evt)
if (hepmc_vertex_is_valid (v)) then
call hepmc_vertex_particle_in_iterator_init (v_it, v)
do while (hepmc_vertex_particle_in_iterator_is_valid (v_it))
prt = hepmc_vertex_particle_in_iterator_get (v_it)
bc = hepmc_particle_get_barcode &
(hepmc_vertex_particle_in_iterator_get (v_it))
do i = 1, size(barcode)
if (bc == barcode(i)) &
call particle_set%prt(i)%set_status (PRT_INCOMING)
end do
call hepmc_vertex_particle_in_iterator_advance (v_it)
end do
call hepmc_vertex_particle_in_iterator_final (v_it)
end if
else if (HEPMC3_AVAILABLE) then
allocate (particle_set%prt (n_tot))
do i = 1, n_tot
barcode(i) = hepmc_particle_get_barcode &
(hepmc_event_get_nth_particle (evt, i))
end do
do i = 1, n_tot
prt = hepmc_event_get_nth_particle (evt, i)
call particle_from_hepmc_particle (particle_set%prt(i), &
prt, model, fallback_model, polarization, barcode)
end do
v = hepmc_event_get_signal_process_vertex (evt)
if (hepmc_vertex_is_valid (v)) then
call hepmc_vertex_particle_in_iterator_init (v_it, v)
do while (hepmc_vertex_particle_in_iterator_is_valid (v_it))
prt = hepmc_vertex_particle_in_iterator_get (v_it)
bc = hepmc_particle_get_barcode &
(hepmc_vertex_particle_in_iterator_get (v_it))
do i = 1, size(barcode)
if (bc == barcode(i)) &
call particle_set%prt(i)%set_status (PRT_INCOMING)
end do
call hepmc_vertex_particle_in_iterator_advance (v_it)
end do
call hepmc_vertex_particle_in_iterator_final (v_it)
end if
end if
do i = 1, n_tot
if (particle_set%prt(i)%get_status () == PRT_VIRTUAL &
.and. particle_set%prt(i)%get_n_children () == 0) &
call particle_set%prt(i)%set_status (PRT_OUTGOING)
end do
if (HEPMC3_AVAILABLE) then
n_beam = hepmc_event_get_n_beams (evt)
do i = 1, n_beam
bc = hepmc_event_get_nth_beam (evt, i)
if (.not. particle_set%prt(bc)%get_status () == PRT_INCOMING) &
call particle_set%prt(bc)%set_status (PRT_BEAM)
end do
do i = 1, n_tot
if (particle_set%prt(i)%get_status () == PRT_VIRTUAL) then
n_parents = particle_set%prt(i)%get_parents ()
if (all &
(particle_set%prt(n_parents)%get_status () == PRT_BEAM)) then
call particle_set%prt(i)%set_status (PRT_INCOMING)
end if
end if
end do
end if
particle_set%n_tot = n_tot
particle_set%n_beam = &
count (particle_set%prt%get_status () == PRT_BEAM)
particle_set%n_in = &
count (particle_set%prt%get_status () == PRT_INCOMING)
particle_set%n_out = &
count (particle_set%prt%get_status () == PRT_OUTGOING)
particle_set%n_vir = &
particle_set%n_tot - particle_set%n_in - particle_set%n_out
end subroutine hepmc_event_to_particle_set
@ %def hepmc_event_to_particle_set
@ Fill a WHIZARD event from a HepMC event record. In HepMC the weights
are in a weight container. If the size of this container is larger than
one, it is ambiguous to assign the event a specific weight. For now we
only allow to read in unweighted events.
<<HEP events: public>>=
public :: hepmc_to_event
<<HEP events: procedures>>=
subroutine hepmc_to_event &
(event, hepmc_event, fallback_model, process_index, &
recover_beams, use_alpha_s, use_scale)
class(generic_event_t), intent(inout), target :: event
type(hepmc_event_t), intent(inout) :: hepmc_event
class(model_data_t), intent(in), target :: fallback_model
integer, intent(out), optional :: process_index
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alpha_s
logical, intent(in), optional :: use_scale
class(model_data_t), pointer :: model
real(default) :: scale, alpha_qcd
type(particle_set_t) :: particle_set
model => event%get_model_ptr ()
call event%set_index (hepmc_event_get_event_index (hepmc_event))
call hepmc_event_to_particle_set (particle_set, &
hepmc_event, model, fallback_model, PRT_DEFINITE_HELICITY)
call event%set_hard_particle_set (particle_set)
call particle_set%final ()
call event%set_weight_ref (1._default)
alpha_qcd = hepmc_event_get_alpha_qcd (hepmc_event)
scale = hepmc_event_get_scale (hepmc_event)
if (present (use_alpha_s)) then
if (use_alpha_s .and. alpha_qcd > 0) &
call event%set_alpha_qcd_forced (alpha_qcd)
end if
if (present (use_scale)) then
if (use_scale .and. scale > 0) &
call event%set_scale_forced (scale)
end if
end subroutine hepmc_to_event
@ %def hepmc_to_event
@
\subsubsection{LCIO event format}
The master output function fills a LCIO event object that is
already initialized, but has no particles in it.
In contrast to HepMC in LCIO there are no vertices (except for tracker
and other detector specifications). So we assign first all incoming
particles and then all outgoing particles to LCIO particle types.
Particles which have neither parent nor children entries (this
should not happen) are dropped. Finally, we insert the beam particles.
If there are none, use the incoming particles instead.
Transform a particle into a [[lcio_particle]] object, including
color and polarization. The LCIO status is equivalent to the HepMC
status, in particular: 0 = null entry, 1 = physical particle, 2 =
decayed/fragmented SM hadron, tau or muon, 3 = other unphysical particle
entry, 4 = incoming particles, 11 = intermediate resonance such as squarks.
The use of 11 for intermediate resonances is as done by HERWIG, see
http://herwig.hepforge.org/trac/wiki/FaQs.
A beam-remnant particle (e.g., ISR photon) that has no children is
tagged as outgoing, otherwise unphysical.
<<HEP events: public>>=
public :: particle_to_lcio
<<HEP events: procedures>>=
subroutine particle_to_lcio (prt, lprt)
type(particle_t), intent(in) :: prt
type(lcio_particle_t), intent(out) :: lprt
integer :: lcio_status
type(vector4_t) :: vtx
select case (prt%get_status ())
case (PRT_UNDEFINED)
lcio_status = 0
case (PRT_OUTGOING)
lcio_status = 1
case (PRT_BEAM_REMNANT)
if (prt%get_n_children () == 0) then
lcio_status = 1
else
lcio_status = 3
end if
case (PRT_BEAM)
lcio_status = 4
case (PRT_RESONANT)
lcio_status = 2
case default
lcio_status = 3
end select
call lcio_particle_init (lprt, &
prt%get_momentum (), &
prt%get_pdg (), &
prt%flv%get_charge (), &
lcio_status)
call lcio_particle_set_color (lprt, prt%get_color ())
vtx = prt%get_vertex ()
call lcio_particle_set_vtx (lprt, space_part (vtx))
call lcio_particle_set_t (lprt, vtx%p(0))
select case (prt%get_polarization_status ())
case (PRT_DEFINITE_HELICITY)
call lcio_polarization_init (lprt, prt%get_helicity ())
case (PRT_GENERIC_POLARIZATION)
call lcio_polarization_init (lprt, prt%get_polarization ())
end select
end subroutine particle_to_lcio
@ %def particle_to_lcio
@
@ Initialize a particle from a LCIO particle object. The model is
necessary for making a fully qualified flavor component.
<<HEP events: public>>=
public :: particle_from_lcio_particle
<<HEP events: procedures>>=
subroutine particle_from_lcio_particle &
(prt, lprt, model, daughters, parents, polarization)
type(particle_t), intent(out) :: prt
type(lcio_particle_t), intent(in) :: lprt
type(model_data_t), intent(in), target :: model
integer, dimension(:), intent(in) :: daughters, parents
type(vector4_t) :: vtx4
type(flavor_t) :: flv
type(color_t) :: col
type(helicity_t) :: hel
type(polarization_t) :: pol
integer, intent(in) :: polarization
select case (lcio_particle_get_status (lprt))
case (1); call prt%set_status (PRT_OUTGOING)
case (2); call prt%set_status (PRT_RESONANT)
case (3)
select case (size (parents))
case (0)
call prt%set_status (PRT_INCOMING)
case default
call prt%set_status (PRT_VIRTUAL)
end select
case (4); call prt%set_status (PRT_BEAM)
end select
call flv%init (lcio_particle_get_pdg (lprt), model)
call col%init (lcio_particle_get_flow (lprt))
if (flv%is_beam_remnant ()) call prt%set_status (PRT_BEAM_REMNANT)
call prt%set_flavor (flv)
call prt%set_color (col)
call prt%set_polarization (polarization)
select case (polarization)
case (PRT_DEFINITE_HELICITY)
call lcio_particle_to_hel (lprt, prt%get_flv (), hel)
call prt%set_helicity (hel)
case (PRT_GENERIC_POLARIZATION)
call lcio_particle_to_pol (lprt, prt%get_flv (), pol)
call prt%set_pol (pol)
end select
call prt%set_momentum (lcio_particle_get_momentum (lprt), &
lcio_particle_get_mass_squared (lprt))
call prt%set_parents (parents)
call prt%set_children (daughters)
vtx4 = vector4_moving (lcio_particle_get_time (lprt), &
lcio_particle_get_vertex (lprt))
if (vtx4 /= vector4_null) call prt%set_vertex (vtx4)
end subroutine particle_from_lcio_particle
@ %def particle_from_lcio_particle
@
<<HEP events: public>>=
public :: lcio_event_from_particle_set
<<HEP events: procedures>>=
subroutine lcio_event_from_particle_set (evt, particle_set)
type(lcio_event_t), intent(inout) :: evt
type(particle_set_t), intent(in) :: particle_set
type(lcio_particle_t), dimension(:), allocatable :: lprt
type(particle_set_t), target :: pset_filtered
integer, dimension(:), allocatable :: parent
integer :: n_tot, i, j, n_beam, n_parents, type, beam_count
call particle_set%filter_particles ( pset_filtered, real_parents = .true. , &
keep_beams = .true. , keep_virtuals = .false.)
n_tot = pset_filtered%n_tot
n_beam = count (pset_filtered%prt%get_status () == PRT_BEAM)
if (n_beam == 0) then
type = PRT_INCOMING
else
type = PRT_BEAM
end if
beam_count = 0
allocate (lprt (n_tot))
do i = 1, n_tot
call particle_to_lcio (pset_filtered%prt(i), lprt(i))
n_parents = pset_filtered%prt(i)%get_n_parents ()
if (n_parents /= 0) then
allocate (parent (n_parents))
parent = pset_filtered%prt(i)%get_parents ()
do j = 1, n_parents
call lcio_particle_set_parent (lprt(i), lprt(parent(j)))
end do
deallocate (parent)
end if
if (pset_filtered%prt(i)%get_status () == type) then
beam_count = beam_count + 1
call lcio_event_set_beam &
(evt, pset_filtered%prt(i)%get_pdg (), beam_count)
end if
call lcio_particle_add_to_evt_coll (lprt(i), evt)
end do
call lcio_event_add_coll (evt)
end subroutine lcio_event_from_particle_set
@ %def lcio_event_from_particle_set
@ If a particle set is initialized from a LCIO event record, we have
to specify the treatment of polarization (unpolarized or density
matrix) which is common to all particles. Correlated polarization
information is not available.
<<HEP events: public>>=
public :: lcio_event_to_particle_set
<<HEP events: procedures>>=
subroutine lcio_event_to_particle_set &
(particle_set, evt, model, fallback_model, polarization)
type(particle_set_t), intent(inout), target :: particle_set
type(lcio_event_t), intent(in) :: evt
class(model_data_t), intent(in), target :: model, fallback_model
integer, intent(in) :: polarization
type(lcio_particle_t) :: prt
integer, dimension(:), allocatable :: parents, daughters
integer :: n_tot, i, j, n_parents, n_children
n_tot = lcio_event_get_n_tot (evt)
allocate (particle_set%prt (n_tot))
do i = 1, n_tot
prt = lcio_event_get_particle (evt, i-1)
n_parents = lcio_particle_get_n_parents (prt)
n_children = lcio_particle_get_n_children (prt)
allocate (daughters (n_children))
allocate (parents (n_parents))
if (n_children > 0) then
do j = 1, n_children
daughters(j) = lcio_get_n_children (evt,i,j)
end do
end if
if (n_parents > 0) then
do j = 1, n_parents
parents(j) = lcio_get_n_parents (evt,i,j)
end do
end if
call particle_from_lcio_particle (particle_set%prt(i), prt, model, &
daughters, parents, polarization)
deallocate (daughters, parents)
end do
do i = 1, n_tot
if (particle_set%prt(i)%get_status () == PRT_VIRTUAL) then
CHECK_BEAM: do j = 1, particle_set%prt(i)%get_n_parents ()
if (particle_set%prt(j)%get_status () == PRT_BEAM) &
call particle_set%prt(i)%set_status (PRT_INCOMING)
exit CHECK_BEAM
end do CHECK_BEAM
end if
end do
particle_set%n_tot = n_tot
particle_set%n_beam = &
count (particle_set%prt%get_status () == PRT_BEAM)
particle_set%n_in = &
count (particle_set%prt%get_status () == PRT_INCOMING)
particle_set%n_out = &
count (particle_set%prt%get_status () == PRT_OUTGOING)
particle_set%n_vir = &
particle_set%n_tot - particle_set%n_in - particle_set%n_out
end subroutine lcio_event_to_particle_set
@ %def lcio_event_to_particle_set
@
<<HEP events: public>>=
public :: lcio_to_event
<<HEP events: procedures>>=
subroutine lcio_to_event &
(event, lcio_event, fallback_model, process_index, recover_beams, &
use_alpha_s, use_scale)
class(generic_event_t), intent(inout), target :: event
type(lcio_event_t), intent(inout) :: lcio_event
class(model_data_t), intent(in), target :: fallback_model
integer, intent(out), optional :: process_index
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alpha_s
logical, intent(in), optional :: use_scale
class(model_data_t), pointer :: model
real(default) :: scale, alpha_qcd
type(particle_set_t) :: particle_set
model => event%get_model_ptr ()
call lcio_event_to_particle_set (particle_set, &
lcio_event, model, fallback_model, PRT_DEFINITE_HELICITY)
call event%set_hard_particle_set (particle_set)
call particle_set%final ()
call event%set_weight_ref (1._default)
alpha_qcd = lcio_event_get_alphas (lcio_event)
scale = lcio_event_get_scaleval (lcio_event)
if (present (use_alpha_s)) then
if (use_alpha_s .and. alpha_qcd > 0) &
call event%set_alpha_qcd_forced (alpha_qcd)
end if
if (present (use_scale)) then
if (use_scale .and. scale > 0) &
call event%set_scale_forced (scale)
end if
end subroutine lcio_to_event
@ %def lcio_to_event
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[hep_events_ut.f90]]>>=
<<File header>>
module hep_events_ut
use unit_tests
use hepmc_interface, only: HEPMC_IS_AVAILABLE
use system_dependencies, only: HEPMC2_AVAILABLE
use hep_events_uti
<<Standard module head>>
<<HEP events: public test>>
contains
<<HEP events: test driver>>
end module hep_events_ut
@ %def hep_events_ut
@
<<[[hep_events_uti.f90]]>>=
<<File header>>
module hep_events_uti
<<Use kinds>>
<<Use strings>>
use lorentz
use flavors
use colors
use helicities
use quantum_numbers
use state_matrices, only: FM_SELECT_HELICITY, FM_FACTOR_HELICITY
use interactions
use evaluators
use model_data
use particles
use subevents
use hepmc_interface
use hep_events
<<Standard module head>>
<<HEP events: test declarations>>
contains
<<HEP events: tests>>
end module hep_events_uti
@ %def hep_events_ut
@ API: driver for the unit tests below.
<<HEP events: public test>>=
public :: hep_events_test
<<HEP events: test driver>>=
subroutine hep_events_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<HEP events: execute tests>>
end subroutine hep_events_test
@ %def particles_test
@ If [[HepMC]] is available, check the routines via [[HepMC]].
Set up a chain of production and decay and factorize the result into
particles. The process is $d\bar d \to Z \to q\bar q$.
<<HEP events: execute tests>>=
if (hepmc_is_available ()) then
call test (hep_events_1, "hep_events_1", &
"check HepMC event routines", &
u, results)
end if
<<HEP events: test declarations>>=
public :: hep_events_1
<<HEP events: tests>>=
subroutine hep_events_1 (u)
use os_interface
integer, intent(in) :: u
type(model_data_t), target :: model
type(flavor_t), dimension(3) :: flv
type(color_t), dimension(3) :: col
type(helicity_t), dimension(3) :: hel
type(quantum_numbers_t), dimension(3) :: qn
type(vector4_t), dimension(3) :: p
type(interaction_t), target :: int1, int2
type(quantum_numbers_mask_t) :: qn_mask_conn
type(evaluator_t), target :: eval
type(interaction_t), pointer :: int
type(particle_set_t) :: particle_set1, particle_set2
type(hepmc_event_t) :: hepmc_event
type(hepmc_iostream_t) :: iostream
real(default) :: cross_section, error, weight
logical :: ok
write (u, "(A)") "* Test output: HEP events"
write (u, "(A)") "* Purpose: test HepMC event routines"
write (u, "(A)")
write (u, "(A)") "* Reading model file"
call model%init_sm_test ()
write (u, "(A)")
write (u, "(A)") "* Initializing production process"
call int1%basic_init (2, 0, 1, set_relations=.true.)
call flv%init ([1, -1, 23], model)
call col%init_col_acl ([0, 0, 0], [0, 0, 0])
call hel(3)%init ( 1, 1)
call qn%init (flv, col, hel)
call int1%add_state (qn, value=(0.25_default, 0._default))
call hel(3)%init ( 1,-1)
call qn%init (flv, col, hel)
call int1%add_state (qn, value=(0._default, 0.25_default))
call hel(3)%init (-1, 1)
call qn%init (flv, col, hel)
call int1%add_state (qn, value=(0._default,-0.25_default))
call hel(3)%init (-1,-1)
call qn%init (flv, col, hel)
call int1%add_state (qn, value=(0.25_default, 0._default))
call hel(3)%init ( 0, 0)
call qn%init (flv, col, hel)
call int1%add_state (qn, value=(0.5_default, 0._default))
call int1%freeze ()
p(1) = vector4_moving (45._default, 45._default, 3)
p(2) = vector4_moving (45._default,-45._default, 3)
p(3) = p(1) + p(2)
call int1%set_momenta (p)
write (u, "(A)")
write (u, "(A)") "* Setup decay process"
call int2%basic_init (1, 0, 2, set_relations=.true.)
call flv%init ([23, 1, -1], model)
call col%init_col_acl ([0, 501, 0], [0, 0, 501])
call hel%init ([1, 1, 1], [1, 1, 1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(1._default, 0._default))
call hel%init ([1, 1, 1], [-1,-1,-1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(0._default, 0.1_default))
call hel%init ([-1,-1,-1], [1, 1, 1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(0._default,-0.1_default))
call hel%init ([-1,-1,-1], [-1,-1,-1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(1._default, 0._default))
call hel%init ([0, 1,-1], [0, 1,-1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(4._default, 0._default))
call hel%init ([0,-1, 1], [0, 1,-1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(2._default, 0._default))
call hel%init ([0, 1,-1], [0,-1, 1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(2._default, 0._default))
call hel%init ([0,-1, 1], [0,-1, 1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(4._default, 0._default))
call flv%init ([23, 2, -2], model)
call hel%init ([0, 1,-1], [0, 1,-1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(0.5_default, 0._default))
call hel%init ([0,-1, 1], [0,-1, 1])
call qn%init (flv, col, hel)
call int2%add_state (qn, value=(0.5_default, 0._default))
call int2%freeze ()
p(2) = vector4_moving (45._default, 45._default, 2)
p(3) = vector4_moving (45._default,-45._default, 2)
call int2%set_momenta (p)
call int2%set_source_link (1, int1, 3)
call int1%basic_write (u)
call int2%basic_write (u)
write (u, "(A)")
write (u, "(A)") "* Concatenate production and decay"
call eval%init_product (int1, int2, qn_mask_conn, &
connections_are_resonant=.true.)
call eval%receive_momenta ()
call eval%evaluate ()
call eval%write (u)
write (u, "(A)")
write (u, "(A)") "* Factorize as subevent (complete, polarized)"
write (u, "(A)")
int => eval%interaction_t
call particle_set1%init &
(ok, int, int, FM_FACTOR_HELICITY, &
[0.2_default, 0.2_default], .false., .true.)
call particle_set1%write (u)
write (u, "(A)")
write (u, "(A)") "* Factorize as subevent (in/out only, selected helicity)"
write (u, "(A)")
int => eval%interaction_t
call particle_set2%init &
(ok, int, int, FM_SELECT_HELICITY, &
[0.9_default, 0.9_default], .false., .false.)
call particle_set2%write (u)
call particle_set2%final ()
write (u, "(A)")
write (u, "(A)") "* Factorize as subevent (complete, selected helicity)"
write (u, "(A)")
int => eval%interaction_t
call particle_set2%init &
(ok, int, int, FM_SELECT_HELICITY, &
[0.7_default, 0.7_default], .false., .true.)
call particle_set2%write (u)
write (u, "(A)")
write (u, "(A)") "* Transfer particle_set to HepMC, print, and output to"
write (u, "(A)") " hep_events.hepmc.dat"
write (u, "(A)")
cross_section = 42.0_default
error = 17.0_default
weight = 1.0_default
call hepmc_event_init (hepmc_event, 11, 127)
call hepmc_event_from_particle_set (hepmc_event, particle_set2, &
cross_section, error)
call hepmc_event_add_weight (hepmc_event, weight)
call hepmc_event_print (hepmc_event)
call hepmc_iostream_open_out &
(iostream , var_str ("hep_events.hepmc.dat"))
call hepmc_iostream_write_event (iostream, hepmc_event)
call hepmc_iostream_close (iostream)
write (u, "(A)")
write (u, "(A)") "* Recover from HepMC file"
write (u, "(A)")
call particle_set2%final ()
call hepmc_event_final (hepmc_event)
call hepmc_event_init (hepmc_event)
call hepmc_iostream_open_in &
(iostream , var_str ("hep_events.hepmc.dat"))
call hepmc_iostream_read_event (iostream, hepmc_event, ok=ok)
call hepmc_iostream_close (iostream)
call hepmc_event_to_particle_set (particle_set2, &
hepmc_event, model, model, PRT_DEFINITE_HELICITY)
call particle_set2%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call particle_set1%final ()
call particle_set2%final ()
call eval%final ()
call int1%final ()
call int2%final ()
call hepmc_event_final (hepmc_event)
call model%final ()
write (u, "(A)")
write (u, "(A)") "* Test output end: hep_events_1"
end subroutine hep_events_1
@
@ %def hep_events_1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{LHEF Input/Output}
The LHEF event record is standardized. It is an ASCII format. We try
our best at using it for both input and output.
<<[[eio_lhef.f90]]>>=
<<File header>>
module eio_lhef
<<Use kinds>>
<<Use strings>>
use io_units
use string_utils
use numeric_utils
use diagnostics
use os_interface
use xml
use event_base
use eio_data
use eio_base
use hep_common
use hep_events
<<Standard module head>>
<<EIO LHEF: public>>
<<EIO LHEF: types>>
contains
<<EIO LHEF: procedures>>
end module eio_lhef
@ %def eio_lhef
@
\subsection{Type}
With sufficient confidence that it will always be three characters, we
can store the version string with a default value.
<<EIO LHEF: public>>=
public :: eio_lhef_t
<<EIO LHEF: types>>=
type, extends (eio_t) :: eio_lhef_t
logical :: writing = .false.
logical :: reading = .false.
integer :: unit = 0
type(event_sample_data_t) :: data
type(cstream_t) :: cstream
character(3) :: version = "1.0"
logical :: keep_beams = .false.
logical :: keep_remnants = .true.
logical :: keep_virtuals = .false.
logical :: recover_beams = .true.
logical :: unweighted = .true.
logical :: write_sqme_ref = .false.
logical :: write_sqme_prc = .false.
logical :: write_sqme_alt = .false.
logical :: use_alphas_from_file = .false.
logical :: use_scale_from_file = .false.
integer :: n_alt = 0
integer, dimension(:), allocatable :: proc_num_id
integer :: i_weight_sqme = 0
type(xml_tag_t) :: tag_lhef, tag_head, tag_init, tag_event
type(xml_tag_t), allocatable :: tag_gen_n, tag_gen_v
type(xml_tag_t), allocatable :: tag_generator, tag_xsecinfo
type(xml_tag_t), allocatable :: tag_sqme_ref, tag_sqme_prc
type(xml_tag_t), dimension(:), allocatable :: tag_sqme_alt, tag_wgts_alt
type(xml_tag_t), allocatable :: tag_weight, tag_weightinfo, tag_weights
contains
<<EIO LHEF: eio lhef: TBP>>
end type eio_lhef_t
@ %def eio_lhef_t
@
\subsection{Specific Methods}
Set parameters that are specifically used with LHEF.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: set_parameters => eio_lhef_set_parameters
<<EIO LHEF: procedures>>=
subroutine eio_lhef_set_parameters (eio, &
keep_beams, keep_remnants, recover_beams, &
use_alphas_from_file, use_scale_from_file, &
version, extension, write_sqme_ref, write_sqme_prc, write_sqme_alt)
class(eio_lhef_t), intent(inout) :: eio
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alphas_from_file
logical, intent(in), optional :: use_scale_from_file
character(*), intent(in), optional :: version
type(string_t), intent(in), optional :: extension
logical, intent(in), optional :: write_sqme_ref
logical, intent(in), optional :: write_sqme_prc
logical, intent(in), optional :: write_sqme_alt
if (present (keep_beams)) eio%keep_beams = keep_beams
if (present (keep_remnants)) eio%keep_remnants = keep_remnants
if (present (recover_beams)) eio%recover_beams = recover_beams
if (present (use_alphas_from_file)) &
eio%use_alphas_from_file = use_alphas_from_file
if (present (use_scale_from_file)) &
eio%use_scale_from_file = use_scale_from_file
if (present (version)) then
select case (version)
case ("1.0", "2.0", "3.0")
eio%version = version
case default
call msg_error ("LHEF version " // version &
// " is not supported. Inserting 2.0")
eio%version = "2.0"
end select
end if
if (present (extension)) then
eio%extension = extension
else
eio%extension = "lhe"
end if
if (present (write_sqme_ref)) eio%write_sqme_ref = write_sqme_ref
if (present (write_sqme_prc)) eio%write_sqme_prc = write_sqme_prc
if (present (write_sqme_alt)) eio%write_sqme_alt = write_sqme_alt
end subroutine eio_lhef_set_parameters
@ %def eio_lhef_set_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: write => eio_lhef_write
<<EIO LHEF: procedures>>=
subroutine eio_lhef_write (object, unit)
class(eio_lhef_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit)
write (u, "(1x,A)") "LHEF event stream:"
if (object%writing) then
write (u, "(3x,A,A)") "Writing to file = ", char (object%filename)
else if (object%reading) then
write (u, "(3x,A,A)") "Reading from file = ", char (object%filename)
else
write (u, "(3x,A)") "[closed]"
end if
write (u, "(3x,A,L1)") "Keep beams = ", object%keep_beams
write (u, "(3x,A,L1)") "Keep remnants = ", object%keep_remnants
write (u, "(3x,A,L1)") "Recover beams = ", object%recover_beams
write (u, "(3x,A,L1)") "Alpha_s from file = ", &
object%use_alphas_from_file
write (u, "(3x,A,L1)") "Scale from file = ", &
object%use_scale_from_file
write (u, "(3x,A,A)") "Version = ", object%version
write (u, "(3x,A,A,A)") "File extension = '", &
char (object%extension), "'"
if (allocated (object%proc_num_id)) then
write (u, "(3x,A)") "Numerical process IDs:"
do i = 1, size (object%proc_num_id)
write (u, "(5x,I0,': ',I0)") i, object%proc_num_id(i)
end do
end if
end subroutine eio_lhef_write
@ %def eio_lhef_write
@ Finalizer: close any open file.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: final => eio_lhef_final
<<EIO LHEF: procedures>>=
subroutine eio_lhef_final (object)
class(eio_lhef_t), intent(inout) :: object
if (allocated (object%proc_num_id)) deallocate (object%proc_num_id)
if (object%writing) then
write (msg_buffer, "(A,A,A)") "Events: closing LHEF file '", &
char (object%filename), "'"
call msg_message ()
call object%write_footer ()
close (object%unit)
object%writing = .false.
else if (object%reading) then
write (msg_buffer, "(A,A,A)") "Events: closing LHEF file '", &
char (object%filename), "'"
call msg_message ()
call object%cstream%final ()
close (object%unit)
object%reading = .false.
end if
end subroutine eio_lhef_final
@ %def eio_lhef_final
@ Common initialization for input and output.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: common_init => eio_lhef_common_init
<<EIO LHEF: procedures>>=
subroutine eio_lhef_common_init (eio, sample, data, extension)
class(eio_lhef_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
if (.not. present (data)) &
call msg_bug ("LHEF initialization: missing data")
eio%data = data
if (data%n_beam /= 2) &
call msg_fatal ("LHEF: defined for scattering processes only")
eio%unweighted = data%unweighted
if (eio%unweighted) then
select case (data%norm_mode)
case (NORM_UNIT)
case default; call msg_fatal &
("LHEF: normalization for unweighted events must be '1'")
end select
else
select case (data%norm_mode)
case (NORM_SIGMA)
case default; call msg_fatal &
("LHEF: normalization for weighted events must be 'sigma'")
end select
end if
eio%n_alt = data%n_alt
eio%sample = sample
if (present (extension)) then
eio%extension = extension
end if
call eio%set_filename ()
eio%unit = free_unit ()
call eio%init_tags (data)
allocate (eio%proc_num_id (data%n_proc), source = data%proc_num_id)
end subroutine eio_lhef_common_init
@ %def eio_lhef_common_init
@ Initialize the tag objects. Some tags depend on the LHEF
version. In particular, the tags that in LHEF 2.0 identify
individual weights by name in each event block, in LHEF 3.0 are
replaced by info tags in the init block and a single \texttt{weights}
tag in the event block. The name attributes of those tags
are specific for \whizard.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: init_tags => eio_lhef_init_tags
<<EIO LHEF: procedures>>=
subroutine eio_lhef_init_tags (eio, data)
class(eio_lhef_t), intent(inout) :: eio
type(event_sample_data_t), intent(in) :: data
real(default), parameter :: pb_per_fb = 1.e-3_default
integer :: i
call eio%tag_lhef%init ( &
var_str ("LesHouchesEvents"), &
[xml_attribute (var_str ("version"), var_str (eio%version))], &
.true.)
call eio%tag_head%init ( &
var_str ("header"), &
.true.)
call eio%tag_init%init ( &
var_str ("init"), &
.true.)
call eio%tag_event%init (var_str ("event"), &
.true.)
select case (eio%version)
case ("1.0")
allocate (eio%tag_gen_n)
call eio%tag_gen_n%init ( &
var_str ("generator_name"), &
.true.)
allocate (eio%tag_gen_v)
call eio%tag_gen_v%init ( &
var_str ("generator_version"), &
.true.)
end select
select case (eio%version)
case ("2.0", "3.0")
allocate (eio%tag_generator)
call eio%tag_generator%init ( &
var_str ("generator"), &
[xml_attribute (var_str ("version"), var_str ("<<Version>>"))], &
.true.)
allocate (eio%tag_xsecinfo)
call eio%tag_xsecinfo%init ( &
var_str ("xsecinfo"), &
[xml_attribute (var_str ("neve"), str (data%n_evt)), &
xml_attribute (var_str ("totxsec"), &
str (data%total_cross_section * pb_per_fb))])
end select
select case (eio%version)
case ("2.0")
allocate (eio%tag_weight)
call eio%tag_weight%init (var_str ("weight"), &
[xml_attribute (var_str ("name"))])
if (eio%write_sqme_ref) then
allocate (eio%tag_sqme_ref)
call eio%tag_sqme_ref%init (var_str ("weight"), &
[xml_attribute (var_str ("name"), var_str ("sqme_ref"))], &
.true.)
end if
if (eio%write_sqme_prc) then
allocate (eio%tag_sqme_prc)
call eio%tag_sqme_prc%init (var_str ("weight"), &
[xml_attribute (var_str ("name"), var_str ("sqme_prc"))], &
.true.)
end if
if (eio%n_alt > 0) then
if (eio%write_sqme_alt) then
allocate (eio%tag_sqme_alt (1))
call eio%tag_sqme_alt(1)%init (var_str ("weight"), &
[xml_attribute (var_str ("name"), var_str ("sqme_alt"))], &
.true.)
end if
allocate (eio%tag_wgts_alt (1))
call eio%tag_wgts_alt(1)%init (var_str ("weight"), &
[xml_attribute (var_str ("name"), var_str ("wgts_alt"))], &
.true.)
end if
case ("3.0")
if (eio%write_sqme_ref) then
allocate (eio%tag_sqme_ref)
call eio%tag_sqme_ref%init (var_str ("weightinfo"), &
[xml_attribute (var_str ("name"), var_str ("sqme_ref"))])
end if
if (eio%write_sqme_prc) then
allocate (eio%tag_sqme_prc)
call eio%tag_sqme_prc%init (var_str ("weightinfo"), &
[xml_attribute (var_str ("name"), var_str ("sqme_prc"))])
end if
if (eio%n_alt > 0) then
if (eio%write_sqme_alt) then
allocate (eio%tag_sqme_alt (eio%n_alt))
do i = 1, eio%n_alt
call eio%tag_sqme_alt(i)%init (var_str ("weightinfo"), &
[xml_attribute (var_str ("name"), &
var_str ("sqme_alt") // str (i))])
end do
end if
allocate (eio%tag_wgts_alt (eio%n_alt))
do i = 1, eio%n_alt
call eio%tag_wgts_alt(i)%init (var_str ("weightinfo"), &
[xml_attribute (var_str ("name"), &
var_str ("wgts_alt") // str (i))])
end do
end if
allocate (eio%tag_weightinfo)
call eio%tag_weightinfo%init (var_str ("weightinfo"), &
[xml_attribute (var_str ("name"))])
allocate (eio%tag_weights)
call eio%tag_weights%init (var_str ("weights"), .true.)
end select
end subroutine eio_lhef_init_tags
@ %def eio_lhef_init_tags
@ Initialize event writing.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: init_out => eio_lhef_init_out
<<EIO LHEF: procedures>>=
subroutine eio_lhef_init_out (eio, sample, data, success, extension)
class(eio_lhef_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
integer :: u, i
call eio%set_splitting (data)
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: writing to LHEF file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
u = eio%unit
open (u, file = char (eio%filename), &
action = "write", status = "replace")
call eio%write_header ()
call heprup_init &
(data%pdg_beam, &
data%energy_beam, &
n_processes = data%n_proc, &
unweighted = data%unweighted, &
negative_weights = data%negative_weights)
do i = 1, data%n_proc
call heprup_set_process_parameters (i = i, &
process_id = data%proc_num_id(i), &
cross_section = data%cross_section(i), &
error = data%error(i))
end do
call eio%tag_init%write (u); write (u, *)
call heprup_write_lhef (u)
select case (eio%version)
case ("2.0"); call eio%write_init_20 (data)
case ("3.0"); call eio%write_init_30 (data)
end select
call eio%tag_init%close (u); write (u, *)
if (present (success)) success = .true.
end subroutine eio_lhef_init_out
@ %def eio_lhef_init_out
@ Initialize event reading. First read the LHEF tag and version, then
read the header and skip over its contents, then read the init block.
(We require the opening and closing tags of the init block to be placed
on separate lines without extra stuff.)
For input, we do not (yet?) support split event files.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: init_in => eio_lhef_init_in
<<EIO LHEF: procedures>>=
subroutine eio_lhef_init_in (eio, sample, data, success, extension)
class(eio_lhef_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
logical :: exist, ok, closing
type(event_sample_data_t) :: data_file
type(string_t) :: string
integer :: u
eio%split = .false.
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: reading from LHEF file '", &
char (eio%filename), "'"
call msg_message ()
inquire (file = char (eio%filename), exist = exist)
if (.not. exist) call msg_fatal ("Events: LHEF file not found.")
eio%reading = .true.
u = eio%unit
open (u, file = char (eio%filename), &
action = "read", status = "old")
call eio%cstream%init (u)
call eio%read_header ()
call eio%tag_init%read (eio%cstream, ok)
if (.not. ok) call err_init
select case (eio%version)
case ("1.0"); call eio%read_init_10 (data_file)
call eio%tag_init%read_content (eio%cstream, string, closing)
if (string /= "" .or. .not. closing) call err_init
case ("2.0"); call eio%read_init_20 (data_file)
case ("3.0"); call eio%read_init_30 (data_file)
end select
call eio%merge_data (data, data_file)
if (present (success)) success = .true.
contains
subroutine err_init
call msg_fatal ("LHEF: syntax error in init tag")
end subroutine err_init
end subroutine eio_lhef_init_in
@ %def eio_lhef_init_in
@ Merge event sample data: we can check the data in the file against
our assumptions and set or reset parameters.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: merge_data => eio_merge_data
<<EIO LHEF: procedures>>=
subroutine eio_merge_data (eio, data, data_file)
class(eio_lhef_t), intent(inout) :: eio
type(event_sample_data_t), intent(inout) :: data
type(event_sample_data_t), intent(in) :: data_file
real, parameter :: tolerance = 1000 * epsilon (1._default)
if (data%unweighted .neqv. data_file%unweighted) call err_weights
if (data%negative_weights .neqv. data_file%negative_weights) &
call err_weights
if (data%norm_mode /= data_file%norm_mode) call err_norm
if (data%n_beam /= data_file%n_beam) call err_beams
if (any (data%pdg_beam /= data_file%pdg_beam)) call err_beams
if (any (abs ((data%energy_beam - data_file%energy_beam)) &
> (data%energy_beam + data_file%energy_beam) * tolerance)) &
call err_beams
if (data%n_proc /= data_file%n_proc) call err_proc
if (any (data%proc_num_id /= data_file%proc_num_id)) call err_proc
where (data%cross_section == 0)
data%cross_section = data_file%cross_section
data%error = data_file%error
end where
data%total_cross_section = sum (data%cross_section)
if (data_file%n_evt > 0) then
if (data%n_evt > 0 .and. data_file%n_evt /= data%n_evt) call err_n_evt
data%n_evt = data_file%n_evt
end if
contains
subroutine err_weights
call msg_fatal ("LHEF: mismatch in event weight properties")
end subroutine err_weights
subroutine err_norm
call msg_fatal ("LHEF: mismatch in event normalization")
end subroutine err_norm
subroutine err_beams
call msg_fatal ("LHEF: mismatch in beam properties")
end subroutine err_beams
subroutine err_proc
call msg_fatal ("LHEF: mismatch in process definitions")
end subroutine err_proc
subroutine err_n_evt
call msg_error ("LHEF: mismatch in specified number of events (ignored)")
end subroutine err_n_evt
end subroutine eio_merge_data
@ %def eio_merge_data
@ Switch from input to output: reopen the file for reading.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: switch_inout => eio_lhef_switch_inout
<<EIO LHEF: procedures>>=
subroutine eio_lhef_switch_inout (eio, success)
class(eio_lhef_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("LHEF: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_lhef_switch_inout
@ %def eio_lhef_switch_inout
@ Split event file: increment the counter, close the current file, open a new
one. If the file needs a header, repeat it for the new file. (We assume that
the common block contents are still intact.)
<<EIO LHEF: eio lhef: TBP>>=
procedure :: split_out => eio_lhef_split_out
<<EIO LHEF: procedures>>=
subroutine eio_lhef_split_out (eio)
class(eio_lhef_t), intent(inout) :: eio
integer :: u
if (eio%split) then
eio%split_index = eio%split_index + 1
call eio%set_filename ()
write (msg_buffer, "(A,A,A)") "Events: writing to LHEF file '", &
char (eio%filename), "'"
call msg_message ()
call eio%write_footer ()
u = eio%unit
close (u)
open (u, file = char (eio%filename), &
action = "write", status = "replace")
call eio%write_header ()
call eio%tag_init%write (u); write (u, *)
call heprup_write_lhef (u)
select case (eio%version)
case ("2.0"); call eio%write_init_20 (eio%data)
case ("3.0"); call eio%write_init_30 (eio%data)
end select
call eio%tag_init%close (u); write (u, *)
end if
end subroutine eio_lhef_split_out
@ %def eio_lhef_split_out
@ Output an event. Write first the event indices, then weight and
squared matrix element, then the particle set.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: output => eio_lhef_output
<<EIO LHEF: procedures>>=
subroutine eio_lhef_output (eio, event, i_prc, reading, passed, pacify)
class(eio_lhef_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
integer :: u
u = given_output_unit (eio%unit); if (u < 0) return
if (present (passed)) then
if (.not. passed) return
end if
if (eio%writing) then
call hepeup_from_event (event, &
process_index = eio%proc_num_id (i_prc), &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants)
write (u, '(A)') "<event>"
call hepeup_write_lhef (eio%unit)
select case (eio%version)
case ("2.0"); call eio%write_event_20 (event)
case ("3.0"); call eio%write_event_30 (event)
end select
write (u, '(A)') "</event>"
else
call eio%write ()
call msg_fatal ("LHEF file is not open for writing")
end if
end subroutine eio_lhef_output
@ %def eio_lhef_output
@ Input an event. Upon input of [[i_prc]], we can just read in the
whole HEPEUP common block. These data are known to come first. The
[[i_prc]] value can be deduced from the IDPRUP value by a table
lookup.
Reading the common block bypasses the [[cstream]] which accesses the
input unit. This is consistent with the LHEF specification. After
the common-block data have been swallowed, we can resume reading from
stream.
We don't catch actual I/O errors. However, we return a negative value in
[[iostat]] if we reached the terminating [[</LesHouchesEvents>]] tag.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: input_i_prc => eio_lhef_input_i_prc
<<EIO LHEF: procedures>>=
subroutine eio_lhef_input_i_prc (eio, i_prc, iostat)
class(eio_lhef_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
integer :: i, proc_num_id
type(string_t) :: s
logical :: ok
iostat = 0
call eio%tag_lhef%read_content (eio%cstream, s, ok)
if (ok) then
if (s == "") then
iostat = -1
else
call err_close
end if
return
else
call eio%cstream%revert_record (s)
end if
call eio%tag_event%read (eio%cstream, ok)
if (.not. ok) then
call err_evt1
return
end if
call hepeup_read_lhef (eio%unit)
call hepeup_get_event_parameters (proc_id = proc_num_id)
i_prc = 0
FIND_I_PRC: do i = 1, size (eio%proc_num_id)
if (eio%proc_num_id(i) == proc_num_id) then
i_prc = i
exit FIND_I_PRC
end if
end do FIND_I_PRC
if (i_prc == 0) call err_index
contains
subroutine err_close
call msg_error ("LHEF: reading events: syntax error in closing tag")
iostat = 1
end subroutine
subroutine err_evt1
call msg_error ("LHEF: reading events: invalid event tag, &
&aborting read")
iostat = 2
end subroutine err_evt1
subroutine err_index
call msg_error ("LHEF: reading events: undefined process ID " &
// char (str (proc_num_id)) // ", aborting read")
iostat = 3
end subroutine err_index
end subroutine eio_lhef_input_i_prc
@ %def eio_lhef_input_i_prc
@ Since we have already read the event information from file, this
input routine can transfer the common-block contents to the event
record. Also, we read any further information in the event record.
Since LHEF doesn't give this information, we must assume that the MCI
group, term, and channel can all be safely set to 1. This works if
there is only one MCI group and term. The channel doesn't matter for
the matrix element.
The event index is incremented, as if the event was generated. The
LHEF format does not support event indices.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: input_event => eio_lhef_input_event
<<EIO LHEF: procedures>>=
subroutine eio_lhef_input_event (eio, event, iostat)
class(eio_lhef_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
type(string_t) :: s
logical :: closing
iostat = 0
call event%reset_contents ()
call event%select (1, 1, 1)
call hepeup_to_event (event, eio%fallback_model, &
recover_beams = eio%recover_beams, &
use_alpha_s = eio%use_alphas_from_file, &
use_scale = eio%use_scale_from_file)
select case (eio%version)
case ("1.0")
call eio%tag_event%read_content (eio%cstream, s, closing = closing)
if (s /= "" .or. .not. closing) call err_evt2
case ("2.0"); call eio%read_event_20 (event)
case ("3.0"); call eio%read_event_30 (event)
end select
call event%increment_index ()
contains
subroutine err_evt2
call msg_error ("LHEF: reading events: syntax error in event record, &
&aborting read")
iostat = 2
end subroutine err_evt2
end subroutine eio_lhef_input_event
@ %def eio_lhef_input_event
@
<<EIO LHEF: eio lhef: TBP>>=
procedure :: skip => eio_lhef_skip
<<EIO LHEF: procedures>>=
subroutine eio_lhef_skip (eio, iostat)
class(eio_lhef_t), intent(inout) :: eio
integer, intent(out) :: iostat
if (eio%reading) then
read (eio%unit, iostat = iostat)
else
call eio%write ()
call msg_fatal ("Raw event file is not open for reading")
end if
end subroutine eio_lhef_skip
@ %def eio_lhef_skip
@
\subsection{Les Houches Event File: header/footer}
These two routines write the header and footer for the Les Houches
Event File format (LHEF).
The current version writes no information except for the generator
name and version (v.1.0 only).
<<EIO LHEF: eio lhef: TBP>>=
procedure :: write_header => eio_lhef_write_header
procedure :: write_footer => eio_lhef_write_footer
<<EIO LHEF: procedures>>=
subroutine eio_lhef_write_header (eio)
class(eio_lhef_t), intent(in) :: eio
integer :: u
u = given_output_unit (eio%unit); if (u < 0) return
call eio%tag_lhef%write (u); write (u, *)
call eio%tag_head%write (u); write (u, *)
select case (eio%version)
case ("1.0")
write (u, "(2x)", advance = "no")
call eio%tag_gen_n%write (var_str ("WHIZARD"), u)
write (u, *)
write (u, "(2x)", advance = "no")
call eio%tag_gen_v%write (var_str ("<<Version>>"), u)
write (u, *)
end select
call eio%tag_head%close (u); write (u, *)
end subroutine eio_lhef_write_header
subroutine eio_lhef_write_footer (eio)
class(eio_lhef_t), intent(in) :: eio
integer :: u
u = given_output_unit (eio%unit); if (u < 0) return
call eio%tag_lhef%close (u)
end subroutine eio_lhef_write_footer
@ %def eio_lhef_write_header eio_lhef_write_footer
@ Reading the header just means finding the tags and ignoring any
contents. When done, we should stand just after the header tag.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: read_header => eio_lhef_read_header
<<EIO LHEF: procedures>>=
subroutine eio_lhef_read_header (eio)
class(eio_lhef_t), intent(inout) :: eio
logical :: success, closing
type(string_t) :: content
call eio%tag_lhef%read (eio%cstream, success)
if (.not. success .or. .not. eio%tag_lhef%has_content) call err_lhef
if (eio%tag_lhef%get_attribute (1) /= eio%version) call err_version
call eio%tag_head%read (eio%cstream, success)
if (.not. success) call err_header
if (eio%tag_head%has_content) then
SKIP_HEADER_CONTENT: do
call eio%tag_head%read_content (eio%cstream, content, closing)
if (closing) exit SKIP_HEADER_CONTENT
end do SKIP_HEADER_CONTENT
end if
contains
subroutine err_lhef
call msg_fatal ("LHEF: LesHouchesEvents tag absent or corrupted")
end subroutine err_lhef
subroutine err_header
call msg_fatal ("LHEF: header tag absent or corrupted")
end subroutine err_header
subroutine err_version
call msg_error ("LHEF: version mismatch: expected " &
// eio%version // ", found " &
// char (eio%tag_lhef%get_attribute (1)))
end subroutine err_version
end subroutine eio_lhef_read_header
@ %def eio_lhef_read_header
@
\subsection{Version-Specific Code: 1.0}
In version 1.0, the init tag contains just HEPRUP data. While a
[[cstream]] is connected to the input unit, we bypass it temporarily
for the purpose of reading the HEPRUP contents. This is consistent
with the LHEF standard.
This routine does not read the closing tag of the init block.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: read_init_10 => eio_lhef_read_init_10
<<EIO LHEF: procedures>>=
subroutine eio_lhef_read_init_10 (eio, data)
class(eio_lhef_t), intent(in) :: eio
type(event_sample_data_t), intent(out) :: data
integer :: n_proc, i
call heprup_read_lhef (eio%unit)
call heprup_get_run_parameters (n_processes = n_proc)
call data%init (n_proc)
data%n_beam = 2
call heprup_get_run_parameters ( &
unweighted = data%unweighted, &
negative_weights = data%negative_weights, &
beam_pdg = data%pdg_beam, &
beam_energy = data%energy_beam)
if (data%unweighted) then
data%norm_mode = NORM_UNIT
else
data%norm_mode = NORM_SIGMA
end if
do i = 1, n_proc
call heprup_get_process_parameters (i, &
process_id = data%proc_num_id(i), &
cross_section = data%cross_section(i), &
error = data%error(i))
end do
end subroutine eio_lhef_read_init_10
@ %def eio_lhef_read_init_10
@
\subsection{Version-Specific Code: 2.0}
This is the init information for the 2.0 format, after the HEPRUP
data. We have the following tags:
\begin{itemize}
\item \texttt{generator} Generator name and version.
\item \texttt{xsecinfo} Cross section and weights data. We have the
total cross section and number of events (assuming that the event
file is intact), but information on minimum and maximum weights is
not available before the file is complete. We just write the
mandatory tags. (Note that the default values of the other tags
describe a uniform unit weight, but we can determine most values
only after the sample is complete.)
\item \texttt{cutsinfo} This optional tag is too specific to represent the
possibilities of WHIZARD, so we skip it.
\item \texttt{procinfo} This optional tag is useful for giving
details of NLO calculations. Skipped.
\item \texttt{mergetype} Optional, also not applicable.
\end{itemize}
<<EIO LHEF: eio lhef: TBP>>=
procedure :: write_init_20 => eio_lhef_write_init_20
<<EIO LHEF: procedures>>=
subroutine eio_lhef_write_init_20 (eio, data)
class(eio_lhef_t), intent(in) :: eio
type(event_sample_data_t), intent(in) :: data
integer :: u
u = eio%unit
call eio%tag_generator%write (u)
write (u, "(A)", advance="no") "WHIZARD"
call eio%tag_generator%close (u); write (u, *)
call eio%tag_xsecinfo%write (u); write (u, *)
end subroutine eio_lhef_write_init_20
@ %def eio_lhef_write_init_20
@ When reading the init block, we first call the 1.0 routine that
fills HEPRUP. Then we consider the possible tags. Only the
\texttt{generator} and \texttt{xsecinfo} tags are of interest. We
skip everything else except for the closing tag.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: read_init_20 => eio_lhef_read_init_20
<<EIO LHEF: procedures>>=
subroutine eio_lhef_read_init_20 (eio, data)
class(eio_lhef_t), intent(inout) :: eio
type(event_sample_data_t), intent(out) :: data
real(default), parameter :: pb_per_fb = 1.e-3_default
type(string_t) :: content
logical :: found, closing
call eio_lhef_read_init_10 (eio, data)
SCAN_INIT_TAGS: do
call eio%tag_generator%read (eio%cstream, found)
if (found) then
if (.not. eio%tag_generator%has_content) call err_generator
call eio%tag_generator%read_content (eio%cstream, content, closing)
call msg_message ("LHEF: Event file has been generated by " &
// char (content) // " " &
// char (eio%tag_generator%get_attribute (1)))
cycle SCAN_INIT_TAGS
end if
call eio%tag_xsecinfo%read (eio%cstream, found)
if (found) then
if (eio%tag_xsecinfo%has_content) call err_xsecinfo
cycle SCAN_INIT_TAGS
end if
call eio%tag_init%read_content (eio%cstream, content, closing)
if (closing) then
if (content /= "") call err_init
exit SCAN_INIT_TAGS
end if
end do SCAN_INIT_TAGS
data%n_evt = &
read_ival (eio%tag_xsecinfo%get_attribute (1))
data%total_cross_section = &
read_rval (eio%tag_xsecinfo%get_attribute (2)) / pb_per_fb
contains
subroutine err_generator
call msg_fatal ("LHEF: invalid generator tag")
end subroutine err_generator
subroutine err_xsecinfo
call msg_fatal ("LHEF: invalid xsecinfo tag")
end subroutine err_xsecinfo
subroutine err_init
call msg_fatal ("LHEF: syntax error after init tag")
end subroutine err_init
end subroutine eio_lhef_read_init_20
@ %def eio_lhef_read_init_20
@ This is additional event-specific information for the 2.0 format,
after the HEPEUP data. We can specify weights, starting from the
master weight and adding alternative weights. The alternative weights
are collected in a common tag.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: write_event_20 => eio_lhef_write_event_20
<<EIO LHEF: procedures>>=
subroutine eio_lhef_write_event_20 (eio, event)
class(eio_lhef_t), intent(in) :: eio
class(generic_event_t), intent(in) :: event
type(string_t) :: s
integer :: i, u
u = eio%unit
if (eio%write_sqme_ref) then
s = str (event%get_sqme_ref ())
call eio%tag_sqme_ref%write (s, u); write (u, *)
end if
if (eio%write_sqme_prc) then
s = str (event%get_sqme_prc ())
call eio%tag_sqme_prc%write (s, u); write (u, *)
end if
if (eio%n_alt > 0) then
if (eio%write_sqme_alt) then
s = str (event%get_sqme_alt(1))
do i = 2, eio%n_alt
s = s // " " // str (event%get_sqme_alt(i)); write (u, *)
end do
call eio%tag_sqme_alt(1)%write (s, u)
end if
s = str (event%get_weight_alt(1))
do i = 2, eio%n_alt
s = s // " " // str (event%get_weight_alt(i)); write (u, *)
end do
call eio%tag_wgts_alt(1)%write (s, u)
end if
end subroutine eio_lhef_write_event_20
@ %def eio_lhef_write_event_20
@ Read extra event data. If there is a weight entry labeled [[sqme_prc]], we
take this as the squared matrix-element value (the new
\emph{reference} value [[sqme_ref]]). Other tags, including
tags written by the above writer, are skipped.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: read_event_20 => eio_lhef_read_event_20
<<EIO LHEF: procedures>>=
subroutine eio_lhef_read_event_20 (eio, event)
class(eio_lhef_t), intent(inout) :: eio
class(generic_event_t), intent(inout) :: event
type(string_t) :: content
logical :: found, closing
SCAN_EVENT_TAGS: do
call eio%tag_weight%read (eio%cstream, found)
if (found) then
if (.not. eio%tag_weight%has_content) call err_weight
call eio%tag_weight%read_content (eio%cstream, content, closing)
if (.not. closing) call err_weight
if (eio%tag_weight%get_attribute (1) == "sqme_prc") then
call event%set_sqme_ref (read_rval (content))
end if
cycle SCAN_EVENT_TAGS
end if
call eio%tag_event%read_content (eio%cstream, content, closing)
if (closing) then
if (content /= "") call err_event
exit SCAN_EVENT_TAGS
end if
end do SCAN_EVENT_TAGS
contains
subroutine err_weight
call msg_fatal ("LHEF: invalid weight tag in event record")
end subroutine err_weight
subroutine err_event
call msg_fatal ("LHEF: syntax error after event tag")
end subroutine err_event
end subroutine eio_lhef_read_event_20
@ %def eio_lhef_read_event_20
@
\subsection{Version-Specific Code: 3.0}
This is the init information for the 3.0 format, after the HEPRUP
data. We have the following tags:
\begin{itemize}
\item \texttt{generator} Generator name and version.
\item \texttt{xsecinfo} Cross section and weights data. We have the
total cross section and number of events (assuming that the event
file is intact), but information on minimum and maximum weights is
not available before the file is complete. We just write the
mandatory tags. (Note that the default values of the other tags
describe a uniform unit weight, but we can determine most values
only after the sample is complete.)
\item \texttt{cutsinfo} This optional tag is too specific to represent the
possibilities of WHIZARD, so we skip it.
\item \texttt{procinfo} This optional tag is useful for giving
details of NLO calculations. Skipped.
\item \texttt{weightinfo} Determine the meaning of optional weights, whose
values are given in the event record.
\end{itemize}
<<EIO LHEF: eio lhef: TBP>>=
procedure :: write_init_30 => eio_lhef_write_init_30
<<EIO LHEF: procedures>>=
subroutine eio_lhef_write_init_30 (eio, data)
class(eio_lhef_t), intent(in) :: eio
type(event_sample_data_t), intent(in) :: data
integer :: u, i
u = given_output_unit (eio%unit)
call eio%tag_generator%write (u)
write (u, "(A)", advance="no") "WHIZARD"
call eiO%tag_generator%close (u); write (u, *)
call eio%tag_xsecinfo%write (u); write (u, *)
if (eio%write_sqme_ref) then
call eio%tag_sqme_ref%write (u); write (u, *)
end if
if (eio%write_sqme_prc) then
call eio%tag_sqme_prc%write (u); write (u, *)
end if
if (eio%write_sqme_alt) then
do i = 1, eio%n_alt
call eio%tag_sqme_alt(i)%write (u); write (u, *)
end do
end if
do i = 1, eio%n_alt
call eio%tag_wgts_alt(i)%write (u); write (u, *)
end do
end subroutine eio_lhef_write_init_30
@ %def eio_lhef_write_init_30
@ When reading the init block, we first call the 1.0 routine that
fills HEPRUP. Then we consider the possible tags. Only the
\texttt{generator} and \texttt{xsecinfo} tags are of interest. We
skip everything else except for the closing tag.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: read_init_30 => eio_lhef_read_init_30
<<EIO LHEF: procedures>>=
subroutine eio_lhef_read_init_30 (eio, data)
class(eio_lhef_t), intent(inout) :: eio
type(event_sample_data_t), intent(out) :: data
real(default), parameter :: pb_per_fb = 1.e-3_default
type(string_t) :: content
logical :: found, closing
integer :: n_weightinfo
call eio_lhef_read_init_10 (eio, data)
n_weightinfo = 0
eio%i_weight_sqme = 0
SCAN_INIT_TAGS: do
call eio%tag_generator%read (eio%cstream, found)
if (found) then
if (.not. eio%tag_generator%has_content) call err_generator
call eio%tag_generator%read_content (eio%cstream, content, closing)
call msg_message ("LHEF: Event file has been generated by " &
// char (content) // " " &
// char (eio%tag_generator%get_attribute (1)))
cycle SCAN_INIT_TAGS
end if
call eio%tag_xsecinfo%read (eio%cstream, found)
if (found) then
if (eio%tag_xsecinfo%has_content) call err_xsecinfo
cycle SCAN_INIT_TAGS
end if
call eio%tag_weightinfo%read (eio%cstream, found)
if (found) then
if (eio%tag_weightinfo%has_content) call err_xsecinfo
n_weightinfo = n_weightinfo + 1
if (eio%tag_weightinfo%get_attribute (1) == "sqme_prc") then
eio%i_weight_sqme = n_weightinfo
end if
cycle SCAN_INIT_TAGS
end if
call eio%tag_init%read_content (eio%cstream, content, closing)
if (closing) then
if (content /= "") call err_init
exit SCAN_INIT_TAGS
end if
end do SCAN_INIT_TAGS
data%n_evt = &
read_ival (eio%tag_xsecinfo%get_attribute (1))
data%total_cross_section = &
read_rval (eio%tag_xsecinfo%get_attribute (2)) / pb_per_fb
contains
subroutine err_generator
call msg_fatal ("LHEF: invalid generator tag")
end subroutine err_generator
subroutine err_xsecinfo
call msg_fatal ("LHEF: invalid xsecinfo tag")
end subroutine err_xsecinfo
subroutine err_init
call msg_fatal ("LHEF: syntax error after init tag")
end subroutine err_init
end subroutine eio_lhef_read_init_30
@ %def eio_lhef_read_init_30
@ This is additional event-specific information for the 3.0 format,
after the HEPEUP data. We can specify weights, starting from the
master weight and adding alternative weights. The weight tags are
already allocated, so we just have to transfer the weight values to
strings, assemble them and write them to file. All weights are
collected in a single tag.
Note: If efficiency turns out to be an issue, we may revert to
traditional character buffer writing. However, we need to know the
maximum length.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: write_event_30 => eio_lhef_write_event_30
<<EIO LHEF: procedures>>=
subroutine eio_lhef_write_event_30 (eio, event)
class(eio_lhef_t), intent(in) :: eio
class(generic_event_t), intent(in) :: event
type(string_t) :: s
integer :: u, i
u = eio%unit
s = ""
if (eio%write_sqme_ref) then
s = s // str (event%get_sqme_ref ()) // " "
end if
if (eio%write_sqme_prc) then
s = s // str (event%get_sqme_prc ()) // " "
end if
if (eio%n_alt > 0) then
if (eio%write_sqme_alt) then
s = s // str (event%get_sqme_alt(1)) // " "
do i = 2, eio%n_alt
s = s // str (event%get_sqme_alt(i)) // " "
end do
end if
s = s // str (event%get_weight_alt(1)) // " "
do i = 2, eio%n_alt
s = s // str (event%get_weight_alt(i)) // " "
end do
end if
if (len_trim (s) > 0) then
call eio%tag_weights%write (trim (s), u); write (u, *)
end if
end subroutine eio_lhef_write_event_30
@ %def eio_lhef_write_event_30
@ Read extra event data. If there is a [[weights]] tag and if there
was a [[weightinfo]] entry labeled [[sqme_prc]], we extract the
corresponding entry from the weights string and store this as the
event's squared matrix-element value. Other tags, including
tags written by the above writer, are skipped.
<<EIO LHEF: eio lhef: TBP>>=
procedure :: read_event_30 => eio_lhef_read_event_30
<<EIO LHEF: procedures>>=
subroutine eio_lhef_read_event_30 (eio, event)
class(eio_lhef_t), intent(inout) :: eio
class(generic_event_t), intent(inout) :: event
type(string_t) :: content, string
logical :: found, closing
integer :: i
SCAN_EVENT_TAGS: do
call eio%tag_weights%read (eio%cstream, found)
if (found) then
if (.not. eio%tag_weights%has_content) call err_weights
call eio%tag_weights%read_content (eio%cstream, content, closing)
if (.not. closing) call err_weights
if (eio%i_weight_sqme > 0) then
SCAN_WEIGHTS: do i = 1, eio%i_weight_sqme
call split (content, string, " ")
content = adjustl (content)
if (i == eio%i_weight_sqme) then
call event%set_sqme_ref (read_rval (string))
exit SCAN_WEIGHTS
end if
end do SCAN_WEIGHTS
end if
cycle SCAN_EVENT_TAGS
end if
call eio%tag_event%read_content (eio%cstream, content, closing)
if (closing) then
if (content /= "") call err_event
exit SCAN_EVENT_TAGS
end if
end do SCAN_EVENT_TAGS
contains
subroutine err_weights
call msg_fatal ("LHEF: invalid weights tag in event record")
end subroutine err_weights
subroutine err_event
call msg_fatal ("LHEF: syntax error after event tag")
end subroutine err_event
end subroutine eio_lhef_read_event_30
@ %def eio_lhef_read_event_30
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_lhef_ut.f90]]>>=
<<File header>>
module eio_lhef_ut
use unit_tests
use eio_lhef_uti
<<Standard module head>>
<<EIO LHEF: public test>>
contains
<<EIO LHEF: test driver>>
end module eio_lhef_ut
@ %def eio_lhef_ut
@
<<[[eio_lhef_uti.f90]]>>=
<<File header>>
module eio_lhef_uti
<<Use kinds>>
<<Use strings>>
use io_units
use model_data
use event_base
use eio_data
use eio_base
use eio_lhef
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
use eio_base_ut, only: eio_prepare_fallback_model, eio_cleanup_fallback_model
<<Standard module head>>
<<EIO LHEF: test declarations>>
contains
<<EIO LHEF: tests>>
end module eio_lhef_uti
@ %def eio_lhef_ut
@ API: driver for the unit tests below.
<<EIO LHEF: public test>>=
public :: eio_lhef_test
<<EIO LHEF: test driver>>=
subroutine eio_lhef_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO LHEF: execute tests>>
end subroutine eio_lhef_test
@ %def eio_lhef_test
@
\subsubsection{Version 1.0 Output}
We test the implementation of all I/O methods. We start with output
according to version 1.0.
<<EIO LHEF: execute tests>>=
call test (eio_lhef_1, "eio_lhef_1", &
"write version 1.0", &
u, results)
<<EIO LHEF: test declarations>>=
public :: eio_lhef_1
<<EIO LHEF: tests>>=
subroutine eio_lhef_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_lhef_1"
write (u, "(A)") "* Purpose: generate an event and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_lhef_1"
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // "." // eio%extension), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:21) == " <generator_version>") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters ()
end select
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lhef_1"
end subroutine eio_lhef_1
@ %def eio_lhef_1
@
\subsubsection{Version 2.0 Output}
Version 2.0 has added a lot of options to the LHEF format. We
implement some of them.
<<EIO LHEF: execute tests>>=
call test (eio_lhef_2, "eio_lhef_2", &
"write version 2.0", &
u, results)
<<EIO LHEF: test declarations>>=
public :: eio_lhef_2
<<EIO LHEF: tests>>=
subroutine eio_lhef_2 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_lhef_2"
write (u, "(A)") "* Purpose: generate an event and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%unweighted = .false.
data%norm_mode = NORM_SIGMA
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_lhef_2"
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters (version = "2.0", write_sqme_prc = .true.)
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // "." // eio%extension), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:10) == "<generator") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lhef_2"
end subroutine eio_lhef_2
@ %def eio_lhef_2
@
\subsubsection{Version 3.0 Output}
Version 3.0 is an update which removes some tags (which we didn't use anyway)
and suggests a new treatment of weights.
<<EIO LHEF: execute tests>>=
call test (eio_lhef_3, "eio_lhef_3", &
"write version 3.0", &
u, results)
<<EIO LHEF: test declarations>>=
public :: eio_lhef_3
<<EIO LHEF: tests>>=
subroutine eio_lhef_3 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(80) :: buffer
write (u, "(A)") "* Test output: eio_lhef_3"
write (u, "(A)") "* Purpose: generate an event and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%unweighted = .false.
data%norm_mode = NORM_SIGMA
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_lhef_3"
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters (version = "3.0", write_sqme_prc = .true.)
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents:"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".lhe"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (buffer(1:10) == "<generator") buffer = "[...]"
if (iostat /= 0) exit
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lhef_3"
end subroutine eio_lhef_3
@ %def eio_lhef_3
@
\subsubsection{Version 1.0 Input}
Check input of a version-1.0 conforming LHEF file.
<<EIO LHEF: execute tests>>=
call test (eio_lhef_4, "eio_lhef_4", &
"read version 1.0", &
u, results)
<<EIO LHEF: test declarations>>=
public :: eio_lhef_4
<<EIO LHEF: tests>>=
subroutine eio_lhef_4 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat, i_prc
write (u, "(A)") "* Test output: eio_lhef_4"
write (u, "(A)") "* Purpose: read a LHEF 1.0 file"
write (u, "(A)")
write (u, "(A)") "* Write a LHEF data file"
write (u, "(A)")
u_file = free_unit ()
sample = "eio_lhef_4"
open (u_file, file = char (sample // ".lhe"), &
status = "replace", action = "readwrite")
write (u_file, "(A)") '<LesHouchesEvents version="1.0">'
write (u_file, "(A)") '<header>'
write (u_file, "(A)") ' <arbitrary_tag opt="foo">content</arbitrary_tag>'
write (u_file, "(A)") ' Text'
write (u_file, "(A)") ' <another_tag />'
write (u_file, "(A)") '</header>'
write (u_file, "(A)") '<init>'
write (u_file, "(A)") ' 25 25 5.0000000000E+02 5.0000000000E+02 &
& -1 -1 -1 -1 3 1'
write (u_file, "(A)") ' 1.0000000000E-01 1.0000000000E-03 &
& 1.0000000000E+00 42'
write (u_file, "(A)") '</init>'
write (u_file, "(A)") '<event>'
write (u_file, "(A)") ' 4 42 3.0574068604E+08 1.0000000000E+03 &
& -1.0000000000E+00 -1.0000000000E+00'
write (u_file, "(A)") ' 25 -1 0 0 0 0 0.0000000000E+00 0.0000000000E+00 &
& 4.8412291828E+02 5.0000000000E+02 1.2500000000E+02 &
& 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 -1 0 0 0 0 0.0000000000E+00 0.0000000000E+00 &
&-4.8412291828E+02 5.0000000000E+02 1.2500000000E+02 &
& 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 1 1 2 0 0 -1.4960220911E+02 -4.6042825611E+02 &
& 0.0000000000E+00 5.0000000000E+02 1.2500000000E+02 &
& 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 1 1 2 0 0 1.4960220911E+02 4.6042825611E+02 &
& 0.0000000000E+00 5.0000000000E+02 1.2500000000E+02 &
& 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") '</event>'
write (u_file, "(A)") '</LesHouchesEvents>'
close (u_file)
write (u, "(A)") "* Initialize test process"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted = .false.)
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters (recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, *)
write (u, "(A)") "* Initialize and read header"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, *)
select type (eio)
type is (eio_lhef_t)
call eio%tag_lhef%write (u); write (u, *)
end select
write (u, *)
call data%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_lhef_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lhef_4"
end subroutine eio_lhef_4
@ %def eio_lhef_4
@
\subsubsection{Version 2.0 Input}
Check input of a version-2.0 conforming LHEF file.
<<EIO LHEF: execute tests>>=
call test (eio_lhef_5, "eio_lhef_5", &
"read version 2.0", &
u, results)
<<EIO LHEF: test declarations>>=
public :: eio_lhef_5
<<EIO LHEF: tests>>=
subroutine eio_lhef_5 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat, i_prc
write (u, "(A)") "* Test output: eio_lhef_5"
write (u, "(A)") "* Purpose: read a LHEF 2.0 file"
write (u, "(A)")
write (u, "(A)") "* Write a LHEF data file"
write (u, "(A)")
u_file = free_unit ()
sample = "eio_lhef_5"
open (u_file, file = char (sample // ".lhe"), &
status = "replace", action = "readwrite")
write (u_file, "(A)") '<LesHouchesEvents version="2.0">'
write (u_file, "(A)") '<header>'
write (u_file, "(A)") '</header>'
write (u_file, "(A)") '<init>'
write (u_file, "(A)") ' 25 25 5.0000000000E+02 5.0000000000E+02 &
&-1 -1 -1 -1 4 1'
write (u_file, "(A)") ' 1.0000000000E-01 1.0000000000E-03 &
& 0.0000000000E+00 42'
write (u_file, "(A)") '<generator version="2.2.3">WHIZARD&
&</generator>'
write (u_file, "(A)") '<xsecinfo neve="1" totxsec="1.0000000000E-01" />'
write (u_file, "(A)") '</init>'
write (u_file, "(A)") '<event>'
write (u_file, "(A)") ' 4 42 3.0574068604E+08 1.0000000000E+03 &
&-1.0000000000E+00 -1.0000000000E+00'
write (u_file, "(A)") ' 25 -1 0 0 0 0 0.0000000000E+00 &
& 0.0000000000E+00 4.8412291828E+02 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 -1 0 0 0 0 0.0000000000E+00 &
& 0.0000000000E+00 -4.8412291828E+02 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 1 1 2 0 0 -1.4960220911E+02 &
&-4.6042825611E+02 0.0000000000E+00 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 1 1 2 0 0 1.4960220911E+02 &
& 4.6042825611E+02 0.0000000000E+00 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") '<weight name="sqme_prc">1.0000000000E+00</weight>'
write (u_file, "(A)") '</event>'
write (u_file, "(A)") '</LesHouchesEvents>'
close (u_file)
write (u, "(A)") "* Initialize test process"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted = .false.)
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters (version = "2.0", recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%unweighted = .false.
data%norm_mode = NORM_SIGMA
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, *)
write (u, "(A)") "* Initialize and read header"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, *)
select type (eio)
type is (eio_lhef_t)
call eio%tag_lhef%write (u); write (u, *)
end select
write (u, *)
call data%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_lhef_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lhef_5"
end subroutine eio_lhef_5
@ %def eio_lhef_5
@
\subsubsection{Version 3.0 Input}
Check input of a version-3.0 conforming LHEF file.
<<EIO LHEF: execute tests>>=
call test (eio_lhef_6, "eio_lhef_6", &
"read version 3.0", &
u, results)
<<EIO LHEF: test declarations>>=
public :: eio_lhef_6
<<EIO LHEF: tests>>=
subroutine eio_lhef_6 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat, i_prc
write (u, "(A)") "* Test output: eio_lhef_6"
write (u, "(A)") "* Purpose: read a LHEF 3.0 file"
write (u, "(A)")
write (u, "(A)") "* Write a LHEF data file"
write (u, "(A)")
u_file = free_unit ()
sample = "eio_lhef_6"
open (u_file, file = char (sample // ".lhe"), &
status = "replace", action = "readwrite")
write (u_file, "(A)") '<LesHouchesEvents version="3.0">'
write (u_file, "(A)") '<header>'
write (u_file, "(A)") '</header>'
write (u_file, "(A)") '<init>'
write (u_file, "(A)") ' 25 25 5.0000000000E+02 5.0000000000E+02 &
&-1 -1 -1 -1 4 1'
write (u_file, "(A)") ' 1.0000000000E-01 1.0000000000E-03 &
& 0.0000000000E+00 42'
write (u_file, "(A)") '<generator version="2.2.3">WHIZARD&
&</generator>'
write (u_file, "(A)") '<xsecinfo neve="1" totxsec="1.0000000000E-01" />'
write (u_file, "(A)") '<weightinfo name="sqme_prc" />'
write (u_file, "(A)") '</init>'
write (u_file, "(A)") '<event>'
write (u_file, "(A)") ' 4 42 3.0574068604E+08 1.0000000000E+03 &
&-1.0000000000E+00 -1.0000000000E+00'
write (u_file, "(A)") ' 25 -1 0 0 0 0 0.0000000000E+00 &
& 0.0000000000E+00 4.8412291828E+02 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 -1 0 0 0 0 0.0000000000E+00 &
& 0.0000000000E+00 -4.8412291828E+02 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 1 1 2 0 0 -1.4960220911E+02 &
&-4.6042825611E+02 0.0000000000E+00 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") ' 25 1 1 2 0 0 1.4960220911E+02 &
& 4.6042825611E+02 0.0000000000E+00 5.0000000000E+02 &
& 1.2500000000E+02 0.0000000000E+00 9.0000000000E+00'
write (u_file, "(A)") '<weights>1.0000000000E+00</weights>'
write (u_file, "(A)") '</event>'
write (u_file, "(A)") '</LesHouchesEvents>'
close (u_file)
write (u, "(A)") "* Initialize test process"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted = .false.)
allocate (eio_lhef_t :: eio)
select type (eio)
type is (eio_lhef_t)
call eio%set_parameters (version = "3.0", recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%unweighted = .false.
data%norm_mode = NORM_SIGMA
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, *)
write (u, "(A)") "* Initialize and read header"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, *)
select type (eio)
type is (eio_lhef_t)
call eio%tag_lhef%write (u); write (u, *)
end select
write (u, *)
call data%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_lhef_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lhef_6"
end subroutine eio_lhef_6
@ %def eio_lhef_6
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{STDHEP File Formats}
Here, we implement the two existing STDHEP file formats, one based on the
HEPRUP/HEPEUP common blocks, the other based on the HEPEVT common block.
The second one is actually the standard STDHEP format.
<<[[eio_stdhep.f90]]>>=
<<File header>>
module eio_stdhep
use kinds, only: i32, i64
<<Use strings>>
use io_units
use string_utils
use diagnostics
use event_base
use hep_common
use hep_events
use eio_data
use eio_base
<<Standard module head>>
<<EIO stdhep: public>>
<<EIO stdhep: types>>
<<EIO stdhep: variables>>
contains
<<EIO stdhep: procedures>>
end module eio_stdhep
@ %def eio_stdhep
@
\subsection{Type}
<<EIO stdhep: public>>=
public :: eio_stdhep_t
<<EIO stdhep: types>>=
type, abstract, extends (eio_t) :: eio_stdhep_t
logical :: writing = .false.
logical :: reading = .false.
integer :: unit = 0
logical :: keep_beams = .false.
logical :: keep_remnants = .true.
logical :: ensure_order = .false.
logical :: recover_beams = .false.
logical :: use_alphas_from_file = .false.
logical :: use_scale_from_file = .false.
integer, dimension(:), allocatable :: proc_num_id
integer(i64) :: n_events_expected = 0
contains
<<EIO stdhep: eio stdhep: TBP>>
end type eio_stdhep_t
@ %def eio_stdhep_t
@
<<EIO stdhep: public>>=
public :: eio_stdhep_hepevt_t
<<EIO stdhep: types>>=
type, extends (eio_stdhep_t) :: eio_stdhep_hepevt_t
end type eio_stdhep_hepevt_t
@ %def eio_stdhep_hepevt_t
@
<<EIO stdhep: public>>=
public :: eio_stdhep_hepeup_t
<<EIO stdhep: types>>=
type, extends (eio_stdhep_t) :: eio_stdhep_hepeup_t
end type eio_stdhep_hepeup_t
@ %def eio_stdhep_hepeup_t
@
<<EIO stdhep: public>>=
public :: eio_stdhep_hepev4_t
<<EIO stdhep: types>>=
type, extends (eio_stdhep_t) :: eio_stdhep_hepev4_t
end type eio_stdhep_hepev4_t
@ %def eio_stdhep_hepev4_t
@
\subsection{Specific Methods}
Set parameters that are specifically used with STDHEP file formats.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: set_parameters => eio_stdhep_set_parameters
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_set_parameters (eio, &
keep_beams, keep_remnants, ensure_order, recover_beams, &
use_alphas_from_file, use_scale_from_file, extension)
class(eio_stdhep_t), intent(inout) :: eio
logical, intent(in), optional :: keep_beams
logical, intent(in), optional :: keep_remnants
logical, intent(in), optional :: ensure_order
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alphas_from_file
logical, intent(in), optional :: use_scale_from_file
type(string_t), intent(in), optional :: extension
if (present (keep_beams)) eio%keep_beams = keep_beams
if (present (keep_remnants)) eio%keep_remnants = keep_remnants
if (present (ensure_order)) eio%ensure_order = ensure_order
if (present (recover_beams)) eio%recover_beams = recover_beams
if (present (use_alphas_from_file)) &
eio%use_alphas_from_file = use_alphas_from_file
if (present (use_scale_from_file)) &
eio%use_scale_from_file = use_scale_from_file
if (present (extension)) then
eio%extension = extension
else
select type (eio)
type is (eio_stdhep_hepevt_t)
eio%extension = "hep"
type is (eio_stdhep_hepev4_t)
eio%extension = "ev4.hep"
type is (eio_stdhep_hepeup_t)
eio%extension = "up.hep"
end select
end if
end subroutine eio_stdhep_set_parameters
@ %def eio_ascii_stdhep_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: write => eio_stdhep_write
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_write (object, unit)
class(eio_stdhep_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit)
write (u, "(1x,A)") "STDHEP event stream:"
if (object%writing) then
write (u, "(3x,A,A)") "Writing to file = ", char (object%filename)
else if (object%reading) then
write (u, "(3x,A,A)") "Reading from file = ", char (object%filename)
else
write (u, "(3x,A)") "[closed]"
end if
write (u, "(3x,A,L1)") "Keep beams = ", object%keep_beams
write (u, "(3x,A,L1)") "Keep remnants = ", object%keep_remnants
write (u, "(3x,A,L1)") "Recover beams = ", object%recover_beams
write (u, "(3x,A,L1)") "Alpha_s from file = ", &
object%use_alphas_from_file
write (u, "(3x,A,L1)") "Scale from file = ", &
object%use_scale_from_file
if (allocated (object%proc_num_id)) then
write (u, "(3x,A)") "Numerical process IDs:"
do i = 1, size (object%proc_num_id)
write (u, "(5x,I0,': ',I0)") i, object%proc_num_id(i)
end do
end if
end subroutine eio_stdhep_write
@ %def eio_stdhep_write
@ Finalizer: close any open file.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: final => eio_stdhep_final
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_final (object)
class(eio_stdhep_t), intent(inout) :: object
if (allocated (object%proc_num_id)) deallocate (object%proc_num_id)
if (object%writing) then
write (msg_buffer, "(A,A,A)") "Events: closing STDHEP file '", &
char (object%filename), "'"
call msg_message ()
call stdhep_write (200)
call stdhep_end ()
object%writing = .false.
else if (object%reading) then
write (msg_buffer, "(A,A,A)") "Events: closing STDHEP file '", &
char (object%filename), "'"
call msg_message ()
object%reading = .false.
end if
end subroutine eio_stdhep_final
@ %def eio_stdhep_final
@ Common initialization for input and output.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: common_init => eio_stdhep_common_init
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_common_init (eio, sample, data, extension)
class(eio_stdhep_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
if (.not. present (data)) &
call msg_bug ("STDHEP initialization: missing data")
if (data%n_beam /= 2) &
call msg_fatal ("STDHEP: defined for scattering processes only")
if (present (extension)) then
eio%extension = extension
end if
eio%sample = sample
call eio%set_filename ()
eio%unit = free_unit ()
allocate (eio%proc_num_id (data%n_proc), source = data%proc_num_id)
end subroutine eio_stdhep_common_init
@ %def eio_stdhep_common_init
@ Split event file: increment the counter, close the current file, open a new
one. If the file needs a header, repeat it for the new file. (We assume that
the common block contents are still intact.)
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: split_out => eio_stdhep_split_out
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_split_out (eio)
class(eio_stdhep_t), intent(inout) :: eio
if (eio%split) then
eio%split_index = eio%split_index + 1
call eio%set_filename ()
write (msg_buffer, "(A,A,A)") "Events: writing to STDHEP file '", &
char (eio%filename), "'"
call msg_message ()
call stdhep_write (200)
call stdhep_end ()
select type (eio)
type is (eio_stdhep_hepeup_t)
call stdhep_init_out (char (eio%filename), &
"WHIZARD <<Version>>", eio%n_events_expected)
call stdhep_write (100)
call stdhep_write (STDHEP_HEPRUP)
type is (eio_stdhep_hepevt_t)
call stdhep_init_out (char (eio%filename), &
"WHIZARD <<Version>>", eio%n_events_expected)
call stdhep_write (100)
type is (eio_stdhep_hepev4_t)
call stdhep_init_out (char (eio%filename), &
"WHIZARD <<Version>>", eio%n_events_expected)
call stdhep_write (100)
end select
end if
end subroutine eio_stdhep_split_out
@ %def eio_stdhep_split_out
@ Initialize event writing.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: init_out => eio_stdhep_init_out
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_init_out (eio, sample, data, success, extension)
class(eio_stdhep_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
integer :: i
if (.not. present (data)) &
call msg_bug ("STDHEP initialization: missing data")
call eio%set_splitting (data)
call eio%common_init (sample, data, extension)
eio%n_events_expected = data%n_evt
write (msg_buffer, "(A,A,A)") "Events: writing to STDHEP file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
select type (eio)
type is (eio_stdhep_hepeup_t)
call heprup_init &
(data%pdg_beam, &
data%energy_beam, &
n_processes = data%n_proc, &
unweighted = data%unweighted, &
negative_weights = data%negative_weights)
do i = 1, data%n_proc
call heprup_set_process_parameters (i = i, &
process_id = data%proc_num_id(i), &
cross_section = data%cross_section(i), &
error = data%error(i))
end do
call stdhep_init_out (char (eio%filename), &
"WHIZARD <<Version>>", eio%n_events_expected)
call stdhep_write (100)
call stdhep_write (STDHEP_HEPRUP)
type is (eio_stdhep_hepevt_t)
call stdhep_init_out (char (eio%filename), &
"WHIZARD <<Version>>", eio%n_events_expected)
call stdhep_write (100)
type is (eio_stdhep_hepev4_t)
call stdhep_init_out (char (eio%filename), &
"WHIZARD <<Version>>", eio%n_events_expected)
call stdhep_write (100)
end select
if (present (success)) success = .true.
end subroutine eio_stdhep_init_out
@ %def eio_stdhep_init_out
@ Initialize event reading.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: init_in => eio_stdhep_init_in
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_init_in (eio, sample, data, success, extension)
class(eio_stdhep_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
integer :: ilbl, lok
logical :: exist
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: reading from STDHEP file '", &
char (eio%filename), "'"
call msg_message ()
inquire (file = char (eio%filename), exist = exist)
if (.not. exist) call msg_fatal ("Events: STDHEP file not found.")
eio%reading = .true.
call stdhep_init_in (char (eio%filename), eio%n_events_expected)
call stdhep_read (ilbl, lok)
if (lok /= 0) then
call stdhep_end ()
write (msg_buffer, "(A)") "Events: STDHEP file appears to" // &
" be empty."
call msg_message ()
end if
if (ilbl == 100) then
write (msg_buffer, "(A)") "Events: reading in STDHEP events"
call msg_message ()
end if
if (present (success)) success = .false.
end subroutine eio_stdhep_init_in
@ %def eio_stdhep_init_in
@ Switch from input to output: reopen the file for reading.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: switch_inout => eio_stdhep_switch_inout
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_switch_inout (eio, success)
class(eio_stdhep_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("STDHEP: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_stdhep_switch_inout
@ %def eio_stdhep_switch_inout
@ Output an event. Write first the event indices, then weight and
squared matrix element, then the particle set.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: output => eio_stdhep_output
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_output (eio, event, i_prc, reading, passed, pacify)
class(eio_stdhep_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
if (present (passed)) then
if (.not. passed) return
end if
if (eio%writing) then
select type (eio)
type is (eio_stdhep_hepeup_t)
call hepeup_from_event (event, &
process_index = eio%proc_num_id (i_prc), &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants)
call stdhep_write (STDHEP_HEPEUP)
type is (eio_stdhep_hepevt_t)
call hepevt_from_event (event, &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order)
call stdhep_write (STDHEP_HEPEVT)
type is (eio_stdhep_hepev4_t)
call hepevt_from_event (event, &
process_index = eio%proc_num_id (i_prc), &
keep_beams = eio%keep_beams, &
keep_remnants = eio%keep_remnants, &
ensure_order = eio%ensure_order, &
fill_hepev4 = .true.)
call stdhep_write (STDHEP_HEPEV4)
end select
else
call eio%write ()
call msg_fatal ("STDHEP file is not open for writing")
end if
end subroutine eio_stdhep_output
@ %def eio_stdhep_output
@ Input an event. We do not allow to read in STDHEP files written via
the HEPEVT common block as there is no control on the process ID.
This implies that the event index cannot be read; it is simply
incremented to count the current event sample.
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: input_i_prc => eio_stdhep_input_i_prc
procedure :: input_event => eio_stdhep_input_event
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_input_i_prc (eio, i_prc, iostat)
class(eio_stdhep_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
integer :: i, ilbl, proc_num_id
iostat = 0
select type (eio)
type is (eio_stdhep_hepevt_t)
if (size (eio%proc_num_id) > 1) then
call msg_fatal ("Events: only single processes allowed " // &
"with the STDHEP HEPEVT format.")
else
proc_num_id = eio%proc_num_id (1)
call stdhep_read (ilbl, lok)
end if
type is (eio_stdhep_hepev4_t)
call stdhep_read (ilbl, lok)
proc_num_id = idruplh
type is (eio_stdhep_hepeup_t)
call stdhep_read (ilbl, lok)
if (lok /= 0) call msg_error ("Events: STDHEP appears to be " // &
"empty or corrupted.")
if (ilbl == 12) then
call stdhep_read (ilbl, lok)
end if
if (ilbl == 11) then
proc_num_id = IDPRUP
end if
end select
FIND_I_PRC: do i = 1, size (eio%proc_num_id)
if (eio%proc_num_id(i) == proc_num_id) then
i_prc = i
exit FIND_I_PRC
end if
end do FIND_I_PRC
if (i_prc == 0) call err_index
contains
subroutine err_index
call msg_error ("STDHEP: reading events: undefined process ID " &
// char (str (proc_num_id)) // ", aborting read")
iostat = 1
end subroutine err_index
end subroutine eio_stdhep_input_i_prc
subroutine eio_stdhep_input_event (eio, event, iostat)
class(eio_stdhep_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
iostat = 0
call event%reset_contents ()
call event%select (1, 1, 1)
call hepeup_to_event (event, eio%fallback_model, &
recover_beams = eio%recover_beams, &
use_alpha_s = eio%use_alphas_from_file, &
use_scale = eio%use_scale_from_file)
call event%increment_index ()
end subroutine eio_stdhep_input_event
@ %def eio_stdhep_input_i_prc
@ %def eio_stdhep_input_event
<<EIO stdhep: eio stdhep: TBP>>=
procedure :: skip => eio_stdhep_skip
<<EIO stdhep: procedures>>=
subroutine eio_stdhep_skip (eio, iostat)
class(eio_stdhep_t), intent(inout) :: eio
integer, intent(out) :: iostat
if (eio%reading) then
read (eio%unit, iostat = iostat)
else
call eio%write ()
call msg_fatal ("Raw event file is not open for reading")
end if
end subroutine eio_stdhep_skip
@ %def eio_stdhep_skip
@ STDHEP speficic routines.
<<EIO stdhep: public>>=
public :: stdhep_init_out
public :: stdhep_init_in
public :: stdhep_write
public :: stdhep_end
<<EIO stdhep: procedures>>=
subroutine stdhep_init_out (file, title, nevt)
character(len=*), intent(in) :: file, title
integer(i64), intent(in) :: nevt
integer(i32) :: nevt32
nevt32 = min (nevt, int (huge (1_i32), i64))
call stdxwinit (file, title, nevt32, istr, lok)
end subroutine stdhep_init_out
subroutine stdhep_init_in (file, nevt)
character(len=*), intent(in) :: file
integer(i64), intent(out) :: nevt
integer(i32) :: nevt32
call stdxrinit (file, nevt32, istr, lok)
if (lok /= 0) call msg_fatal ("STDHEP: error in reading file '" // &
file // "'.")
nevt = int (nevt32, i64)
end subroutine stdhep_init_in
subroutine stdhep_write (ilbl)
integer, intent(in) :: ilbl
call stdxwrt (ilbl, istr, lok)
end subroutine stdhep_write
subroutine stdhep_read (ilbl, lok)
integer, intent(out) :: ilbl, lok
call stdxrd (ilbl, istr, lok)
if (lok /= 0) return
end subroutine stdhep_read
subroutine stdhep_end
call stdxend (istr)
end subroutine stdhep_end
@ %def stdhep_init stdhep_read stdhep_write stdhep_end
@
\subsection{Variables}
<<EIO stdhep: variables>>=
integer, save :: istr, lok
integer, parameter :: &
STDHEP_HEPEVT = 1, STDHEP_HEPEV4 = 4, &
STDHEP_HEPEUP = 11, STDHEP_HEPRUP = 12
@
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_stdhep_ut.f90]]>>=
<<File header>>
module eio_stdhep_ut
use unit_tests
use eio_stdhep_uti
<<Standard module head>>
<<EIO stdhep: public test>>
contains
<<EIO stdhep: test driver>>
end module eio_stdhep_ut
@ %def eio_stdhep_ut
@
<<[[eio_stdhep_uti.f90]]>>=
<<File header>>
module eio_stdhep_uti
<<Use kinds>>
<<Use strings>>
use io_units
use model_data
use event_base
use eio_data
use eio_base
use xdr_wo_stdhep
use eio_stdhep
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
use eio_base_ut, only: eio_prepare_fallback_model, eio_cleanup_fallback_model
<<Standard module head>>
<<EIO stdhep: test declarations>>
contains
<<EIO stdhep: tests>>
end module eio_stdhep_uti
@ %def eio_stdhep_ut
@ API: driver for the unit tests below.
<<EIO stdhep: public test>>=
public :: eio_stdhep_test
<<EIO stdhep: test driver>>=
subroutine eio_stdhep_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO stdhep: execute tests>>
end subroutine eio_stdhep_test
@ %def eio_stdhep_test
@
\subsubsection{Test I/O methods}
We test the implementation of the STDHEP HEPEVT I/O method:
<<EIO stdhep: execute tests>>=
call test (eio_stdhep_1, "eio_stdhep_1", &
"read and write event contents, format [stdhep]", &
u, results)
<<EIO stdhep: test declarations>>=
public :: eio_stdhep_1
<<EIO stdhep: tests>>=
subroutine eio_stdhep_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(215) :: buffer
write (u, "(A)") "* Test output: eio_stdhep_1"
write (u, "(A)") "* Purpose: generate an event in STDHEP HEPEVT format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_stdhep_1"
allocate (eio_stdhep_hepevt_t :: eio)
select type (eio)
type is (eio_stdhep_hepevt_t)
call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (61) ! not supported by reader, actually
call event%evaluate_expressions ()
call event%pacify_particle_set ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* Write STDHEP file contents to ASCII file"
write (u, "(A)")
call write_stdhep_event &
(sample // ".hep", var_str ("eio_stdhep_1.hep.out"), 1)
write (u, "(A)")
write (u, "(A)") "* Read in ASCII contents of STDHEP file"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "eio_stdhep_1.hep.out", &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (iostat /= 0) exit
if (trim (buffer) == "") cycle
if (buffer(1:18) == " total blocks: ") &
buffer = " total blocks: [...]"
if (buffer(1:25) == " title: WHIZARD") &
buffer = " title: WHIZARD [version]"
if (buffer(1:17) == " date:") &
buffer = " date: [...]"
if (buffer(1:17) == " closing date:") &
buffer = " closing date: [...]"
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_stdhep_hepevt_t :: eio)
select type (eio)
type is (eio_stdhep_hepevt_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_stdhep_1"
end subroutine eio_stdhep_1
@ %def eio_stdhep_1
@
We test the implementation of the STDHEP HEPEUP I/O method:
<<EIO stdhep: execute tests>>=
call test (eio_stdhep_2, "eio_stdhep_2", &
"read and write event contents, format [stdhep]", &
u, results)
<<EIO stdhep: test declarations>>=
public :: eio_stdhep_2
<<EIO stdhep: tests>>=
subroutine eio_stdhep_2 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(model_data_t), pointer :: fallback_model
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(215) :: buffer
write (u, "(A)") "* Test output: eio_stdhep_2"
write (u, "(A)") "* Purpose: generate an event in STDHEP HEPEUP format"
write (u, "(A)") "* and write weight to file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted = .false.)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_stdhep_2"
allocate (eio_stdhep_hepeup_t :: eio)
select type (eio)
type is (eio_stdhep_hepeup_t)
call eio%set_parameters ()
end select
call eio%set_fallback_model (fallback_model)
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (62) ! not supported by reader, actually
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* Write STDHEP file contents to ASCII file"
write (u, "(A)")
call write_stdhep_event &
(sample // ".up.hep", var_str ("eio_stdhep_2.hep.out"), 2)
write (u, "(A)")
write (u, "(A)") "* Read in ASCII contents of STDHEP file"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "eio_stdhep_2.hep.out", &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (iostat /= 0) exit
if (trim (buffer) == "") cycle
if (buffer(1:18) == " total blocks: ") &
buffer = " total blocks: [...]"
if (buffer(1:25) == " title: WHIZARD") &
buffer = " title: WHIZARD [version]"
if (buffer(1:17) == " date:") &
buffer = " date: [...]"
if (buffer(1:17) == " closing date:") &
buffer = " closing date: [...]"
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_stdhep_hepeup_t :: eio)
select type (eio)
type is (eio_stdhep_hepeup_t)
call eio%set_parameters (keep_beams = .true.)
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_stdhep_2"
end subroutine eio_stdhep_2
@ %def eio_stdhep_2
@
Check input from a StdHep file, HEPEVT block.
<<EIO stdhep: execute tests>>=
call test (eio_stdhep_3, "eio_stdhep_3", &
"read StdHep file, HEPEVT block", &
u, results)
<<EIO stdhep: test declarations>>=
public :: eio_stdhep_3
<<EIO stdhep: tests>>=
subroutine eio_stdhep_3 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: iostat, i_prc
write (u, "(A)") "* Test output: eio_stdhep_3"
write (u, "(A)") "* Purpose: read a StdHep file, HEPEVT block"
write (u, "(A)")
write (u, "(A)") "* Write a StdHep data file, HEPEVT block"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_stdhep_3"
allocate (eio_stdhep_hepevt_t :: eio)
select type (eio)
type is (eio_stdhep_hepevt_t)
call eio%set_parameters ()
end select
call eio%set_fallback_model (fallback_model)
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (63) ! not supported by reader, actually
call event%evaluate_expressions ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (eio)
deallocate (fallback_model)
write (u, "(A)") "* Initialize test process"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted = .false.)
allocate (eio_stdhep_hepevt_t :: eio)
select type (eio)
type is (eio_stdhep_hepevt_t)
call eio%set_parameters (recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, *)
write (u, "(A)") "* Initialize"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_stdhep_hepevt_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_stdhep_3"
end subroutine eio_stdhep_3
@ %def eio_stdhep_3
@
Check input from a StdHep file, HEPEVT block.
<<EIO stdhep: execute tests>>=
call test (eio_stdhep_4, "eio_stdhep_4", &
"read StdHep file, HEPRUP/HEPEUP block", &
u, results)
<<EIO stdhep: test declarations>>=
public :: eio_stdhep_4
<<EIO stdhep: tests>>=
subroutine eio_stdhep_4 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: iostat, i_prc
write (u, "(A)") "* Test output: eio_stdhep_3"
write (u, "(A)") "* Purpose: read a StdHep file, HEPRUP/HEPEUP block"
write (u, "(A)")
write (u, "(A)") "* Write a StdHep data file, HEPRUP/HEPEUP block"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event)
call data%init (1)
data%n_evt = 1
data%n_beam = 2
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event, HEPEUP/HEPRUP"
write (u, "(A)")
sample = "eio_stdhep_4"
allocate (eio_stdhep_hepeup_t :: eio)
select type (eio)
type is (eio_stdhep_hepeup_t)
call eio%set_parameters ()
end select
call eio%set_fallback_model (fallback_model)
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (64) ! not supported by reader, actually
call event%evaluate_expressions ()
call event%pacify_particle_set ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (eio)
deallocate (fallback_model)
write (u, "(A)") "* Initialize test process"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted = .false.)
allocate (eio_stdhep_hepeup_t :: eio)
select type (eio)
type is (eio_stdhep_hepeup_t)
call eio%set_parameters (recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, *)
write (u, "(A)") "* Initialize"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_stdhep_hepeup_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_stdhep_4"
end subroutine eio_stdhep_4
@ %def eio_stdhep_4
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{HepMC Output}
The HepMC event record is standardized. It is an ASCII format. We try
our best at using it for both input and output.
<<[[eio_hepmc.f90]]>>=
<<File header>>
module eio_hepmc
<<Use kinds>>
<<Use strings>>
use io_units
use string_utils
use diagnostics
use particles
use model_data
use event_base
use hep_events
use eio_data
use eio_base
use hepmc_interface
<<Standard module head>>
<<EIO HepMC: public>>
<<EIO HepMC: types>>
contains
<<EIO HepMC: procedures>>
end module eio_hepmc
@ %def eio_hepmc
@
\subsection{Type}
A type [[hepmc_event]] is introduced as container to store HepMC event
data, particularly for splitting the reading into read out of the process
index and the proper event data.
Note: the [[keep_beams]] flag is not supported. Beams will always
be written. Tools like \texttt{Rivet} can use the cross section
information of a HepMC file for scaling plots. As there is no header in
HepMC and this is written for every event, we make it optional with
[[output_cross_section]].
<<EIO HepMC: public>>=
public :: eio_hepmc_t
<<EIO HepMC: types>>=
type, extends (eio_t) :: eio_hepmc_t
logical :: writing = .false.
logical :: reading = .false.
type(event_sample_data_t) :: data
! logical :: keep_beams = .false.
logical :: recover_beams = .false.
logical :: use_alphas_from_file = .false.
logical :: use_scale_from_file = .false.
logical :: output_cross_section = .false.
logical :: hepmc2_mode = .false.
type(hepmc_iostream_t) :: iostream
type(hepmc_event_t) :: hepmc_event
integer, dimension(:), allocatable :: proc_num_id
contains
<<EIO HepMC: eio hepmc: TBP>>
end type eio_hepmc_t
@ %def eio_hepmc_t
@
\subsection{Specific Methods}
Set parameters that are specifically used with HepMC.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: set_parameters => eio_hepmc_set_parameters
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_set_parameters &
(eio, &
recover_beams, use_alphas_from_file, use_scale_from_file, &
extension, output_cross_section, hepmc2_mode)
class(eio_hepmc_t), intent(inout) :: eio
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alphas_from_file
logical, intent(in), optional :: use_scale_from_file
logical, intent(in), optional :: output_cross_section
type(string_t), intent(in), optional :: extension
logical, intent(in), optional :: hepmc2_mode
if (present (recover_beams)) &
eio%recover_beams = recover_beams
if (present (use_alphas_from_file)) &
eio%use_alphas_from_file = use_alphas_from_file
if (present (use_scale_from_file)) &
eio%use_scale_from_file = use_scale_from_file
if (present (extension)) then
eio%extension = extension
else
eio%extension = "hepmc"
end if
if (present (output_cross_section)) &
eio%output_cross_section = output_cross_section
if (present (hepmc2_mode)) &
eio%hepmc2_mode = hepmc2_mode
end subroutine eio_hepmc_set_parameters
@ %def eio_hepmc_set_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: write => eio_hepmc_write
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_write (object, unit)
class(eio_hepmc_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit)
write (u, "(1x,A)") "HepMC event stream:"
if (object%writing) then
write (u, "(3x,A,A)") "Writing to file = ", char (object%filename)
else if (object%reading) then
write (u, "(3x,A,A)") "Reading from file = ", char (object%filename)
else
write (u, "(3x,A)") "[closed]"
end if
write (u, "(3x,A,L1)") "Recover beams = ", object%recover_beams
write (u, "(3x,A,L1)") "Alpha_s from file = ", &
object%use_alphas_from_file
write (u, "(3x,A,L1)") "Scale from file = ", &
object%use_scale_from_file
write (u, "(3x,A,A,A)") "File extension = '", &
char (object%extension), "'"
write (u, "(3x,A,L1)") "HepMC2 compat. = ", object%hepmc2_mode
if (allocated (object%proc_num_id)) then
write (u, "(3x,A)") "Numerical process IDs:"
do i = 1, size (object%proc_num_id)
write (u, "(5x,I0,': ',I0)") i, object%proc_num_id(i)
end do
end if
end subroutine eio_hepmc_write
@ %def eio_hepmc_write
@ Finalizer: close any open file.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: final => eio_hepmc_final
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_final (object)
class(eio_hepmc_t), intent(inout) :: object
if (allocated (object%proc_num_id)) deallocate (object%proc_num_id)
if (object%writing) then
write (msg_buffer, "(A,A,A)") "Events: closing HepMC file '", &
char (object%filename), "'"
call msg_message ()
call hepmc_iostream_close (object%iostream, object%hepmc2_mode)
object%writing = .false.
else if (object%reading) then
write (msg_buffer, "(A,A,A)") "Events: closing HepMC file '", &
char (object%filename), "'"
call msg_message ()
call hepmc_iostream_close (object%iostream, object%hepmc2_mode)
object%reading = .false.
end if
end subroutine eio_hepmc_final
@ %def eio_hepmc_final
@ Split event file: increment the counter, close the current file, open a new
one. If the file needs a header, repeat it for the new file.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: split_out => eio_hepmc_split_out
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_split_out (eio)
class(eio_hepmc_t), intent(inout) :: eio
if (eio%split) then
eio%split_index = eio%split_index + 1
call eio%set_filename ()
write (msg_buffer, "(A,A,A)") "Events: writing to HepMC file '", &
char (eio%filename), "'"
call msg_message ()
call hepmc_iostream_close (eio%iostream, eio%hepmc2_mode)
call hepmc_iostream_open_out (eio%iostream, &
eio%filename, eio%hepmc2_mode)
end if
end subroutine eio_hepmc_split_out
@ %def eio_hepmc_split_out
@ Common initialization for input and output.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: common_init => eio_hepmc_common_init
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_common_init (eio, sample, data, extension)
class(eio_hepmc_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
if (.not. present (data)) &
call msg_bug ("HepMC initialization: missing data")
eio%data = data
if (data%n_beam /= 2) &
call msg_fatal ("HepMC: defined for scattering processes only")
! We could relax this condition now with weighted hepmc events
if (data%unweighted) then
select case (data%norm_mode)
case (NORM_UNIT)
case default; call msg_fatal &
("HepMC: normalization for unweighted events must be '1'")
end select
end if
eio%sample = sample
if (present (extension)) then
eio%extension = extension
end if
call eio%set_filename ()
allocate (eio%proc_num_id (data%n_proc), source = data%proc_num_id)
end subroutine eio_hepmc_common_init
@ %def eio_hepmc_common_init
@ Initialize event writing.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: init_out => eio_hepmc_init_out
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_init_out (eio, sample, data, success, extension)
class(eio_hepmc_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
call eio%set_splitting (data)
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: writing to HepMC file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
call hepmc_iostream_open_out (eio%iostream, &
eio%filename, eio%hepmc2_mode)
if (present (success)) success = .true.
end subroutine eio_hepmc_init_out
@ %def eio_hepmc_init_out
@ Initialize event reading. For input, we do not (yet) support split
event files.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: init_in => eio_hepmc_init_in
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_init_in (eio, sample, data, success, extension)
class(eio_hepmc_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
logical :: exist
eio%split = .false.
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: reading from HepMC file '", &
char (eio%filename), "'"
call msg_message ()
inquire (file = char (eio%filename), exist = exist)
if (.not. exist) call msg_fatal ("Events: HepMC file not found.")
eio%reading = .true.
call hepmc_iostream_open_in (eio%iostream, &
eio%filename, eio%hepmc2_mode)
if (present (success)) success = .true.
end subroutine eio_hepmc_init_in
@ %def eio_hepmc_init_in
@ Switch from input to output: reopen the file for reading.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: switch_inout => eio_hepmc_switch_inout
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_switch_inout (eio, success)
class(eio_hepmc_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("HepMC: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_hepmc_switch_inout
@ %def eio_hepmc_switch_inout
@ Output an event to the allocated HepMC output stream. For the
moment, we set [[alpha_qed]] always to -1. There should be methods for
the handling of $\alpha$ in [[me_methods]] in the same way as for
$\alpha_s$.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: output => eio_hepmc_output
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_output (eio, event, i_prc, reading, passed, pacify)
class(eio_hepmc_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
type(particle_set_t), pointer :: pset_ptr
if (present (passed)) then
if (.not. passed) return
end if
if (eio%writing) then
pset_ptr => event%get_particle_set_ptr ()
call hepmc_event_init (eio%hepmc_event, &
proc_id = eio%proc_num_id(i_prc), &
event_id = event%get_index ())
if (eio%output_cross_section) then
call hepmc_event_from_particle_set (eio%hepmc_event, pset_ptr, &
eio%data%cross_section(i_prc), eio%data%error(i_prc))
else
call hepmc_event_from_particle_set (eio%hepmc_event, pset_ptr)
end if
call hepmc_event_set_scale (eio%hepmc_event, event%get_fac_scale ())
call hepmc_event_set_alpha_qcd (eio%hepmc_event, event%get_alpha_s ())
call hepmc_event_set_alpha_qed (eio%hepmc_event, -1._default)
if (.not. eio%data%unweighted) &
call hepmc_event_add_weight (eio%hepmc_event, event%weight_prc)
call hepmc_iostream_write_event (eio%iostream, &
eio%hepmc_event, eio%hepmc2_mode)
call hepmc_event_final (eio%hepmc_event)
else
call eio%write ()
call msg_fatal ("HepMC file is not open for writing")
end if
end subroutine eio_hepmc_output
@ %def eio_hepmc_output
@ Input an event.
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: input_i_prc => eio_hepmc_input_i_prc
procedure :: input_event => eio_hepmc_input_event
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_input_i_prc (eio, i_prc, iostat)
class(eio_hepmc_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
logical :: ok
integer :: i, proc_num_id
iostat = 0
call hepmc_event_init (eio%hepmc_event)
call hepmc_iostream_read_event (eio%iostream, &
eio%hepmc_event, ok=ok, hepmc2=eio%hepmc2_mode)
proc_num_id = hepmc_event_get_process_id (eio%hepmc_event)
if (.not. ok) then
iostat = -1
return
end if
i_prc = 0
FIND_I_PRC: do i = 1, size (eio%proc_num_id)
if (eio%proc_num_id(i) == proc_num_id) then
i_prc = i
exit FIND_I_PRC
end if
end do FIND_I_PRC
if (i_prc == 0) call err_index
contains
subroutine err_index
call msg_error ("HepMC: reading events: undefined process ID " &
// char (str (proc_num_id)) // ", aborting read")
iostat = 1
end subroutine err_index
end subroutine eio_hepmc_input_i_prc
subroutine eio_hepmc_input_event (eio, event, iostat)
class(eio_hepmc_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
iostat = 0
call event%reset_contents ()
call event%select (1, 1, 1)
call hepmc_to_event (event, eio%hepmc_event, &
eio%fallback_model, &
recover_beams = eio%recover_beams, &
use_alpha_s = eio%use_alphas_from_file, &
use_scale = eio%use_scale_from_file)
call hepmc_event_final (eio%hepmc_event)
end subroutine eio_hepmc_input_event
@ %def eio_hepmc_input_i_prc
@ %def eio_hepmc_input_event
@
<<EIO HepMC: eio hepmc: TBP>>=
procedure :: skip => eio_hepmc_skip
<<EIO HepMC: procedures>>=
subroutine eio_hepmc_skip (eio, iostat)
class(eio_hepmc_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_hepmc_skip
@ %def eio_hepmc_skip
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_hepmc_ut.f90]]>>=
<<File header>>
module eio_hepmc_ut
use unit_tests
use system_dependencies, only: HEPMC2_AVAILABLE
use system_dependencies, only: HEPMC3_AVAILABLE
use eio_hepmc_uti
<<Standard module head>>
<<EIO HepMC: public test>>
contains
<<EIO HepMC: test driver>>
end module eio_hepmc_ut
@ %def eio_hepmc_ut
@
<<[[eio_hepmc_uti.f90]]>>=
<<File header>>
module eio_hepmc_uti
<<Use kinds>>
<<Use strings>>
use system_dependencies, only: HEPMC2_AVAILABLE
use system_dependencies, only: HEPMC3_AVAILABLE
use io_units
use diagnostics
use model_data
use event_base
use eio_data
use eio_base
use eio_hepmc
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
use eio_base_ut, only: eio_prepare_fallback_model, eio_cleanup_fallback_model
<<Standard module head>>
<<EIO HepMC: test declarations>>
contains
<<EIO HepMC: tests>>
end module eio_hepmc_uti
@ %def eio_hepmc_ut
@ API: driver for the unit tests below.
<<EIO HepMC: public test>>=
public :: eio_hepmc_test
<<EIO HepMC: test driver>>=
subroutine eio_hepmc_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO HepMC: execute tests>>
end subroutine eio_hepmc_test
@ %def eio_hepmc_test
@
\subsubsection{Test I/O methods}
We test the implementation of all I/O methods.
<<EIO HepMC: execute tests>>=
if (HEPMC2_AVAILABLE) then
call test (eio_hepmc_1, "eio_hepmc2_1", &
"write event contents", &
u, results)
else if (HEPMC3_AVAILABLE) then
call test (eio_hepmc_1, "eio_hepmc3_1", &
"write event contents", &
u, results)
end if
<<EIO HepMC: test declarations>>=
public :: eio_hepmc_1
<<EIO HepMC: tests>>=
subroutine eio_hepmc_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat
character(116) :: buffer
write (u, "(A)") "* Test output: eio_hepmc_1"
write (u, "(A)") "* Purpose: write a HepMC file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event, unweighted=.false.)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_hepmc_1"
allocate (eio_hepmc_t :: eio)
select type (eio)
type is (eio_hepmc_t)
call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (55)
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* File contents (blanking out last two digits):"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = char (sample // ".hepmc"), &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (iostat /= 0) exit
if (trim (buffer) == "") cycle
if (buffer(1:14) == "HepMC::Version") cycle
if (HEPMC2_AVAILABLE) then
if (buffer(1:10) == "P 10001 25") &
call buffer_blanker (buffer, 32, 55, 78)
if (buffer(1:10) == "P 10002 25") &
call buffer_blanker (buffer, 33, 56, 79)
if (buffer(1:10) == "P 10003 25") &
call buffer_blanker (buffer, 29, 53, 78, 101)
if (buffer(1:10) == "P 10004 25") &
call buffer_blanker (buffer, 28, 51, 76, 99)
else if (HEPMC3_AVAILABLE) then
if (buffer(1:8) == "P 1 0 25") &
call buffer_blanker (buffer, 26, 49, 72)
if (buffer(1:8) == "P 2 0 25") &
call buffer_blanker (buffer, 26, 49, 73)
if (buffer(1:9) == "P 3 -1 25") &
call buffer_blanker (buffer, 28, 52, 75)
if (buffer(1:9) == "P 4 -1 25") &
call buffer_blanker (buffer, 27, 50, 73)
end if
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_hepmc_t :: eio)
select type (eio)
type is (eio_hepmc_t)
call eio%set_parameters ()
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_hepmc_1"
contains
subroutine buffer_blanker (buf, pos1, pos2, pos3, pos4)
character(len=*), intent(inout) :: buf
integer, intent(in) :: pos1, pos2, pos3
integer, intent(in), optional :: pos4
type(string_t) :: line
line = var_str (trim (buf))
line = replace (line, pos1, "XX")
line = replace (line, pos2, "XX")
line = replace (line, pos3, "XX")
if (present (pos4)) then
line = replace (line, pos4, "XX")
end if
line = replace (line, "4999999999999", "5000000000000")
buf = char (line)
end subroutine buffer_blanker
end subroutine eio_hepmc_1
@ %def eio_hepmc_1
@ Test also the reading of HepMC events.
<<EIO HepMC: execute tests>>=
if (HEPMC2_AVAILABLE) then
call test (eio_hepmc_2, "eio_hepmc2_2", &
"read event contents", &
u, results)
else if (HEPMC3_AVAILABLE) then
call test (eio_hepmc_2, "eio_hepmc3_2", &
"read event contents", &
u, results)
end if
<<EIO HepMC: test declarations>>=
public :: eio_hepmc_2
<<EIO HepMC: tests>>=
subroutine eio_hepmc_2 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: u_file, iostat, i_prc
write (u, "(A)") "* Test output: eio_hepmc_2"
write (u, "(A)") "* Purpose: read a HepMC event"
write (u, "(A)")
write (u, "(A)") "* Write a HepMC data file"
write (u, "(A)")
u_file = free_unit ()
sample = "eio_hepmc_2"
open (u_file, file = char (sample // ".hepmc"), &
status = "replace", action = "readwrite")
if (HEPMC2_AVAILABLE) then
write (u_file, "(A)") "HepMC::Version 2.06.09"
write (u_file, "(A)") "HepMC::IO_GenEvent-START_EVENT_LISTING"
write (u_file, "(A)") "E 66 -1 -1.0000000000000000e+00 &
&-1.0000000000000000e+00 &
&-1.0000000000000000e+00 42 0 1 10001 10002 0 0"
write (u_file, "(A)") "U GEV MM"
write (u_file, "(A)") "V -1 0 0 0 0 0 2 2 0"
write (u_file, "(A)") "P 10001 25 0 0 4.8412291827592713e+02 &
&5.0000000000000000e+02 &
&1.2499999999999989e+02 3 0 0 -1 0"
write (u_file, "(A)") "P 10002 25 0 0 -4.8412291827592713e+02 &
&5.0000000000000000e+02 &
&1.2499999999999989e+02 3 0 0 -1 0"
write (u_file, "(A)") "P 10003 25 -1.4960220911365536e+02 &
&-4.6042825611414656e+02 &
&0 5.0000000000000000e+02 1.2500000000000000e+02 1 0 0 0 0"
write (u_file, "(A)") "P 10004 25 1.4960220911365536e+02 &
&4.6042825611414656e+02 &
&0 5.0000000000000000e+02 1.2500000000000000e+02 1 0 0 0 0"
write (u_file, "(A)") "HepMC::IO_GenEvent-END_EVENT_LISTING"
else if (HEPMC3_AVAILABLE) then
write (u_file, "(A)") "HepMC::Version 3.01.01"
write (u_file, "(A)") "HepMC::Asciiv3-START_EVENT_LISTING"
write (u_file, "(A)") "E 55 1 4"
write (u_file, "(A)") "U GEV MM"
write (u_file, "(A)") "A 0 alphaQCD -1"
write (u_file, "(A)") "A 0 event_scale 1000"
write (u_file, "(A)") "A 0 signal_process_id 42"
write (u_file, "(A)") "P 1 0 25 0.0000000000000000e+00 &
&0.0000000000000000e+00 4.8412291827592713e+02 &
&5.0000000000000000e+02 1.2499999999999989e+02 3"
write (u_file, "(A)") "P 2 0 25 0.0000000000000000e+00 &
&0.0000000000000000e+00 -4.8412291827592713e+02 &
&5.0000000000000000e+02 1.2499999999999989e+02 3"
write (u_file, "(A)") "V -1 0 [1,2]"
write (u_file, "(A)") "P 3 -1 25 -1.4960220911365536e+02 &
&-4.6042825611414656e+02 0.0000000000000000e+00 &
&5.0000000000000000e+02 1.2500000000000000e+02 1"
write (u_file, "(A)") "P 4 -1 25 1.4960220911365536e+02 &
&4.6042825611414656e+02 0.0000000000000000e+00 &
&5.0000000000000000e+02 1.2500000000000000e+02 1"
write (u_file, "(A)") "HepMC::Asciiv3-END_EVENT_LISTING"
else
call msg_fatal &
("Trying to execute eio_hepmc unit tests without a linked HepMC")
end if
close (u_file)
write (u, "(A)") "* Initialize test process"
write (u, "(A)")
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event, unweighted=.false.)
allocate (eio_hepmc_t :: eio)
select type (eio)
type is (eio_hepmc_t)
call eio%set_parameters (recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, "(A)")
write (u, "(A)") "* Initialize"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_hepmc_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_hepmc_2"
end subroutine eio_hepmc_2
@ %def eio_hepmc_2
@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{LCIO Output}
The LCIO event record is standardized for the use with Linear $e^+e^-$
colliders. It is a binary event format. We try our best at using it
for both input and output.
<<[[eio_lcio.f90]]>>=
<<File header>>
module eio_lcio
<<Use kinds>>
<<Use strings>>
use io_units
use string_utils
use diagnostics
use particles
use event_base
use hep_events
use eio_data
use eio_base
use lcio_interface
<<Standard module head>>
<<EIO LCIO: public>>
<<EIO LCIO: types>>
contains
<<EIO LCIO: procedures>>
end module eio_lcio
@ %def eio_lcio
@
\subsection{Type}
A type [[lcio_event]] is introduced as container to store LCIO event
data, particularly for splitting the reading into read out of the process
index and the proper event data.
Note: the [[keep_beams]] flag is not supported.
<<EIO LCIO: public>>=
public :: eio_lcio_t
<<EIO LCIO: types>>=
type, extends (eio_t) :: eio_lcio_t
logical :: writing = .false.
logical :: reading = .false.
type(event_sample_data_t) :: data
logical :: recover_beams = .false.
logical :: use_alphas_from_file = .false.
logical :: use_scale_from_file = .false.
integer :: n_alt = 0
type(lcio_writer_t) :: lcio_writer
type(lcio_reader_t) :: lcio_reader
type(lcio_run_header_t) :: lcio_run_hdr
type(lcio_event_t) :: lcio_event
integer, dimension(:), allocatable :: proc_num_id
contains
<<EIO LCIO: eio lcio: TBP>>
end type eio_lcio_t
@ %def eio_lcio_t
@
\subsection{Specific Methods}
Set parameters that are specifically used with LCIO.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: set_parameters => eio_lcio_set_parameters
<<EIO LCIO: procedures>>=
subroutine eio_lcio_set_parameters &
(eio, recover_beams, use_alphas_from_file, use_scale_from_file, &
extension)
class(eio_lcio_t), intent(inout) :: eio
logical, intent(in), optional :: recover_beams
logical, intent(in), optional :: use_alphas_from_file
logical, intent(in), optional :: use_scale_from_file
type(string_t), intent(in), optional :: extension
if (present (recover_beams)) eio%recover_beams = recover_beams
if (present (use_alphas_from_file)) &
eio%use_alphas_from_file = use_alphas_from_file
if (present (use_scale_from_file)) &
eio%use_scale_from_file = use_scale_from_file
if (present (extension)) then
eio%extension = extension
else
eio%extension = "slcio"
end if
end subroutine eio_lcio_set_parameters
@ %def eio_lcio_set_parameters
@
\subsection{Common Methods}
Output. This is not the actual event format, but a readable account
of the current object status.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: write => eio_lcio_write
<<EIO LCIO: procedures>>=
subroutine eio_lcio_write (object, unit)
class(eio_lcio_t), intent(in) :: object
integer, intent(in), optional :: unit
integer :: u, i
u = given_output_unit (unit)
write (u, "(1x,A)") "LCIO event stream:"
if (object%writing) then
write (u, "(3x,A,A)") "Writing to file = ", char (object%filename)
else if (object%reading) then
write (u, "(3x,A,A)") "Reading from file = ", char (object%filename)
else
write (u, "(3x,A)") "[closed]"
end if
write (u, "(3x,A,L1)") "Recover beams = ", object%recover_beams
write (u, "(3x,A,L1)") "Alpha_s from file = ", &
object%use_alphas_from_file
write (u, "(3x,A,L1)") "Scale from file = ", &
object%use_scale_from_file
write (u, "(3x,A,A,A)") "File extension = '", &
char (object%extension), "'"
if (allocated (object%proc_num_id)) then
write (u, "(3x,A)") "Numerical process IDs:"
do i = 1, size (object%proc_num_id)
write (u, "(5x,I0,': ',I0)") i, object%proc_num_id(i)
end do
end if
end subroutine eio_lcio_write
@ %def eio_lcio_write
@ Finalizer: close any open file.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: final => eio_lcio_final
<<EIO LCIO: procedures>>=
subroutine eio_lcio_final (object)
class(eio_lcio_t), intent(inout) :: object
if (allocated (object%proc_num_id)) deallocate (object%proc_num_id)
if (object%writing) then
write (msg_buffer, "(A,A,A)") "Events: closing LCIO file '", &
char (object%filename), "'"
call msg_message ()
call lcio_writer_close (object%lcio_writer)
object%writing = .false.
else if (object%reading) then
write (msg_buffer, "(A,A,A)") "Events: closing LCIO file '", &
char (object%filename), "'"
call msg_message ()
call lcio_reader_close (object%lcio_reader)
object%reading = .false.
end if
end subroutine eio_lcio_final
@ %def eio_lcio_final
@ Split event file: increment the counter, close the current file, open a new
one. If the file needs a header, repeat it for the new file.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: split_out => eio_lcio_split_out
<<EIO LCIO: procedures>>=
subroutine eio_lcio_split_out (eio)
class(eio_lcio_t), intent(inout) :: eio
if (eio%split) then
eio%split_index = eio%split_index + 1
call eio%set_filename ()
write (msg_buffer, "(A,A,A)") "Events: writing to LCIO file '", &
char (eio%filename), "'"
call msg_message ()
call lcio_writer_close (eio%lcio_writer)
call lcio_writer_open_out (eio%lcio_writer, eio%filename)
end if
end subroutine eio_lcio_split_out
@ %def eio_lcio_split_out
@ Common initialization for input and output.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: common_init => eio_lcio_common_init
<<EIO LCIO: procedures>>=
subroutine eio_lcio_common_init (eio, sample, data, extension)
class(eio_lcio_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
if (.not. present (data)) &
call msg_bug ("LCIO initialization: missing data")
eio%data = data
if (data%n_beam /= 2) &
call msg_fatal ("LCIO: defined for scattering processes only")
if (data%unweighted) then
select case (data%norm_mode)
case (NORM_UNIT)
case default; call msg_fatal &
("LCIO: normalization for unweighted events must be '1'")
end select
else
call msg_fatal ("LCIO: events must be unweighted")
end if
eio%n_alt = data%n_alt
eio%sample = sample
if (present (extension)) then
eio%extension = extension
end if
call eio%set_filename ()
allocate (eio%proc_num_id (data%n_proc), source = data%proc_num_id)
end subroutine eio_lcio_common_init
@ %def eio_lcio_common_init
@ Initialize event writing.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: init_out => eio_lcio_init_out
<<EIO LCIO: procedures>>=
subroutine eio_lcio_init_out (eio, sample, data, success, extension)
class(eio_lcio_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(in), optional :: data
logical, intent(out), optional :: success
call eio%set_splitting (data)
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: writing to LCIO file '", &
char (eio%filename), "'"
call msg_message ()
eio%writing = .true.
call lcio_writer_open_out (eio%lcio_writer, eio%filename)
call lcio_run_header_init (eio%lcio_run_hdr)
call lcio_run_header_write (eio%lcio_writer, eio%lcio_run_hdr)
if (present (success)) success = .true.
end subroutine eio_lcio_init_out
@ %def eio_lcio_init_out
@ Initialize event reading. For input, we do not (yet) support split
event files.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: init_in => eio_lcio_init_in
<<EIO LCIO: procedures>>=
subroutine eio_lcio_init_in (eio, sample, data, success, extension)
class(eio_lcio_t), intent(inout) :: eio
type(string_t), intent(in) :: sample
type(string_t), intent(in), optional :: extension
type(event_sample_data_t), intent(inout), optional :: data
logical, intent(out), optional :: success
logical :: exist
eio%split = .false.
call eio%common_init (sample, data, extension)
write (msg_buffer, "(A,A,A)") "Events: reading from LCIO file '", &
char (eio%filename), "'"
call msg_message ()
inquire (file = char (eio%filename), exist = exist)
if (.not. exist) call msg_fatal ("Events: LCIO file not found.")
eio%reading = .true.
call lcio_open_file (eio%lcio_reader, eio%filename)
if (present (success)) success = .true.
end subroutine eio_lcio_init_in
@ %def eio_lcio_init_in
@ Switch from input to output: reopen the file for reading.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: switch_inout => eio_lcio_switch_inout
<<EIO LCIO: procedures>>=
subroutine eio_lcio_switch_inout (eio, success)
class(eio_lcio_t), intent(inout) :: eio
logical, intent(out), optional :: success
call msg_bug ("LCIO: in-out switch not supported")
if (present (success)) success = .false.
end subroutine eio_lcio_switch_inout
@ %def eio_lcio_switch_inout
@ Output an event to the allocated LCIO writer.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: output => eio_lcio_output
<<EIO LCIO: procedures>>=
subroutine eio_lcio_output (eio, event, i_prc, reading, passed, pacify)
class(eio_lcio_t), intent(inout) :: eio
class(generic_event_t), intent(in), target :: event
integer, intent(in) :: i_prc
logical, intent(in), optional :: reading, passed, pacify
type(particle_set_t), pointer :: pset_ptr
real(default) :: sqme_prc, weight
integer :: i
if (present (passed)) then
if (.not. passed) return
end if
if (eio%writing) then
pset_ptr => event%get_particle_set_ptr ()
call lcio_event_init (eio%lcio_event, &
proc_id = eio%proc_num_id (i_prc), &
event_id = event%get_index ())
call lcio_event_from_particle_set (eio%lcio_event, pset_ptr)
call lcio_event_set_weight (eio%lcio_event, event%weight_prc)
call lcio_event_set_sqrts (eio%lcio_event, event%get_sqrts ())
+ call lcio_event_set_sqme (eio%lcio_event, event%get_sqme_prc ())
call lcio_event_set_scale (eio%lcio_event, event%get_fac_scale ())
call lcio_event_set_alpha_qcd (eio%lcio_event, event%get_alpha_s ())
call lcio_event_set_xsec (eio%lcio_event, eio%data%cross_section(i_prc), &
eio%data%error(i_prc))
call lcio_event_set_polarization (eio%lcio_event, &
event%get_polarization ())
call lcio_event_set_beam_file (eio%lcio_event, &
event%get_beam_file ())
call lcio_event_set_process_name (eio%lcio_event, &
event%get_process_name ())
do i = 1, eio%n_alt
sqme_prc = event%get_sqme_alt(i)
weight = event%get_weight_alt(i)
call lcio_event_set_alt_sqme (eio%lcio_event, sqme_prc, i)
call lcio_event_set_alt_weight (eio%lcio_event, weight, i)
end do
call lcio_event_write (eio%lcio_writer, eio%lcio_event)
call lcio_event_final (eio%lcio_event)
else
call eio%write ()
call msg_fatal ("LCIO file is not open for writing")
end if
end subroutine eio_lcio_output
@ %def eio_lcio_output
@ Input an event.
<<EIO LCIO: eio lcio: TBP>>=
procedure :: input_i_prc => eio_lcio_input_i_prc
procedure :: input_event => eio_lcio_input_event
<<EIO LCIO: procedures>>=
subroutine eio_lcio_input_i_prc (eio, i_prc, iostat)
class(eio_lcio_t), intent(inout) :: eio
integer, intent(out) :: i_prc
integer, intent(out) :: iostat
logical :: ok
integer :: i, proc_num_id
iostat = 0
call lcio_read_event (eio%lcio_reader, eio%lcio_event, ok)
if (.not. ok) then
iostat = -1
return
end if
proc_num_id = lcio_event_get_process_id (eio%lcio_event)
i_prc = 0
FIND_I_PRC: do i = 1, size (eio%proc_num_id)
if (eio%proc_num_id(i) == proc_num_id) then
i_prc = i
exit FIND_I_PRC
end if
end do FIND_I_PRC
if (i_prc == 0) call err_index
contains
subroutine err_index
call msg_error ("LCIO: reading events: undefined process ID " &
// char (str (proc_num_id)) // ", aborting read")
iostat = 1
end subroutine err_index
end subroutine eio_lcio_input_i_prc
subroutine eio_lcio_input_event (eio, event, iostat)
class(eio_lcio_t), intent(inout) :: eio
class(generic_event_t), intent(inout), target :: event
integer, intent(out) :: iostat
iostat = 0
call event%reset_contents ()
call event%select (1, 1, 1)
call event%set_index (lcio_event_get_event_index (eio%lcio_event))
call lcio_to_event (event, eio%lcio_event, eio%fallback_model, &
recover_beams = eio%recover_beams, &
use_alpha_s = eio%use_alphas_from_file, &
use_scale = eio%use_scale_from_file)
call lcio_event_final (eio%lcio_event)
end subroutine eio_lcio_input_event
@ %def eio_lcio_input_i_prc
@ %def eio_lcio_input_event
@
<<EIO LCIO: eio lcio: TBP>>=
procedure :: skip => eio_lcio_skip
<<EIO LCIO: procedures>>=
subroutine eio_lcio_skip (eio, iostat)
class(eio_lcio_t), intent(inout) :: eio
integer, intent(out) :: iostat
iostat = 0
end subroutine eio_lcio_skip
@ %def eio_lcio_skip
@
\subsection{Unit tests}
Test module, followed by the corresponding implementation module.
<<[[eio_lcio_ut.f90]]>>=
<<File header>>
module eio_lcio_ut
use unit_tests
use eio_lcio_uti
<<Standard module head>>
<<EIO LCIO: public test>>
contains
<<EIO LCIO: test driver>>
end module eio_lcio_ut
@ %def eio_lcio_ut
@
<<[[eio_lcio_uti.f90]]>>=
<<File header>>
module eio_lcio_uti
<<Use kinds>>
<<Use strings>>
use io_units
use model_data
use particles
use event_base
use eio_data
use eio_base
use hep_events
use lcio_interface
use eio_lcio
use eio_base_ut, only: eio_prepare_test, eio_cleanup_test
use eio_base_ut, only: eio_prepare_fallback_model, eio_cleanup_fallback_model
<<Standard module head>>
<<EIO LCIO: test declarations>>
contains
<<EIO LCIO: tests>>
end module eio_lcio_uti
@ %def eio_lcio_ut
@ API: driver for the unit tests below.
<<EIO LCIO: public test>>=
public :: eio_lcio_test
<<EIO LCIO: test driver>>=
subroutine eio_lcio_test (u, results)
integer, intent(in) :: u
type(test_results_t), intent(inout) :: results
<<EIO LCIO: execute tests>>
end subroutine eio_lcio_test
@ %def eio_lcio_test
@
\subsubsection{Test I/O methods}
We test the implementation of all I/O methods.
<<EIO LCIO: execute tests>>=
call test (eio_lcio_1, "eio_lcio_1", &
"write event contents", &
u, results)
<<EIO LCIO: test declarations>>=
public :: eio_lcio_1
<<EIO LCIO: tests>>=
subroutine eio_lcio_1 (u)
integer, intent(in) :: u
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(particle_set_t), pointer :: pset_ptr
type(string_t) :: sample
integer :: u_file, iostat
character(215) :: buffer
write (u, "(A)") "* Test output: eio_lcio_1"
write (u, "(A)") "* Purpose: write a LCIO file"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
call eio_prepare_test (event)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_lcio_1"
allocate (eio_lcio_t :: eio)
select type (eio)
type is (eio_lcio_t)
call eio%set_parameters ()
end select
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (77)
call event%pacify_particle_set ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
write (u, "(A)")
write (u, "(A)") "* Reset data"
write (u, "(A)")
deallocate (eio)
allocate (eio_lcio_t :: eio)
select type (eio)
type is (eio_lcio_t)
call eio%set_parameters ()
end select
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Write LCIO file contents to ASCII file"
write (u, "(A)")
select type (eio)
type is (eio_lcio_t)
call lcio_event_init (eio%lcio_event, &
proc_id = 42, &
event_id = event%get_index ())
pset_ptr => event%get_particle_set_ptr ()
call lcio_event_from_particle_set &
(eio%lcio_event, pset_ptr)
call write_lcio_event (eio%lcio_event, var_str ("test_file.slcio"))
call lcio_event_final (eio%lcio_event)
end select
write (u, "(A)")
write (u, "(A)") "* Read in ASCII contents of LCIO file"
write (u, "(A)")
u_file = free_unit ()
open (u_file, file = "test_file.slcio", &
action = "read", status = "old")
do
read (u_file, "(A)", iostat = iostat) buffer
if (iostat /= 0) exit
if (trim (buffer) == "") cycle
if (buffer(1:12) == " - timestamp") cycle
if (buffer(1:6) == " date:") cycle
write (u, "(A)") trim (buffer)
end do
close (u_file)
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio_cleanup_test (event)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lcio_1"
end subroutine eio_lcio_1
@ %def eio_lcio_1
@ Test also the reading of LCIO events.
<<EIO LCIO: execute tests>>=
call test (eio_lcio_2, "eio_lcio_2", &
"read event contents", &
u, results)
<<EIO LCIO: test declarations>>=
public :: eio_lcio_2
<<EIO LCIO: tests>>=
subroutine eio_lcio_2 (u)
integer, intent(in) :: u
class(model_data_t), pointer :: fallback_model
class(generic_event_t), pointer :: event
type(event_sample_data_t) :: data
class(eio_t), allocatable :: eio
type(string_t) :: sample
integer :: iostat, i_prc
write (u, "(A)") "* Test output: eio_lcio_2"
write (u, "(A)") "* Purpose: read a LCIO event"
write (u, "(A)")
write (u, "(A)") "* Initialize test process"
allocate (fallback_model)
call eio_prepare_fallback_model (fallback_model)
call eio_prepare_test (event)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
data%cross_section(1) = 100
data%error(1) = 1
data%total_cross_section = sum (data%cross_section)
write (u, "(A)")
write (u, "(A)") "* Generate and write an event"
write (u, "(A)")
sample = "eio_lcio_2"
allocate (eio_lcio_t :: eio)
select type (eio)
type is (eio_lcio_t)
call eio%set_parameters (recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call eio%init_out (sample, data)
call event%generate (1, [0._default, 0._default])
call event%set_index (88)
call event%evaluate_expressions ()
call event%pacify_particle_set ()
call eio%output (event, i_prc = 1)
call eio%write (u)
call eio%final ()
deallocate (eio)
call event%reset_contents ()
call event%reset_index ()
write (u, "(A)")
write (u, "(A)") "* Initialize"
write (u, "(A)")
allocate (eio_lcio_t :: eio)
select type (eio)
type is (eio_lcio_t)
call eio%set_parameters (recover_beams = .false.)
end select
call eio%set_fallback_model (fallback_model)
call data%init (1)
data%n_beam = 2
data%unweighted = .true.
data%norm_mode = NORM_UNIT
data%pdg_beam = 25
data%energy_beam = 500
data%proc_num_id = [42]
call data%write (u)
write (u, *)
write (u, "(A)") "* Initialize"
write (u, "(A)")
call eio%init_in (sample, data)
call eio%write (u)
write (u, "(A)")
write (u, "(A)") "* Read event"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
select type (eio)
type is (eio_lcio_t)
write (u, "(A,I0,A,I0)") "Found process #", i_prc, &
" with ID = ", eio%proc_num_id(i_prc)
end select
call eio%input_event (event, iostat)
call event%write (u)
write (u, "(A)")
write (u, "(A)") "* Read closing"
write (u, "(A)")
call eio%input_i_prc (i_prc, iostat)
write (u, "(A,I0)") "iostat = ", iostat
write (u, "(A)")
write (u, "(A)") "* Cleanup"
call eio%final ()
call eio_cleanup_test (event)
call eio_cleanup_fallback_model (fallback_model)
deallocate (fallback_model)
write (u, "(A)")
write (u, "(A)") "* Test output end: eio_lcio_2"
end subroutine eio_lcio_2
@ %def eio_lcio_2
Index: trunk/share/tests/functional_tests/ref-output-quad/lcio_2.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output-quad/lcio_2.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output-quad/lcio_2.ref (revision 8337)
@@ -1,118 +1,119 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_2_lib': recorded process 'lcio_2_p'
sqrts = 1.000000000000E+03
| Integrate: current process library needs compilation
| Process library 'lcio_2_lib': compiling ...
| Process library 'lcio_2_lib': writing makefile
| Process library 'lcio_2_lib': removing old files
| Process library 'lcio_2_lib': writing driver
| Process library 'lcio_2_lib': creating source code
| Process library 'lcio_2_lib': compiling sources
| Process library 'lcio_2_lib': linking
| Process library 'lcio_2_lib': loading
| Process library 'lcio_2_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_2_p:
| Beam structure: e-, e+ => isr
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV)
| e+ (mass = 5.1100000E-04 GeV)
| sqrts = 1.000000000000E+03 GeV
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_2_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_2_p'
| Library name = 'lcio_2_lib'
| Process index = 1
| Process components:
| 1: 'lcio_2_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
| Beam structure: isr, none => none, isr
| Beam structure: 1 channels, 2 dimensions
Warning: No cuts have been defined.
| Starting integration for process 'lcio_2_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 4 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 9.9402933E+01 4.65E+00 4.67 0.47* 24.86
|-----------------------------------------------------------------------------|
1 100 9.9402933E+01 4.65E+00 4.67 0.47 24.86
|=============================================================================|
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_2_p'
| Simulate: using integration grids from file 'lcio_2_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 1.0060E-02
| Events: writing to LCIO file 'lcio_2_p.slcio'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_2_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_2_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 1000,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 99.4029,
parameter crossSectionError [float]: 4.64628,
parameter scale [float]: 998.962,
+ parameter sqme [float]: 1.34846e+06,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_2_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 5.00e+02| 5.00e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,4]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [3,5]
[00000006] 2| 11| 0.00e+00, 0.00e+00, 4.99e+02| 4.99e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0] - [6,7]
[00000007] 3| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [1] - [6,7]
[00000008] 4| 22| 0.00e+00, 0.00e+00, 1.04e+00| 1.04e+00| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0] - []
[00000009] 5| 22| 0.00e+00, 0.00e+00,-2.44e-06| 2.44e-06| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [1] - []
[00000010] 6| 13| 2.77e+01,-2.11e+02,-4.52e+02| 5.00e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
[00000011] 7| -13|-2.77e+01, 2.11e+02, 4.51e+02| 4.99e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output-ext/lcio_2.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output-ext/lcio_2.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output-ext/lcio_2.ref (revision 8337)
@@ -1,118 +1,119 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_2_lib': recorded process 'lcio_2_p'
sqrts = 1.000000000000E+03
| Integrate: current process library needs compilation
| Process library 'lcio_2_lib': compiling ...
| Process library 'lcio_2_lib': writing makefile
| Process library 'lcio_2_lib': removing old files
| Process library 'lcio_2_lib': writing driver
| Process library 'lcio_2_lib': creating source code
| Process library 'lcio_2_lib': compiling sources
| Process library 'lcio_2_lib': linking
| Process library 'lcio_2_lib': loading
| Process library 'lcio_2_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_2_p:
| Beam structure: e-, e+ => isr
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV)
| e+ (mass = 5.1100000E-04 GeV)
| sqrts = 1.000000000000E+03 GeV
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_2_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_2_p'
| Library name = 'lcio_2_lib'
| Process index = 1
| Process components:
| 1: 'lcio_2_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
| Beam structure: isr, none => none, isr
| Beam structure: 1 channels, 2 dimensions
Warning: No cuts have been defined.
| Starting integration for process 'lcio_2_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 4 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 9.9402995E+01 4.65E+00 4.67 0.47* 24.86
|-----------------------------------------------------------------------------|
1 100 9.9402995E+01 4.65E+00 4.67 0.47 24.86
|=============================================================================|
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_2_p'
| Simulate: using integration grids from file 'lcio_2_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 1.0060E-02
| Events: writing to LCIO file 'lcio_2_p.slcio'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_2_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_2_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 1000,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 99.403,
parameter crossSectionError [float]: 4.64628,
parameter scale [float]: 998.962,
+ parameter sqme [float]: 1.34846e+06,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_2_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 5.00e+02| 5.00e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,4]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [3,5]
[00000006] 2| 11| 0.00e+00, 0.00e+00, 4.99e+02| 4.99e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0] - [6,7]
[00000007] 3| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [1] - [6,7]
[00000008] 4| 22| 0.00e+00, 0.00e+00, 1.04e+00| 1.04e+00| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0] - []
[00000009] 5| 22| 0.00e+00, 0.00e+00,-2.44e-06| 2.44e-06| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [1] - []
[00000010] 6| 13| 2.77e+01,-2.11e+02,-4.52e+02| 5.00e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
[00000011] 7| -13|-2.77e+01, 2.11e+02, 4.51e+02| 4.99e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output-double/lcio_2.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output-double/lcio_2.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output-double/lcio_2.ref (revision 8337)
@@ -1,118 +1,119 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_2_lib': recorded process 'lcio_2_p'
sqrts = 1.000000000000E+03
| Integrate: current process library needs compilation
| Process library 'lcio_2_lib': compiling ...
| Process library 'lcio_2_lib': writing makefile
| Process library 'lcio_2_lib': removing old files
| Process library 'lcio_2_lib': writing driver
| Process library 'lcio_2_lib': creating source code
| Process library 'lcio_2_lib': compiling sources
| Process library 'lcio_2_lib': linking
| Process library 'lcio_2_lib': loading
| Process library 'lcio_2_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_2_p:
| Beam structure: e-, e+ => isr
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV)
| e+ (mass = 5.1100000E-04 GeV)
| sqrts = 1.000000000000E+03 GeV
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_2_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_2_p'
| Library name = 'lcio_2_lib'
| Process index = 1
| Process components:
| 1: 'lcio_2_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
| Beam structure: isr, none => none, isr
| Beam structure: 1 channels, 2 dimensions
Warning: No cuts have been defined.
| Starting integration for process 'lcio_2_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 4 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 9.9403105E+01 4.65E+00 4.67 0.47* 24.86
|-----------------------------------------------------------------------------|
1 100 9.9403105E+01 4.65E+00 4.67 0.47 24.86
|=============================================================================|
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_2_p'
| Simulate: using integration grids from file 'lcio_2_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 1.0060E-02
| Events: writing to LCIO file 'lcio_2_p.slcio'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_2_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_2_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 1000,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 99.4031,
parameter crossSectionError [float]: 4.64628,
parameter scale [float]: 998.962,
+ parameter sqme [float]: 1.34846e+06,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_2_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 5.00e+02| 5.00e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,4]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [3,5]
[00000006] 2| 11| 0.00e+00, 0.00e+00, 4.99e+02| 4.99e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0] - [6,7]
[00000007] 3| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [1] - [6,7]
[00000008] 4| 22| 0.00e+00, 0.00e+00, 1.04e+00| 1.04e+00| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0] - []
[00000009] 5| 22| 0.00e+00, 0.00e+00,-2.44e-06| 2.44e-06| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [1] - []
[00000010] 6| 13| 2.77e+01,-2.11e+02,-4.52e+02| 5.00e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
[00000011] 7| -13|-2.77e+01, 2.11e+02, 4.51e+02| 4.99e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output/lcio_10.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output/lcio_10.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output/lcio_10.ref (revision 8337)
@@ -1,219 +1,220 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?alphas_is_fixed = true
seed = 0
| Process library 'lcio_10_lib': recorded process 'lcio_10_p'
sqrts = 8.000000000000E+03
openmp_num_threads = 1
n_events = 1
?unweighted = true
?read_raw = false
?write_raw = false
?update_sqme = true
?update_weight = true
?keep_beams = true
QCD.alphas => 1.250000000000E-01
QCD.alphas => 2.500000000000E-01
QCD.alphas => 5.000000000000E-01
QCD.alphas => 1.000000000000E+00
QCD.alphas => 2.000000000000E+00
QCD.alphas => 4.000000000000E+00
QCD.alphas => 8.000000000000E+00
QCD.alphas => 1.600000000000E+01
QCD.alphas => 3.200000000000E+01
QCD.alphas => 6.400000000000E+01
| Starting simulation for process 'lcio_10_p'
| Simulate: process 'lcio_10_p' needs integration
| Integrate: current process library needs compilation
| Process library 'lcio_10_lib': compiling ...
| Process library 'lcio_10_lib': writing makefile
| Process library 'lcio_10_lib': removing old files
| Process library 'lcio_10_lib': writing driver
| Process library 'lcio_10_lib': creating source code
| Process library 'lcio_10_lib': compiling sources
| Process library 'lcio_10_lib': linking
| Process library 'lcio_10_lib': loading
| Process library 'lcio_10_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_10_p:
| Beam structure: p, p => pdf_builtin
| Beam data (collision):
| p (mass = 0.0000000E+00 GeV)
| p (mass = 0.0000000E+00 GeV)
| sqrts = 8.000000000000E+03 GeV
| Initialized builtin PDF CTEQ6L
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_10_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_10_p'
| Library name = 'lcio_10_lib'
| Process index = 1
| Process components:
| 1: 'lcio_10_p_i1': gl, gl => t, tbar [omega]
| ------------------------------------------------------------------------
| Phase space: 5 channels, 2 dimensions
| Phase space: found 5 channels, collected in 2 groves.
| Phase space: Using 9 equivalences between channels.
| Phase space: wood
| Beam structure: pdf_builtin, none => none, pdf_builtin
| Beam structure: 1 channels, 2 dimensions
Warning: No cuts have been defined.
| Starting integration for process 'lcio_10_p'
| Integrate: iterations = 1:1000
| Integrator: 2 chains, 5 channels, 4 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 1000 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 1000 9.7927939E+04 2.08E+04 21.24 6.72* 1.51
|-----------------------------------------------------------------------------|
1 1000 9.7927939E+04 2.08E+04 21.24 6.72 1.51
|=============================================================================|
| Simulate: integration done
| Simulate: using integration grids from file 'lcio_10_p.m1.vg'
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 2
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 3
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 4
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 5
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 6
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 7
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 8
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 9
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| Simulate: initializing alternate process setup ...
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 10
Warning: Reading phs file: MD5 sum check disabled
| Phase space: keeping configuration file 'lcio_10_p.i1.phs'
| ... alternate process setup complete.
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 11
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 1.0212E-05
| Events: writing to LCIO file 'lcio_10_p.slcio'
| Events: writing to weight stream file 'lcio_10_p.weights.dat'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 0.32 %
| Events: closing LCIO file 'lcio_10_p.slcio'
| Events: closing weight stream file 'lcio_10_p.weights.dat'
| There were no errors and 11 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_10_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 2212,
parameter beamPDG2 [int]: 2212,
parameter Energy [float]: 8000,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter alternateSqme1 [float]: 135.189,
parameter alternateSqme10 [float]: 3.54389e+07,
parameter alternateSqme2 [float]: 540.754,
parameter alternateSqme3 [float]: 2163.02,
parameter alternateSqme4 [float]: 8652.07,
parameter alternateSqme5 [float]: 34608.3,
parameter alternateSqme6 [float]: 138433,
parameter alternateSqme7 [float]: 553732,
parameter alternateSqme8 [float]: 2.21493e+06,
parameter alternateSqme9 [float]: 8.85972e+06,
parameter alternateWeight1 [float]: 1.12598,
parameter alternateWeight10 [float]: 295168,
parameter alternateWeight2 [float]: 4.50391,
parameter alternateWeight3 [float]: 18.0156,
parameter alternateWeight4 [float]: 72.0625,
parameter alternateWeight5 [float]: 288.25,
parameter alternateWeight6 [float]: 1153,
parameter alternateWeight7 [float]: 4612,
parameter alternateWeight8 [float]: 18448,
parameter alternateWeight9 [float]: 73792,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 97927.9,
parameter crossSectionError [float]: 20802.6,
parameter scale [float]: 488.791,
+ parameter sqme [float]: 120.063,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_10_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 2212| 0.00e+00, 0.00e+00, 4.00e+03| 4.00e+03| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,4]
[00000005] 1| 2212| 0.00e+00, 0.00e+00,-4.00e+03| 4.00e+03| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [3,5]
[00000006] 2| 21| 0.00e+00, 0.00e+00, 7.22e+01| 7.22e+01| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (1, 2) | [0] - [6,7]
[00000007] 3| 21| 0.00e+00, 0.00e+00,-8.27e+02| 8.27e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (3, 1) | [1] - [6,7]
[00000008] 4| 93| 0.00e+00, 0.00e+00, 3.93e+03| 3.93e+03| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (2, 1) | [0] - []
[00000009] 5| 93| 0.00e+00, 0.00e+00,-3.17e+03| 3.17e+03| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 0.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (1, 3) | [1] - []
[00000010] 6| 6| 1.60e+02,-2.33e+01,-4.88e+02| 5.42e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.73e+02| 6.67e-01| 0.00e+00, 0.00e+00, 0.00e+00| (3, 0) | [2,3] - []
[00000011] 7| -6|-1.60e+02, 2.33e+01,-2.67e+02| 3.57e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.73e+02|-6.67e-01| 0.00e+00, 0.00e+00, 0.00e+00| (0, 2) | [2,3] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output/lcio_1.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output/lcio_1.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output/lcio_1.ref (revision 8337)
@@ -1,112 +1,113 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_1_lib': recorded process 'lcio_1_p'
sqrts = 1.000000000000E+03
| Integrate: current process library needs compilation
| Process library 'lcio_1_lib': compiling ...
| Process library 'lcio_1_lib': writing makefile
| Process library 'lcio_1_lib': removing old files
| Process library 'lcio_1_lib': writing driver
| Process library 'lcio_1_lib': creating source code
| Process library 'lcio_1_lib': compiling sources
| Process library 'lcio_1_lib': linking
| Process library 'lcio_1_lib': loading
| Process library 'lcio_1_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_1_p:
| Beam structure: [any particles]
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV)
| e+ (mass = 5.1100000E-04 GeV)
| sqrts = 1.000000000000E+03 GeV
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_1_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_1_p'
| Library name = 'lcio_1_lib'
| Process index = 1
| Process components:
| 1: 'lcio_1_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
Warning: No cuts have been defined.
| Starting integration for process 'lcio_1_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 2 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 8.4620428E+01 1.81E+00 2.14 0.21* 65.91
|-----------------------------------------------------------------------------|
1 100 8.4620428E+01 1.81E+00 2.14 0.21 65.91
|=============================================================================|
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_1_p'
| Simulate: using integration grids from file 'lcio_1_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 1.1817E-02
| Events: writing to LCIO file 'lcio_1_p.slcio'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_1_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_1_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 1000,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 84.6204,
parameter crossSectionError [float]: 1.8082,
parameter scale [float]: 1000,
+ parameter sqme [float]: 0.00878025,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_1_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 5.00e+02| 5.00e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-5.00e+02| 5.00e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000006] 2| 13| 2.85e+02, 3.98e+02,-1.04e+02| 5.00e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0,1] - []
[00000007] 3| -13|-2.85e+02,-3.98e+02, 1.04e+02| 5.00e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0,1] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output/lcio_3.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output/lcio_3.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output/lcio_3.ref (revision 8337)
@@ -1,117 +1,118 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_3_lib': recorded process 'lcio_3_p'
sqrts = 5.000000000000E+02
| Integrate: current process library needs compilation
| Process library 'lcio_3_lib': compiling ...
| Process library 'lcio_3_lib': writing makefile
| Process library 'lcio_3_lib': removing old files
| Process library 'lcio_3_lib': writing driver
| Process library 'lcio_3_lib': creating source code
| Process library 'lcio_3_lib': compiling sources
| Process library 'lcio_3_lib': linking
| Process library 'lcio_3_lib': loading
| Process library 'lcio_3_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_3_p:
| Beam structure: e-, e+
| polarization (beam 1):
| @(-1: -1: ( 1.000000000000E+00, 0.000000000000E+00))
| polarization (beam 2):
| @(+1: +1: ( 1.000000000000E+00, 0.000000000000E+00))
| polarization degree = 0.8000000, 0.3000000
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV) polarized
| e+ (mass = 5.1100000E-04 GeV) polarized
| sqrts = 5.000000000000E+02 GeV
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_3_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_3_p'
| Library name = 'lcio_3_lib'
| Process index = 1
| Process components:
| 1: 'lcio_3_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
Warning: No cuts have been defined.
| Starting integration for process 'lcio_3_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 2 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 4.1971732E+02 8.97E+00 2.14 0.21* 65.91
|-----------------------------------------------------------------------------|
1 100 4.1971732E+02 8.97E+00 2.14 0.21 65.91
|=============================================================================|
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_3_p'
| Simulate: using integration grids from file 'lcio_3_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 2.3826E-03
| Events: writing to LCIO file 'lcio_3_p.slcio'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_3_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_3_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 500,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: -0.8,
parameter beamPol2 [float]: 0.3,
parameter crossSection [float]: 419.717,
parameter crossSectionError [float]: 8.96867,
parameter scale [float]: 500,
+ parameter sqme [float]: 0.0108875,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_3_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 2.50e+02| 2.50e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-2.50e+02| 2.50e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000006] 2| 13| 1.42e+02, 1.99e+02,-5.22e+01| 2.50e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0,1] - []
[00000007] 3| -13|-1.42e+02,-1.99e+02, 5.22e+01| 2.50e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0,1] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output/lcio_5.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output/lcio_5.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output/lcio_5.ref (revision 8337)
@@ -1,115 +1,116 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_5_lib': recorded process 'lcio_5_p'
sqrts = 5.000000000000E+02
| Integrate: current process library needs compilation
| Process library 'lcio_5_lib': compiling ...
| Process library 'lcio_5_lib': writing makefile
| Process library 'lcio_5_lib': removing old files
| Process library 'lcio_5_lib': writing driver
| Process library 'lcio_5_lib': creating source code
| Process library 'lcio_5_lib': compiling sources
| Process library 'lcio_5_lib': linking
| Process library 'lcio_5_lib': loading
| Process library 'lcio_5_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_5_p:
| Beam structure: [any particles]
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV)
| e+ (mass = 5.1100000E-04 GeV)
| sqrts = 5.000000000000E+02 GeV
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_5_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_5_p'
| Library name = 'lcio_5_lib'
| Process index = 1
| Process components:
| 1: 'lcio_5_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
Warning: No cuts have been defined.
| Starting integration for process 'lcio_5_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 2 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 3.3848171E+02 7.23E+00 2.14 0.21* 65.91
|-----------------------------------------------------------------------------|
1 100 3.3848171E+02 7.23E+00 2.14 0.21 65.91
|=============================================================================|
| Particle m- declared as polarized
| Particle m+ declared as polarized
?polarized_events = true
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_5_p'
| Simulate: using integration grids from file 'lcio_5_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 2.9544E-03
| Events: writing to LCIO file 'lcio_5_p.slcio'
| Events: generating 1 unweighted, polarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_5_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_5_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 500,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 338.482,
parameter crossSectionError [float]: 7.2328,
parameter scale [float]: 500,
+ parameter sqme [float]: 0.00878025,
parameter BeamSpectrum [string]: ,
parameter processName [string]: lcio_5_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 2.50e+02| 2.50e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-2.50e+02| 2.50e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000006] 2| 13| 1.42e+02, 1.99e+02,-5.22e+01| 2.50e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 1.00e+00| (0, 0) | [0,1] - []
[00000007] 3| -13|-1.42e+02,-1.99e+02, 5.22e+01| 2.50e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00,-1.00e+00| (0, 0) | [0,1] - []
--------------------------------------------------------------------------------
Index: trunk/share/tests/functional_tests/ref-output/lcio_4.ref
===================================================================
--- trunk/share/tests/functional_tests/ref-output/lcio_4.ref (revision 8336)
+++ trunk/share/tests/functional_tests/ref-output/lcio_4.ref (revision 8337)
@@ -1,122 +1,123 @@
?openmp_logging = false
?vis_history = false
?integration_timer = false
?write_raw = false
seed = 0
| Process library 'lcio_4_lib': recorded process 'lcio_4_p'
sqrts = 5.000000000000E+02
$circe2_file = "ilc500.circe"
$circe2_design = "ILC"
?circe2_polarized = false
| Integrate: current process library needs compilation
| Process library 'lcio_4_lib': compiling ...
| Process library 'lcio_4_lib': writing makefile
| Process library 'lcio_4_lib': removing old files
| Process library 'lcio_4_lib': writing driver
| Process library 'lcio_4_lib': creating source code
| Process library 'lcio_4_lib': compiling sources
| Process library 'lcio_4_lib': linking
| Process library 'lcio_4_lib': loading
| Process library 'lcio_4_lib': ... success.
| Integrate: compilation done
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 0
| Initializing integration for process lcio_4_p:
| Beam structure: e-, e+ => circe2
| Beam data (collision):
| e- (mass = 5.1100000E-04 GeV)
| e+ (mass = 5.1100000E-04 GeV)
| sqrts = 5.000000000000E+02 GeV
| CIRCE2: activating generator mode
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 1
| Phase space: generating configuration ...
| Phase space: ... success.
| Phase space: writing configuration file 'lcio_4_p.i1.phs'
| ------------------------------------------------------------------------
| Process [scattering]: 'lcio_4_p'
| Library name = 'lcio_4_lib'
| Process index = 1
| Process components:
| 1: 'lcio_4_p_i1': e-, e+ => m-, m+ [omega]
| ------------------------------------------------------------------------
| Phase space: 1 channels, 2 dimensions
| Phase space: found 1 channel, collected in 1 grove.
| Phase space: Using 1 equivalence between channels.
| Phase space: wood
| Beam structure: circe2
| Beam structure: 1 channels, 0 dimensions
Warning: No cuts have been defined.
| Starting integration for process 'lcio_4_p'
| Integrate: iterations = 1:100
| Integrator: 1 chains, 1 channels, 2 dimensions
| Integrator: Using VAMP channel equivalences
| Integrator: 100 initial calls, 20 bins, stratified = T
| Integrator: VAMP
|=============================================================================|
| It Calls Integral[fb] Error[fb] Err[%] Acc Eff[%] Chi2 N[It] |
|=============================================================================|
1 100 3.6192633E+02 9.69E+00 2.68 0.27* 43.00
|-----------------------------------------------------------------------------|
1 100 3.6192633E+02 9.69E+00 2.68 0.27 43.00
|=============================================================================|
n_events = 1
openmp_num_threads = 1
| Starting simulation for process 'lcio_4_p'
| Simulate: using integration grids from file 'lcio_4_p.m1.vg'
| RNG: Initializing TAO random-number generator
| RNG: Setting seed for random-number generator to 2
| Simulation: requested number of events = 1
| corr. to luminosity [fb-1] = 2.7630E-03
| Events: writing to LCIO file 'lcio_4_p.slcio'
| Events: generating 1 unweighted, unpolarized events ...
| Events: event normalization mode '1'
| ... event sample complete.
| Events: actual unweighting efficiency = 100.00 %
| Events: closing LCIO file 'lcio_4_p.slcio'
| There were no errors and 1 warning(s).
| WHIZARD run finished.
|=============================================================================|
Output from running lcio_4_rd:
============================================================================
Event : 1 - run: 0 - timestamp [...]
============================================================================
date: [...]
detector : unknown
event parameters:
parameter Event Number [int]: 1,
parameter ProcessID [int]: 1,
parameter Run ID [int]: 0,
parameter beamPDG1 [int]: 11,
parameter beamPDG2 [int]: -11,
parameter Energy [float]: 500,
parameter _weight [float]: 1,
parameter alphaQCD [float]: 0.1178,
parameter beamPol1 [float]: 0,
parameter beamPol2 [float]: 0,
parameter crossSection [float]: 361.926,
parameter crossSectionError [float]: 9.68695,
parameter scale [float]: 457.78,
+ parameter sqme [float]: 0.00878025,
parameter BeamSpectrum [string]: CIRCE2: ilc500.circe,
parameter processName [string]: lcio_4_p,
collection name : MCParticle
parameters:
--------------- print out of MCParticle collection ---------------
flag: 0x0
simulator status bits: [sbvtcls] s: created in simulation b: backscatter v: vertex is not endpoint of parent t: decayed in tracker c: decayed in calorimeter l: has left detector s: stopped o: overlay
[ id ]index| PDG | px, py, pz | energy |gen|[simstat ]| vertex x, y , z | mass | charge | spin | colorflow | [parents] - [daughters]
[00000004] 0| 11| 0.00e+00, 0.00e+00, 2.50e+02| 2.50e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000005] 1| -11| 0.00e+00, 0.00e+00,-2.50e+02| 2.50e+02| 4 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 5.11e-04| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [] - [2,3]
[00000006] 2| 11| 0.00e+00, 0.00e+00, 2.24e+02| 2.24e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0,1] - [4,5]
[00000007] 3| -11| 0.00e+00, 0.00e+00,-2.34e+02| 2.34e+02| 3 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 0.00e+00| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [0,1] - [4,5]
[00000008] 4| 13| 1.30e+02, 1.82e+02,-5.25e+01| 2.30e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01|-1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
[00000009] 5| -13|-1.30e+02,-1.82e+02, 4.31e+01| 2.28e+02| 1 |[ 0 ]| 0.00e+00, 0.00e+00, 0.00e+00| 1.06e-01| 1.00e+00| 0.00e+00, 0.00e+00, 0.00e+00| (0, 0) | [2,3] - []
--------------------------------------------------------------------------------

File Metadata

Mime Type
text/x-diff
Expires
Sat, Dec 21, 5:50 PM (6 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4023701
Default Alt Text
(726 KB)

Event Timeline