Issues Concerning the PhysicsVectors/CLHEP Vector Merge ------------------------------------------------------- The merge of ZOOM PhysicsVdectors and the CLHEP Vector package is completed. The purpose of this document is to list the major issues that affected the merge of these packages, and where relevant describe the resolutions. More detailed documents describe more minor issues. ---------------- General Approach ----------------- As agreed at the June 2000 CLHEP workshop, the approach is to combine the features of each ZOOM class with the corresponding CLHEP class, expanding the interface to create a single "lingua franca" of what a Hep3Vector (for example) means. We are not forming SpaceVector as an class derived from Hep3Vector and enhancing it in that way. Another rule imposed by the agreement is to avoid using the Exceptions package (even though that will later go into CLHEP for other uses). A desirable goal is to avoid cluttering the interface and enlarging the code linked in when ordinary CLHEP Vector functionallity is used. To this end, I have placed almost all the new features in a separate, second section of the header, and have created separate .cc files for sensible subsets of the methods. In particular, if a program uses only the methods found in the original CLHEP classes, very little additional code is linked in. ------- Classes ------- The corresponding classes are: Hep3Vector SpaceVector HepLorentzVector LorentzVector HepLorentzRotation LorentzTransformation HepRotation Rotation Classes new to CLHEP are: HepAxisAngle AxisAngle HepEulerAngles EulerAngles Hep2Vector PlaneVector HepRotationX RotationX HepRotationY RotationY HepRotationZ RotationZ HepBoost LorentzBoost HepBoostX LorentzBoostX HepBoostY LorentzBoostY HepBoostZ LorentzBoostZ ----------------------------- Exceptional cases and ZMthrow ----------------------------- PhsyicsVectors is set up for use of the Exceptions package. Though we are directed not to use it quite yet, I am not giving up on it eventually being in use; it has advantages. For now, I leave the ZMthrows in, but substitute macros (in ZMxpv.h) which turn usage of ZXMthrow into cerr<< message lines. (Issuing of messages to cerr is done elsewhere in Vectors.) To avoid clashes with other ZOOM packages in the definition of the ZMthrow macro, I replaced ZMthrow with ZMthrowA in this package. ZMthrowA, when used, will issue its message and exit (-1). Also, I introduce a macro ZMthrowC which I use wherever it seems there is a sensible way to continue processing after reporting the problem. When (if ever) the actual ZOOM exceptions package is incorporated into Vector ZMthrowC may eventually be #defined as ZMthrow since the Exceptions mechanism can handle the selective continuiing. However, we don't want to change the functionallity when this is used in the ZOOM context. To retain true ZOOM Exception features, we provide in ZMxpv.h a define of ENABLE_ZOOM_EXCEPTIONS. In CLEHP this is not defined, and ZMthrowA and ZMthrowC become macros that behave as above. When we build for ZOOM, we use a version with the #define turned on, and this pulls in the ZOOM Exception behaviour. Thus in our ZOOM builds, people still get the ZOOM Exceptions behaviour they are used to (an absolute requirement for us) -- but pure CLHEP users do not see the Exceptions package at all. The only slight annoyance is that now for ZOOM users CLHEP will depend on Exceptions (and ZMutility) -- where a minimalist would note that only the CLHEP/Vector subpackage needed to depend on these even in ZOOM. The linker is such a minimalist: It warns ZOOM applications which use CLHEP packages other Vectors about the fact that the Exceptions library is not used to resolve any symbol. When we in ZOOM break up CLHEP into packages the way it is in the official version of CLHEP, this annoyance will go away. -------------------------------------------- Additions to the "original" CLHEP interface -------------------------------------------- In order not to burden CLHEP users who may not care about PhysicsVectors, I have placed almost all the features not originally in CLHEP in separate, second sections of the header, and have created separate .cc files for sensible subsets of the methods. I felt that the following small set of methods were useful enough to belong in the main part of the headers, and to be implemented (if not inline) in the main .cc files for each class (e.g., ThreeVector.cc): ThreeVector: set (x,y,z) setRThetaPhi(r, theta, phi) setREtaPhi(r, eta, phi) setRhoPhiZ(rho, phi, z) setRhoPhiTheta(rho, phi, theta) setRhoPhiEta(rho, phi, eta) setEta (eta), setCylTheta (theta), setCylEta (theta) operator / (double) operator /= (double) isNear, HowNear, and DeltaR cos2Theta LorentzVector: inline HepLorentzVector(HepDouble, const Hep3Vector &); setRThetaPhi(r, theta, phi) setREtaPhi(r, eta, phi) setRhoPhiZ(rho, phi, z) operator /= (Hepdouble c) operator / (const LorentzVector & v, Hepdouble c) inline bool isSpacelike() const; inline bool isTimelike() const; inline bool isLightlike(Scalar epsilon=tolerance) const; HepLorentzVector & boostX( HepDouble beta ); HepLorentzVector & boostY( HepDouble beta ); HepLorentzVector & boostZ( HepDouble beta ); HepDouble et(); HepDouble et2(); HepRotation: operator() (LrentzVector) HepRotation (AxisAngle) and corresponding set() HepRotation (EulerAngles) and corresponding set() colX(), colY(), colZ(), rowX(), rowY(), rowZ() phi(), theta(), psi() axis(), delta() setPhi(), setAxis(), and so forth. setRows() compare(), operator>, operator<, operator>=, operator<= distance2(), howNear(), isNear() norm2() rectify() static Rotation::IDENTITY methods treating the Rotation as a Hep4RotationInterface: col1 ... col4; row1 ... row4 (To avoid bloat in the code pulled in for programs which don't use all these features, we split the implementation .cc files. Only isNear() goes into the original Rotation.cc) --------------------------------------- HepAxisAngle and HepEulerAngles classes --------------------------------------- These classes are very useful and simple structures for holding the result of a nice intuituve decomposition of a rotation: Axis, and how far to rotate, or the three Euler angles. They are worth retaining. In the global namespace these are called HepEulerAngles and HepAxisAngle. The Euler angle conventions used are those from ZOOM: The Goldstein (p. 109) conventions. Euler angles were not in the original CLHEP. We reject the horrible option of setting up a static variable to indicate which choice of EulerAngles conventions to use. And it would break user code if we were to change to some other convention and strand existing ZOOM users. ------------------- Splits of .cc files ------------------- ThreeVector: The original methods requiring loading HepRotation ThreeVectorR.cc The polar/azimuthal decomposition methods SpaceVectorD.cc All new methods involving rotation SpaceVectorR.cc Other new intrinsic and relative properties SpaceVectorP.cc All other new methods (constructors, nearness, ...) SpaceVector.cc The original methods not pulling in HepRotation ThreeVector.cc LorentzVector: The original methods not pulling in HepRotation LorentzVector.cc Methods involving HepRotation LorentzVectorR.cc Original methods involving HepLorentzRotation LorentzVectorL.cc Comparison operations from ZOOM LorentzVectorC.cc relativistic kinematics from ZOOM LorentzVectorK.cc boosts and rotations from ZOOM LorentzVectorB.cc (Note that these do not bring in HepRotation or HepLorentzRotation) Rotation: IO RotationIO.cc Axis-angle routines RotationA.cc Euler angle routines RotationE.cc Long routines involving rectifying near-rotations RotationC.cc (for example, constructor from 3 column vectors) 3-Rotation routines involving 4-rotation arguments RotationL.cc (thus requiring linking 4-rotation code units) Original CLHEP Rotation, plus isNear() Rotation.cc All other methods originating in PhysicsVectors RotationP.cc LorentzRotation: set(col1, col2, col3, col4) and related constructors LorentzRotationC.cc all the decompose methods, and mthodes than use them LorentzRotationD.cc everything else, including all CLHEP methods LorentzRotation.cc ----------------------- ZOOM Back Compatibility ----------------------- The classes with old ZOOM names (like SpaceVector) are implemented as small wrappers, in headers that live in the old ZOOM PhysicsVectors package. These are of course not part of CLHEP. The ZOOM area obeys the following rules: - It is kept as a ZOOM package as before. - The headers are found exactly as before, so as not to break user code. - All ZOOM classes for which there are corresponding CLHEP Vector classes are either typedefed to those or derived from those. - All code in the ZOOM area is implemented in the headers; there is no longer much content in the distinct ZOOM PhysicsVectors library. The only content left in the library is the object files representing the various Exception objects. When we build the CLHEP classes for the ZOOM repository, we will set up so as to use ZOOM excpetions. (The version placed into the official CLHEP, however, will not use ZOOM Exceptions at this point.) Hep3Vector (similarly HepLorentzVector etc.) is not enclosed in a namespace. In ZOOM, SpaceVector is (but we can disable namespace usage and most of our users do so at this point). What I do is leave Hep3Vector in the global namespace, and in the ZOOM headers I put SpaceVector namespace zmpv. ----------------- Symbol pollution: ----------------- The SpaceVectors class defines symbols DEGREES RADIANS and ETA, It is undesirable to pollute the global namespace in CLHEP usage with those symbols, since users may well use the same words. So these are restricted to the ZOOM area, and placed purely into the ZMpv namespace, which is defined in the SpaceVector.h backward-compatibility header. This has the side consequence that the plethora of SpaceVector constructors involving these symbols is moved out of ThreeVector.h, greatly simplifying that header. ---------- UnitVector ---------- Some code at Fermilab uses UnitVector, and I have also found some situations where the efficiency can make a significant difference. I provide UnitVector as a class for ZOOM users, in the zmpv namespace, via a file UnitVector.h. This no longer inherits from SpaceVector; that avoids the design flaw of "specialization by non-virtual inheritance." The entire implementation is inline (by casting to Hep3Vector to get its implementations) so no additional code need go into the CLHEP library. Since UnitVector is not in CLHEP, of necessity no CLHEP classes (in particular not Hep3Vector and not HepRotation) will be aware of the existance of UnitVector. Note that although UnitVector does not inherit from Hep3Vector, EVERY const method of Hep3Vector is present for UnitVector. Some, like unit() and mag(), become quite trivial; most use the Hep3Vector implementations. Since UnitVector is not in CLHEP (for now) we just retain the name UnitVector. However, it may eventually become part of CLHEP, so I chose to parallel the situation for SpaceVector w.r.t. Hep3Vector. Thus, the header defines HepUnit3Vector in the global namespace, and inside the zmpv namespace it typedef's UnitVector to be HepUnit3Vector. The conversion operator to Hep3Vector makes it trivial to use UnitVector as an argument to any routine that takes a Hep3Vector. There will be cases where it would be beneficial to have a special method taking advantage of the knowledge that a UnitVector need not be normalized. For the present, we will not attempt to obtain this advantage. --------------------------------------- Rotation classes inheritance structure: --------------------------------------- I am telescoping a lot of thought into a few words here. ZOOM has RotationInterface and LorentzTransformationInterface (for short, RI and LTI), which provide those methods available for GETTING INFORMATION ABOUT (but not modifying) generic Rotations and LorentzTransformations. For example, if an object might be either a Rotation or a RotationZ, since RI has methods axis() and delta(), a routine can be passed a RI& and take axis() and delta(). We need to keep this interface. What is the proper inheritance structure? Clearly RI derives from LTI, because anything you wish to ask about a LT you could equally well ask about a Rotation. From RI, one derives Rotation and its special cases RotationX etc. We can't derive RotationX from Rotation (that would introduce a bunch of inapplicable methods, plus greatly increase the size of member data for RotationX). Similarly, from LTI, one derives HepLorentzRotation along with HepBoost, HepBoostX, and so forth. The Hep classes expressing RI and LTI are Hep3RotationInterface and Hep4RotationInterface; these appear together in RotationInterfaces.h As usual, the ZOOM names are placed in a separate wrapper in the ZOOM package and will be namespace-guarded. In ZOOM we had in the inheritance tree classes RotationAboutCoordinateAxis and BoostAlongCoordinateAxis. These mainly let us avoid duplication of code but were not useful enought to be worth their complexity cost; they are gone. -------------------------- ZOOM Features Discontinued -------------------------- The following features of the ZOOM package were felt to be extreme overkill. These have been discontinued, after checking that no existing user code was utilizing them: - Direct use of non-trivial accessors as L-values, as in SpaceVector v; v.phi() = myAngle; - Methods applicble to containers of 4-vectors, as in std::list s; double m = s.invariantMass(); - Application of Rotations and LorentzTransformations to containers of 3- and 4-vectors, as in Rotation R; std::vector vv; std::vector Rvv = R(vv); We retained the feature of using ZOOM Exceptions: + Problematic cases are still caught, and in the version in the ZOOM repository, they do still go through the ZOOM Exceptions mechanism. If you use the code in the CLHEP repository, then instead of ZOOM exceptions you would get "write to cerr and exit(-1)" behavior. --------- Testing: --------- All existing CLHEP tests (testThreeVector and testRotation) have been applied and they pass in the merged product. This deomnstrates that no (tested) CLHEP functionallity has been compromised. All the PhysicsVectors tests have been vetted to remove the few features no longer supported (e.g. syntax like v.r() = 4.), and have been applied and pass. This deomnstrates that no ZOOM functionallity other than the few identified cutbacks has been compromised. Also, since the ZOOM classes other than UnitVector directly utilize the CHEP classes (mostly by typedef), the very extensive ZOOM test suite heavily excercises 90% of the methods of all the CLHEP classes. The exceptions are such methods as v.orthogonal() and R.rotateAxes(vx,vy,vz) which were not in the original ZOOM package. Since the ZOOM area is not being checked back into the original CLHEP, these extensive tests are not going to be part of CLHEP. If somebody feels it worthwhile to place these tests into CLHEP/Vector/tests and change the names of the classes to the Hep names, this would be reasonable, but I will not give any priority for myself to do it. ======================================================================== ======================================================================== ... And a few less major issues: ------------------------------------------- Coupling between Hep3Vector and HepRotation ------------------------------------------- In PhysicsVectors, there was a heirarchy in which vectors do not know about rotations. The methods Hep3Vector::transform(const HepRotation &) and Hep3Vector*=(const HepRotation &) break this heirarchy. Thus in the opriginal CLHEP, **any clhep program that used Hep3Vector would link in hepRotation.cc. This is not desirable. As part of the merge, I broke apart ThreeVector.cc, putting the HepRotation dependent methods in their own little file, ThreeVectorR.cc. If the user uses Hep3Vectors but not HepRotations, he won't pull everything in. Similarly for HepLorentzVector, with regards to uses HepRotation and HepLorentzRotation. ----------------------------- R, rho nomenclature confusion ----------------------------- In ThreeVector, CLHEP, --IN COMMENTS ONLY-- refers to the radius in spherical coordinates as "rho", and the distance from the Z axis in cylindrical coordinates as R. ZOOM uses the oppopsite names, and in fact uses these names in method names. I did not change the ZOOM method names. I have altered the CLHEP comments to make the nomenclature consistent; the meanings are still clear from the comments. For example: inline HepDouble perp() const; // The transverse component (rho in cylindrical coordinate system). -------------- Metric selector -------------- ZOOM allows the user to set metric as TimePositive or TimeNegative; the default is TimePositive. CLHEP always does TimePositive. The cost of the flexibility is small: Roughly 10% in dot, diff2, and mag2 and no other routines are altered. Because of this, I am keeping metric flexibility in the package. "Pure" CLHEP users need never see this. ------------------------------------------------ mag2(), m2(), and restMass2() for LorentzVector: ------------------------------------------------ CLHEP treats mag2() as the same as restMass2(). This is the only possible meaning when the metric is fixed as ---+. However, if there is flexibility in the sense of the metric, it is most natural to consider mag2() to be defined as w.dot(w). This is how ZOOM treats it. Since CLHEP users will not have altered the choice of metric, they will not be affected if the ZOOM definition is used, so we go that way. On the other hand, m2() really sounds like it should mean the physics mass squared; what we call in ZOOM restMass2(). ZOOM does not have a method m2(). So we leave m2 as metric independant, and identical to ZOOM's restMass2(). --------------- New Method: et() --------------- We provide a new method, et() which is the transverse energy. This is defined as E sin theta, or E Pperp/P. For completeness, we also have et(v) the transverse energy with respect to a given direction: p.et(v) = p.t() * p.V().perp(v) / p.V().mag(). ---------------------------- 3x3 and 4x4 representations: ---------------------------- ZOOM declares a Rep3x3 struct which is very usreful for people who "just want the damn matrix." This is useful enough that we add it to CLHEP in RotationInterfaces.h. Thus we have HepRep3x3 and HepRep4x4. Note that using HepMatrix for this purpose would violate CLHEP coupling and dependency rules. --------------------- Rotation operator>> --------------------- It might be nice to have an input method such that if you take the output of operator<< you get the original. However, that was not present in either ZOOM or CLHEP and I am not coding it at this time. This something that I feel ought to be done but is not a part of the merge process. -------------------------- To inline or not to inline -------------------------- Several inline methods of HepRotation FAR exceed sensible standards for inlining. I have moved these to the .cc file. Some examples are: operator==(), isIdentity(). --------------------------------------------------------- Operator *= with a 3- or 4-vector and a 3- or 4-rotation: --------------------------------------------------------- For example, v *= R where v is a Hep3Vector and R a HepRotation. In C++ semantics, z *= b usually means a = a * b, so this leads you to expect the behaviour v = v*R. But physicists know that they would rarely apply a rotation on the right like that, and thus CLHEP defined v *= R as v = R*v. This is a case where ZOOM decided there was no misleading way to treat the operator and thus omitted it, while CLHEP has just decided which way to treat it. We must retain this meaning for compatibility. We will point out the unnatural syntax in both the header file and the documentation, to warn users that they will get the useful physics operation rather than the expected meaning of operator *=.