Flow123d  jenkins-Flow123d-linux-release-multijob-282
math_fce.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file
26  * @ingroup la
27  * @brief Auxiliary math functions.
28  *
29  * Small matrix and vectors should be implemented by armadillo library.
30  *
31  */
32 
33 #include <math.h>
34 #include "global_defs.h"
35 #include "system/system.hh"
36 #include "system/math_fce.h"
37 
38 
39 static double Inverse2(SmallMtx2 a,SmallMtx2 b);
40 static double Inverse3(SmallMtx3 a,SmallMtx3 b);
41 static double Inverse4(SmallMtx4 a,SmallMtx4 b);
42 
43 //=============================================================================
44 // LENGTH OF VECTOR
45 //=============================================================================
46 double vector_length( double v[] )
47 {
48  return sqrt( v[0]*v[0]+v[1]*v[1]+v[2]*v[2] );
49 }
50 //=============================================================================
51 // SCALAR PRODUCT OF VECTORS
52 //=============================================================================
53 double scalar_product( double u[], double v[] )
54 {
55  return u[0]*v[0]+u[1]*v[1]+u[2]*v[2];
56 }
57 //=============================================================================
58 // NORMALIZE GIVEN VECTOR
59 //=============================================================================
60 void normalize_vector( double u[] )
61 {
62  double l;
63 
64  if ((l = vector_length( u )) < NUM_ZERO ) {
65  xprintf(Warn,"Normalization of nearly zero vector.\n");
66  }
67  u[0] /= l; u[1] /= l; u[2] /= l;
68 }
69 //=============================================================================
70 // MULTIPLE VECTOR BY REAL NUMBER
71 //=============================================================================
72 void scale_vector( double u[], double k )
73 {
74  u[ 0 ] *= k; u[ 1 ] *= k; u[ 2 ] *= k;
75 }
76 
77 //=============================================================================
78 // VECTOR PRODUCT OF VECTORS
79 //=============================================================================
80 void vector_product( double u[], double v[], double x[] )
81 {
82  // u, v - inputs
83  // x - output, result
84 
85  x[ 0 ] = u[ 1 ] * v[ 2 ] - u[ 2 ] * v[ 1 ];
86  x[ 1 ] = u[ 2 ] * v[ 0 ] - u[ 0 ] * v[ 2 ];
87  x[ 2 ] = u[ 0 ] * v[ 1 ] - u[ 1 ] * v[ 0 ];
88 }
89 //=============================================================================
90 // VECTOR DIFFERENCE OF VECTORS
91 //=============================================================================
92 void vector_difference( double u[], double v[], double x[] )
93 {
94  x[ 0 ] = u[ 0 ] - v[ 0 ];
95  x[ 1 ] = u[ 1 ] - v[ 1 ];
96  x[ 2 ] = u[ 2 ] - v[ 2 ];
97 }
98 
99 /*************************************************
100  * SMALL MATRIX OPERATIONS
101  *************************************************/
102 
103 /**************************************************
104  * determinant 3x3
105  * *************************/
106 double Det3( SmallMtx3 a ) {
107  return a[0][0]*SUBDET2(1,2,1,2)
108  -a[0][1]*SUBDET2(1,2,0,2)
109  +a[0][2]*SUBDET2(1,2,0,1);
110 }
111 
112 /*************************************************
113  * Inverse of general small matrix with given size
114  * a - input; b - output; returns determinant
115  * ************************************************/
116 double MatrixInverse(double *a, double *b, int size) {
117  switch (size) {
118  case 1:
119  *b=1/(*a); return (*a);
120  case 2:
121  return ( Inverse2((SmallMtx2)a, (SmallMtx2)b) );
122  case 3:
123  return ( Inverse3((SmallMtx3)a, (SmallMtx3)b) );
124  case 4:
125  return ( Inverse4((SmallMtx4)a, (SmallMtx4)b) );
126  }
127  return 0.0;
128 }
129 
130 
131 /******************************************************************
132  * Inverse of 2x2 matrix with determinant
133  * a - input; b - output; returns determinant;
134  * *****************************************************************/
136  double Det;
137 
138  Det=SUBDET2(0,1,0,1);
139  if ( fabs(Det) < NUM_ZERO ) return Det;
140  b[0][0]=a[1][1]/Det;
141  b[1][0]=-a[1][0]/Det;
142  b[0][1]=-a[0][1]/Det;
143  b[1][1]=a[0][0]/Det;
144  return Det;
145 }
146 
147 /******************************************************************
148  * Inverse of 3x3 matrix with determinant
149  * a - input; b - output; returns determinant;
150  * *****************************************************************/
151 
153  double Det;
154 
155  b[0][0]=SUBDET2(1,2,1,2);
156  b[1][0]=-SUBDET2(1,2,0,2);
157  b[2][0]=SUBDET2(1,2,0,1);
158 
159  Det=a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0];
160  if ( fabs(Det)< NUM_ZERO) return Det;
161  b[0][0]/=Det; b[1][0]/=Det; b[2][0]/=Det;
162 
163  b[0][1]=-SUBDET2(0,2,1,2)/Det;
164  b[1][1]=SUBDET2(0,2,0,2)/Det;
165  b[2][1]=-SUBDET2(0,2,0,1)/Det;
166 
167  b[0][2]=SUBDET2(0,1,1,2)/Det;
168  b[1][2]=-SUBDET2(0,1,0,2)/Det;
169  b[2][2]=SUBDET2(0,1,0,1)/Det;
170  return Det;
171 }
172 
173 /******************************************************************
174  * Inverse of 4x4 matrix with determinant
175  * a - input; b - output; det - determinant; returns determinant
176  * *****************************************************************/
177 
179  double u[6], l[6], Det;
180  // 2x2 subdets of rows 1,2
181  u[0]=SUBDET2(0,1,0,1);
182  u[1]=SUBDET2(0,1,0,2);
183  u[2]=SUBDET2(0,1,0,3);
184  u[3]=SUBDET2(0,1,1,2);
185  u[4]=SUBDET2(0,1,1,3);
186  u[5]=SUBDET2(0,1,2,3);
187 
188  //1x1 subdets of rows 2,3
189  l[0]=SUBDET2(2,3,0,1);
190  l[1]=SUBDET2(2,3,0,2);
191  l[2]=SUBDET2(2,3,0,3);
192  l[3]=SUBDET2(2,3,1,2);
193  l[4]=SUBDET2(2,3,1,3);
194  l[5]=SUBDET2(2,3,2,3);
195 
196  // 3x3 subdets
197  b[0][0]=+a[1][1]*l[5]-a[1][2]*l[4]+a[1][3]*l[3];
198  b[1][0]=-a[1][0]*l[5]+a[1][2]*l[2]-a[1][3]*l[1];
199  b[2][0]=+a[1][0]*l[4]-a[1][1]*l[2]+a[1][3]*l[0];
200  b[3][0]=-a[1][0]*l[3]+a[1][1]*l[1]-a[1][2]*l[0];
201  // 4x4 det
202  Det=a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];
203  if ( fabs(Det)< NUM_ZERO) return Det;
204  b[0][0]/=Det; b[1][0]/=Det; b[2][0]/=Det; b[3][0]/=Det;
205 
206  b[0][1]=(-a[0][1]*l[5]+a[0][2]*l[4]-a[0][3]*l[3])/Det;
207  b[1][1]=(+a[0][0]*l[5]-a[0][2]*l[2]+a[0][3]*l[1])/Det;
208  b[2][1]=(-a[0][0]*l[4]+a[0][1]*l[2]-a[0][3]*l[0])/Det;
209  b[3][1]=(+a[0][0]*l[3]-a[0][1]*l[1]+a[0][2]*l[0])/Det;
210 
211  b[0][2]=(+a[3][1]*u[5]-a[3][2]*u[4]+a[3][3]*u[3])/Det;
212  b[1][2]=(-a[3][0]*u[5]+a[3][2]*u[2]-a[3][3]*u[1])/Det;
213  b[2][2]=(+a[3][0]*u[4]-a[3][1]*u[2]+a[3][3]*u[0])/Det;
214  b[3][2]=(-a[3][0]*u[3]+a[3][1]*u[1]-a[3][2]*u[0])/Det;
215 
216  b[0][3]=(-a[2][1]*u[5]+a[2][2]*u[4]-a[2][3]*u[3])/Det;
217  b[1][3]=(+a[2][0]*u[5]-a[2][2]*u[2]+a[2][3]*u[1])/Det;
218  b[2][3]=(-a[2][0]*u[4]+a[2][1]*u[2]-a[2][3]*u[0])/Det;
219  b[3][3]=(+a[2][0]*u[3]-a[2][1]*u[1]+a[2][2]*u[0])/Det;
220  return Det;
221 }
222 
223 /******************************************************************
224  * Print a full matrix stored in a vector size x size
225  * *****************************************************************/
226 void PrintSmallMatrix(double *mtx, int size ) {
227  int i,j;
228  printf("matrix %d x %d :\n",size,size);
229  for (i=0;i<size;i++) {
230  for(j=0;j<size;j++) printf("%f ",mtx[i*size+j]);
231  printf("\n");
232  }
233 }
234 
235 /*******************************************************************************
236  * at place inverse of an NxN matrix by Gauss-Jordan elimination without pivotation
237  * this should by faster then via adjung. matrix at least for N>3
238  * *****************************************************************************/
239 void MatInverse(int n,double **a) {
240  int row,subrow,col;
241  double Div,Mult;
242 
243  // forward run - lower triangle and diagonal of the inverse matrix
244  for(row=0;row<n-1;row++) {
245  // divide the row by diagonal
246  Div=a[row][row];a[row][row]=1;
247  for(col=0;col<n;col++) a[row][col]/=Div;
248  // eliminate the lower part of column "row"
249  for(subrow=row+1;subrow<n;subrow++) {
250  Mult=a[subrow][row];a[subrow][row]=0;
251  for(col=0;col<n;col++) a[subrow][col]-=a[row][col]*Mult;
252  }
253  }
254  // divide the last row
255  Div=a[row][row];a[row][row]=1;
256  for(col=0;col<n;col++) a[row][col]/=Div;
257  //backward run - upper trinagle
258  for(;row>0;row--) {
259  // eliminate the upper part of column "row"
260  for(subrow=row-1;subrow>=0;subrow--) {
261  Mult=a[subrow][row];a[subrow][row]=0;
262  for(col=0;col<n;col++) a[subrow][col]-=a[row][col]*Mult;
263  }
264  }
265 }
266 
267 //=============================================================================
268 // solve equation system - gauss; returns 1 - one result 0 - system doesn't have result; 2 - oo results
269 // !!! THIS FUNCTION IS NOT USED and probably is WRONG !!!
270 //=============================================================================
271 
272 int gauss(double *A, double *B,int s,double *R)
273 {
274  int res=1,i,j,k,size;
275  double koef,tmp,max;
276  double *M;
277  size=s+1;
278  M = (double *) xmalloc( (size-1) * size * sizeof(double));
279  for(i=0;i<s;i++)
280  {
281  for(j=0;j<s;j++)
282  M[i*(size)+j]=A[i*s+j];
283  M[i*(size)+j]=B[i];
284  }
285  for(i=0;i<size-1;i++)
286  {
287  if(M[i*size+i]==0)
288  {
289  for(j=i+1;j<size-1;j++)
290  {
291  if(M[j*size+i]!=0)
292  {
293  for(k=0;k<size;k++)
294  {
295  tmp=M[j*size+k];
296  M[j*size+k]=M[i*size+k];
297  M[i*size+k]=tmp;
298  }
299  j=size-1;
300  }
301  }
302  }
303  max=0;
304  for(k=0;k<size;k++)
305  if (fabs(max)<fabs(M[i*size+k])) max=fabs(M[i*size+k]);
306  if (max!=0)
307  for(k=0;k<size;k++)
308  M[i*size+k]/=max;
309  for(j=i+1;j<size-1;j++)
310  {
311  if (M[j*size+i]!=0)
312  {
313  koef=M[i*size+i]/M[j*size+i];
314  koef=fabs(koef);
315  if((M[i*size+i]>=0 && M[j*size+i]>=0) ||
316  (M[i*size+i]<0 && M[j*size+i]<0)) koef*=-1;
317  for(k=i;k<size;k++)
318  M[j*size+k]=M[j*size+k]*koef + M[i*size+k];
319 // M[j*size+i] = 0;
320  }
321  }
322  }
323  for(i=size-1-1;i>=0;i--)
324  {
325  koef=0;
326  for(j=i+1;j<size-1;j++)
327  {
328  koef=koef+R[j]*M[i*size+j];
329  }
330  if (!(DBL_EQ(M[i*size+i],0)))
331  R[i]=(M[i*size + size-1]-koef)/M[i*size+i];
332  else
333  {
334  if (koef==0 && M[i*size + size-1]==0)
335  return 2;
336  else
337  return 0;
338  }
339  }
340  xfree(M);
341  return res;
342 }
343 //=============================================================================
344 // ANGLE BETWEEN TWO VECTORS
345 // !!! THIS FUNCTION IS NOT USED !!!
346 //=============================================================================
347 
348 double get_vectors_angle( double u[ 3 ], double v[ 3 ] )
349 {
350  double a,b,fi,p;
351  a = scalar_product (u, v);
352  b = vector_length( u ) * vector_length( v );
353  p = a / b;
354  if (p > 1) p = 1;
355  if (p < -1) p = -1;
356  fi = acos( p );
357  return fi * 180 / M_PI;
358 }
359 //=============================================================================
360 // MATRIX TIMES MATRIX
361 // !!! THIS FUNCTION IS NOT USED !!!
362 //=============================================================================
363 
364 void matrix_x_matrix(double *A,int ra, int ca,
365  double *B, int rb, int cb, double *X)
366 {
367  int i,j,k;
368  ASSERT(!(ca != rb),"Matrix A has different number of columns than matrix B rows in the function matrix_x_matrix()\n");
369  for (i = 0; i < ra; i++)
370  for (j = 0; j < cb; j++)
371  {
372  X[ i* cb + j] = 0;
373  for (k = 0; k < rb; k++)
374  X[ i * cb + j] += A[ i * ca + k] * B[ k * cb + j];
375  }
376  return;
377 }
378 //-----------------------------------------------------------------------------
379 // vim: set cindent:
void vector_product(double u[], double v[], double x[])
Definition: math_fce.cc:80
static double Inverse3(SmallMtx3 a, SmallMtx3 b)
Definition: math_fce.cc:152
#define SUBDET2(i, j, k, l)
Definition: math_fce.h:71
SmallVec3_t * SmallMtx3
Definition: math_fce.h:43
void matrix_x_matrix(double *A, int ra, int ca, double *B, int rb, int cb, double *X)
Definition: math_fce.cc:364
#define M_PI
Definition: math_fce.h:73
SmallVec4_t * SmallMtx4
Definition: math_fce.h:44
void normalize_vector(double u[])
Definition: math_fce.cc:60
double vector_length(double v[])
Definition: math_fce.cc:46
void scale_vector(double u[], double k)
Definition: math_fce.cc:72
Global macros to enhance readability and debugging, general constants.
static double Inverse2(SmallMtx2 a, SmallMtx2 b)
Definition: math_fce.cc:135
#define ASSERT(...)
Definition: global_defs.h:121
Definition: system.hh:72
#define DBL_EQ(i, j)
Definition: math_fce.h:62
double scalar_product(double u[], double v[])
Definition: math_fce.cc:53
void MatInverse(int n, double **a)
Definition: math_fce.cc:239
void PrintSmallMatrix(double *mtx, int size)
Definition: math_fce.cc:226
#define xprintf(...)
Definition: system.hh:100
#define NUM_ZERO
Numerical helpers.
Definition: math_fce.h:53
void * xmalloc(size_t size)
Memory allocation with checking.
Definition: system.cc:209
double Det3(SmallMtx3 a)
Definition: math_fce.cc:106
double MatrixInverse(double *a, double *b, int size)
Definition: math_fce.cc:116
void vector_difference(double u[], double v[], double x[])
Definition: math_fce.cc:92
SmallVec2_t * SmallMtx2
Definition: mh_fe_values.hh:22
int gauss(double *A, double *B, int s, double *R)
Definition: math_fce.cc:272
#define xfree(p)
Definition: system.hh:108
static double Inverse4(SmallMtx4 a, SmallMtx4 b)
Definition: math_fce.cc:178
double get_vectors_angle(double u[3], double v[3])
Definition: math_fce.cc:348