7
7
#include "GmshMessage.h"
12
#include <gsl/gsl_errno.h>
13
#include <gsl/gsl_math.h>
14
#include <gsl/gsl_min.h>
15
#include <gsl/gsl_multimin.h>
16
#include <gsl/gsl_multiroots.h>
17
#include <gsl/gsl_linalg.h>
19
void my_gsl_msg(const char *reason, const char *file, int line,
22
Msg::Error("GSL: %s (%s, line %d)", reason, file, line);
27
// set new error handler
28
gsl_set_error_handler(&my_gsl_msg);
30
// initilize robust geometric predicates
35
static double (*f_statN) (double*, void *data);
37
static void (*df_statN) (double*, double*, double &, void *data);
39
static double fobjN (const gsl_vector *x, void *data)
41
return f_statN(x->data, data);
44
static void dfobjN(const gsl_vector *x, void *params, gsl_vector *g)
47
df_statN(x->data, g->data, f, params);
50
static void fdfobjN(const gsl_vector *x, void *params, double *f, gsl_vector *g)
52
df_statN(x->data, g->data, *f, params);
55
void minimize_N(int N, double (*f)(double*, void *data),
56
void (*df)(double*, double*, double &, void *data),
57
void *data, int niter, double *U, double &res)
65
const gsl_multimin_fdfminimizer_type *T;
66
gsl_multimin_fdfminimizer *s;
68
gsl_multimin_function_fdf my_func;
72
my_func.fdf = &fdfobjN;
74
my_func.params = data;
76
x = gsl_vector_alloc(N);
77
for (int i = 0; i < N; i++)
78
gsl_vector_set(x, i, U[i]);
80
T = gsl_multimin_fdfminimizer_conjugate_fr;
81
s = gsl_multimin_fdfminimizer_alloc(T, N);
83
gsl_multimin_fdfminimizer_set(s, &my_func, x, 0.01, 1e-4);
87
status = gsl_multimin_fdfminimizer_iterate(s);
92
status = gsl_multimin_test_gradient(s->gradient, 1e-3);
94
while (status == GSL_CONTINUE && iter < niter);
96
for (int i = 0; i < N; i++)
97
U[i] = gsl_vector_get(s->x, i);
99
gsl_multimin_fdfminimizer_free(s);
111
void minimize_N(int N, double (*f) (double*, void *data),
112
void (*df) (double*, double*, double &, void *data) ,
113
void *data,int niter,
114
double *, double &res)
116
Msg::Error("Gmsh must be compiled with GSL support for minimize_N");
10
#define SQU(a) ((a)*(a))
12
double myatan2(double a, double b)
14
if(a == 0.0 && b == 0)
19
double myasin(double a)
29
double myacos(double a)
39
void matvec(double mat[3][3], double vec[3], double res[3])
41
res[0] = mat[0][0] * vec[0] + mat[0][1] * vec[1] + mat[0][2] * vec[2];
42
res[1] = mat[1][0] * vec[0] + mat[1][1] * vec[1] + mat[1][2] * vec[2];
43
res[2] = mat[2][0] * vec[0] + mat[2][1] * vec[1] + mat[2][2] * vec[2];
46
void normal3points(double x0, double y0, double z0,
47
double x1, double y1, double z1,
48
double x2, double y2, double z2,
51
double t1[3] = {x1 - x0, y1 - y0, z1 - z0};
52
double t2[3] = {x2 - x0, y2 - y0, z2 - z0};
57
int sys2x2(double mat[2][2], double b[2], double res[2])
62
norm = SQU(mat[0][0]) + SQU(mat[1][1]) + SQU(mat[0][1]) + SQU(mat[1][0]);
63
det = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
65
// TOLERANCE ! WARNING WARNING
66
if(norm == 0.0 || fabs(det) / norm < 1.e-12) {
68
Msg::Debug("Assuming 2x2 matrix is singular (det/norm == %.16g)",
70
res[0] = res[1] = 0.0;
75
res[0] = b[0] * mat[1][1] - mat[0][1] * b[1];
76
res[1] = mat[0][0] * b[1] - mat[1][0] * b[0];
78
for(i = 0; i < 2; i++)
84
double det3x3(double mat[3][3])
86
return (mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
87
mat[0][1] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
88
mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]));
91
double trace3x3(double mat[3][3])
93
return mat[0][0] + mat[1][1] + mat[2][2];
96
double trace2 (double mat[3][3])
98
double a00 = mat[0][0] * mat[0][0] + mat[1][0] * mat[0][1] + mat[2][0] * mat[0][2];
99
double a11 = mat[1][0] * mat[0][1] + mat[1][1] * mat[1][1] + mat[1][2] * mat[2][1];
100
double a22 = mat[2][0] * mat[0][2] + mat[2][1] * mat[1][2] + mat[2][2] * mat[2][2];
102
return a00 + a11 + a22;
105
int sys3x3(double mat[3][3], double b[3], double res[3], double *det)
113
res[0] = res[1] = res[2] = 0.0;
119
res[0] = b[0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
120
mat[0][1] * (b[1] * mat[2][2] - mat[1][2] * b[2]) +
121
mat[0][2] * (b[1] * mat[2][1] - mat[1][1] * b[2]);
123
res[1] = mat[0][0] * (b[1] * mat[2][2] - mat[1][2] * b[2]) -
124
b[0] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
125
mat[0][2] * (mat[1][0] * b[2] - b[1] * mat[2][0]);
127
res[2] = mat[0][0] * (mat[1][1] * b[2] - b[1] * mat[2][1]) -
128
mat[0][1] * (mat[1][0] * b[2] - b[1] * mat[2][0]) +
129
b[0] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]);
131
for(i = 0; i < 3; i++)
136
int sys3x3_with_tol(double mat[3][3], double b[3], double res[3], double *det)
141
out = sys3x3(mat, b, res, det);
143
SQU(mat[0][0]) + SQU(mat[0][1]) + SQU(mat[0][2]) +
144
SQU(mat[1][0]) + SQU(mat[1][1]) + SQU(mat[1][2]) +
145
SQU(mat[2][0]) + SQU(mat[2][1]) + SQU(mat[2][2]);
147
// TOLERANCE ! WARNING WARNING
148
if(norm == 0.0 || fabs(*det) / norm < 1.e-12) {
150
Msg::Debug("Assuming 3x3 matrix is singular (det/norm == %.16g)",
152
res[0] = res[1] = res[2] = 0.0;
159
double det2x2(double mat[2][2])
161
return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
164
double det2x3(double mat[2][3])
166
double v1[3] = {mat[0][0], mat[0][1], mat[0][2]};
167
double v2[3] = {mat[1][0], mat[1][1], mat[1][2]};
174
double inv2x2(double mat[2][2], double inv[2][2])
176
const double det = det2x2(mat);
178
double ud = 1. / det;
179
inv[0][0] = mat[1][1] * ud;
180
inv[1][0] = -mat[1][0] * ud;
181
inv[0][1] = -mat[0][1] * ud;
182
inv[1][1] = mat[0][0] * ud;
185
Msg::Error("Singular matrix");
186
for(int i = 0; i < 2; i++)
187
for(int j = 0; j < 2; j++)
193
double inv3x3(double mat[3][3], double inv[3][3])
195
double det = det3x3(mat);
197
double ud = 1. / det;
198
inv[0][0] = (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) * ud;
199
inv[1][0] = -(mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) * ud;
200
inv[2][0] = (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]) * ud;
201
inv[0][1] = -(mat[0][1] * mat[2][2] - mat[0][2] * mat[2][1]) * ud;
202
inv[1][1] = (mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0]) * ud;
203
inv[2][1] = -(mat[0][0] * mat[2][1] - mat[0][1] * mat[2][0]) * ud;
204
inv[0][2] = (mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1]) * ud;
205
inv[1][2] = -(mat[0][0] * mat[1][2] - mat[0][2] * mat[1][0]) * ud;
206
inv[2][2] = (mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]) * ud;
209
Msg::Error("Singular matrix");
210
for(int i = 0; i < 3; i++)
211
for(int j = 0; j < 3; j++)
217
double angle_02pi(double A3)
219
double DP = 2 * M_PI;
220
while(A3 > DP || A3 < 0.) {
229
double angle_plan(double V[3], double P1[3], double P2[3], double n[3])
231
double PA[3], PB[3], angplan;
232
double cosc, sinc, c[3];
234
PA[0] = P1[0] - V[0];
235
PA[1] = P1[1] - V[1];
236
PA[2] = P1[2] - V[2];
238
PB[0] = P2[0] - V[0];
239
PB[1] = P2[1] - V[1];
240
PB[2] = P2[2] - V[2];
247
prosca(PA, PB, &cosc);
249
angplan = myatan2(sinc, cosc);
254
double triangle_area(double p0[3], double p1[3], double p2[3])
256
double a[3], b[3], c[3];
258
a[0] = p2[0] - p1[0];
259
a[1] = p2[1] - p1[1];
260
a[2] = p2[2] - p1[2];
262
b[0] = p0[0] - p1[0];
263
b[1] = p0[1] - p1[1];
264
b[2] = p0[2] - p1[2];
267
return 0.5 * sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
270
char float2char(float f)
272
// float normalized in [-1, 1], char in [-127, 127]
274
if(f > 127.) return 127;
275
else if(f < -127.) return -127;
279
float char2float(char c)
283
if(f > 1.) return 1.;
284
else if(f < -1) return -1.;
288
double InterpolateIso(double *X, double *Y, double *Z,
289
double *Val, double V, int I1, int I2,
290
double *XI, double *YI, double *ZI)
292
if(Val[I1] == Val[I2]) {
299
double coef = (V - Val[I1]) / (Val[I2] - Val[I1]);
300
*XI = coef * (X[I2] - X[I1]) + X[I1];
301
*YI = coef * (Y[I2] - Y[I1]) + Y[I1];
302
*ZI = coef * (Z[I2] - Z[I1]) + Z[I1];
307
void gradSimplex(double *x, double *y, double *z, double *v, double *grad)
309
// p = p1 * (1-u-v-w) + p2 u + p3 v + p4 w
313
mat[0][0] = x[1] - x[0];
314
mat[1][0] = x[2] - x[0];
315
mat[2][0] = x[3] - x[0];
316
mat[0][1] = y[1] - y[0];
317
mat[1][1] = y[2] - y[0];
318
mat[2][1] = y[3] - y[0];
319
mat[0][2] = z[1] - z[0];
320
mat[1][2] = z[2] - z[0];
321
mat[2][2] = z[3] - z[0];
325
sys3x3(mat, b, grad, &det);
328
double ComputeVonMises(double *V)
330
double tr = (V[0] + V[4] + V[8]) / 3.;
331
double v11 = V[0] - tr, v12 = V[1], v13 = V[2];
332
double v21 = V[3], v22 = V[4] - tr, v23 = V[5];
333
double v31 = V[6], v32 = V[7], v33 = V[8] - tr;
334
return sqrt(1.5 * (v11 * v11 + v12 * v12 + v13 * v13 +
335
v21 * v21 + v22 * v22 + v23 * v23 +
336
v31 * v31 + v32 * v32 + v33 * v33));
339
double ComputeScalarRep(int numComp, double *val)
343
else if(numComp == 3)
344
return sqrt(val[0] * val[0] + val[1] * val[1] + val[2] * val[2]);
345
else if(numComp == 9)
346
return ComputeVonMises(val);
350
void eigenvalue(double mat[3][3], double v[3])
352
// characteristic polynomial of T : find v root of
353
// v^3 - I1 v^2 + I2 T - I3 = 0
354
// I1 : first invariant , trace(T)
355
// I2 : second invariant , 1/2 (I1^2 -trace(T^2))
356
// I3 : third invariant , det T
360
c[2] = - trace3x3(mat);
361
c[1] = 0.5 * (c[2] * c[2] - trace2(mat));
362
c[0] = - det3x3(mat);
364
//printf("%g %g %g\n", mat[0][0], mat[0][1], mat[0][2]);
365
//printf("%g %g %g\n", mat[1][0], mat[1][1], mat[1][2]);
366
//printf("%g %g %g\n", mat[2][0], mat[2][1], mat[2][2]);
367
//printf("%g x^3 + %g x^2 + %g x + %g = 0\n", c[3], c[2], c[1], c[0]);
370
FindCubicRoots(c, v, imag);
374
void FindCubicRoots(const double coef[4], double real[3], double imag[3])
382
Msg::Error("Degenerate cubic: use a second degree solver!");
390
double q = (3.0*c - (b*b))/9.0;
391
double r = -(27.0*d) + b*(9.0*c - 2.0*(b*b));
394
double discrim = q*q*q + r*r;
395
imag[0] = 0.0; // The first root is always real.
396
double term1 = (b/3.0);
398
if (discrim > 0) { // one root is real, two are complex
399
double s = r + sqrt(discrim);
400
s = ((s < 0) ? -pow(-s, (1.0/3.0)) : pow(s, (1.0/3.0)));
401
double t = r - sqrt(discrim);
402
t = ((t < 0) ? -pow(-t, (1.0/3.0)) : pow(t, (1.0/3.0)));
403
real[0] = -term1 + s + t;
404
term1 += (s + t)/2.0;
405
real[1] = real[2] = -term1;
406
term1 = sqrt(3.0)*(-t + s)/2;
412
// The remaining options are all real
413
imag[1] = imag[2] = 0.0;
416
if (discrim == 0){ // All roots real, at least two are equal.
417
r13 = ((r < 0) ? -pow(-r,(1.0/3.0)) : pow(r,(1.0/3.0)));
418
real[0] = -term1 + 2.0*r13;
419
real[1] = real[2] = -(r13 + term1);
423
// Only option left is that all roots are real and unequal (to get
427
dum1 = acos(r/sqrt(dum1));
429
real[0] = -term1 + r13*cos(dum1/3.0);
430
real[1] = -term1 + r13*cos((dum1 + 2.0*M_PI)/3.0);
431
real[2] = -term1 + r13*cos((dum1 + 4.0*M_PI)/3.0);
434
void eigsort(double d[3])
439
for (i=0; i<3; i++) {
442
if (d[j] >= p) p=d[k=j];
450
void invert_singular_matrix3x3(double MM[3][3], double II[3][3])
455
for(i = 1; i <= n; i++) {
456
for(j = 1; j <= n; j++) {
457
II[i - 1][j - 1] = 0.0;
458
TT[i - 1][j - 1] = 0.0;
462
gmshMatrix<double> M(3, 3), V(3, 3);
463
gmshVector<double> W(3);
464
for(i = 1; i <= n; i++){
465
for(j = 1; j <= n; j++){
466
M(i - 1, j - 1) = MM[i - 1][j - 1];
470
for(i = 1; i <= n; i++) {
471
for(j = 1; j <= n; j++) {
472
double ww = W(i - 1);
473
if(fabs(ww) > 1.e-16) { // singular value precision
474
TT[i - 1][j - 1] += M(j - 1, i - 1) / ww;
478
for(i = 1; i <= n; i++) {
479
for(j = 1; j <= n; j++) {
480
for(k = 1; k <= n; k++) {
481
II[i - 1][j - 1] += V(i - 1, k - 1) * TT[k - 1][j - 1];
487
bool newton_fd(void (*func)(gmshVector<double> &, gmshVector<double> &, void *),
488
gmshVector<double> &x, void *data, double relax, double tolx)
490
const int MAXIT = 50;
491
const double EPS = 1.e-4;
492
const int N = x.size();
494
gmshMatrix<double> J(N, N);
495
gmshVector<double> f(N), feps(N), dx(N);
497
for (int iter = 0; iter < MAXIT; iter++){
500
for (int j = 0; j < N; j++){
501
double h = EPS * fabs(x(j));
505
for (int i = 0; i < N; i++)
506
J(i, j) = (feps(i) - f(i)) / h;
511
dx(0) = f(0) / J(0, 0);
515
for (int i = 0; i < N; i++)
516
x(i) -= relax * dx(i);
518
if(dx.norm() < tolx) return true;