and

(April 1998) CLHEP Vector Sub-Package

These packages cover similar functions; this note will contrast features present in one or the other. We also point out differences in treatment which might be considered a plus or minus for either side. We omit things which are either purely cosmetic (slight differences in naming choices).

The ZOOM PhysicsVectors package supplies CLHEP compatibility headers, meant to allow code using CLHEP Vectors classes to run via the ZOOM package, unchanged except for substituting the ZOOM versions of #include HepThreeVector.h etc. This comparison marks with the symbol @ cases where CLHEP functionality which becomes supported in ZOOM only if the compatibility headers are used.

Some methods in CLHEP are mathematically ambiguous on the face of it, but use arbitrary subtle assumptions and references to make them sensible. These are driven by opertions convenient to Geant4. We will point out these differences as GEANT4 rather than as usual feature differences. Again, the caompatibility headers support all these features.

Each package has four fundamental sorts of objects: 3- and 4-vectors and 3D and 4D transformations. These are listed here, along with closely related classes.

HepThreeVector SpaceVector (UnitVector) HepLorentzVector LorentzVector HepRotation Rotation (RotationX, RotationY, RotationZ) HepLorentzRotation LorentzTransformation (LorentzBoost, LorentzBoostX, LorentzBoostY, LorentzBoostZ)

We will use **v** for a 3-vector, **w** for a 4-vector,
**R** for a rotation, and **T** for
a Lorentz transformation in these illustrations.

- Component access The PhysicsVectors package has the following attitude about components specifying a vector or transformation:
- There may be several forms of components, that is, ways to specify a vector; for example, Cartesian vs Spherical coordinates.
- For each form of components, the package provides the obvious means of constructing and setting supplying all three components, and of getting individual components.
- Also, for each form of components, the package provides a way to change any one of the components, keeping the remaining ones constant.
- Although explicit get and set methods are provided, the packas also provides access operators that can be used on either side of an assignment, as in v.x() = 7.5.
- Specialized Classes There are minor conceptual advantages, and at times substatntial efficiency advantages, to classes for UnitVector, pure boost, and coordinate axis rotations and boosts. There are also some side consequences.
- Nearness and distance metrics Because comparisons are often meaningful only within some precision (dictated either be accuracy of data input or by round-off error), the PhysicsVectors class provides boolean isNear() methods, with default or user-specified tolerances. In the same vein, the package supplies the raw "distance" measure, which the user can cut on, plot, or whatever.
- Methods on 3-vectors The PhysicsVectors class provides a variety of methods acting on 3-vectors. The primary extensions relative to the CLHEP classes are that many methods which have an implied Z reference direction also have forms (in SpaceVector) taking an arbitrary reference direction. The PhysicsVectors package also has rapidity and angle decomposition methods.
- Operator overloading of * and application of rotations It was agreed that PhysicsVectors would not overload * to mean dot product and application of rotations. It was felt that ambiguities in meaning would be present if we did. However, this convenient notation is popular enough that it is supported via PhysVec.h
- 4-Vector methods The PhysicsVectors package has more kinematics methods, and can work with containers of LorentzVectors.
- Treatment of Rotations and Lorentz Transformations
- Sorting comparisons Each data type in PhysicsVector contains "dictionary ordering" coparison operators so that one can form a standard container of that class and use all the various sort and search algorithms. HepVector, having been created before standard containers were sensible to use, saw no need for these.

PhysicsVectors CLHEP Vector -------------- ------------== Accessor mechanism ==+ v.x() = whatever; or also v.setX(whatever) v.setX(whatever) only + w.x() = whatever; + v.x() += whatever; and so forth + v.r() = whatever; + v.phi() = whatever; + v.theta() = whatever; + p = v.r() along with p=v.mag() v.mag() only @ v(j) components by index== Cylindrical coordinates ==+ p = v.rho(); + v.rho() = whatever; + setCylTheta(theta): keeping rho, phi fixed.== PseudoRapidity substituting for theta ==+ p = v.eta();This is a big one; users work with eta along the Z axis rather that theta very often.+ v.eta() = whatever;keeping r and phi fixed+ v.setCylEtakeeping rho and phi fixedPhysicsVectors CLHEP Vector -------------- ------------== Rotation in terms of axis/delta and in terms of EulerAngles ==+ Rotation(axis, delta) - rotate(axis, delta)does a further rotation around this new axis; related to multiplication.+ p = R.axis() + p = R.delta() + R.axis() = whatever; + R.delta() = whatever; + R.delta()+= whatever; + R.delta()*= whatever; e.g R.delta -= 1 + R ( phi, theta, psi ); + p = R.psi() and R.psi() = whatever; + p = R.theta() and R.theta() = whatever; + p = R.phi() and R.phi() = whatever;== Rows and columns ==+ u = R.rowX() u = R.rowY(); u = R.rowZ();One note about a major performance hit in a CLHEP-using code was because they were extracting rows by multiplying by unit coordinate vectors. This would make such a happening unlikely!+ w = T.row1(); w=T.row2(); w = T.row3(); w=T.row4(); Constructor from 3 columns RotateAxes from 3 columns + Constructor from 3 rows + T.row1() T.row2() T.row3() T.row4() T.row1() T.row2() T.row3() T.row4() for LorentzTransformation + Constructor of T from 4 columns. + R.ZMpvRep3x3() + T.ZMpvRep4x4() for all 9 or 16 elements in one chunk

PhysicsVectors CLHEP Vector -------------- ------------ + UnitVectorWhenever a reference direction is needed, the fore-knowledge that this need not be normalized is a major performance edge.@ UnitVector(v) v.unit() X_HAT, Y_HAT, Z_HAT HepXhat, HepYhat, HepZhat known to be unit vectors + RotationX + RotationY + RotationZ + LorentzBoost + LorentzBoostX + LorentzBoostY + LorentzBoostZ Comment: These are important both in terms of stroage and when applying a transformation to a vector or 4-vector. + Rotation::IDENTITY + LorentzTransfomration::IDENTITY

PhysicsVectors CLHEP Vector -------------- ------------ + v.isNear(v2) + v.howNear(v2) + v.deltaR(v2)This has been requested by quite a few people from CDF and D0 independantly. Both experiments use the same term for the same concept so its meaning is clear to the key people.deltaR = sqrt(delta_eta**2 + delta_phi**2) + v.isParallel(v2) + v.howParallel(v2) + v.isOrthogonal(v2) + v.howOrthogonal(v2) + w.isNear(w2) + w.howNear(w2) + w.isNearCM(w2) + w.howNearCM(w2)Lorentz invariant measures of nearness in CM frame; these are applicable only to timelike 4-vectors.+ w.deltaR(w2) + w.delta2Euclidean(w2) + w.isSpacelike() + w.isTimelike() + w.isLightlike() + w.howLightlike() + w.isParallel(w2) + w.howParallel(w2)

PhysicsVectors CLHEP Vector -------------- ------------ v.perp2() v.perp() v.perp2() v.perp() + v.perp2(u) v.perp(u) + v.perpPart() v.perpPart(u) + v.project() v.project(u) + v.polarAngle(u) + v.azimAngle(u)There are some methods in HepVector that are specific for the convenience of Geant4. These are mathematically unnatural or contain hidden assumptions in their definitions. Nonetheless, the compatibility headers support these, as they are useful to the Geant4 crowd.Angle decomposition methods stemmed from a discussion with Marc Paterno.+ v.rotate(Euler angles) + v/scalar + unary minus on vectors and 4-vectors + v.rapidity v.rapidity(u) + v.colinearRapidity() v.angle(u) v.angle(v) + v.cosTheta(u)

PhysicsVectors CLHEP Vector (and PhysicsVectors compaibility) -------------- --------------------------------- GEANT4 v.orthogonal()returns a vector orthogonal to v; the choice is contrivedGEANT4 R.rotateUz()Rotates axes so that the Z axis is along some new vector. The choice among the set of such rotations is contrived

PhysicsVectors CLHEP Vector -------------- ------------ @ v1.dot(v2) v1 * v2 or v1.dot(w2) @ w1.dot(w2) w1 * w2 or w1.dot(w2) @ R(v) R*vThe "apply" syntax makes more sense mathematically but since physicists think of a rotation in terms of its matrix representation, the natural looking R*v will be in PhysVec.hR(v) v.transform(R)This is a serious design difference. In the PhysicsVectors package,+ v*R + w*TSpaceVectoris at a "lower" level thanRotation, and the class does not know about Rotation at all -- direct rotations are expressed in terms of EulerAngles or axis and delta. So if Rotations as objects in their own right are not part of the user's task, he need not pull in the Rotation class. In consequence, however, there can be no method ofSpaceVectorthat works with aRotationargument.These are defined such that constructs likev1*R*v2andw1*T*w2are associative and give the expected results.

PhysicsVectors CLHEP Vector -------------- ------------ + setMetric()HepLorentzVectors have more convenient notation for working with their 3-vector parts. These are obviously provided as a remnant of the 4-vector inheriting from 3-vector: The methods would have worked then, so they must work now. PhysicsVectors could be extended to include those notations if desired but since there are many more 3-vector methods available, it is more work.At the January workshop, it was indicated that the desired metric was(+ + + -). CLHEP uses (- - - +) which in many ways is much more convenient. To resolve this, PhysicsVectors defaults to the CLHEP standard, but allows the user to change to TimeNegative.w(j)components by indexw.plus() w.minus() w.plus() w.minus() + w.plus(u) w.minus(u) + w.eta() w.eta(u) + w.rapidity() w.colinearRapidity() + restVector() + invariantMass (Container) + findBoostToCM (Container) + applyBoostToCM(Container)

PhysicsVectors CLHEP Vector -------------- ------------ @ w.getV().phi() w.phi() @ w.getV().theta() w.theta() @ w.getV().r() w.rho()Several differences reflect a matter of taste:Note naming differnece: with no cylindrical coordinates, using rho for radius is sensible.@ w.getV().perp() or w.z() w.perp() @ w.getV().perp2(v) w.perp2(v) @ w.getV().angle(v) w.angle(v) w.v() HepThreeVector(w)The cast to a 3-vector, dropping the t component, is potentially trappy and confusiing. But again, it is needed for back compatibility with CLHEP versions using inheritance.@ w.px() w.py() w.pz() w.E() w.x() w.y() w.z() w.t() w.x() w.y() w.z() w.t()

PhysicsVectors CLHEP Vector -------------- ------------ T(w) w.transform(T) w.invariantMass2() w.m2() w.invariantMass() w.m() w.findBoostToCM() w.boostVector() LorentzVector(x,y,z,Tcomponent(t)) HepLorentzVector(x,y,z,t) LorentzVector(Tcomponent(t),x,y,z)The convenience of not haveing to specify which is the T component, versus the trap of not catching the error of supplying(t,x,y,z).

PhysicsVectors CLHEP Vector -------------- ------------ + rectify()In case a long series of operations might accumulate round-off error.+ w1 = R(w2) v = R*wThe application of a Rotation to HepLorentzVector in CLHEP yields a 3-vector, dropping the t component. This is plain wrong.@ R(i,j) @ T(i,j)components by index(R == Rotation::IDENTITY) R.isIdentity() @ R.transform(R2)left-multiplication analog of *= that is, R = R2*RinverseOf(R) R.inverse() + T.decompose(B, R) + T.decompose(R, B) + LorentzBoost b.direction() + b.beta() + b.gamma() + R(Container) + R(Container ) + T(Container ) GEANT4 R.phiX() const; GEANT4 R.phiY() const; GEANT4 R.phiZ() const; GEANT4 R.thetaX() const; GEANT4 R.thetaY() const; GEANT4 R.thetaZ() const; Angles made by rotated axes against the originals; Mathematically needs one more piece of info for phi to be well defined.

PhysicsVectors CLHEP Vector -------------- ------------ + operator > operator < + operator >= operator <=

Mark Fischler Last modified: June 10, 1998