Skip to content

Commit 62d01c6

Browse files
author
GitHub Actions Bot
committed
References for 'BlueBrain/nmodl#1344'.
1 parent 237859f commit 62d01c6

File tree

85 files changed

+18371
-1293
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+18371
-1293
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
* Copyright 2023 Blue Brain Project, EPFL.
3+
* See the top-level LICENSE file for details.
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#pragma once
9+
10+
/**
11+
* \dir
12+
* \brief Solver for a system of linear equations : Crout matrix decomposition
13+
*
14+
* \file
15+
* \brief Implementation of Crout matrix decomposition (LU decomposition) followed by
16+
* Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c
17+
*/
18+
19+
#include <Eigen/Core>
20+
#include <cmath>
21+
22+
#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC)
23+
#include "coreneuron/utils/offload.hpp"
24+
#endif
25+
26+
namespace nmodl {
27+
namespace crout {
28+
29+
/**
30+
* \brief Crout matrix decomposition : in-place LU Decomposition of matrix a.
31+
*
32+
* Implementation details : (Legacy code) nrn / scopmath / crout.c
33+
*
34+
* Returns: 0 if no error; -1 if matrix is singular or ill-conditioned
35+
*/
36+
#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC)
37+
nrn_pragma_acc(routine seq)
38+
nrn_pragma_omp(declare target)
39+
#endif
40+
template <typename T>
41+
EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) {
42+
// roundoff is the minimal value for a pivot element without its being considered too close to
43+
// zero
44+
double roundoff = 1.e-20;
45+
int i, j, k, r, pivot, irow, save_i = 0, krow;
46+
T sum, equil_1, equil_2;
47+
48+
/* Initialize permutation and rowmax vectors */
49+
50+
for (i = 0; i < n; i++) {
51+
perm[i] = i;
52+
k = 0;
53+
for (j = 1; j < n; j++)
54+
if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k]))
55+
k = j;
56+
rowmax[i] = a[i * n + k];
57+
}
58+
59+
/* Loop over rows and columns r */
60+
61+
for (r = 0; r < n; r++) {
62+
/*
63+
* Operate on rth column. This produces the lower triangular matrix
64+
* of terms needed to transform the constant vector.
65+
*/
66+
67+
for (i = r; i < n; i++) {
68+
sum = 0.0;
69+
irow = perm[i];
70+
for (k = 0; k < r; k++) {
71+
krow = perm[k];
72+
sum += a[irow * n + k] * a[krow * n + r];
73+
}
74+
a[irow * n + r] -= sum;
75+
}
76+
77+
/* Find row containing the pivot in the rth column */
78+
79+
pivot = perm[r];
80+
equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]);
81+
for (i = r + 1; i < n; i++) {
82+
irow = perm[i];
83+
equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]);
84+
if (equil_2 > equil_1) {
85+
/* make irow the new pivot row */
86+
87+
pivot = irow;
88+
save_i = i;
89+
equil_1 = equil_2;
90+
}
91+
}
92+
93+
/* Interchange entries in permutation vector if necessary */
94+
95+
if (pivot != perm[r]) {
96+
perm[save_i] = perm[r];
97+
perm[r] = pivot;
98+
}
99+
100+
/* Check that pivot element is not too small */
101+
102+
if (std::fabs(a[pivot * n + r]) < roundoff)
103+
return -1;
104+
105+
/*
106+
* Operate on row in rth position. This produces the upper
107+
* triangular matrix whose diagonal elements are assumed to be unity.
108+
* This matrix is used in the back substitution algorithm.
109+
*/
110+
111+
for (j = r + 1; j < n; j++) {
112+
sum = 0.0;
113+
for (k = 0; k < r; k++) {
114+
krow = perm[k];
115+
sum += a[pivot * n + k] * a[krow * n + j];
116+
}
117+
a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r];
118+
}
119+
}
120+
return 0;
121+
}
122+
#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC)
123+
nrn_pragma_omp(end declare target)
124+
#endif
125+
126+
/**
127+
* \brief Crout matrix decomposition : Forward/Backward substitution.
128+
*
129+
* Implementation details : (Legacy code) nrn / scopmath / crout.c
130+
*
131+
* Returns: no return variable
132+
*/
133+
#define y_(arg) p[y[arg]]
134+
#define b_(arg) b[arg]
135+
#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC)
136+
nrn_pragma_acc(routine seq)
137+
nrn_pragma_omp(declare target)
138+
#endif
139+
template <typename T>
140+
EIGEN_DEVICE_FUNC inline int solveCrout(int n,
141+
T const* const a,
142+
T const* const b,
143+
T* const p,
144+
int const* const perm,
145+
int const* const y = nullptr) {
146+
int i, j, pivot;
147+
T sum;
148+
149+
/* Perform forward substitution with pivoting */
150+
if (y) {
151+
for (i = 0; i < n; i++) {
152+
pivot = perm[i];
153+
sum = 0.0;
154+
for (j = 0; j < i; j++)
155+
sum += a[pivot * n + j] * (y_(j));
156+
y_(i) = (b_(pivot) - sum) / a[pivot * n + i];
157+
}
158+
159+
/*
160+
* Note that the y vector is already in the correct order for back
161+
* substitution. Perform back substitution, pivoting the matrix but not
162+
* the y vector. There is no need to divide by the diagonal element as
163+
* this is assumed to be unity.
164+
*/
165+
166+
for (i = n - 1; i >= 0; i--) {
167+
pivot = perm[i];
168+
sum = 0.0;
169+
for (j = i + 1; j < n; j++)
170+
sum += a[pivot * n + j] * (y_(j));
171+
y_(i) -= sum;
172+
}
173+
} else {
174+
for (i = 0; i < n; i++) {
175+
pivot = perm[i];
176+
sum = 0.0;
177+
for (j = 0; j < i; j++)
178+
sum += a[pivot * n + j] * (p[j]);
179+
p[i] = (b_(pivot) - sum) / a[pivot * n + i];
180+
}
181+
182+
/*
183+
* Note that the y vector is already in the correct order for back
184+
* substitution. Perform back substitution, pivoting the matrix but not
185+
* the y vector. There is no need to divide by the diagonal element as
186+
* this is assumed to be unity.
187+
*/
188+
189+
for (i = n - 1; i >= 0; i--) {
190+
pivot = perm[i];
191+
sum = 0.0;
192+
for (j = i + 1; j < n; j++)
193+
sum += a[pivot * n + j] * (p[j]);
194+
p[i] -= sum;
195+
}
196+
}
197+
return 0;
198+
}
199+
#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC)
200+
nrn_pragma_omp(end declare target)
201+
#endif
202+
203+
#undef y_
204+
#undef b_
205+
206+
} // namespace crout
207+
} // namespace nmodl

0 commit comments

Comments
 (0)