OOFEM 3.0
Loading...
Searching...
No Matches
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 - 2025 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 "oofemenv.h"
44
45#include <cmath>
46#include <cfloat> // For _isnan
47
48namespace oofem {
49class 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
59inline int min(int i, int j)
60{ return ( i <= j ? i : j ); }
61
63inline long min(long i, long j)
64{ return ( i <= j ? i : j ); }
65
67inline unsigned long min(unsigned long i, unsigned long j)
68{
69 return (i <= j ? i : j);
70}
71
72#ifdef _WIN32
74inline std::size_t min(std::size_t i, std::size_t j)
75{ return ( i <= j ? i : j ); }
76#endif
77
78
80inline double min(double i, double j)
81{ return ( i <= j ? i : j ); }
82
84inline int max(int i, int j)
85{ return ( i >= j ? i : j ); }
86
88inline double clamp(int a, int lower, int upper)
89{ return ( a <= lower ? lower : ( a >= upper ? upper : a ) ); }
90
92inline long max(long i, long j)
93{ return ( i >= j ? i : j ); }
94
96inline double max(double i, double j)
97{ return ( i >= j ? i : j ); }
98
100inline double clamp(double a, double lower, double upper)
101{ return ( a <= lower ? lower : ( a >= upper ? upper : a ) ); }
102
104inline double sgn(double i)
105{ return ( i < 0. ? -1. : 1. ); }
106
108double signum(double i);
109
110#ifndef HAVE_ISNAN
111 #ifdef _MSC_VER
113inline bool isnan(double x) { return _isnan(x) != 0; }
114 #else
115// Last attempt to find a isnan function, rely on C++11
116inline bool isnan(double x) { return std :: isnan(x); }
117 #endif
118#endif
119
120#ifndef HAVE_CBRT
122inline double cbrt(double x) { return sgn(x) * pow(fabs(x), 1.0 / 3.0); }
123#endif
124
125inline double sqr(double x) { return x * x; }
126
128inline double macbra(double x) { return ( x >= 0 ? x : 0 ); }
130inline double negbra(double x) { return ( x <= 0 ? x : 0 ); }
131
144void cubic(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num);
145
162void cubic3r(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num);
163
167int iperm(int val, int rank);
168
169
170#define MATHFEM_C 0.38196601
171#define MATHFEM_R ( 1 - MATHFEM_C )
172#define MATHFEM_BRENT_MAXITER 100
173
174template< class T > class mem_fun
175{
176 double ( T :: *pmf )(double);
177 T *ptr;
178public:
179 mem_fun( T * o, double ( T :: *p )(double) ) : pmf(p), ptr(o) { }
180 double operator() (double x) const { return ( ptr->*pmf )(x); }
181};
182
183
185{
186 double ( * func )(double);
187public:
188 c_fun( double ( * p )(double) ) : func(p) { }
189 double operator() (double x) const { return ( * func )( x ); }
190};
191
192
193
208template< class T > double gss(double ax, double bx, double cx, const T &f,
209 double tol, double &xmin)
210{
211 [[maybe_unused]] int ii = 0;
212 double f1, f2, x0, x1, x2, x3;
213
214 x0 = ax;
215 x3 = cx;
216
217 // initialization x0-x1 made the smaller segment
218 if ( fabs(cx - bx) > fabs(bx - ax) ) {
219 x1 = bx;
220 x2 = bx + MATHFEM_C * ( cx - bx );
221 } else {
222 x2 = bx;
223 x1 = bx - MATHFEM_C * ( bx - ax );
224 }
225
226 f1 = f(x1);
227 f2 = f(x2);
228
229 // iteration loop
230 while ( fabs(x3 - x0) > tol * ( fabs(x1) + fabs(x2) ) ) {
231 if ( f2 < f1 ) {
232 // minimum bracketed by (x1,x2,x3) triplet
233 x0 = x1;
234 x1 = x2;
235 x2 = MATHFEM_R * x1 + MATHFEM_C * x3; // x2=x1+C*(x3-x1)
236
237 f1 = f2;
238 f2 = f(x2);
239 } else {
240 // minimum bracketed by (x0,x1,x2) triplet
241 x3 = x2;
242 x2 = x1;
243 x1 = MATHFEM_R * x2 + MATHFEM_C * x0; // x1 = x2+c*(x0-x2)
244
245 f2 = f1;
246 f1 = f(x1);
247 }
248
249 ii++;
250 }
251
252 //printf ("gss: convergence reached in %d iterations\n", ii);
253 if ( f1 < f2 ) {
254 xmin = x1;
255 return f1;
256 } else {
257 xmin = x2;
258 return f2;
259 }
260}
261
262template< class T > double brent(double ax, double bx, double cx, const T &f,
263 double tol, double &xmin)
264{
265 int ii;
266 double x_left = ax, x_right = cx;
267 double x, x_midpoint, v, w, u, tol1, tol2, p, q, r, e_tmp, d = 0.0, fx, fv, fw, fu;
268 double e = 0.0;
269
270 x = v = w = bx;
271 fx = fv = fw = f(x);
272
273 for ( ii = 1; ii <= MATHFEM_BRENT_MAXITER; ii++ ) {
274 x_midpoint = 0.5 * ( x_left + x_right );
275
276 // check for convergence here
277 tol1 = tol * fabs(x) + 1.0e-10;
278 tol2 = 2.0 * tol1;
279 if ( fabs(x - x_midpoint) <= ( tol2 - 0.5 * ( x_right - x_left ) ) ) {
280 //printf ("brent: convergence in %d iterations\n", ii);
281 xmin = x;
282 return fx;
283 }
284
285 if ( fabs(e) > tol1 ) {
286 /* fit parabola */
287 r = ( x - w ) * ( fx - fv );
288 q = ( x - v ) * ( fx - fw );
289 p = ( x - v ) * q - ( x - w ) * r;
290 q = 2.0 * ( q - r );
291
292 if ( q > 0 ) {
293 p = -p;
294 } else {
295 q = -q;
296 }
297
298 e_tmp = e;
299 e = d;
300
301 if ( fabs(p) < fabs(0.5 * q * e_tmp) && p < q * ( x - x_left ) && p < q * ( x_right - x ) ) {
302 d = p / q;
303 u = x + d;
304 if ( ( u - x_left ) < tol2 || ( x_right - u ) < tol2 ) {
305 d = ( x < x_midpoint ) ? tol1 : -tol1;
306 }
307 } else {
308 e = ( x < x_midpoint ) ? x_right - x : -( x - x_left );
309 d = MATHFEM_C * e;
310 }
311 } else {
312 e = ( x < x_midpoint ) ? x_right - x : -( x - x_left );
313 d = MATHFEM_C * e;
314 }
315
316 if ( fabs(d) >= tol1 ) {
317 u = x + d;
318 } else {
319 u = x + ( ( d > 0 ) ? tol1 : -tol1 );
320 }
321
322 fu = f(u);
323
324 if ( fu <= fx ) {
325 if ( u >= x ) {
326 x_left = x;
327 } else {
328 x_right = x;
329 }
330
331 v = w;
332 w = x;
333 x = u;
334 fv = fw;
335 fw = fx;
336 fx = fu;
337 } else {
338 if ( u < x ) {
339 x_left = u;
340 } else {
341 x_right = u;
342 }
343
344 if ( fu <= fw || w == x ) {
345 v = w;
346 w = u;
347 fv = fw;
348 fw = fu;
349 } else if ( fu <= fv || v == x || v == w ) {
350 v = u;
351 fv = fu;
352 }
353 }
354 }
355
356 // too many iterations
357 OOFEM_LOG_WARNING("brent : too many iterations\n");
358 xmin = x;
359 return fx;
360}
361
368void ls2fit(const FloatArray &x, const FloatArray &y, FloatArray &a);
369} // end namespace oofem
370#endif // mathfem_h
double(* func)(double)
Definition mathfem.h:186
c_fun(double(*p)(double))
Definition mathfem.h:188
double(T ::* pmf)(double)
Definition mathfem.h:176
mem_fun(T *o, double(T ::*p)(double))
Definition mathfem.h:179
double operator()(double x) const
Definition mathfem.h:180
#define OOFEM_LOG_WARNING(...)
Definition logger.h:139
#define MATHFEM_R
Definition mathfem.h:171
#define MATHFEM_C
Definition mathfem.h:170
#define MATHFEM_BRENT_MAXITER
Definition mathfem.h:172
FloatArrayF< N > min(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
double cbrt(double x)
Returns the cubic root of x.
Definition mathfem.h:122
double macbra(double x)
Returns the positive part of given float.
Definition mathfem.h:128
double sqr(double x)
Definition mathfem.h:125
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
void cubic3r(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Definition mathfem.C:155
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:327
double gss(double ax, double bx, double cx, const T &f, double tol, double &xmin)
Definition mathfem.h:208
bool isnan(double x)
Definition mathfem.h:116
double negbra(double x)
Returns the negative part of given float.
Definition mathfem.h:130
void cubic(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Definition mathfem.C:43
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1).
Definition mathfem.h:104
int iperm(int val, int rank)
Definition mathfem.C:261
void ls2fit(const FloatArray &x, const FloatArray &y, FloatArray &a)
Definition mathfem.C:272
double brent(double ax, double bx, double cx, const T &f, double tol, double &xmin)
Definition mathfem.h:262
double clamp(int a, int lower, int upper)
Returns the clamped value of a between upper and lower.
Definition mathfem.h:88
#define OOFEM_EXPORT
Definition oofemcfg.h:7

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011