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.
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.
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.setCylEta keeping rho and phi fixed PhysicsVectors 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 -------------- ------------ + UnitVector Whenever 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) 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)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.
PhysicsVectors CLHEP Vector (and PhysicsVectors compaibility) -------------- --------------------------------- GEANT4 v.orthogonal() returns a vector orthogonal to v; the choice is contrived GEANT4 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*v The "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.h R(v) v.transform(R) This is a serious design difference. In the PhysicsVectors package, SpaceVector is at a "lower" level than Rotation, 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 of SpaceVector that works with a Rotation argument. + v*R + w*T These are defined such that constructs like v1*R*v2 and w1*T*w2 are associative and give the expected results.
PhysicsVectors CLHEP Vector -------------- ------------ + setMetric() 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 index w.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)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.
PhysicsVectors CLHEP Vector -------------- ------------ @ w.getV().phi() w.phi() @ w.getV().theta() w.theta() @ w.getV().r() w.rho() 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()Several differences reflect a matter of taste:
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*w The 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*R inverseOf(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 <=