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