Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
luc.c
Go to the documentation of this file.
1/* get the inverse of a matrix using LU decomposition */
2#include <math.h>
3#include <stdio.h>
4#include "NR.h"
5
6#define TINY 1.0e-20
7
8#ifdef __cplusplus
9namespace neBEM {
10#endif
11
12void ludcmp(double **a, int n, int *index, double *d) {
13 int i, j, k;
14 int imax = 1;
15 double big, sum, dum;
16 double *vv; /* vv stores the implicit scaling of each row */
17
18 vv = dvector(1, n); /* No looping yet. */
19 *d = 1.0; /* loop over rows to get implicit scaling info. */
20#ifdef _OPENMP
21#pragma omp parallel for private(j, big)
22#endif
23 for (i = 1; i <= n; i++) {
24 big = 0.0;
25 for (j = 1; j <= n; j++)
26 if (fabs(a[i][j]) > big) big = fabs(a[i][j]);
27 if (big == 0.0) nrerror("Singular matrix in routine LUDCMP");
28 vv[i] = 1.0 / big;
29 }
30
31 for (j = 1; j <= n; j++) /* outer loop of Crout's method */
32 {
33 for (i = 1; i < j; i++) {
34 sum = a[i][j];
35#ifdef _OPENMP
36#pragma omp parallel for private(k) reduction(- : sum)
37#endif
38 for (k = 1; k < i; k++) // OMPChk: parallelization may not help much
39 sum = sum - a[i][k] * a[k][j];
40 a[i][j] = sum;
41 }
42
43 big = 0.0; /* search for largest pivotal element. */
44 for (i = j; i <= n; i++) {
45 sum = a[i][j];
46#ifdef _OPENMP
47#pragma omp parallel for private(k) reduction(- : sum)
48#endif
49 for (k = 1; k < j; k++) // OMPChk: parallelization may not help much
50 sum = sum - a[i][k] * a[k][j];
51 a[i][j] = sum;
52
53 dum = vv[i] * fabs(sum);
54 if (dum >= big) { /* is the figure of merit better */
55 big = dum; /* than the best? */
56 imax = i;
57 }
58 }
59
60 if (j != imax) {
61#ifdef _OPENMP
62#pragma omp parallel for private(k, dum)
63#endif
64 for (k = 1; k <= n; k++) {
65 dum = a[imax][k];
66 a[imax][k] = a[j][k];
67 a[j][k] = dum;
68 }
69 *d = -(*d); /* change the parity of d. */
70 vv[imax] = vv[j]; /* interchange the scale factor. */
71 }
72 index[j] = imax;
73 if (a[j][j] == 0.0) /* for some applications on singular */
74 a[j][j] = TINY; /* matrices, it is desirable to */
75 /* substitute TINY for zero. */
76
77 if (j != n) /* finally, divide by the pivot element. */
78 {
79 dum = 1.0 / a[j][j];
80#ifdef _OPENMP
81#pragma omp parallel for private(i) // OMPCheck: may not help much
82#endif
83 for (i = j + 1; i <= n; i++) a[i][j] = a[i][j] * dum;
84 }
85 }
86
87 free_dvector(vv, 1, n);
88}
89
90void lubksb(double **a, int n, int *index, double *b) {
91 int i, ii = 0, ip, j;
92 double sum;
93
94 for (i = 1; i <= n; i++) /* forward substitution. */
95 {
96 ip = index[i];
97 sum = b[ip];
98 b[ip] = b[i];
99 if (ii) {
100#ifdef _OPENMP
101#pragma omp parallel for private(j) reduction(- : sum)
102#endif
103 for (j = ii; j <= i; j++) sum = sum - a[i][j] * b[j];
104 } else if (sum)
105 ii = i;
106 b[i] = sum;
107 }
108
109 for (i = n; i >= 1; i--) /* back substitution. */
110 {
111 sum = b[i];
112#ifdef _OPENMP
113#pragma omp parallel for private(j) reduction(- : sum)
114#endif
115 for (j = i + 1; j <= n; j++) sum = sum - a[i][j] * b[j];
116 b[i] = sum / a[i][i];
117 }
118}
119
120/*
121void main(void)
122{
123double **a, **y, d, *col;
124int n, i, j, *index;
125char filename[50];
126FILE *fp;
127
128printf("Give filename: ");
129scanf("%s", filename);
130fp = fopen(filename, "r");
131fscanf(fp, "%d", &n);
132a = dmatrix(1, n, 1, n);
133y = dmatrix(1, n, 1, n);
134col = dvector(1, n);
135index = ivector(1, n);
136for(i = 1; i <= n; ++i)
137 for(j = 1; j <= n; ++j)
138 fscanf(fp, "%le", &a[i][j]);
139fclose(fp);
140fp = fopen("luc1.out", "w");
141for(i = 1; i <= n; ++i)
142 {
143 for(j = 1; j <= n; ++j)
144 fprintf(fp, "%f ", a[i][j]);
145 fprintf(fp, "\n");
146 }
147fclose(fp);
148
149ludcmp(a, n, index, &d); Decompose the matrix just once.
150
151fp = fopen("luc2.out", "w");
152for(i = 1; i <= n; ++i)
153 {
154 for(j = 1; j <= n; ++j)
155 fprintf(fp, "%f ", a[i][j]);
156 fprintf(fp, "\n");
157 }
158fclose(fp);
159
160for(j = 1; j <= n; j++) Find inverse by columns.
161 {
162 for(i = 1; i <= n; i++)
163 col[i] = 0.0;
164 col[j] = 1.0;
165
166 lubksb(a, n, index, col);
167 for(i = 1; i <= n; i++)
168 y[i][j] = col[i];
169 }
170
171fp = fopen("luc.out", "w");
172for(i = 1; i <= n; ++i)
173 {
174 for(j = 1; j <= n; ++j)
175 fprintf(fp, "%f ", y[i][j]);
176 fprintf(fp, "\n");
177 }
178fclose(fp);
179}
180*/
181
182#ifdef __cplusplus
183} // namespace
184#endif
NRGLOBAL void nrerror()
void lubksb(double **a, int n, int *index, double *b)
Definition: luc.c:90
#define TINY
Definition: luc.c:6
void ludcmp(double **a, int n, int *index, double *d)
Definition: luc.c:12
void free_dvector(double *v, long nl, long)
Definition: nrutil.c:470
double * dvector(long nl, long nh)
Definition: nrutil.c:63