Flow123d
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 Det2( SmallMtx2 a);
40 static double Inverse2(SmallMtx2 a,SmallMtx2 b);
41 static double Inverse3(SmallMtx3 a,SmallMtx3 b);
42 static double Inverse4(SmallMtx4 a,SmallMtx4 b);
43 
44 //=============================================================================
45 // LENGTH OF VECTOR
46 //=============================================================================
47 double vector_length( double v[] )
48 {
49  return sqrt( v[0]*v[0]+v[1]*v[1]+v[2]*v[2] );
50 }
51 //=============================================================================
52 // SCALAR PRODUCT OF VECTORS
53 //=============================================================================
54 double scalar_product( double u[], double v[] )
55 {
56  return u[0]*v[0]+u[1]*v[1]+u[2]*v[2];
57 }
58 //=============================================================================
59 // NORMALIZE GIVEN VECTOR
60 //=============================================================================
61 void normalize_vector( double u[] )
62 {
63  double l;
64 
65  if ((l = vector_length( u )) < NUM_ZERO ) {
66  xprintf(Warn,"Normalization of nearly zero vector.\n");
67  }
68  u[0] /= l; u[1] /= l; u[2] /= l;
69 }
70 //=============================================================================
71 // MULTIPLE VECTOR BY REAL NUMBER
72 //=============================================================================
73 void scale_vector( double u[], double k )
74 {
75  u[ 0 ] *= k; u[ 1 ] *= k; u[ 2 ] *= k;
76 }
77 
78 //=============================================================================
79 // VECTOR PRODUCT OF VECTORS
80 //=============================================================================
81 void vector_product( double u[], double v[], double x[] )
82 {
83  // u, v - inputs
84  // x - output, result
85 
86  x[ 0 ] = u[ 1 ] * v[ 2 ] - u[ 2 ] * v[ 1 ];
87  x[ 1 ] = u[ 2 ] * v[ 0 ] - u[ 0 ] * v[ 2 ];
88  x[ 2 ] = u[ 0 ] * v[ 1 ] - u[ 1 ] * v[ 0 ];
89 }
90 //=============================================================================
91 // VECTOR DIFFERENCE OF VECTORS
92 //=============================================================================
93 void vector_difference( double u[], double v[], double x[] )
94 {
95  x[ 0 ] = u[ 0 ] - v[ 0 ];
96  x[ 1 ] = u[ 1 ] - v[ 1 ];
97  x[ 2 ] = u[ 2 ] - v[ 2 ];
98 }
99 
100 /*************************************************
101  * SMALL MATRIX OPERATIONS
102  *************************************************/
103 
104 //=============================================================================
105 // DETERMINANT OF MATRIX 2x2
106 //=============================================================================
107 double Det2( SmallMtx2 a) {
108  return SUBDET2(0,1,0,1);
109 }
110 
111 /**************************************************
112  * determinant 3x3
113  * *************************/
114 double Det3( SmallMtx3 a ) {
115  return a[0][0]*SUBDET2(1,2,1,2)
116  -a[0][1]*SUBDET2(1,2,0,2)
117  +a[0][2]*SUBDET2(1,2,0,1);
118 }
119 
120 /*************************************************
121  * Inverse of general small matrix with given size
122  * a - input; b - output; returns determinant
123  * ************************************************/
124 double MatrixInverse(double *a, double *b, int size) {
125  switch (size) {
126  case 1:
127  *b=1/(*a); return (*a);
128  case 2:
129  return ( Inverse2((SmallMtx2)a, (SmallMtx2)b) );
130  case 3:
131  return ( Inverse3((SmallMtx3)a, (SmallMtx3)b) );
132  case 4:
133  return ( Inverse4((SmallMtx4)a, (SmallMtx4)b) );
134  }
135  return 0.0;
136 }
137 
138 
139 /******************************************************************
140  * Inverse of 2x2 matrix with determinant
141  * a - input; b - output; returns determinant;
142  * *****************************************************************/
144  double Det;
145 
146  Det=SUBDET2(0,1,0,1);
147  if ( fabs(Det) < NUM_ZERO ) return Det;
148  b[0][0]=a[1][1]/Det;
149  b[1][0]=-a[1][0]/Det;
150  b[0][1]=-a[0][1]/Det;
151  b[1][1]=a[0][0]/Det;
152  return Det;
153 }
154 
155 /******************************************************************
156  * Inverse of 3x3 matrix with determinant
157  * a - input; b - output; returns determinant;
158  * *****************************************************************/
159 
161  double Det;
162 
163  b[0][0]=SUBDET2(1,2,1,2);
164  b[1][0]=-SUBDET2(1,2,0,2);
165  b[2][0]=SUBDET2(1,2,0,1);
166 
167  Det=a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0];
168  if ( fabs(Det)< NUM_ZERO) return Det;
169  b[0][0]/=Det; b[1][0]/=Det; b[2][0]/=Det;
170 
171  b[0][1]=-SUBDET2(0,2,1,2)/Det;
172  b[1][1]=SUBDET2(0,2,0,2)/Det;
173  b[2][1]=-SUBDET2(0,2,0,1)/Det;
174 
175  b[0][2]=SUBDET2(0,1,1,2)/Det;
176  b[1][2]=-SUBDET2(0,1,0,2)/Det;
177  b[2][2]=SUBDET2(0,1,0,1)/Det;
178  return Det;
179 }
180 
181 /******************************************************************
182  * Inverse of 4x4 matrix with determinant
183  * a - input; b - output; det - determinant; returns determinant
184  * *****************************************************************/
185 
187  double u[6], l[6], Det;
188  // 2x2 subdets of rows 1,2
189  u[0]=SUBDET2(0,1,0,1);
190  u[1]=SUBDET2(0,1,0,2);
191  u[2]=SUBDET2(0,1,0,3);
192  u[3]=SUBDET2(0,1,1,2);
193  u[4]=SUBDET2(0,1,1,3);
194  u[5]=SUBDET2(0,1,2,3);
195 
196  //1x1 subdets of rows 2,3
197  l[0]=SUBDET2(2,3,0,1);
198  l[1]=SUBDET2(2,3,0,2);
199  l[2]=SUBDET2(2,3,0,3);
200  l[3]=SUBDET2(2,3,1,2);
201  l[4]=SUBDET2(2,3,1,3);
202  l[5]=SUBDET2(2,3,2,3);
203 
204  // 3x3 subdets
205  b[0][0]=+a[1][1]*l[5]-a[1][2]*l[4]+a[1][3]*l[3];
206  b[1][0]=-a[1][0]*l[5]+a[1][2]*l[2]-a[1][3]*l[1];
207  b[2][0]=+a[1][0]*l[4]-a[1][1]*l[2]+a[1][3]*l[0];
208  b[3][0]=-a[1][0]*l[3]+a[1][1]*l[1]-a[1][2]*l[0];
209  // 4x4 det
210  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];
211  if ( fabs(Det)< NUM_ZERO) return Det;
212  b[0][0]/=Det; b[1][0]/=Det; b[2][0]/=Det; b[3][0]/=Det;
213 
214  b[0][1]=(-a[0][1]*l[5]+a[0][2]*l[4]-a[0][3]*l[3])/Det;
215  b[1][1]=(+a[0][0]*l[5]-a[0][2]*l[2]+a[0][3]*l[1])/Det;
216  b[2][1]=(-a[0][0]*l[4]+a[0][1]*l[2]-a[0][3]*l[0])/Det;
217  b[3][1]=(+a[0][0]*l[3]-a[0][1]*l[1]+a[0][2]*l[0])/Det;
218 
219  b[0][2]=(+a[3][1]*u[5]-a[3][2]*u[4]+a[3][3]*u[3])/Det;
220  b[1][2]=(-a[3][0]*u[5]+a[3][2]*u[2]-a[3][3]*u[1])/Det;
221  b[2][2]=(+a[3][0]*u[4]-a[3][1]*u[2]+a[3][3]*u[0])/Det;
222  b[3][2]=(-a[3][0]*u[3]+a[3][1]*u[1]-a[3][2]*u[0])/Det;
223 
224  b[0][3]=(-a[2][1]*u[5]+a[2][2]*u[4]-a[2][3]*u[3])/Det;
225  b[1][3]=(+a[2][0]*u[5]-a[2][2]*u[2]+a[2][3]*u[1])/Det;
226  b[2][3]=(-a[2][0]*u[4]+a[2][1]*u[2]-a[2][3]*u[0])/Det;
227  b[3][3]=(+a[2][0]*u[3]-a[2][1]*u[1]+a[2][2]*u[0])/Det;
228  return Det;
229 }
230 
231 /******************************************************************
232  * Print a full matrix stored in a vector size x size
233  * *****************************************************************/
234 void PrintSmallMatrix(double *mtx, int size ) {
235  int i,j;
236  printf("matrix %d x %d :\n",size,size);
237  for (i=0;i<size;i++) {
238  for(j=0;j<size;j++) printf("%f ",mtx[i*size+j]);
239  printf("\n");
240  }
241 }
242 
243 /*******************************************************************************
244  * at place inverse of an NxN matrix by Gauss-Jordan elimination without pivotation
245  * this should by faster then via adjung. matrix at least for N>3
246  * *****************************************************************************/
247 void MatInverse(int n,double **a) {
248  int row,subrow,col;
249  double Div,Mult;
250 
251  // forward run - lower triangle and diagonal of the inverse matrix
252  for(row=0;row<n-1;row++) {
253  // divide the row by diagonal
254  Div=a[row][row];a[row][row]=1;
255  for(col=0;col<n;col++) a[row][col]/=Div;
256  // eliminate the lower part of column "row"
257  for(subrow=row+1;subrow<n;subrow++) {
258  Mult=a[subrow][row];a[subrow][row]=0;
259  for(col=0;col<n;col++) a[subrow][col]-=a[row][col]*Mult;
260  }
261  }
262  // divide the last row
263  Div=a[row][row];a[row][row]=1;
264  for(col=0;col<n;col++) a[row][col]/=Div;
265  //backward run - upper trinagle
266  for(;row>0;row--) {
267  // eliminate the upper part of column "row"
268  for(subrow=row-1;subrow>=0;subrow--) {
269  Mult=a[subrow][row];a[subrow][row]=0;
270  for(col=0;col<n;col++) a[subrow][col]-=a[row][col]*Mult;
271  }
272  }
273 }
274 
275 //=============================================================================
276 // solve equation system - gauss; returns 1 - one result 0 - system doesn't have result; 2 - oo results
277 // !!! THIS FUNCTION IS NOT USED and probably is WRONG !!!
278 //=============================================================================
279 
280 int gauss(double *A, double *B,int s,double *R)
281 {
282  int res=1,i,j,k,size;
283  double koef,tmp,max;
284  double *M;
285  size=s+1;
286  M = (double *) xmalloc( (size-1) * size * sizeof(double));
287  for(i=0;i<s;i++)
288  {
289  for(j=0;j<s;j++)
290  M[i*(size)+j]=A[i*s+j];
291  M[i*(size)+j]=B[i];
292  }
293  for(i=0;i<size-1;i++)
294  {
295  if(M[i*size+i]==0)
296  {
297  for(j=i+1;j<size-1;j++)
298  {
299  if(M[j*size+i]!=0)
300  {
301  for(k=0;k<size;k++)
302  {
303  tmp=M[j*size+k];
304  M[j*size+k]=M[i*size+k];
305  M[i*size+k]=tmp;
306  }
307  j=size-1;
308  }
309  }
310  }
311  max=0;
312  for(k=0;k<size;k++)
313  if (fabs(max)<fabs(M[i*size+k])) max=fabs(M[i*size+k]);
314  if (max!=0)
315  for(k=0;k<size;k++)
316  M[i*size+k]/=max;
317  for(j=i+1;j<size-1;j++)
318  {
319  if (M[j*size+i]!=0)
320  {
321  koef=M[i*size+i]/M[j*size+i];
322  koef=fabs(koef);
323  if((M[i*size+i]>=0 && M[j*size+i]>=0) ||
324  (M[i*size+i]<0 && M[j*size+i]<0)) koef*=-1;
325  for(k=i;k<size;k++)
326  M[j*size+k]=M[j*size+k]*koef + M[i*size+k];
327 // M[j*size+i] = 0;
328  }
329  }
330  }
331  for(i=size-1-1;i>=0;i--)
332  {
333  koef=0;
334  for(j=i+1;j<size-1;j++)
335  {
336  koef=koef+R[j]*M[i*size+j];
337  }
338  if (!(DBL_EQ(M[i*size+i],0)))
339 // if (M[i*size+i] != 0)
340  R[i]=(M[i*size + size-1]-koef)/M[i*size+i];
341  else
342  {
343  if (koef==0 && M[i*size + size-1]==0)
344  return 2;
345  else
346  return 0;
347  }
348  }
349  xfree(M);
350  return res;
351 }
352 //=============================================================================
353 // ANGLE BETWEEN TWO VECTORS
354 // !!! THIS FUNCTION IS NOT USED !!!
355 //=============================================================================
356 
357 double get_vectors_angle( double u[ 3 ], double v[ 3 ] )
358 {
359  double a,b,fi,p;
360  a = scalar_product (u, v);
361  b = vector_length( u ) * vector_length( v );
362  p = a / b;
363  if (p > 1) p = 1;
364  if (p < -1) p = -1;
365  fi = acos( p );
366  return fi * 180 / M_PI;
367 }
368 //=============================================================================
369 // MATRIX TIMES MATRIX
370 // !!! THIS FUNCTION IS NOT USED !!!
371 //=============================================================================
372 
373 void matrix_x_matrix(double *A,int ra, int ca,
374  double *B, int rb, int cb, double *X)
375 {
376  int i,j,k;
377  ASSERT(!(ca != rb),"Matrix A has different number of columns than matrix B rows in the function matrix_x_matrix()\n");
378  for (i = 0; i < ra; i++)
379  for (j = 0; j < cb; j++)
380  {
381  X[ i* cb + j] = 0;
382  for (k = 0; k < rb; k++)
383  X[ i * cb + j] += A[ i * ca + k] * B[ k * cb + j];
384  }
385  return;
386 }
387 //-----------------------------------------------------------------------------
388 // vim: set cindent: