1 | //-------------------------------------------------------------------------- |
---|
2 | #ifndef HEPMC_FLOW_H |
---|
3 | #define HEPMC_FLOW_H |
---|
4 | |
---|
5 | ////////////////////////////////////////////////////////////////////////// |
---|
6 | // Matt.Dobbs@Cern.CH, January 2000, refer to: |
---|
7 | // M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for |
---|
8 | // High Energy Physics", Computer Physics Communications (to be published). |
---|
9 | // |
---|
10 | // particle's flow object |
---|
11 | // keeps track of an arbitrary number of flow patterns within a graph |
---|
12 | // (i.e. color flow, charge flow, lepton number flow, ...) |
---|
13 | // Flow patterns are coded with an integer, in the same manner as in Herwig. |
---|
14 | // Note: 0 is NOT allowed as code index nor as flow code since it |
---|
15 | // is used to indicate null. |
---|
16 | ////////////////////////////////////////////////////////////////////////// |
---|
17 | |
---|
18 | // This class can be used to keep track of flow patterns within |
---|
19 | // a graph. An example is color flow. If we have two quarks going through |
---|
20 | // an s-channel gluon to form two more quarks: |
---|
21 | // |
---|
22 | // \q1 /q3 then we can keep track of the color flow with the |
---|
23 | // \_______/ HepMC::Flow class as follows: |
---|
24 | // / g \. |
---|
25 | // /q2 \q4 |
---|
26 | // |
---|
27 | // lets say the color flows from q2-->g-->q3 and q1-->g-->q4 |
---|
28 | // the individual colors are unimportant, but the flow pattern is. |
---|
29 | // We can capture this flow by assigning the first pattern (q2-->g-->q3) |
---|
30 | // a unique (arbitrary) flow code 678 and the second pattern (q1-->g-->q4) |
---|
31 | // flow code 269 ( you can ask HepMC::Flow to choose |
---|
32 | // a unique code for you using Flow::set_unique_icode() ). |
---|
33 | // The first two code indices are reserved for color codes, so we store |
---|
34 | // these codes with the particles as follows: |
---|
35 | // q2->flow().set_icode(1,678); |
---|
36 | // g->flow().set_icode(1,678); |
---|
37 | // q3->flow().set_icode(1,678); |
---|
38 | // q1->flow().set_icode(1,269); |
---|
39 | // g->flow().set_icode(2,269); |
---|
40 | // q4->flow().set_icode(1,269); |
---|
41 | // later on if we wish to know the color partner of q1 we can ask for a list |
---|
42 | // of all particles connected via this code to q1 which do have less than |
---|
43 | // 2 color partners using: |
---|
44 | // vector<GenParticle*> result=q1->dangling_connected_partners(q1->icode(1),1,2); |
---|
45 | // this will return a list containing q1 and q4. |
---|
46 | // vector<GenParticle*> result=q1->connected_partners(q1->icode(1),1,2); |
---|
47 | // would return a list containing q1, g, and q4. |
---|
48 | // |
---|
49 | |
---|
50 | #include <iostream> |
---|
51 | #include <map> |
---|
52 | #include <vector> |
---|
53 | |
---|
54 | namespace HepMC { |
---|
55 | |
---|
56 | class GenParticle; |
---|
57 | |
---|
58 | //! The flow object |
---|
59 | |
---|
60 | /// |
---|
61 | /// \class Flow |
---|
62 | /// The particle's flow object |
---|
63 | /// keeps track of an arbitrary number of flow patterns within a graph |
---|
64 | /// (i.e. color flow, charge flow, lepton number flow, ...) |
---|
65 | /// Flow patterns are coded with an integer, in the same manner as in Herwig. |
---|
66 | class Flow { |
---|
67 | |
---|
68 | /// for printing |
---|
69 | friend std::ostream& operator<<( std::ostream& ostr, const Flow& f ); |
---|
70 | |
---|
71 | public: |
---|
72 | /// default constructor |
---|
73 | Flow( GenParticle* particle_owner = 0 ); |
---|
74 | /// copy |
---|
75 | Flow( const Flow& ); |
---|
76 | virtual ~Flow(); |
---|
77 | /// swap |
---|
78 | void swap( Flow & other); |
---|
79 | /// make a copy |
---|
80 | Flow& operator=( const Flow& ); |
---|
81 | /// equality |
---|
82 | bool operator==( const Flow& a ) const; //compares only flow |
---|
83 | /// inequality |
---|
84 | bool operator!=( const Flow& a ) const; //patterns not owner |
---|
85 | |
---|
86 | /// print Flow information to ostr |
---|
87 | void print( std::ostream& ostr = std::cout ) const; |
---|
88 | |
---|
89 | /// returns all connected particles which have "code" in any of the |
---|
90 | /// num_indices beginning with index code_index. |
---|
91 | std::vector<HepMC::GenParticle*> connected_partners( int code, int code_index =1, |
---|
92 | int num_indices = 2 ) const; |
---|
93 | /// same as connected_partners, but returns only those particles which |
---|
94 | /// are connected to <=1 other particles (i.e. the flow line "dangles" |
---|
95 | /// at these particles) |
---|
96 | std::vector<HepMC::GenParticle*> dangling_connected_partners( int code, |
---|
97 | int code_index = 1, int num_indices = 2 ) const; |
---|
98 | |
---|
99 | //////////////////// |
---|
100 | // access methods // |
---|
101 | //////////////////// |
---|
102 | |
---|
103 | /// find particle owning this Flow |
---|
104 | const GenParticle* particle_owner() const; |
---|
105 | /// flow code |
---|
106 | int icode( int code_index = 1 ) const; |
---|
107 | /// set flow code |
---|
108 | Flow set_icode( int code_index, int code ); |
---|
109 | /// set unique flow code |
---|
110 | Flow set_unique_icode( int code_index = 1 ); |
---|
111 | |
---|
112 | ////////////////////// |
---|
113 | // container access // |
---|
114 | ////////////////////// |
---|
115 | |
---|
116 | /// return true if there is no flow container |
---|
117 | bool empty() const; |
---|
118 | /// size of flow pattern container |
---|
119 | int size() const; |
---|
120 | /// clear flow patterns |
---|
121 | void clear(); |
---|
122 | /// empty flow pattern container |
---|
123 | bool erase( int code_index ); |
---|
124 | |
---|
125 | /// iterator for flow pattern container |
---|
126 | typedef std::map<int,int>::iterator iterator; |
---|
127 | /// const iterator for flow pattern container |
---|
128 | typedef std::map<int,int>::const_iterator const_iterator; |
---|
129 | /// beginning of flow pattern container |
---|
130 | iterator begin(); |
---|
131 | /// end of flow pattern container |
---|
132 | iterator end(); |
---|
133 | /// beginning of flow pattern container |
---|
134 | const_iterator begin() const; |
---|
135 | /// end of flow pattern container |
---|
136 | const_iterator end() const; |
---|
137 | |
---|
138 | protected: // intended for internal use only |
---|
139 | /// for internal use only |
---|
140 | void connected_partners( std::vector<HepMC::GenParticle*>* output, |
---|
141 | int code, |
---|
142 | int code_index, |
---|
143 | int num_indices ) const; |
---|
144 | /// for internal use only |
---|
145 | void dangling_connected_partners( std::vector<HepMC::GenParticle*>* |
---|
146 | output, |
---|
147 | std::vector<HepMC::GenParticle*>* |
---|
148 | visited_particles, |
---|
149 | int code, int code_index, |
---|
150 | int num_indices ) const; |
---|
151 | private: |
---|
152 | GenParticle* m_particle_owner; |
---|
153 | std::map<int,int> m_icode; // stores flow patterns as(code_index,icode) |
---|
154 | }; |
---|
155 | |
---|
156 | /////////////////////////// |
---|
157 | // INLINE Access Methods // |
---|
158 | /////////////////////////// |
---|
159 | |
---|
160 | inline const GenParticle* Flow::particle_owner() const { |
---|
161 | return m_particle_owner; |
---|
162 | } |
---|
163 | inline int Flow::icode( int code_index ) const { |
---|
164 | std::map<int,int>::const_iterator a = m_icode.find(code_index); |
---|
165 | return a==m_icode.end() ? 0 : (*a).second; |
---|
166 | } |
---|
167 | inline Flow Flow::set_icode( int code_index, int code ) { |
---|
168 | m_icode[code_index] = code; |
---|
169 | return *this; |
---|
170 | } |
---|
171 | inline Flow Flow::set_unique_icode( int flow_num ) { |
---|
172 | /// use this method if you want to assign a unique flow code, but |
---|
173 | /// do not want the burden of choosing it yourself |
---|
174 | m_icode[flow_num] = size_t(this); |
---|
175 | return *this; |
---|
176 | } |
---|
177 | inline bool Flow::empty() const { return (bool)m_icode.empty(); } |
---|
178 | inline int Flow::size() const { return (int)m_icode.size(); } |
---|
179 | inline void Flow::clear() { m_icode.clear(); } |
---|
180 | inline bool Flow::erase( int code_index ) { |
---|
181 | // this will return true if the number of elements removed is nonzero |
---|
182 | return m_icode.erase( code_index )==0 ? false : true ; |
---|
183 | } |
---|
184 | inline Flow::iterator Flow::begin() { return m_icode.begin(); } |
---|
185 | inline Flow::iterator Flow::end() { return m_icode.end(); } |
---|
186 | inline Flow::const_iterator Flow::begin() const { return m_icode.begin(); } |
---|
187 | inline Flow::const_iterator Flow::end() const { return m_icode.end(); } |
---|
188 | |
---|
189 | /////////////////////////// |
---|
190 | // INLINE Operators // |
---|
191 | /////////////////////////// |
---|
192 | |
---|
193 | inline bool Flow::operator==( const Flow& a ) const { |
---|
194 | /// equivalent flows have the same flow codes for all flow_numbers |
---|
195 | /// (i.e. their m_icode maps are identical), but they need not have the |
---|
196 | /// same m_particle owner |
---|
197 | return (m_icode == a.m_icode); |
---|
198 | } |
---|
199 | inline bool Flow::operator!=( const Flow& a ) const { |
---|
200 | return !( *this == a ); |
---|
201 | } |
---|
202 | inline Flow& Flow::operator=( const Flow& inflow ) { |
---|
203 | /// copies only the m_icode ... not the particle_owner |
---|
204 | /// this is intuitive behaviour so you can do |
---|
205 | /// oneparticle->flow() = otherparticle->flow() |
---|
206 | // |
---|
207 | m_icode = inflow.m_icode; |
---|
208 | return *this; |
---|
209 | } |
---|
210 | |
---|
211 | } // HepMC |
---|
212 | |
---|
213 | #endif // HEPMC_FLOW_H |
---|
214 | //-------------------------------------------------------------------------- |
---|
215 | |
---|