MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
mthrdslv.c
Go to the documentation of this file.
1 /*
2  * MBDyn (C) is a multibody analysis code.
3  * http://www.mbdyn.org
4  *
5  * Copyright (C) 2004-2017
6  *
7  * Pierangelo Masarati <masarati@aero.polimi.it>
8  * Paolo Mantegazza <mantegazza@aero.polimi.it>
9  *
10  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
11  * via La Masa, 34 - 20156 Milano, Italy
12  * http://www.aero.polimi.it
13  *
14  * Changing this copyright notice is forbidden.
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation (version 2 of the License).
19  *
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29  */
30 
31 /*
32 neq: is the matrix size;
33 a: is used to store matrix elements; a[row][col] is the element in row
34  row and column col;
35 nzr and nzc: are vectors of size neq, used to count the nonzero elements of a particular row or
36  column, respectively;
37 ri and ci: are neq x neq matrices used to store nonzero element indices; ri[col][i]
38  (resp. ci[row][i]), with i < nzr[col] (i < nzc[row]), is the row (column)
39  index of one of the nzr[col] (nzc[row]) nonzero elements in
40  column col (row row); note that indices in ri[col] and ci[row] are
41  not ordered;
42 nz: nz[row][col] is true if the element in row row and column col is
43  nonzero, false otherwise;
44 piv: is a vector of size neq.
45 
46 
47 The subroutine naivfct perform the LU factorization, naivslv the back-solve.
48 
49 */
50 
51 
52 #ifdef HAVE_CONFIG_H
53 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
54 
55 #include <math.h>
56 #include "ac/f2c.h"
57 
58 #else /* !HAVE_CONFIG_H */
59 /* to ease compilation outside of MBDyn...
60  * replace long and double with the preferred types */
61 #include <math.h>
62 typedef long int integer;
63 typedef double doublereal;
64 #endif /* !HAVE_CONFIG_H */
65 
66 #include <stdlib.h>
67 #include <limits.h>
68 
69 #include "mthrdslv.h"
70 
71 #define BIGINT (1 << 30)
72 
73 #define MINPIV 1.0e-8
74 
75 int
76 naivfct(RMAT a, integer neq, integer *nzr, IMAT ri,
77  integer *nzc, IMAT ci, NZMAT nz,
78  integer *piv, doublereal minpiv)
79 {
80  char todo[neq];
81  integer i, j, k, pvr, pvc, nr, nc, r;
82  integer *pri, *pci;
83  char *prik;
84  doublereal den, mul, mulpiv, fari;
85 #if 0
86  doublereal fapvr;
87 #endif
88  doublereal *par, *papvr;
89 
90  if (neq <= 0 || (unsigned long)neq > NAIVE_MAX) {
91  return NAIVE_ERANGE;
92  }
93 
94  if (!minpiv) {
95  minpiv = MINPIV;
96  }
97  for (pvr = 0; pvr < neq; pvr++) {
98  todo[pvr] = 1;
99  }
100  for (i = 0; i < neq; i++) {
101  if (!nzr[i]) { return NAIVE_ENULCOL + i; }
102  nc = neq + 1;
103  nr = nzr[i];
104  mul = 0.0;
105  pri = ri[i];
106  pvr = pri[0];
107  mulpiv = 0.;
108 #if 0
109  fapvr = 0.;
110  for (k = 0; k < nr; k++) {
111  r = pri[k];
112  if (todo[r]) {
113  fari = fabs(a[r][i]);
114  if (fari > mul) {
115  mulpiv = fari*minpiv;
116  if (nzc[r] <= nc || mulpiv > fapvr) {
117  nc = nzc[pvr = r];
118  fapvr = fari;
119  }
120  mul = fari;
121  } else if (nzc[r] < nc && fari > mulpiv) {
122  nc = nzc[pvr = r];
123  }
124  }
125  }
126 #endif
127  for (k = 0; k < nr; k++) {
128  r = pri[k];
129  if (todo[r]) {
130  fari = fabs(a[r][i]);
131  if (fari > mul) {
132  mul = fari;
133  }
134  }
135  }
136  mulpiv = mul*minpiv;
137  for (k = 0; k < nr; k++) {
138  r = pri[k];
139  if (todo[r]) {
140  fari = fabs(a[r][i]);
141  if (fari >= mulpiv && nzc[r] < nc) {
142  nc = nzc[pvr = r];
143  }
144  }
145  }
146  if (nc == neq + 1) { return NAIVE_ENOPIV + i; }
147  if (mulpiv == 0.) { return NAIVE_ENOPIV + i; }
148 
149  piv[i] = pvr;
150  todo[pvr] = 0;
151  papvr = a[pvr];
152  den = papvr[i] = 1.0/papvr[i];
153 
154  for (k = 0; k < nr; k++) {
155  if (!todo[r = pri[k]]) { continue; }
156  par = a[r];
157  mul = par[i] = par[i]*den;
158  prik = nz[r];
159  pci = ci[pvr];
160  for (j = 0; j < nc; j++) {
161  if ((pvc = pci[j]) <= i) { continue; }
162  if (prik[pvc]) {
163  par[pvc] -= mul*papvr[pvc];
164  } else {
165  par[pvc] = -mul*papvr[pvc];
166  prik[pvc] = 1;
167  ri[pvc][nzr[pvc]++] = r;
168  ci[r][nzc[r]++] = pvc;
169  }
170  }
171  }
172  }
173  return 0;
174 }
175 
176 /*
177  * to solve A * x = b
178  *
179  * actually solve P * A * x = P * b
180  *
181  * compute P * L and P * U such that P * A = P * L * P^-1 * P * U
182  *
183  * and store P * L, P * U
184  *
185  * first step: P * L * f = P * b (but actually store P * f)
186  *
187  * second step: P * U * x = P * f
188  */
189 int
190 naivslv(RMAT a, integer neq, integer *nzc, IMAT ci,
191  doublereal *rhs, doublereal * sol,
192  integer *piv)
193 {
194  doublereal fwd[neq];
195 
196  integer i, k, nc, r, c;
197  integer *pci;
198  doublereal s;
199  doublereal *par;
200 
201  if (neq <= 0 || (unsigned long)neq > NAIVE_MAX) {
202  return NAIVE_ERANGE;
203  }
204 
205  fwd[0] = rhs[piv[0]];
206  for (i = 1; i < neq; i++) {
207  nc = nzc[r = piv[i]];
208  s = rhs[r];
209  par = a[r];
210  pci = ci[r];
211  for (k = 0; k < nc; k++) {
212  if ((c = pci[k]) < i) {
213  s -= par[c]*fwd[c];
214  }
215  }
216  fwd[i] = s;
217  }
218 
219  r = piv[--neq];
220  sol[neq] = fwd[neq]*a[r][neq];
221  for (i = neq - 1; i >= 0; i--) {
222  nc = nzc[r = piv[i]];
223  s = fwd[i];
224  par = a[r];
225  pci = ci[r];
226  for (k = 0; k < nc; k++) {
227  if ((c = pci[k]) > i) {
228  s -= par[c]*sol[c];
229  }
230  }
231  sol[i] = s*par[i];
232  }
233 
234  return 0;
235 }
236 
#define NAIVE_MAX
Definition: mthrdslv.h:71
long int integer
Definition: mthrdslv.c:62
char ** NZMAT
Definition: mthrdslv.h:80
GradientExpression< UnaryExpr< FuncFabs, Expr > > fabs(const GradientExpression< Expr > &u)
Definition: gradient.h:2973
int naivfct(RMAT a, integer neq, integer *nzr, IMAT ri, integer *nzc, IMAT ci, NZMAT nz, integer *piv, doublereal minpiv)
Definition: mthrdslv.c:76
#define NAIVE_ERANGE
Definition: mthrdslv.h:75
integer ** IMAT
Definition: mthrdslv.h:78
#define MINPIV
Definition: mthrdslv.c:73
#define NAIVE_ENOPIV
Definition: mthrdslv.h:74
static std::stack< cleanup * > c
Definition: cleanup.cc:59
#define NAIVE_ENULCOL
Definition: mthrdslv.h:73
static const doublereal a
Definition: hfluid_.h:289
double doublereal
Definition: colamd.c:52
long int integer
Definition: colamd.c:51
doublereal ** RMAT
Definition: mthrdslv.h:79
double doublereal
Definition: mthrdslv.c:63
int naivslv(RMAT a, integer neq, integer *nzc, IMAT ci, doublereal *rhs, doublereal *sol, integer *piv)
Definition: mthrdslv.c:190