ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
utils.h
Go to the documentation of this file.
00001 /*
00002   Copyright (C) 2010,2011,2012,2013 The ESPResSo project
00003   Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 
00004     Max-Planck-Institute for Polymer Research, Theory Group
00005   
00006   This file is part of ESPResSo.
00007   
00008   ESPResSo is free software: you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation, either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   ESPResSo is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
00020 */
00021 #ifndef _UTILS_H
00022 #define _UTILS_H
00023 /** \file utils.h
00024  *    Small functions that are useful not only for one modul.
00025 
00026  *  just some nice utilities... 
00027  *  and some constants...
00028  *
00029 */
00030 #include <math.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include "config.h"
00035 #include "debug.h"
00036 #include "errorhandling.h"
00037 
00038 /*************************************************************/
00039 /** \name Mathematical, physical and chemical constants.     */
00040 /*************************************************************/
00041 /*@{*/
00042 /** Pi. */
00043 #define PI     3.14159265358979323846264338328 
00044 /** Square root of Pi */
00045 #define wupi   1.77245385090551602729816748334 
00046 /** One over square root of Pi. */
00047 #define wupii  0.56418958354775627928034964498 
00048 /** Pi to the power 1/3. */
00049 #define driwu2 1.25992104989487316476721060728 
00050 
00051 /// error code if no error occured
00052 #define ES_OK    0
00053 /// error code if an error occured
00054 #define ES_ERROR 1
00055 
00056 /** space necessary for an (64-bit) integer with sprintf.
00057     Analog to Tcl
00058  */
00059 #define ES_INTEGER_SPACE 24
00060 /** space necessary for an double with sprintf. Precision
00061     is 17 digits, plus sign, dot, e, sign of exponent and
00062     3 digits exponent etc. Analog to Tcl
00063 */
00064 #define ES_DOUBLE_SPACE 27
00065 
00066 /*@}*/
00067 
00068 /************************************************
00069  * data types
00070  ************************************************/
00071 
00072 /** Integer list. 
00073     Use the functions specified in list operations. */
00074 typedef struct {
00075   /** Dynamically allocated integer field. */
00076   int *e;
00077   /** number of used elements in the integer field. */
00078   int n;
00079   /** allocated size of the integer field. This value is ONLY changed
00080       in the routines specified in list operations ! */
00081   int max;
00082 } IntList;
00083 
00084 /** Double list.
00085     Use the functions specified in list operations. */
00086 typedef struct {
00087   /** Dynamically allocated double field. */
00088   double *e;
00089   /** number of used elements in the double field. */
00090   int n;
00091   /** allocated size of the double field. This value is ONLY changed
00092       in the routines specified in list operations ! */
00093   int max;
00094 } DoubleList;
00095 
00096 /*************************************************************/
00097 /** \name Dynamic memory allocation.                         */
00098 /*************************************************************/
00099 /*@{*/
00100 
00101 /* to enable us to make sure that freed pointers are invalidated, we normally try to use realloc.
00102    Unfortunately allocating zero bytes (which should be avoided) actually allocates 16 bytes, and
00103    reallocating to 0 also. To avoid this, we use our own malloc and realloc procedures. */
00104 #ifndef MEM_DEBUG
00105 
00106 #ifdef realloc
00107 #undef realloc
00108 #endif
00109 
00110 #ifdef malloc
00111 #undef malloc
00112 #endif
00113 
00114 /** used instead of realloc.
00115     Makes sure that resizing to zero FREEs pointer */
00116 MDINLINE void *prealloc(void *old, int size)
00117 {
00118   void *p;
00119   if (size <= 0) {
00120     free(old);
00121     return NULL;
00122   }
00123   p = (void *)realloc(old, size);
00124   if(p == NULL) {
00125     fprintf(stderr, "Could not allocate memory.\n");
00126     errexit();
00127   }
00128   return p;
00129 }
00130 
00131 /** used instead of malloc.
00132     Makes sure that a zero size allocation returns a NULL pointer */
00133 MDINLINE void *pmalloc(int size)
00134 {
00135   void *p;
00136   if (size <= 0) {
00137     return NULL;
00138   }
00139   p = (void *)malloc(size);
00140   if(p == NULL) {
00141     fprintf(stderr, "Could not allocate memory.\n");
00142     errexit();
00143   }
00144   return p;
00145 }
00146 
00147 /** use our own realloc which makes sure that realloc(0) is actually a free. */
00148 #define realloc prealloc
00149 
00150 /** use our own malloc which makes sure that malloc(0) returns NULL. */
00151 #define malloc pmalloc
00152 
00153 #endif
00154 /*@}*/
00155 
00156 /*************************************************************/
00157 /* mass helper macro                                         */
00158 /*************************************************************/
00159 
00160 #ifdef MASS
00161 /** macro for easy use of mass. If masses are not switched on, the particle mass is defined to 1,
00162     so it should be compiled out in most cases. */
00163 #define PMASS(pt) (pt).p.mass
00164 #else
00165 #define PMASS(pt) 1
00166 #endif
00167 
00168 /*************************************************************/
00169 /** \name List operations .                                  */
00170 /*************************************************************/
00171 /*@{*/
00172 
00173 /** Initialize an \ref IntList.  */
00174 MDINLINE void init_intlist(IntList *il)
00175 {
00176   il->n   = 0;
00177   il->max = 0;
00178   il->e   = NULL;
00179 }
00180 extern int this_node;
00181 
00182 /** Allocate an \ref IntList of size size. If you need an \ref IntList
00183     with variable size better use \ref realloc_intlist */
00184 MDINLINE void alloc_intlist(IntList *il, int size)
00185 {
00186   il->max = size;
00187   il->e = (int *) malloc(sizeof(int)*il->max);
00188 }
00189 
00190 /** Reallocate an \ref IntList */
00191 MDINLINE void realloc_intlist(IntList *il, int size)
00192 {
00193   if(size != il->max) {
00194     il->max = size;
00195     il->e = (int *) realloc(il->e, sizeof(int)*il->max);
00196   }
00197 }
00198 
00199 /** Allocate an \ref IntList, but only to multiples of grain. */
00200 MDINLINE void alloc_grained_intlist(IntList *il, int size, int grain)
00201 {
00202   il->max = grain*((size + grain - 1)/grain);
00203   il->e = (int *) malloc(sizeof(int)*il->max);
00204 }
00205 
00206 /** Reallocate an \ref IntList, but only to multiples of grain. */
00207 MDINLINE void realloc_grained_intlist(IntList *il, int size, int grain)
00208 {
00209   if(size >= il->max)
00210     il->max = grain*((size + grain - 1)/grain);
00211   else
00212     /* shrink not as fast, just lose half, rounded up */
00213     il->max = grain*(((il->max + size + 1)/2 +
00214                       grain - 1)/grain);
00215 
00216   il->e = (int *) realloc(il->e, sizeof(int)*il->max);
00217 }
00218 
00219 /** Check wether an \ref IntList contains the value c */
00220 MDINLINE int intlist_contains(IntList *il, int c)
00221 {
00222   int i;
00223   for (i = 0; i < il->n; i++)
00224     if (c == il->e[i]) return 1;
00225   return 0;
00226 }
00227 
00228 /** Initialize an \ref DoubleList.  */
00229 MDINLINE void init_doublelist(DoubleList *il)
00230 {
00231   il->n   = 0;
00232   il->max = 0;
00233   il->e   = NULL;
00234 }
00235 
00236 /** Allocate an \ref DoubleList of size size. If you need an \ref DoubleList
00237     with variable size better use \ref realloc_doublelist */
00238 MDINLINE void alloc_doublelist(DoubleList *dl, int size)
00239 {
00240   dl->max = size;
00241   dl->e = (double *) malloc(sizeof(double)*dl->max);
00242 }
00243 
00244 /** Reallocate an \ref DoubleList */
00245 MDINLINE void realloc_doublelist(DoubleList *dl, int size)
00246 {
00247   if(size != dl->max) {
00248     dl->max = size;
00249     dl->e = (double *) realloc(dl->e, sizeof(double)*dl->max);
00250   }
00251 }
00252 
00253 /** Allocate an \ref DoubleList, but only to multiples of grain. */
00254 MDINLINE void alloc_grained_doublelist(DoubleList *dl, int size, int grain)
00255 {
00256   dl->max = grain*((size + grain - 1)/grain);
00257   dl->e = (double *) malloc(sizeof(double)*dl->max);
00258 }
00259 
00260 /** Reallocate an \ref DoubleList, but only to multiples of grain. */
00261 MDINLINE void realloc_grained_doublelist(DoubleList *dl, int size, int grain)
00262 {
00263   if(size >= dl->max)
00264     dl->max = grain*((size + grain - 1)/grain);
00265   else
00266     /* shrink not as fast, just lose half, rounded up */
00267     dl->max = grain*(((dl->max + size + 1)/2 +
00268                       grain - 1)/grain);
00269 
00270   dl->e = (double *) realloc(dl->e, sizeof(double)*dl->max);
00271 }
00272 /*@}*/
00273 
00274 
00275 /*************************************************************/
00276 /** \name Mathematical functions.                            */
00277 /*************************************************************/
00278 /*@{*/
00279 
00280 /** Calculates the maximum of 'double'-typed a and b, returning 'double'. */
00281 MDINLINE double dmax(double a, double b) { return (a>b) ? a : b; }
00282 
00283 /** Calculates the minimum of 'double'-typed a and b, returning 'double'. */
00284 MDINLINE double dmin(double a, double b) { return (a<b) ? a : b; }
00285 
00286 /** Calculates the maximum of 'int'-typed a and b, returning 'int'. */
00287 MDINLINE int imax(int a, int b) { return (a>b) ? a : b; }
00288 
00289 /** Calculates the minimum of 'int'-typed a and b, returning 'int'. */
00290 MDINLINE int imin(int a, int b) { return (a<b) ? a : b; }
00291 
00292 /** Calculates the remainder of a division */
00293 MDINLINE double drem_down(double a, double b) { return a - floor(a/b)*b; }
00294 
00295 /** vector difference */
00296 MDINLINE void vector_subt(double res[3], double a[3], double b[3])
00297 {
00298   int i;
00299   for (i=0;i<3;i++)
00300     res[i]=a[i]-b[i];
00301 }
00302 
00303 /** Very slow sort routine for small integer arrays. Sorts the values
00304     in decending order.  
00305     \param data   the integer array 
00306     \param size   size of the array
00307  */
00308 MDINLINE void sort_int_array(int *data, int size)
00309 {
00310   int i,j,tmp;
00311   for(i=0;i<size-1;i++)
00312     for(j=i+1;j<size;j++) {
00313       if(data[i]<data[j]) {
00314         tmp=data[i]; data[i]=data[j]; data[j]=tmp;
00315       }
00316     }
00317 }
00318 
00319 /** permute an interger array field of size size about permute positions. */
00320 MDINLINE void permute_ifield(int *field, int size, int permute)
00321 {
00322   int i,tmp;
00323 
00324   if(permute==0) return;
00325   if(permute<0) permute = (size + permute);
00326   while(permute>0) {
00327     tmp=field[0];
00328     for(i=1;i<size;i++) field[i-1] = field[i];
00329     field[size-1]=tmp;
00330     permute--;
00331   }
00332 }
00333 
00334 /** Mathematically rounds 'double'-typed x, returning 'double'. */
00335 MDINLINE double dround(double x) { return floor(x+0.5); }
00336 
00337 /** Calculates the SQuaRe of 'double' x, returning 'double'. */
00338 MDINLINE double SQR(double x) { return x*x; }
00339 
00340 /** approximates \f$ \exp(d^2) \mathrm{erfc}(d)\f$ by applying a formula from:
00341     Abramowitz/Stegun: Handbook of Mathematical Functions, Dover
00342     (9. ed.), chapter 7 */
00343 MDINLINE double AS_erfc_part(double d)
00344 {
00345 #define AS_a1  0.254829592
00346 #define AS_a2 -0.284496736
00347 #define AS_a3  1.421413741
00348 #define AS_a4 -1.453152027
00349 #define AS_a5  1.061405429
00350 #define AS_p   0.3275911
00351   double t;
00352   
00353   t = 1.0 / (1.0 + AS_p * d);
00354   
00355   return t * (AS_a1 + t * (AS_a2 + t * (AS_a3 + t * (AS_a4 + t * AS_a5) ) ) );
00356 }
00357 
00358 /** Calculates the sinc-function as sin(PI*x)/(PI*x).
00359  *
00360  * (same convention as in Hockney/Eastwood). In order to avoid
00361  * divisions by 0, arguments, whose modulus is smaller than epsi, will
00362  * be evaluated by an 8th order Taylor expansion of the sinc
00363  * function. Note that the difference between sinc(x) and this
00364  * expansion is smaller than 0.235e-12, if x is smaller than 0.1. (The
00365  * next term in the expansion is the 10th order contribution
00366  * PI^10/39916800 * x^10 = 0.2346...*x^12).  This expansion should
00367  * also save time, since it reduces the number of function calls to
00368  * sin().  
00369 */
00370 MDINLINE double sinc(double d)
00371 {
00372 #define epsi 0.1
00373 
00374 #define c2 -0.1666666666667e-0
00375 #define c4  0.8333333333333e-2
00376 #define c6 -0.1984126984127e-3
00377 #define c8  0.2755731922399e-5
00378 
00379   double PId = PI*d, PId2;
00380 
00381   if (fabs(d)>epsi)
00382     return sin(PId)/PId;
00383   else {
00384     PId2 = SQR(PId);
00385     return 1.0 + PId2*(c2+PId2*(c4+PId2*(c6+PId2*c8)));
00386   }
00387 }
00388 
00389 /** factorizes small numbers up to a maximum of max factors. */
00390 MDINLINE int calc_factors(int n, int *factors, int max)
00391 {
00392   int f=2,i=0;
00393   while(n>1) {
00394     while(f<=n) {
00395       if(n%f==0) {
00396         if(i>=max) return 0;
00397         n /= f;
00398         factors[i]=f;
00399         i++;
00400         f=n;
00401       } 
00402       f++;
00403     }
00404     f=2;
00405   }
00406   return i;
00407 }
00408 /*@}*/
00409 
00410 
00411 /*************************************************************/
00412 /** \name Vector and matrix operations for three dimensons.  */
00413 /*************************************************************/
00414 /*@{*/
00415 
00416 /** Subtracts vector v2 from vector v1 and stores resuld in vector dv */
00417 MDINLINE void vecsub(double v1[3], double v2[3], double dv[3])
00418 {
00419   dv[0] = v1[0] - v2[0];
00420   dv[1] = v1[1] - v2[1];
00421   dv[2] = v1[2] - v2[2];
00422 }
00423 
00424 
00425 /** calculates the length of a vector */
00426 MDINLINE double normr(double v[3]) {
00427   double d2 = 0.0;
00428   int i;
00429   for(i=0;i<3;i++)
00430     d2 += SQR(v[i]);
00431   d2 = sqrtf(d2);
00432   return d2;
00433 }
00434 
00435 /** calculates the squared length of a vector */
00436 MDINLINE double sqrlen(double v[3]) {
00437   double d2 = 0.0;
00438   int i;
00439   for(i=0;i<3;i++)
00440     d2 += SQR(v[i]);
00441   return d2;
00442 }
00443 
00444 /** calculates unit vector */
00445 MDINLINE void unit_vector(double v[3],double y[3]) {
00446   double d = 0.0;
00447   int i;
00448   d=sqrt( sqrlen(v) );
00449   
00450   for(i=0;i<3;i++)
00451     y[i] = v[i]/d;
00452     
00453   return;
00454 }
00455 
00456 /** calculates the scalar product of two vectors a nd b */
00457 MDINLINE double scalar(double a[3], double b[3]) {
00458   double d2 = 0.0;
00459   int i;
00460   for(i=0;i<3;i++)
00461     d2 += a[i]*b[i];
00462   return d2;
00463 }
00464 
00465 /** calculates the vector product c of two vectors a and b */
00466 MDINLINE void vector_product(double a[3], double b[3], double c[3]) {
00467   c[0]=a[1]*b[2]-a[2]*b[1];
00468   c[1]=a[2]*b[0]-a[0]*b[2];
00469   c[2]=a[0]*b[1]-a[1]*b[0];
00470   return ;
00471 }
00472  
00473 /** rotates vector around axis by alpha */
00474 MDINLINE void vec_rotate(double *axis, double alpha, double *vector, double *result){
00475   double sina,cosa,absa,a[3];
00476   sina=sin(alpha);
00477   cosa=cos(alpha);
00478   absa=sqrt(scalar(axis,axis));
00479 
00480   a[0]=axis[0]/absa;
00481   a[1]=axis[1]/absa;
00482   a[2]=axis[2]/absa;
00483 
00484   result[0]=(cosa+SQR(a[0])*(1-cosa))*vector[0]+(a[0]*a[1]*(1-cosa)-a[2]*sina)*vector[1]+(a[0]*a[2]*(1-cosa)+a[1]*sina)*vector[2];
00485   result[1]=(a[0]*a[1]*(1-cosa)+a[2]*sina)*vector[0]+(cosa+SQR(a[1])*(1-cosa))*vector[1]+(a[1]*a[2]*(1-cosa)-a[0]*sina)*vector[2];
00486   result[2]=(a[0]*a[2]*(1-cosa)-a[1]*sina)*vector[0]+(a[1]*a[2]*(1-cosa)+a[0]*sina)*vector[1]+(cosa+SQR(a[2])*(1-cosa))*vector[2];
00487 
00488   return;
00489 }
00490 
00491 /** Calc eigevalues of a 3x3 matrix stored in q as a 9x1 array*/
00492 MDINLINE int calc_eigenvalues_3x3(double *q,  double *eva) {
00493   double q11,q22,q33,q12,q13,q23;
00494   double a,b,c;
00495   double QQ,R,R2,QQ3;
00496   double theta,root1,root2,x1,x2,x3,help;
00497   int anzdiff=3;
00498 
00499   /* copy tensor to local variables (This is really a fuc off code!) */
00500   q11 = *q++;    q12 = *q++;   q13 = *q;
00501   q22 = *(q+=2); q23 = *(++q); q33 = *(q+=3);
00502   
00503   /* solve the cubic equation of the eigenvalue problem */
00504   a = -(q11 + q22 + q33);
00505   b = q11*q22 + q11*q33 + q22*q33 - q12*q12 - q13*q13 - q23*q23;
00506   c = -(q11*q22*q33 + 2*q12*q23*q13 - q12*q12*q33 - q13*q13*q22 - q23*q23*q11);
00507   QQ = (a*a-3*b)/9.0;
00508   R = (2*a*a*a - 9*a*b + 27*c)/54;
00509   QQ3 = QQ*QQ*QQ;
00510   R2 = R*R;
00511 
00512   if (R2 < QQ3) {
00513     theta = acos(R/sqrt(QQ3));
00514     root1 = sqrt(QQ)*cos(theta/3.0);
00515     root2 = sqrt(QQ*3.0)*sin(theta/3.0);
00516     x1 = - 2*root1 - a/3.0;
00517     x2 =   root1 - root2 - a/3.0;
00518     x3 =   root1 + root2 - a/3.0;
00519   }
00520   else {
00521     double AA,BB,signum = 1.0;
00522 
00523     if (R < 0) { signum = -1.0; R = -R; }
00524     AA = - signum*exp( log(R + sqrt(R2-QQ3))/3.0);
00525     if (AA==0.0) BB = 0.0;
00526     else BB = QQ/AA;
00527 
00528     /* compute the second way of the diagonalization
00529      * remark : a diagonal matrix has to have real eigenvalues (=>x2=x3)
00530      * but (!), the general solution of this case can have in general 
00531      * imaginary solutions for x2,x3 (see numerical recipies p. 185) */
00532     x1 = (AA+BB) - a/3.0;
00533     x2 = 0.5*(AA+BB) - a/3.0;
00534     x3 = x2;
00535   }
00536 
00537   /* order the eigenvalues in decreasing order */
00538   if (x1<x2) { help = x1; x1 = x2; x2 = help; }
00539   if (x1<x3) { help = x1; x1 = x3; x3 = help; }
00540   if (x2<x3) { help = x2; x2 = x3; x3 = help; }
00541   eva[0] = x1; eva[1] = x2; eva[2] = x3;
00542 
00543   /* calculate number of different eigenvalues */
00544   if(x1==x2) anzdiff--;
00545   if(x2==x3) anzdiff--;
00546   
00547   return anzdiff;
00548 }
00549 
00550 /** Calc eigevectors of a 3x3 matrix stored in a as a 9x1 array*/
00551 /** Given an eigenvalue (eva) returns the corresponding eigenvector (eve)*/
00552 MDINLINE int calc_eigenvector_3x3(double *a,double eva,double *eve) {
00553   int i,j,ind1,ind2,ind3,row1,row2;
00554   double A_x1[3][3],coeff1,coeff2,norm;
00555 
00556   /* build (matrix - eva*unity) */ 
00557   for(i=0;i<3;i++) {
00558     for(j=0;j<3;j++) A_x1[i][j]=a[3*i+j];
00559     A_x1[i][i]-=eva;
00560   }
00561 
00562   /* solve the linear equation system */
00563   for(ind1=0;ind1<3;ind1++) {
00564     ind2=(ind1+1) % 3;    ind3=(ind1+2) % 3;
00565     row1=0;
00566     do {
00567       row1++;
00568     } while ((row1<3) && (A_x1[ind3][row1]==0));
00569 
00570     /* okay, if one whole column is empty then we can take this 
00571        direction as the eigenvector
00572        remember : {eigenvectors} = kernel(A_x1) */
00573     if (row1 == 3) {
00574       eve[ind3]=1.0;
00575       eve[(ind3+1) % 3]=0.0;
00576       eve[(ind3+2) % 3]=0.0;
00577       return 1;
00578     }
00579 
00580     for(i=1;i<3;i++) {
00581       row2=(row1+i) % 3;
00582       coeff1=A_x1[ind1][row1]*A_x1[ind3][row2]-
00583                     A_x1[ind1][row2]*A_x1[ind3][row1];
00584       coeff2=A_x1[ind2][row1]*A_x1[ind3][row2]-
00585                     A_x1[ind2][row2]*A_x1[ind3][row1];
00586       if (coeff1!=0.0) {
00587         eve[ind2]=1.0;
00588         eve[ind1]=-coeff2/coeff1;
00589         eve[ind3]=-( A_x1[ind2][row1]+eve[ind1]* A_x1[ind1][row1])
00590                               /A_x1[ind3][row1];
00591         norm = sqrt(eve[0]*eve[0] + eve[1]*eve[1] + eve[2]*eve[2]);
00592         eve[0]/=norm; eve[1]/=norm; eve[2]/=norm;
00593         return 1;
00594       }
00595       else {
00596         if (coeff2!=0.0) {
00597           eve[ind1]=1.0;
00598           eve[ind2]=-coeff1/coeff2;
00599           eve[ind3]=-( A_x1[ind1][row1]+eve[ind2]* A_x1[ind2][row1])
00600                             /A_x1[ind3][row1];
00601           norm = sqrt(eve[0]*eve[0] + eve[1]*eve[1] + eve[2]*eve[2]);
00602           eve[0]/=norm; eve[1]/=norm; eve[2]/=norm;
00603           return(1);
00604         }
00605       }
00606     } /* loop over the different rows */
00607   }   /* loop over the different columns */
00608 
00609   /* the try failed => not a singular matrix: only solution is (0,0,0) */                    
00610   return 0;
00611 }
00612 /*@}*/
00613 
00614 /*************************************************************/
00615 /** \name Linear algebra functions                           */
00616 /*************************************************************/
00617 /*@{*/
00618 
00619 /** Calculate the LU decomposition of a matrix A. Uses Crout's method
00620  *  with partial implicit pivoting.  The original matrix A is replaced
00621  *  by its LU decomposition.  Due to the partial pivoting the result
00622  *  may contain row permutations which are recorded in perms.
00623  *  @return 0 for success, -1 otherwise (i.e. matrix is singular)
00624  *  @param A     Matrix to be decomposed (Input/Output) 
00625  *  @param n     Dimension of the matrix (Input) 
00626  *  @param perms Records row permutations effected by pivoting (Output)
00627  */
00628 MDINLINE int lu_decompose_matrix(double **A, int n, int *perms) {
00629   int i, j, k, ip;
00630   double max, sum, tmp;
00631 
00632   double *scal = (double *)malloc(n*sizeof(double));
00633 
00634   /* loop over rows and store implicit scaling factors */
00635   for (i=0; i<n; i++) {
00636     max = 0.0;
00637     for (j=0; j<n; j++) {
00638       if ( (tmp=fabs(A[i][j])) > max) max=tmp;
00639     }
00640     if (max == 0.0) {
00641       /* matrix has a zero row and is singular */
00642       return -1;
00643     }
00644     scal[i] = 1.0/max;
00645   }
00646 
00647   /** Crout's algorithm: Calculate L and U columnwise from top to
00648    *  bottom. The diagonal elements of L are chosen to be 1. Only
00649    *  previously determined entries are used in the calculation. The
00650    *  original matrix elements are used only once and can be
00651    *  overwritten with the elements of L and U, the diagonal of L not
00652    *  being stored. Rows may be permuted according to the largest
00653    *  element (pivot) in the lower part, where rows are normalized to
00654    *  have the largest element scaled to unity.
00655    */
00656 
00657   /* loop over columns */
00658   for (j=0; j<n; j++) {
00659 
00660     /* calculate upper triangle part (without diagonal) */
00661     for (i=0; i<j; i++) {
00662       sum = A[i][j];
00663       for (k=0;k<=i-1;k++) sum -= A[i][k]*A[k][j];
00664       A[i][j] = sum;
00665     }
00666     
00667     /* calculate diagonal and lower triangle part */
00668     /* pivot is determined on the fly, but not yet divided by */
00669     ip = j;
00670     max = 0.0;
00671     for (i=j; i<n; i++) {
00672       sum = A[i][j];
00673       for (k=0; k<=j-1; k++) sum -= A[i][k]*A[k][j];
00674       A[i][j] = sum;
00675       if ((tmp=scal[i]*fabs(sum)) > max) {
00676         max = tmp;
00677         ip = i;
00678       }
00679     }
00680 
00681     /* swap rows according to pivot index */
00682     if (j != ip) {
00683       for (k=0; k<n; k++) {
00684         tmp = A[j][k];
00685         A[j][k] = A[ip][k];
00686         A[ip][k] = tmp;
00687       }
00688       scal[ip] = scal[j];
00689     }
00690     perms[j] = ip;
00691 
00692     if (A[j][j] == 0.0) {
00693       /* zero pivot indicates singular matrix */
00694       return -1;
00695     }
00696 
00697     /* now divide by pivot element */
00698     if (j != n) {
00699       tmp = 1.0/A[j][j];
00700       for (i=j+1; i<n; i++)
00701         A[i][j] *= tmp;
00702     }
00703 
00704   }
00705 
00706   free(scal);
00707   
00708   return 0;
00709 }
00710 
00711 /** Solve the linear equation system for a LU decomposed matrix A.
00712  *  Uses forward substitution for the lower triangle part and
00713  *  backsubstitution for the upper triangle part. Row permutations as
00714  *  indicated in perms are applied to b accordingly. The solution is
00715  *  written to b in place.
00716  *  @param A     Matrix in LU decomposed form (Input) 
00717  *  @param n     Dimension of the matrix (Input) 
00718  *  @param perms Indicates row permutations due to pivoting (Input)
00719  *  @param b     Right-hand side of equation system (Input).
00720  *               Is destroyed and contains the solution x afterwards (Output).
00721  */
00722 MDINLINE void lu_solve_system(double **A, int n, int *perms, double *b) {
00723   int i, j;
00724   double sum;
00725 
00726   /* Step 1: Solve Ly=b */
00727 
00728   /* forward substitution for lower triangle part */
00729   for (i=0; i<n; i++) {
00730     /* take care of the correct permutations */
00731     sum=b[perms[i]];
00732     b[perms[i]]=b[i];
00733     for (j=0; j<=i-1; j++) sum -= A[i][j]*b[j];
00734     b[i] = sum;
00735   }
00736 
00737   /* Step 2: Solve Ux=y */
00738 
00739   /* backsubstitution for upper triangle part */
00740   for (i=n-1; i>=0; i--) {
00741     sum = b[i];
00742     for (j=i+1; j<n; j++) sum -= A[i][j]*b[j];
00743     b[i]=sum/A[i][i];
00744   }
00745 
00746 }
00747 /*@}*/
00748 
00749 /*************************************************************/
00750 /** \name Three dimensional grid operations                  */
00751 /*************************************************************/
00752 /*@{*/
00753 
00754 /** get the linear index from the position (a,b,c) in a 3D grid
00755  *  of dimensions adim[]. returns linear index.
00756  *
00757  * @return        the linear index
00758  * @param a       x position 
00759  * @param b       y position 
00760  * @param c       z position 
00761  * @param adim    dimensions of the underlying grid  
00762  */
00763 MDINLINE int get_linear_index(int a, int b, int c, int adim[3])
00764 {
00765   return (a + adim[0]*(b + adim[1]*c));   
00766 }
00767 
00768 /** get the position a[] from the linear index in a 3D grid
00769  *  of dimensions adim[].
00770  *
00771  * @param i       linear index
00772  * @param a       x position (return value) 
00773  * @param b       y position (return value) 
00774  * @param c       z position (return value) 
00775  * @param adim    dimensions of the underlying grid  
00776  */
00777 MDINLINE void get_grid_pos(int i, int *a, int *b, int *c, int adim[3])
00778 {
00779   *a = i % adim[0];
00780   i /= adim[0];
00781   *b = i % adim[1];
00782   i /= adim[1];
00783   *c = i;
00784 }
00785 
00786 /** Malloc a 3d grid for doubles with dimension dim[3] . 
00787  * @param grid    pointer to grid.
00788  * @param dim  dimension of the grid.
00789 */
00790 MDINLINE int malloc_3d_grid(double ****grid, int dim[3])
00791 {
00792   int i,j;
00793   *grid = (double***)malloc(sizeof(double **)*dim[0]);
00794   if(*grid==NULL) return 0;
00795   for(i=0;i<dim[0];i++) {
00796     (*grid)[i] = (double**)malloc(sizeof(double *)*dim[1]);
00797     if((*grid)[i]==NULL) return 0;
00798     for(j=0;j<dim[1];j++) {
00799       (*grid)[i][j] = (double*)malloc(sizeof(double)*dim[2]);
00800       if((*grid)[i][j]==NULL) return 0;
00801     }
00802   }
00803   return 1;
00804 }
00805 
00806 /** print a block of a 3D array.
00807  *  @param data    3D array.
00808  *  @param start   start coordinate for the block.
00809  *  @param size    size of the block.
00810  *  @param dim     dimension of the array.
00811  *  @param element size of the elements in the array.
00812  *  @param num     number of element to print.
00813 
00814 */
00815 MDINLINE void print_block(double *data, int start[3], int size[3], int dim[3], int element, int num)
00816 {
00817   int i0,i1,i2,b=1;
00818   int divide=0,block1=0,start1;
00819   double tmp;
00820 
00821   while(divide==0) {
00822     if(b*size[2] > 7) {
00823       block1=b;
00824       divide = (int)ceil(size[1]/(double)block1);
00825     }
00826     b++;
00827   }
00828   fprintf(stderr,"?: print_block (%d of %d): (%d,%d,%d)+(%d,%d,%d) from grid (%d,%d,%d)\n",
00829           num+1,element,
00830           start[0],start[1],start[2],size[0],size[1],size[2],dim[0],dim[1],dim[2]);
00831   for(b=0;b<divide;b++) {
00832     start1 = b*block1+start[1];
00833     for(i0=start[0]+size[0]-1; i0>=start[0]; i0--) {
00834       for(i1=start1; i1<imin(start1+block1,start[1]+size[1]);i1++) {
00835         for(i2=start[2]; i2<start[2]+size[2];i2++) {
00836           tmp=data[num+(element*(i2+dim[2]*(i1+dim[1]*i0)))];
00837           if(tmp<0) fprintf(stderr,"%1.2e",tmp);
00838           else      fprintf(stderr," %1.2e",tmp);
00839         }
00840         fprintf(stderr," | ");
00841       }
00842       fprintf(stderr,"\n");
00843     }
00844     fprintf(stderr,"\n");
00845   }
00846 }
00847 /*@}*/
00848 
00849 
00850 /*************************************************************/
00851 /** \name Distance calculations.  */
00852 /*************************************************************/
00853 /*@{*/
00854 
00855 /** returns the distance between two position. 
00856  *  \param pos1 Position one.
00857  *  \param pos2 Position two.
00858 */
00859 MDINLINE double distance(double pos1[3], double pos2[3])
00860 {
00861   return sqrt( SQR(pos1[0]-pos2[0]) + SQR(pos1[1]-pos2[1]) + SQR(pos1[2]-pos2[2]) );
00862 }
00863 
00864 /** returns the distance between two positions squared.
00865  *  \param pos1 Position one.
00866  *  \param pos2 Position two.
00867 */
00868 MDINLINE double distance2(double pos1[3], double pos2[3])
00869 {
00870   return SQR(pos1[0]-pos2[0]) + SQR(pos1[1]-pos2[1]) + SQR(pos1[2]-pos2[2]);
00871 }
00872 
00873 /** Returns the distance between two positions squared and stores the
00874     distance vector pos1-pos2 in vec.
00875  *  \param pos1 Position one.
00876  *  \param pos2 Position two.
00877  *  \param vec  vecotr pos1-pos2.
00878  *  \return distance squared
00879 */
00880 MDINLINE double distance2vec(double pos1[3], double pos2[3], double vec[3])
00881 {
00882   vec[0] = pos1[0]-pos2[0];
00883   vec[1] = pos1[1]-pos2[1];
00884   vec[2] = pos1[2]-pos2[2];
00885   return SQR(vec[0]) + SQR(vec[1]) + SQR(vec[2]);
00886 }
00887 
00888 /** returns the distance between the unfolded coordintes of two particles. 
00889  *  \param pos1       Position of particle one.
00890  *  \param image_box1 simulation box index of particle one .
00891  *  \param pos2       Position of particle two.
00892  *  \param image_box2 simulation box index of particle two .
00893  *  \param box_l      size of simulation box.
00894 */
00895 MDINLINE double unfolded_distance(double pos1[3], int image_box1[3], 
00896                                   double pos2[3], int image_box2[3], double box_l[3])
00897 {
00898   int i;
00899   double dist = 0;
00900   double lpos1[3],lpos2[3];
00901   for(i=0;i<3;i++){
00902     lpos1[i] = pos1[i];
00903     lpos2[i] = pos2[i];
00904     lpos1[i] += image_box1[i]*box_l[i];
00905     lpos2[i] += image_box2[i]*box_l[i];
00906     dist += SQR(lpos1[i]-lpos2[i]);
00907   }
00908   return sqrt(dist);
00909 }
00910 /*@}*/
00911 
00912 /*************************************************************/
00913 /** \name String helper functions                            */
00914 /*************************************************************/
00915 /*@{*/
00916 
00917 /** extend a string with another one. Like strcat, just automatically
00918     increases the string space */
00919 MDINLINE char *strcat_alloc(char *left, char *right)
00920 {
00921   if (!left) {
00922     char *res = (char *)malloc(strlen(right) + 1);
00923     strcpy(res, right);
00924     return res;
00925   }
00926   else {
00927     char *res = (char *)realloc(left, strlen(left) + strlen(right) + 1);
00928     strcat(res, right);
00929     return res;
00930   }
00931 }
00932 
00933 /*@}*/
00934 
00935 /*************************************************************/
00936 /** \name Object-in-fluid functions                          */
00937 /*************************************************************/
00938 /*@{*/
00939 
00940 /** Computes the area of triangle between vectors P1 and P2, 
00941  *  by computing the crossproduct P1 x P2 and taking the half of its norm */
00942 MDINLINE double area_triangle_new(double *P1, double *P2) {
00943  double area;
00944  double normal[3], n; //auxiliary variables
00945  vector_product(P1,P2,normal); 
00946  n=normr(normal);
00947  area = 0.5*n;
00948  return area;
00949 }
00950 
00951 /** Computes the area of triangle between vectors P1,P2,P3, 
00952  *  by computing the crossproduct P1P2 x P1P3 and taking the half of its norm */
00953 MDINLINE double area_triangle(double *P1, double *P2, double *P3) {
00954         double area;
00955         double u[3],v[3],normal[3], n; //auxiliary variables
00956         u[0] = P2[0] - P1[0]; // u = P1P2
00957         u[1] = P2[1] - P1[1]; 
00958         u[2] = P2[2] - P1[2]; 
00959         v[0] = P3[0] - P1[0]; // v = P1P3
00960         v[1] = P3[1] - P1[1]; 
00961         v[2] = P3[2] - P1[2]; 
00962         vector_product(u,v,normal); 
00963         n=normr(normal);
00964         area = 0.5*n;
00965         return area;
00966 }
00967 
00968 /** Computes the normal vector to the plane given by points P1P2P3 */
00969 MDINLINE void get_n_triangle(double* p1, double* p2, double* p3, double* n){
00970         n[0]=(p2[1]-p1[1])*(p3[2]-p1[2])-(p2[2]-p1[2])*(p3[1]-p1[1]);
00971         n[1]=(p2[2]-p1[2])*(p3[0]-p1[0])-(p2[0]-p1[0])*(p3[2]-p1[2]);
00972         n[2]=(p2[0]-p1[0])*(p3[1]-p1[1])-(p2[1]-p1[1])*(p3[0]-p1[0]);
00973 }
00974 
00975 /** This function returns the angle btw the triangle p1,p2,p3 and p2,p3,p4. 
00976  *  Be careful, the angle depends on the orientation of the trianlges! 
00977  *  You need to be sure that the orientation (direction of normal vector) 
00978  *  of p1p2p3 is given by the cross product p2p1 x p2p3. 
00979  *  The orientation of p2p3p4 must be given by p2p3 x p2p4. 
00980  * 
00981  *  Example: p1 = (0,0,1), p2 = (0,0,0), p3=(1,0,0), p4=(0,1,0). 
00982  *  The orientation of p1p2p3 should be in the direction (0,1,0) 
00983  *  and indeed: p2p1 x p2p3 = (0,0,1)x(1,0,0) = (0,1,0)
00984  *  This function is called in the beginning of the simulation when creating 
00985  *  bonds depending on the angle btw the triangles, the bending_force.
00986  *  Here, we determine the orientations by looping over the triangles 
00987  *  and checking the correct orientation. So when defining the bonds by tcl command
00988  *  "part p2 bond xxxx p1 p3 p4", we correctly input the particle id's.
00989  *  So if you have the access to the order of particles, you are safe to call this
00990  *  function with exactly this order. Otherwise you need to check the orientations. */
00991 MDINLINE double angle_btw_triangles(double *P1, double *P2, double *P3, double *P4) {
00992         double phi;
00993         double u[3],v[3],normal1[3],normal2[3]; //auxiliary variables
00994         u[0] = P1[0] - P2[0]; // u = P2P1
00995         u[1] = P1[1] - P2[1]; 
00996         u[2] = P1[2] - P2[2]; 
00997         v[0] = P3[0] - P2[0]; // v = P2P3
00998         v[1] = P3[1] - P2[1]; 
00999         v[2] = P3[2] - P2[2]; 
01000         vector_product(u,v,normal1); 
01001         u[0] = P3[0] - P2[0]; // u = P2P3
01002         u[1] = P3[1] - P2[1]; 
01003         u[2] = P3[2] - P2[2]; 
01004         v[0] = P4[0] - P2[0]; // v = P2P4
01005         v[1] = P4[1] - P2[1]; 
01006         v[2] = P4[2] - P2[2]; 
01007         vector_product(u,v,normal2); 
01008 
01009         double tmp11,tmp22,tmp33;
01010         // Now we compute the scalar product of n1 and n2 divided by the norms of n1 and n2
01011         //tmp11 = dot(3,normal1,normal2);         // tmp11 = n1.n2
01012         tmp11 = scalar(normal1,normal2);         // tmp11 = n1.n2
01013         
01014         /*      
01015         tmp22 = normr(normal1);
01016         tmp33 = normr(normal2);
01017         tmp11 /= (tmp22*tmp33);  // tmp11 = n1.n2/(|n1||n2|)
01018 */
01019         tmp11 *= fabs(tmp11); // tmp11 = (n1.n2)^2
01020         tmp22 = sqrlen(normal1);  //tmp22 = |n1|^2
01021         tmp33 = sqrlen(normal2);  //tmp33 = |n1|^2
01022         tmp11 /= (tmp22*tmp33);  // tmp11 = (n1.n2/(|n1||n2|))^2
01023         if (tmp11 > 0 ) {
01024                 tmp11 = sqrt(tmp11);
01025         } else {
01026                 tmp11 = - sqrt(- tmp11);
01027         }               
01028 
01029         if(tmp11>=1.) { tmp11=0.0;}
01030         else if(tmp11<=-1.) { tmp11=M_PI;}
01031         phi = M_PI - acos(tmp11);       // The angle between the faces (not considering the orientation, always less or equal to Pi) is
01032                                                                 // equal to Pi minus angle between the normals
01033         
01034         // Now we need to determine, if the angle btw two triangles is less than Pi or more than Pi. To do this we check, 
01035         // if the point P4 lies in the halfspace given by trianlge P1P2P3 and the normal to this triangle. If yes, we have 
01036         // angle less than Pi, if not, we have angle more than Pi.
01037         // General equation of the plane is n_x*x + n_y*y + n_z*z + d = 0 where (n_x,n_y,n_z) is the normal to the plane.
01038         // Point P1 lies in the plane, therefore d = -(n_x*P1_x + n_y*P1_y + n_z*P1_z)
01039         // Point P4 lies in the halfspace given by normal iff n_x*P4_x + n_y*P4_y + n_z*P4_z + d >= 0
01040         tmp11 = - (normal1[0]*P1[0] + normal1[1]*P1[1] + normal1[2]*P1[2]);
01041         if (normal1[0]*P4[0] + normal1[1]*P4[1] + normal1[2]*P4[2] + tmp11 < 0) phi = 2*M_PI - phi;
01042         return phi;
01043 }
01044 
01045 /*@}*/
01046 
01047 #endif