OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
mathfem.h
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 /*
36  * This file contains some functions used in the finite element application.
37  * ref : Lippman p 104
38  */
39 #ifndef mathfem_h
40 #define mathfem_h
41 
42 #include "error.h"
43 #include "oofemcfg.h"
44 
45 #include <cmath>
46 #include <cfloat> // For _isnan
47 
48 namespace oofem {
49 class FloatArray;
50 
51 #ifndef M_PI
52  #define M_PI 3.1415926535897932384626433832795029L
53 #endif
54 #ifndef M_LN2
55  #define M_LN2 0.6931471805599453094172321214581766L
56 #endif
57 
59 inline int min(int i, int j)
60 { return ( i <= j ? i : j ); }
61 
63 inline long min(long i, long j)
64 { return ( i <= j ? i : j ); }
65 
67 inline double min(double i, double j)
68 { return ( i <= j ? i : j ); }
69 
71 inline int max(int i, int j)
72 { return ( i >= j ? i : j ); }
73 
75 inline double clamp(int a, int lower, int upper)
76 { return ( a <= lower ? lower : ( a >= upper ? upper : a ) ); }
77 
79 inline long max(long i, long j)
80 { return ( i >= j ? i : j ); }
81 
83 inline double max(double i, double j)
84 { return ( i >= j ? i : j ); }
85 
87 inline double clamp(double a, double lower, double upper)
88 { return ( a <= lower ? lower : ( a >= upper ? upper : a ) ); }
89 
91 inline double sgn(double i)
92 { return ( i < 0. ? -1. : 1. ); }
93 
95 double signum(double i);
96 
97 #ifndef HAVE_ISNAN
98  #ifdef _MSC_VER
99 inline bool isnan(double x) { return _isnan(x) != 0; }
101  #else
102 // Last attempt to find a isnan function, rely on C++11
103 inline bool isnan(double x) { return std :: isnan(x); }
104  #endif
105 #endif
106 
107 #ifndef HAVE_CBRT
108 inline double cbrt(double x) { return sgn(x) * pow(fabs(x), 1.0 / 3.0); }
110 #endif
111 
112 inline double sqr(double x) { return x * x; }
113 
115 inline double macbra(double x) { return ( x >= 0 ? x : 0 ); }
117 inline double negbra(double x) { return ( x <= 0 ? x : 0 ); }
118 
131 void cubic(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num);
132 
149 void cubic3r(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num);
150 
154 int iperm(int val, int rank);
155 
156 
157 #define MATHFEM_C 0.38196601
158 #define MATHFEM_R ( 1 - MATHFEM_C )
159 #define MATHFEM_BRENT_MAXITER 100
160 
161 template< class T > class mem_fun
162 {
163  double ( T :: *pmf )(double);
164  T *ptr;
165 public:
166  mem_fun( T * o, double ( T :: *p )(double) ) : pmf(p), ptr(o) { }
167  double operator() (double x) const { return ( ptr->*pmf )(x); }
168 };
169 
170 
171 class OOFEM_EXPORT c_fun
172 {
173  double ( * func )(double);
174 public:
175  c_fun( double ( * p )(double) ) : func(p) { }
176  double operator() (double x) const { return ( * func )( x ); }
177 };
178 
179 
180 
195 template< class T > double gss(double ax, double bx, double cx, const T &f,
196  double tol, double &xmin)
197 {
198  int ii = 0;
199  double f1, f2, x0, x1, x2, x3;
200 
201  x0 = ax;
202  x3 = cx;
203 
204  // initialization x0-x1 made the smaller segment
205  if ( fabs(cx - bx) > fabs(bx - ax) ) {
206  x1 = bx;
207  x2 = bx + MATHFEM_C * ( cx - bx );
208  } else {
209  x2 = bx;
210  x1 = bx - MATHFEM_C * ( bx - ax );
211  }
212 
213  f1 = f(x1);
214  f2 = f(x2);
215 
216  // iteration loop
217  while ( fabs(x3 - x0) > tol * ( fabs(x1) + fabs(x2) ) ) {
218  if ( f2 < f1 ) {
219  // minimum bracketed by (x1,x2,x3) triplet
220  x0 = x1;
221  x1 = x2;
222  x2 = MATHFEM_R * x1 + MATHFEM_C * x3; // x2=x1+C*(x3-x1)
223 
224  f1 = f2;
225  f2 = f(x2);
226  } else {
227  // minimum bracketed by (x0,x1,x2) triplet
228  x3 = x2;
229  x2 = x1;
230  x1 = MATHFEM_R * x2 + MATHFEM_C * x0; // x1 = x2+c*(x0-x2)
231 
232  f2 = f1;
233  f1 = f(x1);
234  }
235 
236  ii++;
237  }
238 
239  //printf ("gss: convergence reached in %d iterations\n", ii);
240  if ( f1 < f2 ) {
241  xmin = x1;
242  return f1;
243  } else {
244  xmin = x2;
245  return f2;
246  }
247 }
248 
249 template< class T > double brent(double ax, double bx, double cx, const T &f,
250  double tol, double &xmin)
251 {
252  int ii;
253  double x_left = ax, x_right = cx;
254  double x, x_midpoint, v, w, u, tol1, tol2, p, q, r, e_tmp, d = 0.0, fx, fv, fw, fu;
255  double e = 0.0;
256 
257  x = v = w = bx;
258  fx = fv = fw = f(x);
259 
260  for ( ii = 1; ii <= MATHFEM_BRENT_MAXITER; ii++ ) {
261  x_midpoint = 0.5 * ( x_left + x_right );
262 
263  // check for convergence here
264  tol1 = tol * fabs(x) + 1.0e-10;
265  tol2 = 2.0 * tol1;
266  if ( fabs(x - x_midpoint) <= ( tol2 - 0.5 * ( x_right - x_left ) ) ) {
267  //printf ("brent: convergence in %d iterations\n", ii);
268  xmin = x;
269  return fx;
270  }
271 
272  if ( fabs(e) > tol1 ) {
273  /* fit parabola */
274  r = ( x - w ) * ( fx - fv );
275  q = ( x - v ) * ( fx - fw );
276  p = ( x - v ) * q - ( x - w ) * r;
277  q = 2.0 * ( q - r );
278 
279  if ( q > 0 ) {
280  p = -p;
281  } else {
282  q = -q;
283  }
284 
285  e_tmp = e;
286  e = d;
287 
288  if ( fabs(p) < fabs(0.5 * q * e_tmp) && p < q * ( x - x_left ) && p < q * ( x_right - x ) ) {
289  d = p / q;
290  u = x + d;
291  if ( ( u - x_left ) < tol2 || ( x_right - u ) < tol2 ) {
292  d = ( x < x_midpoint ) ? tol1 : -tol1;
293  }
294  } else {
295  e = ( x < x_midpoint ) ? x_right - x : -( x - x_left );
296  d = MATHFEM_C * e;
297  }
298  } else {
299  e = ( x < x_midpoint ) ? x_right - x : -( x - x_left );
300  d = MATHFEM_C * e;
301  }
302 
303  if ( fabs(d) >= tol1 ) {
304  u = x + d;
305  } else {
306  u = x + ( ( d > 0 ) ? tol1 : -tol1 );
307  }
308 
309  fu = f(u);
310 
311  if ( fu <= fx ) {
312  if ( u >= x ) {
313  x_left = x;
314  } else {
315  x_right = x;
316  }
317 
318  v = w;
319  w = x;
320  x = u;
321  fv = fw;
322  fw = fx;
323  fx = fu;
324  } else {
325  if ( u < x ) {
326  x_left = u;
327  } else {
328  x_right = u;
329  }
330 
331  if ( fu <= fw || w == x ) {
332  v = w;
333  w = u;
334  fv = fw;
335  fw = fu;
336  } else if ( fu <= fv || v == x || v == w ) {
337  v = u;
338  fv = fu;
339  }
340  }
341  }
342 
343  // too many iterations
344  OOFEM_LOG_WARNING("brent : too many iterations\n");
345  xmin = x;
346  return fx;
347 }
348 
355 void ls2fit(const FloatArray &x, const FloatArray &y, FloatArray &a);
356 } // end namespace oofem
357 #endif // mathfem_h
mem_fun(T *o, double(T::*p)(double))
Definition: mathfem.h:166
int max(int i, int j)
Returns bigger value form two given decimals.
Definition: mathfem.h:71
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
Definition: mathfem.h:91
#define MATHFEM_BRENT_MAXITER
Definition: mathfem.h:159
double macbra(double x)
Returns the positive part of given float.
Definition: mathfem.h:115
bool isnan(double x)
Definition: mathfem.h:103
double sqr(double x)
Definition: mathfem.h:112
void cubic(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Solves cubic equation for real roots.
Definition: mathfem.C:43
#define MATHFEM_R
Definition: mathfem.h:158
double(T::* pmf)(double)
Definition: mathfem.h:163
#define MATHFEM_C
Definition: mathfem.h:157
#define OOFEM_LOG_WARNING(...)
Definition: logger.h:123
void cubic3r(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Solves cubic equation for real roots, assuming that if cubic polynomial given then the only possibili...
Definition: mathfem.C:155
int iperm(int val, int rank)
Returns iperm of val, in specific rank.
Definition: mathfem.C:260
double brent(double ax, double bx, double cx, const T &f, double tol, double &xmin)
Definition: mathfem.h:249
c_fun(double(*p)(double))
Definition: mathfem.h:175
void ls2fit(const FloatArray &x, const FloatArray &y, FloatArray &a)
Least-square fit of 2nd degree polynomial .
Definition: mathfem.C:271
Class representing vector of real numbers.
Definition: floatarray.h:82
double clamp(int a, int lower, int upper)
Returns the clamped value of a between upper and lower.
Definition: mathfem.h:75
double cbrt(double x)
Returns the cubic root of x.
Definition: mathfem.h:109
double operator()(double x) const
Definition: mathfem.h:167
double signum(double i)
Returns the signum of given value (i = 0 returns 0, i < 0 returns -1, i > 0 returns 1) ...
Definition: mathfem.C:326
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
the oofem namespace is to define a context or scope in which all oofem names are defined.
double negbra(double x)
Returns the negative part of given float.
Definition: mathfem.h:117
double gss(double ax, double bx, double cx, const T &f, double tol, double &xmin)
Minimize function of one variable using golden section search.
Definition: mathfem.h:195

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:29 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011