Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4FunctionSolver.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4FunctionSolver
27//
28// Class description:
29//
30// Templated utility class to solve equation F(x) = 0 on interval [a, b]
31// Parameters of the class: tolerance - relative accuracy of the method,
32// maxIter - max number of iterations. User should provide a class with
33// only one method: T_Function::Function(G4double x). The main method
34// of the class is 'G4bool G4FunctionSolver::FindRoot(G4double& x)', where
35// user defines initial value x, which is modifided to be a final solution
36// of the equation.
37//
38// If the equation cannot be resolved with required accuracy FindRoot()
39// method returns "false".
40//
41// Parameters of the solver may be changed before the new call via Set
42// methods.
43//
44// Created 04.10.2025 V.Ivanchenko
45//
46
47#ifndef G4FunctionSolver_h
48#define G4FunctionSolver_h 1
49
50#include "globals.hh"
51
52template <class T_Function> class G4FunctionSolver
53{
54public:
55
56 G4FunctionSolver(T_Function* ff, const G4int iterations, const G4double tol)
57 : maxIter(iterations), tolerance(tol), tF(ff) {};
58
59 // copy constructor
60 G4FunctionSolver(const G4FunctionSolver& right) = delete;
61
62 // destructor
63 ~G4FunctionSolver() = default;
64
65 // operators
67 G4bool operator==(const G4FunctionSolver& right) const = delete;
68 G4bool operator!=(const G4FunctionSolver& right) const = delete;
69
70 inline void SetMaxIterations(const G4int iterations)
71 { maxIter = iterations; }
72
73 inline void SetTolerance(const G4double epsilon)
74 { tolerance = epsilon; }
75
76 inline void SetIntervalLimits(const G4double Limit1, const G4double Limit2)
77 {
78 aa = std::min(Limit1, Limit2);
79 bb = std::max(Limit1, Limit2);
80 }
81
82 // Calculates the root of the equation Function(x)=0
84 {
85 G4double a = aa;
86 G4double b = bb;
87
88 // check the interval before the start
89 x = std::min(std::max(x, a), b);
90
91 // check initial function
92 G4double fc = tF->Function(x);
93 if (0.0 == fc) { return true; }
94
95 // define accuracy in X
96 G4double epsX = tolerance*x;
97 // define accuracy in Y
98 G4double epsY = tolerance*fc;
99
100 // the interval is too small
101 if (std::abs(a - b) <= epsX)
102 {
103 x = 0.5*(a + b);
104 return true;
105 }
106
107 // check edges
108 G4double fa = tF->Function(a);
109 G4double fb = tF->Function(b);
110
111 // root should be inside interval
112 if (fa*fb >= 0.0)
113 {
114 x = (std::abs(fa) <= std::abs(fb)) ? a : b;
115 return (std::min(std::abs(fa), std::abs(fb)) < epsY);
116 }
117
118 // fa*fb < 0.0 - finding the root by iterative procedure,
119 // the loop is completed if function is below epsY
120 // or if x become close to edges with accuracy epsX
121 for (G4int i = 0; i < maxIter; ++i)
122 {
123 x = (a*fb - b*fa)/(fb - fa);
124 fc = tF->Function(x);
125 if (std::abs(fc) < epsY) { return true; }
126
127 G4double delta = std::min((x - a), (b - x));
128 if (delta < epsX) { return true; }
129 else if (fa*fc < 0.0) { b = x; fb = fc; }
130 else { a = x; fa = fc; }
131 }
132 // number of iterations exceed the limit
133 return false;
134 }
135
136private:
137
138 // maximum number of iterations
139 G4int maxIter;
140 // relative accuracy in X and Y
141 G4double tolerance;
142
143 // interval limits [a,b]
144 G4double aa{0.0};
145 G4double bb{0.0};
146
147 T_Function* tF;
148};
149
150#endif
G4double epsilon(G4double density, G4double temperature)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4FunctionSolver(T_Function *ff, const G4int iterations, const G4double tol)
G4bool operator==(const G4FunctionSolver &right) const =delete
G4FunctionSolver & operator=(const G4FunctionSolver &right)=delete
void SetIntervalLimits(const G4double Limit1, const G4double Limit2)
G4bool FindRoot(G4double &x)
G4FunctionSolver(const G4FunctionSolver &right)=delete
G4bool operator!=(const G4FunctionSolver &right) const =delete
~G4FunctionSolver()=default
void SetTolerance(const G4double epsilon)
void SetMaxIterations(const G4int iterations)