FastJet 3.4.1
ClusterSequence_N2.cc
1//FJSTARTHEADER
2// $Id$
3//
4// Copyright (c) 2005-2023, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
5//
6//----------------------------------------------------------------------
7// This file is part of FastJet.
8//
9// FastJet is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 2 of the License, or
12// (at your option) any later version.
13//
14// The algorithms that underlie FastJet have required considerable
15// development. They are described in the original FastJet paper,
16// hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
17// FastJet as part of work towards a scientific publication, please
18// quote the version you use and include a citation to the manual and
19// optionally also to hep-ph/0512210.
20//
21// FastJet is distributed in the hope that it will be useful,
22// but WITHOUT ANY WARRANTY; without even the implied warranty of
23// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24// GNU General Public License for more details.
25//
26// You should have received a copy of the GNU General Public License
27// along with FastJet. If not, see <http://www.gnu.org/licenses/>.
28//----------------------------------------------------------------------
29//FJENDHEADER
30
31
32// The plain N^2 part of the ClusterSequence class -- separated out
33// from the rest of the class implementation so as to speed up
34// compilation of this particular part while it is under test.
35
36#include "fastjet/internal/ClusterSequence_N2.icc"
37
38#include<iostream>
39
40FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
41
42
43using namespace std;
44
45
46//*************************************************************************
47//
48// THINGS FOR E+E-
49//
50//*************************************************************************
51
52
53//----------------------------------------------------------------------
54template<> inline void ClusterSequence::_bj_set_jetinfo(
55 EEBriefJet * const jetA, const int _jets_index) const {
56
57 double E = _jets[_jets_index].E();
58 double scale = E*E; // the default energy scale for the kt alg
59 double p = jet_def().extra_param(); // in case we're ee_genkt
60 switch (_jet_algorithm) {
61 case ee_kt_algorithm:
62 assert(_Rparam > 2.0); // force this to be true! [not best place, but works]
63 // recall that _invR2 is artificially set to 1 for this alg
64 // so that we automatically have dij = scale * 2(1-cos theta_ij)
65 // Normally, _Rparam should be automatically set to 4 from JetDefinition
66 break;
68 if (p <= 0 && scale < 1e-300) scale = 1e-300; // same dodgy safety as genkt
69 scale = pow(scale,p);
70 break;
71 default:
72 throw Error("Unrecognised jet algorithm");
73 }
74 jetA->kt2 = scale; // "kt2" might one day be renamed as "scale" or some such
75
76 double norm = _jets[_jets_index].modp2();
77 if (norm > 0) {
78 norm = 1.0/sqrt(norm);
79 jetA->nx = norm * _jets[_jets_index].px();
80 jetA->ny = norm * _jets[_jets_index].py();
81 jetA->nz = norm * _jets[_jets_index].pz();
82 } else {
83 jetA->nx = 0.0;
84 jetA->ny = 0.0;
85 jetA->nz = 1.0;
86 }
87 jetA->_jets_index = _jets_index;
88 // initialise NN info as well
89 jetA->NN_dist = _R2;
90 jetA->NN = NULL;
91}
92
93// this is declared to ensure that calls with the EEAccurateBriefJet
94// are redirected to the EEBriefJet implementation (otherwise
95// it tries the default pp template)
96template<> inline void ClusterSequence::_bj_set_jetinfo(
97 EEAccurateBriefJet * const jetA, const int _jets_index) const {
98 _bj_set_jetinfo<EEBriefJet>(jetA, _jets_index);
99}
100
101
102//----------------------------------------------------------------------
103// returns the angular distance between the two jets, defined as
104// 2*(1-cos theta_ab)
105template<> double ClusterSequence::_bj_dist(
106 const EEBriefJet * const jeta,
107 const EEBriefJet * const jetb) const {
108 double dist = 1.0
109 - jeta->nx*jetb->nx
110 - jeta->ny*jetb->ny
111 - jeta->nz*jetb->nz;
112
113 return dist*2; // distance is _2_*min(Ei^2,Ej^2)*(1-cos theta)
114}
115
116//----------------------------------------------------------------------
117// returns the angular distance between the two jets, defined as
118// 2*(1-cos theta_ab)
119template<> double ClusterSequence::_bj_dist(
120 const EEAccurateBriefJet * const jeta,
121 const EEAccurateBriefJet * const jetb) const {
122 double dist = 1.0
123 - jeta->nx*jetb->nx
124 - jeta->ny*jetb->ny
125 - jeta->nz*jetb->nz;
126
127 // if the distance is smaller than sqrt(epsilon), then switch to
128 // cross-product based evaluation; this is intended to ensure an
129 // absolute accuracy on sqrt(bj_dist), that is somewhere in the region
130 // of max(epsilon, sqrt(epsilon) * dist) rather than epsilon.
131 //
132 // Let's write cos(theta) == cos and sin(theta)==sin; then we have
133 //
134 // 2*(1-cos) = 2*(1-cos^2)/(1+cos) = 2*sin^2/(1+cos);
135 //
136 // To save a division, we then replace 2/(1+cos) -> 1, which introduces
137 // a relative error of order sin^2(theta), which is sqrt(epsilon) when
138 // dist is itself sqrt(epsilon). For that value of dist, the relative
139 // error on the normal dot-product calculation of dist is itself
140 // sqrt(epsilon). This motivates the choice switchover point.
141 //
142 // This approach has been adopted from PanScales work.
143 if (dist*dist < numeric_limits<double>::epsilon()) {
144 double cross_x = jeta->ny * jetb->nz - jetb->ny * jeta->nz;
145 double cross_y = jeta->nz * jetb->nx - jetb->nz * jeta->nx;
146 double cross_z = jeta->nx * jetb->ny - jetb->nx * jeta->ny;
147
148 // 2(1-cos(theta)) ~ theta^2, which is |cross_product|^2
149 dist = cross_x*cross_x + cross_y*cross_y + cross_z*cross_z;
150 return dist;
151 }
152
153 // this alternative code has higher accuracy in some boundary regions
154 // but is almost a factor of two slower than the plain dot product
155 // (the code above is only 15% slower on a standard-looking event).
156 //if (dist < 1) {
157 // double cross_x = jeta->ny * jetb->nz - jetb->ny * jeta->nz;
158 // double cross_y = jeta->nz * jetb->nx - jetb->nz * jeta->nx;
159 // double cross_z = jeta->nx * jetb->ny - jetb->nx * jeta->ny;
160 //
161 // // 2(1-cos(theta)) ~ theta^2, which is |cross_product|^2
162 // double sinsqr = cross_x*cross_x + cross_y*cross_y + cross_z*cross_z;
163 // return 2*sinsqr/(2.0-dist);
164 // //return dist;
165 //}
166
167 return dist*2; // distance is _2_*min(Ei^2,Ej^2)*(1-cos theta)
168}
169
170
171
172// get explicit copies of the two N2 cluster cases we need
173// plain BriefJet
174void ClusterSequence::_simple_N2_cluster_BriefJet() {
175 _simple_N2_cluster<BriefJet>();
176}
177
178
179// e+e- BriefJet
180void ClusterSequence::_simple_N2_cluster_EEBriefJet() {
181 _simple_N2_cluster<EEBriefJet>();
182}
183
184void ClusterSequence::_simple_N2_cluster_EEAccurateBriefJet() {
185 _simple_N2_cluster<EEAccurateBriefJet>();
186}
187
188
189// //----------------------------------------------------------------------
190// /// Force instantiation of desired versions of _simple_N2_cluster
191// ///
192// /// This is not very elegant...
193// void ClusterSequence::_dummy_N2_cluster_instantiation() {
194// _simple_N2_cluster<BriefJet>();
195// _simple_N2_cluster<EEBriefJet>();
196// }
197
198FASTJET_END_NAMESPACE
199
double norm(const VPoint p)
norm of a vector
Definition: Voronoi.hh:155
@ ee_genkt_algorithm
the e+e- genkt algorithm (R > 2 and p=1 gives ee_kt)
@ ee_kt_algorithm
the e+e- kt algorithm