Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:18

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2018-2022 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 
0013 #include <algorithm>
0014 #include <array>
0015 #include <cassert>
0016 #include <cmath>
0017 #include <iomanip>
0018 #include <limits>
0019 #include <ostream>
0020 #include <sstream>
0021 
0022 namespace Acts {
0023 
0024 /// A constrained step class for the steppers.
0025 ///
0026 /// This class is symmetrical for forward and backward propagation. The sign of
0027 /// the propagation direction should not enter here but rather be applied the
0028 /// step is actually taken.
0029 ///
0030 /// As simple as this class looks it hides a few very important details:
0031 /// - Overstepping handling. The step size sign will flip if we happened to pass
0032 /// our target.
0033 /// - Convergence handling. Smaller and smaller step sizes have to be used in
0034 /// order to converge on a target.
0035 ///
0036 /// Because of the points mentioned above, the update function will always
0037 /// prefer negative step sizes. A side effect of this is that we will propagate
0038 /// in the opposite direction if the target is "behind us".
0039 ///
0040 /// The hierarchy is:
0041 /// - Overstepping resolution / backpropagation
0042 /// - Convergence
0043 /// - Step into the void with `std::numeric_limits<Scalar>::max()`
0044 class ConstrainedStep {
0045  public:
0046   using Scalar = ActsScalar;
0047 
0048   /// the types of constraints
0049   /// from actor    - this would be a typical navigation step
0050   /// from aborter  - this would be a target condition
0051   /// from user     - this is user given for what reason ever
0052   enum Type : int { actor = 0, aborter = 1, user = 2 };
0053 
0054   /// Number of iterations needed by the stepsize finder
0055   /// (e.g. Runge-Kutta) of the stepper.
0056   std::size_t nStepTrials = std::numeric_limits<std::size_t>::max();
0057 
0058   constexpr ConstrainedStep() = default;
0059 
0060   /// constructor from Scalar
0061   /// @param value is the user given initial value
0062   constexpr explicit ConstrainedStep(Scalar value) { setUser(value); }
0063 
0064   /// set accuracy by one Scalar
0065   ///
0066   /// this will set only the accuracy, as this is the most
0067   /// exposed to the Propagator
0068   ///
0069   /// @param value is the new accuracy value
0070   constexpr void setAccuracy(Scalar value) {
0071     assert(value > 0 && "ConstrainedStep accuracy must be > 0.");
0072     // set the accuracy value
0073     m_accuracy = value;
0074   }
0075 
0076   /// set user by one Scalar
0077   ///
0078   /// @param value is the new user value
0079   constexpr void setUser(Scalar value) {
0080     // TODO enable assert; see https://github.com/acts-project/acts/issues/2543
0081     // assert(value != 0 && "ConstrainedStep user must be != 0.");
0082     // set the user value
0083     m_values[user] = value;
0084   }
0085 
0086   /// returns the min step size
0087   constexpr Scalar value() const {
0088     Scalar min = *std::min_element(m_values.begin(), m_values.end());
0089     // accuracy is always positive and therefore handled separately
0090     Scalar result = std::min(std::abs(min), m_accuracy);
0091     return std::signbit(min) ? -result : result;
0092   }
0093 
0094   /// Access a specific value
0095   ///
0096   /// @param type is the requested parameter type
0097   constexpr Scalar value(Type type) const { return m_values[type]; }
0098 
0099   /// Access the accuracy value
0100   constexpr Scalar accuracy() const { return m_accuracy; }
0101 
0102   /// release a certain constraint value
0103   ///
0104   /// @param type is the constraint type to be released
0105   constexpr void release(Type type) { m_values[type] = kNotSet; }
0106 
0107   /// release accuracy
0108   constexpr void releaseAccuracy() { m_accuracy = kNotSet; }
0109 
0110   /// Update the step size of a certain type
0111   ///
0112   /// Only navigation and target abortion step size
0113   /// updates may change the sign due to overstepping
0114   ///
0115   /// @param value is the new value to be updated
0116   /// @param type is the constraint type
0117   /// @param releaseStep Allow step size to increase again
0118   constexpr void update(Scalar value, Type type, bool releaseStep = false) {
0119     if (releaseStep) {
0120       release(type);
0121     }
0122     // check the current value and set it if appropriate
0123     // this will also allow signed values due to overstepping
0124     if (std::abs(value) < std::abs(m_values[type])) {
0125       // TODO enable assert; see
0126       // https://github.com/acts-project/acts/issues/2543
0127       // assert(value != 0 && "ConstrainedStep user must be != 0.");
0128       m_values[type] = value;
0129     }
0130   }
0131 
0132   std::ostream& toStream(std::ostream& os) const {
0133     // Helper method to avoid unreadable screen output
0134     auto streamValue = [&](Scalar val) {
0135       os << std::setw(5);
0136       if (std::abs(val) == kNotSet) {
0137         os << (val > 0 ? "+∞" : "-∞");
0138       } else {
0139         os << val;
0140       }
0141     };
0142 
0143     os << "(";
0144     streamValue(m_accuracy);
0145     os << ", ";
0146     streamValue(value(actor));
0147     os << ", ";
0148     streamValue(value(aborter));
0149     os << ", ";
0150     streamValue(value(user));
0151     os << ")";
0152 
0153     return os;
0154   }
0155 
0156   std::string toString() const {
0157     std::stringstream dstream;
0158     toStream(dstream);
0159     return dstream.str();
0160   }
0161 
0162  private:
0163   inline static constexpr auto kNotSet = std::numeric_limits<Scalar>::max();
0164 
0165   /// the step size tuple
0166   std::array<Scalar, 3> m_values = {kNotSet, kNotSet, kNotSet};
0167   /// the accuracy value - this can vary up and down given a good step estimator
0168   Scalar m_accuracy = kNotSet;
0169 };
0170 
0171 inline std::ostream& operator<<(std::ostream& os, const ConstrainedStep& step) {
0172   return step.toStream(os);
0173 }
0174 
0175 }  // namespace Acts