MAGiC  V5.0
Mailleurs Automatiques de Géometries intégrés à la Cao
ot_root_find.cpp
Aller à la documentation de ce fichier.
1 //####//------------------------------------------------------------
2 //####//------------------------------------------------------------
3 //####// MAGiC
4 //####// Jean Christophe Cuilliere et Vincent FRANCOIS
5 //####// Departement de Genie Mecanique - UQTR
6 //####//------------------------------------------------------------
7 //####// MAGIC est un projet de recherche de l equipe ERICCA
8 //####// du departement de genie mecanique de l Universite du Quebec a Trois Rivieres
9 //####// http://www.uqtr.ca/ericca
10 //####// http://www.uqtr.ca/
11 //####//------------------------------------------------------------
12 //####//------------------------------------------------------------
13 //####//
14 //####// ot_root_find.cpp
15 //####//
16 //####//------------------------------------------------------------
17 //####//------------------------------------------------------------
18 //####// COPYRIGHT 2000-2024
19 //####// jeu 13 jun 2024 11:53:59 EDT
20 //####//------------------------------------------------------------
21 //####//------------------------------------------------------------
22 
23 
24 #include <stdio.h>
25 #include <math.h>
26 
27 #pragma hdrstop
28 
29 #include "ot_root_find.h"
30 
31 #pragma package(smart_init)
32 
33 #define SMALL_NUM_1 1E-14
34 #define SMALL_NUM_2 1E-28
35 
36 unsigned OT_ROOT_FIND_1D::ZeroBracOut (Function fn, double &x1, double &x2, void* pvData) {
37  const double FACTOR = 1.6;
38  const unsigned NTRY = 50;
39 
40  double f1 = fn (x1, pvData), f2 = fn (x2, pvData);
41  unsigned j;
42 
43  if (x1 == x2)
44  {
45  // printf ("you have to guess an initial range");
46  return 1e8;
47  }
48  for (j = 1; j <= NTRY; j++) {
49  if (f1*f2 < 0.) return 1; // found a root
50  if (fabs (f1) < fabs (f2)) {
51  x1 += FACTOR*(x1-x2); // expand towards x1
52  f1 = fn (x1, pvData);
53  }
54  else {
55  x2 += FACTOR*(x2-x1); // ... or towards x2
56  f2 = fn (x2, pvData);
57  }
58  }
59  return 1E8;
60 } // no root bracketed
61 
62 unsigned OT_ROOT_FIND_1D::ZeroBracOut (Function fn, double xStart, double xEnd, double &x1, double &x2, void* pvData) {
63  const double FACTOR = 1.6;
64  const unsigned NTRY = 50;
65 
66  if (x1>x2) {
67  double tmp=x1;
68  x1=x2;
69  x2=tmp;
70  }
71  if (xStart>xEnd) {
72  double tmp=xStart;
73  xEnd=xStart;
74  xEnd=tmp;
75  }
76  double deltaT=xEnd-xStart;
77 
78  if (x1 < xStart)
79  x1 = xStart;
80  else if (x1 > xEnd)
81  x1 = xEnd;
82  if (x2 < xStart)
83  x2 = xStart;
84  else if (x2 > xEnd)
85  x2 = xEnd;
86 
87  if (x1 == x2)
88  {
89  x1 -= .1*deltaT;
90  x1 = (x1>xStart)?x1:xStart;
91  x2 += .1*deltaT;
92  x2 = (x2<xEnd)?x2:xEnd;
93  }
94 
95  double f1 = fn (x1, pvData), f2 = fn (x2, pvData);
96  unsigned j;
97 
98  if (x1 == x2)
99  {
100  // printf ("you have to guess an initial range");
101  return 1E8;
102  }
103  for (j = 1; j <= NTRY; j++) {
104  if (f1*f2 < 0.) return 1; // found a root
105  if (fabs (f1) < fabs (f2) && x1 > xStart )
106  {
107  if (x1+FACTOR*(x1-x2) > xStart)
108  {
109  x1 += FACTOR*(x1-x2); // expand towards x1
110  }
111  else
112  {
113  x1 = xStart;
114  }
115  f1 = fn (x1, pvData);
116  }
117  else if (x2 < xEnd ) {
118  if (x2+FACTOR*(x2-x1) < xEnd)
119  {
120  x2 += FACTOR*(x2-x1); // ... or towards x2
121  }
122  else
123  {
124  x2 = xEnd;
125  }
126  f2 = fn (x2, pvData);
127  }
128  else
129  break;
130  }
131  return 0;
132 } // no root bracketed
133 
134 unsigned OT_ROOT_FIND_1D::ZeroBracIn (Function fn, const double &x1, const double &x2,
135  unsigned n, double xb1[], double xb2[], unsigned nb, void* pvData) {
136  unsigned i, nbb = nb;
137  double x = x1, dx = (x2-x1)/n, // determine appropriate spacing
138  fp = fn (x, pvData);
139 
140  nb = 0;
141  for (i = 1; i <= n; i++) { // loop over all intervals
142  double fc;
143 
144  x += dx;
145  fc = fn (x, pvData);
146  if (fc*fp < 0.) { // if a sign change occurs, record
147  xb1[nb] = x-dx; // values for the bounds.
148  xb2[nb] = x;
149  nb++;
150  }
151  fp = fc;
152  if (nbb == nb) return nb;
153  }
154  return nb;
155 }
156 
157 
158 double OT_ROOT_FIND_1D::RootBisect (Function fn, const double &x1, const double &x2, const double &xacc, void* pvData)
159 {
160  const unsigned JMAX = 50;
161  double fmid = fn (x2, pvData), f = fn (x1, pvData), rtbis, dx;
162  unsigned j;
163 
164  if (fmid*f >= 0)
165  {
166  // printf ("root must be bracketed for bisection");
167  return 1E308;
168  }
169 
170  if (f < 0.) { // orient the search so that f > 0
171  rtbis = x1; // lies at x+dx.
172  dx = x2-x1;
173  }
174  else {
175  rtbis = x2;
176  dx = x1-x2;
177  }
178 
179  for (j = 1; j <= JMAX; j++) { // bisection loop
180  double xmid;
181 
182  dx *= .5; // here we halve the interval
183  xmid = rtbis+dx; // and update boundaries and
184  fmid = fn (xmid, pvData); // function value
185  if (fmid <= 0.) rtbis = xmid;
186  if ((fabs (dx) <= xacc)||(fmid == 0.)) return rtbis;
187  }
188  // printf ("too many bisections");
189  return 1E308;
190 } // this should happen rarely (2^-50 ~ 10^-15)
191 
192 
193 double OT_ROOT_FIND_1D::RootFlsPos (Function fn, const double &x1, const double &x2,
194  const double &xacc, void* pvData) {
195  const unsigned MAXIT = 40;
196  double flo = fn (x1, pvData), fhi = fn (x2, pvData), xl, xh, dx, dummy;
197  unsigned j;
198 
199  if (flo*fhi >= 0)
200  {
201  // printf ("root must be bracketed for false position");
202  return 1E308;
203  }
204 
205  if (flo < 0.) { // let xl correspond to the low side
206  xl = x1;
207  xh = x2;
208  }
209  else {
210  {
211  dummy=flo;
212  flo=fhi;
213  fhi=dummy;
214  }
215  xl = x2;
216  xh = x1;
217  }
218  dx = xh-xl;
219 
220  for (j = 1; j <= MAXIT; j++) { // false position loop
221  double rtflsp = xl+dx*flo/(flo-fhi),// increment w/ respect to latest
222  f = fn (rtflsp, pvData), // value
223  del = (f < 0.)? xl-rtflsp: xh-rtflsp;
224 
225  if (f < 0.) { // replace appropriate limit
226  xl = rtflsp;
227  flo = f;
228  }
229  else {
230  xh = rtflsp;
231  fhi = f;
232  }
233  dx = xh-xl;
234 
235  if ((fabs (del) <= xacc)||(f == 0.)) return rtflsp;
236  } // convergence
237 
238  // printf ("RootFlsPos exceeded maximum iterations");
239  return 1E308;
240 }
241 
242 
243 double OT_ROOT_FIND_1D::RootNewton (Function fn, Function df,
244  const double &x1, const double &x2, const double &xacc, void* pvData) {
245  const unsigned JMAX = 20;
246  double rtnewt = .5*(x1+x2); // initial guess
247  unsigned j;
248 
249  for (j = 1; j <= JMAX; j++) {
250  double f = fn (rtnewt, pvData), fs = df (rtnewt, pvData),
251  dx = f/fs;
252 
253  rtnewt -= dx;
254  if ((x1-rtnewt)*(rtnewt-x2) < 0.)
255  {
256  // printf ("jumped out of brackets");
257  return 1E308;
258  }
259  if (fabs (dx) < xacc) return rtnewt;
260  } // convergence
261 
262  // printf("RootNewton exceeded maximum iterations");
263  return 1E308;
264 }
265 
266 double OT_ROOT_FIND_1D::RootSafe (Function fn, Function df,
267  const double &x1, const double &x2, const double &xacc, void* pvData) {
268  const unsigned JMAX = 100;
269 
270  double fl = fn (x1, pvData), fh = fn (x2, pvData), xl, xh;
271 
272  if (fl*fh > SMALL_NUM_2)
273  {
274  // printf ("root must be bracketed");
275  return 1E308;
276  }
277  if (fl < 0) { // orient the search so that f (xl) < 0
278  xl = x1;
279  xh = x2;
280  }
281  else {
282  xl = x2;
283  xh = x1;
284  }
285 
286  double rtsafe = .5*(x1+x2); // initial guess
287  double dxold = fabs (x2-x1),
288  dx = dxold;
289  double f = fn (rtsafe, pvData), fp = df (rtsafe, pvData);
290 
291  for (unsigned j = 1; j <= JMAX; j++) {
292  if ( ( ((rtsafe-xh)*fp-f)*((rtsafe-xl)*fp-f) >= 0 ) || // bisect if newton out of brackets
293  ( fabs (2*f) > fabs (dxold*fp) ) ) { // or not decreasing fast enough
294  dxold = dx;
295  dx = .5*(xh -xl);
296  rtsafe = xl+dx;
297  if (xl == rtsafe) return rtsafe;
298  } // change in root is negligible
299  else {
300  dxold = dx;
301  dx = f/fp;
302  double temp = rtsafe;
303  rtsafe -= dx;
304  if (temp == rtsafe) return rtsafe;
305  }
306  if (fabs (dx) < xacc) return rtsafe; // convergence
307  f = fn (rtsafe, pvData);
308  fp = df (rtsafe, pvData);
309  if (f < 0) xl = rtsafe;
310  else xh = rtsafe;
311  }
312  // printf("too many iterations");
313  return 1E308;
314 }
315 
OT_ROOT_FIND_1D::RootNewton
static double RootNewton(Function fn, Function df, const double &x1, const double &x2, const double &xacc, void *pvData=0)
Definition: ot_root_find.cpp:243
OT_ROOT_FIND_1D::RootBisect
static double RootBisect(Function fn, const double &x1, const double &x2, const double &xacc, void *pvData=0)
Definition: ot_root_find.cpp:158
ot_root_find.h
f
double f(double x, long nb, double *xfonc, double *fonc, double eng, double eni, double lambda, double nor, double *fonc2)
Definition: fct_generateur_calibrage.cpp:96
OT_ROOT_FIND_1D::RootSafe
static double RootSafe(Function fn, Function df, const double &x1, const double &x2, const double &xacc, void *pvData=0)
Definition: ot_root_find.cpp:266
SMALL_NUM_2
#define SMALL_NUM_2
Definition: ot_root_find.cpp:34
OT_ROOT_FIND_1D::RootFlsPos
static double RootFlsPos(Function fn, const double &x1, const double &x2, const double &xacc, void *pvData=0)
Definition: ot_root_find.cpp:193
OT_ROOT_FIND_1D::ZeroBracOut
static unsigned ZeroBracOut(Function fn, double &x1, double &x2, void *pvData=0)
Definition: ot_root_find.cpp:36
OT_ROOT_FIND_1D::ZeroBracIn
static unsigned ZeroBracIn(Function fn, const double &x1, const double &x2, unsigned n, double xb1[], double xb2[], unsigned nb, void *pvData=0)
Definition: ot_root_find.cpp:134