|
|
|||
File indexing completed on 2026-10-26 09:34:36
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file corecel/math/BisectionRootFinder.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <cmath> 0010 #include <type_traits> 0011 0012 #include "corecel/Config.hh" 0013 0014 #include "corecel/Assert.hh" 0015 #include "corecel/Macros.hh" 0016 #include "corecel/Types.hh" 0017 0018 #include "Algorithms.hh" 0019 0020 namespace celeritas 0021 { 0022 //---------------------------------------------------------------------------// 0023 /*! 0024 * Find a local root using the bisection algorithm. 0025 * 0026 * Using a \em left and \em right bound a Bisection approximates the \em 0027 * root as: \f[ root = 0.5 * (left + right) \f] 0028 * 0029 * Then value of \em func at the root is calculated compared to values of 0030 * \em func at the bounds. The \em root is then used update the bounds based on 0031 * the sign of \em func(root) and whether it matches the sign of \em func(left) 0032 * or \em func(right) . Performing this update of the bounds allows for the 0033 * iteration on root, using the convergence criteria based on \em func(root) 0034 * proximity to 0. 0035 */ 0036 template<class F> 0037 class BisectionRootFinder 0038 { 0039 public: 0040 // Construct with function to solve and solution tolerance 0041 inline CELER_FUNCTION BisectionRootFinder(F&& func, real_type tol); 0042 0043 // Solve for a root between two points 0044 inline CELER_FUNCTION real_type operator()(real_type left, real_type right); 0045 0046 private: 0047 F func_; 0048 real_type tol_; 0049 0050 // Maximum amount of iterations 0051 static constexpr int max_iters_ = 50; 0052 }; 0053 0054 //---------------------------------------------------------------------------// 0055 // TEMPLATE DEDUCTION 0056 //---------------------------------------------------------------------------// 0057 0058 template<class F, class... Args> 0059 CELER_CTAD_FUNCTION BisectionRootFinder(F&&, Args...) 0060 -> BisectionRootFinder<F>; 0061 0062 //---------------------------------------------------------------------------// 0063 // INLINE DEFINITIONS 0064 //---------------------------------------------------------------------------// 0065 /*! 0066 * Construct from function. 0067 */ 0068 template<class F> 0069 CELER_FUNCTION BisectionRootFinder<F>::BisectionRootFinder(F&& func, 0070 real_type tol) 0071 : func_{celeritas::forward<F>(func)}, tol_{tol} 0072 { 0073 CELER_EXPECT(tol_ > 0); 0074 } 0075 0076 //---------------------------------------------------------------------------// 0077 /*! 0078 * Solve for a root between the two points. 0079 */ 0080 template<class F> 0081 CELER_FUNCTION real_type BisectionRootFinder<F>::operator()(real_type left, 0082 real_type right) 0083 { 0084 using namespace celeritas::literals; 0085 0086 // Initialize Iteration parameters 0087 real_type f_left = func_(left); 0088 real_type f_root = 1; 0089 real_type root = 0; 0090 int remaining_iters = max_iters_; 0091 0092 // Iterate on root 0093 do 0094 { 0095 // Estimate root and update value 0096 root = 0.5_r * (left + right); 0097 f_root = func_(root); 0098 0099 // Update the bound which produces the same sign as the root 0100 if (signum(f_left) == signum(f_root)) 0101 { 0102 left = root; 0103 f_left = f_root; 0104 } 0105 else 0106 { 0107 right = root; 0108 } 0109 } while (std::fabs(f_root) > tol_ && --remaining_iters > 0); 0110 0111 CELER_ENSURE(remaining_iters > 0); 0112 return root; 0113 } 0114 0115 //---------------------------------------------------------------------------// 0116 } // namespace celeritas
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|