1 #include <../../nrnconf.h>
9 #define DcX(x, y, z) (g->dc_x * PERM(x, y, z))
10 #define DcY(x, y, z) (g->dc_y * PERM(x, y, z))
11 #define DcZ(x, y, z) (g->dc_z * PERM(x, y, z))
16 (ALPHA(x1, y, z) * ALPHA(x2, y, z) * DcX(x1, y, z) * \
17 (g->states[IDX(x1, y, z)] - g->states[IDX(x2, y, z)]) / \
18 ((ALPHA(x1, y, z) + ALPHA(x2, y, z))))
19 #define Fxy(y1, y1d, y2) \
20 (ALPHA(x, y1, z) * ALPHA(x, y2, z) * DcY(x, y1d, z) * \
21 (g->states[IDX(x, y1, z)] - g->states[IDX(x, y2, z)]) / \
22 ((ALPHA(x, y1, z) + ALPHA(x, y2, z))))
23 #define Fxz(z1, z1d, z2) \
24 (ALPHA(x, y, z1) * ALPHA(x, y, z2) * DcZ(x, y, z1d) * \
25 (g->states[IDX(x, y, z1)] - g->states[IDX(x, y, z2)]) / \
26 ((ALPHA(x, y, z1) + ALPHA(x, y, z2))))
28 (ALPHA(x, y1, z) * ALPHA(x, y2, z) * DcY(x, y1, z) * \
29 (g->states[IDX(x, y1, z)] - g->states[IDX(x, y2, z)]) / \
30 ((ALPHA(x, y1, z) + ALPHA(x, y2, z))))
32 (ALPHA(x, y, z1) * ALPHA(x, y, z2) * DcZ(x, y, z1) * \
33 (g->states[IDX(x, y, z1)] - g->states[IDX(x, y, z2)]) / \
34 ((ALPHA(x, y, z1) + ALPHA(x, y, z2))))
37 #define FLUX(pidx, idx) \
38 (VOLFRAC(pidx) * VOLFRAC(idx) * (states[pidx] - states[idx])) / \
39 (0.5 * (VOLFRAC(pidx) + VOLFRAC(idx)))
60 c[0] = u_diag[0] /
diag[0];
61 b[0] = b[0] /
diag[0];
63 for (
i = 1;
i < N - 1;
i++) {
64 c[
i] = u_diag[
i] / (
diag[
i] - l_diag[
i - 1] *
c[
i - 1]);
65 b[
i] = (b[
i] - l_diag[
i - 1] * b[
i - 1]) / (
diag[
i] - l_diag[
i - 1] *
c[
i - 1]);
67 b[N - 1] = (b[N - 1] - l_diag[N - 2] * b[N - 2]) / (
diag[N - 1] - l_diag[N - 2] *
c[N - 2]);
71 for (
i = N - 2;
i >= 0;
i--) {
72 b[
i] = b[
i] -
c[
i] * b[
i + 1];
92 double const*
const state,
94 double*
const scratch) {
95 int yp, ypd, ym, ymd, zp, zpd, zm, zmd;
104 (y == 0 || z == 0 || y == g->
size_y - 1 || z == g->
size_z - 1)) {
105 for (x = 0; x < g->
size_x; x++)
111 div_y = ((y == 0 || y == g->
size_y - 1) ? 1.0 : 0.5) *
SQ(g->
dy);
112 div_z = ((z == 0 || z == g->
size_z - 1) ? 1.0 : 0.5) *
SQ(g->
dz);
119 yp = (y == g->
size_y - 1) ? y - 1 : y + 1;
120 ypd = (y == g->
size_y - 1) ? y : y + 1;
121 ym = (y == 0) ? y + 1 : y - 1;
122 ymd = (y == 0) ? 1 : y;
130 zp = (z == g->
size_z - 1) ? z - 1 : z + 1;
131 zpd = (z == g->
size_z - 1) ? z : z + 1;
132 zm = (z == 0) ? z + 1 : z - 1;
133 zmd = (z == 0) ? 1 : z;
143 RHS[0] += (
Fxy(yp, ypd, y) -
Fxy(y, ymd, ym)) / div_y;
145 RHS[0] += (
Fxz(zp, zpd, z) -
Fxz(z, zmd, zm)) / div_z;
153 diag = (
double*) malloc(g->
size_x *
sizeof(
double));
154 l_diag = (
double*) malloc((g->
size_x - 1) *
sizeof(double));
155 u_diag = (
double*) malloc((g->
size_x - 1) *
sizeof(double));
157 for (x = 1; x < g->
size_x - 1; x++) {
179 RHS[x] = state[
IDX(x, y, z)] +
181 ((
Fxx(x + 1, x) /
SQ(g->
dx)) + (
Fxy(yp, ypd, y) -
Fxy(y, ymd, ym)) / div_y +
182 (
Fxz(zp, zpd, z) -
Fxz(z, zmd, zm)) / div_z) +
186 RHS[x] = state[
IDX(x, y, z)] +
188 ((
Fxx(x - 1, x)) /
SQ(g->
dx) + (
Fxy(yp, ypd, y) -
Fxy(y, ymd, ym)) / div_y +
189 (
Fxz(zp, zpd, z) -
Fxz(z, zmd, zm)) / div_z) +
195 l_diag[g->
size_x - 2] = 0;
200 for (x = 1; x < g->
size_x - 1; x++) {
202 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, y, z)]), 0, 1);
203 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, yp, z)]), 0, 0);
204 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, ym, z)]), 0, 0);
205 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, ypd, z)]), 0, 0);
206 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, ymd, z)]), 0, 0);
208 RHS[x] = state[
IDX(x, y, z)] +
210 (
Fxy(yp, ypd, y) -
Fxy(y, ymd, ym)) / div_y +
211 (
Fxz(zp, zpd, z) -
Fxz(z, zmd, zm)) / div_z) +
236 double const*
const state,
238 double*
const scratch) {
247 (x == 0 || z == 0 || x == g->
size_x - 1 || z == g->
size_z - 1)) {
248 for (y = 0; y < g->
size_y; y++)
262 diag = (
double*) malloc(g->
size_y *
sizeof(
double));
263 l_diag = (
double*) malloc((g->
size_y - 1) *
sizeof(double));
264 u_diag = (
double*) malloc((g->
size_y - 1) *
sizeof(double));
266 for (y = 1; y < g->
size_y - 1; y++) {
296 l_diag[g->
size_y - 2] = 0;
300 for (y = 1; y < g->
size_y - 1; y++) {
330 double const*
const state,
332 double*
const scratch) {
341 (x == 0 || y == 0 || x == g->
size_x - 1 || y == g->
size_y - 1)) {
342 for (z = 0; z < g->
size_z; z++)
355 diag = (
double*) malloc(g->
size_z *
sizeof(
double));
356 l_diag = (
double*) malloc((g->
size_z - 1) *
sizeof(double));
357 u_diag = (
double*) malloc((g->
size_z - 1) *
sizeof(double));
359 for (z = 1; z < g->
size_z - 1; z++) {
389 l_diag[g->
size_z - 2] = 0;
393 for (z = 1; z < g->
size_z - 1; z++) {
431 double const*
const state,
433 double*
const scratch) {
434 int yp, ypd, ym, ymd, zp, zpd, zm, zmd, div_y, div_z;
441 (y == 0 || z == 0 || y == g->
size_y - 1 || z == g->
size_z - 1)) {
442 for (x = 0; x < g->
size_x; x++)
448 div_y = (y == 0 || y == g->
size_y - 1) ? 2 : 1;
449 div_z = (z == 0 || z == g->
size_z - 1) ? 2 : 1;
456 yp = (y == g->
size_y - 1) ? y - 1 : y + 1;
457 ypd = (y == g->
size_y - 1) ? y : y + 1;
458 ym = (y == 0) ? y + 1 : y - 1;
459 ymd = (y == 0) ? 1 : y;
467 zp = (z == g->
size_z - 1) ? z - 1 : z + 1;
468 zpd = (z == g->
size_z - 1) ? z : z + 1;
469 zm = (z == 0) ? z + 1 : z - 1;
470 zmd = (z == 0) ? 1 : z;
479 RHS[0] += (
DcY(0, ypd, z) * state[
IDX(0, yp, z)] -
480 (
DcY(0, ypd, z) +
DcY(0, ymd, z)) * state[
IDX(0, y, z)] +
481 DcY(0, ymd, z) * state[
IDX(0, ym, z)]) /
484 RHS[0] += (
DcZ(0, y, zpd) * state[
IDX(0, y, zp)] -
485 (
DcZ(0, y, zpd) +
DcZ(0, y, zmd)) * state[
IDX(0, y, z)] +
486 DcZ(0, y, zmd) * state[
IDX(0, y, zm)]) /
494 diag = (
double*) malloc(g->
size_x *
sizeof(
double));
495 l_diag = (
double*) malloc((g->
size_x - 1) *
sizeof(double));
496 u_diag = (
double*) malloc((g->
size_x - 1) *
sizeof(double));
498 for (x = 1; x < g->
size_x - 1; x++) {
499 l_diag[x - 1] = -
dt *
DcX(x, y, z) / (2. *
SQ(g->
dx));
501 u_diag[x] = -
dt *
DcX(x + 1, y, z) / (2. *
SQ(g->
dx));
507 u_diag[0] = -0.5 *
dt *
DcX(1, y, z) /
SQ(g->
dx);
512 RHS[0] = state[
IDX(0, y, z)] +
513 dt * ((
DcX(1, y, z) * state[
IDX(1, y, z)] -
DcX(1, y, z) * state[
IDX(0, y, z)]) /
515 (
DcY(0, ypd, z) * state[
IDX(0, yp, z)] -
516 (
DcY(0, ypd, z) +
DcY(0, ymd, z)) * state[
IDX(0, y, z)] +
517 DcY(0, ymd, z) * state[
IDX(0, ym, z)]) /
518 (div_y *
SQ(g->
dy)) +
519 (
DcZ(0, y, zpd) * state[
IDX(0, y, zp)] -
520 (
DcZ(0, y, zpd) +
DcZ(0, y, zmd)) * state[
IDX(0, y, z)] +
521 DcZ(0, y, zmd) * state[
IDX(0, y, zm)]) /
522 (div_z *
SQ(g->
dz))) +
526 state[
IDX(x, y, z)] +
527 dt * ((
DcX(x, y, z) * state[
IDX(x - 1, y, z)] -
DcX(x, y, z) * state[
IDX(x, y, z)]) /
529 (
DcY(x, ypd, z) * state[
IDX(x, yp, z)] -
530 (
DcY(x, ypd, z) +
DcY(x, ymd, z)) * state[
IDX(x, y, z)] +
531 DcY(x, ymd, z) * state[
IDX(x, ym, z)]) /
532 (div_y *
SQ(g->
dy)) +
533 (
DcZ(x, y, zpd) * state[
IDX(x, y, zp)] -
534 (
DcZ(x, y, zpd) +
DcZ(x, y, zmd)) * state[
IDX(x, y, z)] +
535 DcZ(x, y, zmd) * state[
IDX(x, y, zm)]) /
536 (div_z *
SQ(g->
dz))) +
543 l_diag[g->
size_x - 2] = 0.0;
548 for (x = 1; x < g->
size_x - 1; x++) {
550 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, y, z)]), 0, 1);
551 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, yp, z)]), 0, 0);
552 __builtin_prefetch(&(state[
IDX(x +
PREFETCH, ym, z)]), 0, 0);
555 RHS[x] = state[
IDX(x, y, z)] +
556 dt * ((
DcX(x + 1, y, z) * state[
IDX(x + 1, y, z)] -
557 (
DcX(x + 1, y, z) +
DcX(x, y, z)) * state[
IDX(x, y, z)] +
558 DcX(x, y, z) * state[
IDX(x - 1, y, z)]) /
560 (
DcY(x, ypd, z) * state[
IDX(x, yp, z)] -
561 (
DcY(x, ypd, z) +
DcY(x, ymd, z)) * state[
IDX(x, y, z)] +
562 DcY(x, ymd, z) * state[
IDX(x, ym, z)]) /
563 (div_y *
SQ(g->
dy)) +
564 (
DcZ(x, y, zpd) * state[
IDX(x, y, zp)] -
565 (
DcZ(x, y, zpd) +
DcZ(x, y, zmd)) * state[
IDX(x, y, z)] +
566 DcZ(x, y, zmd) * state[
IDX(x, y, zm)]) /
567 (div_z *
SQ(g->
dz))) +
593 double const*
const state,
595 double*
const scratch) {
603 (x == 0 || z == 0 || x == g->
size_x - 1 || z == g->
size_z - 1)) {
604 for (y = 0; y < g->
size_y; y++)
618 diag = (
double*) malloc(g->
size_y *
sizeof(
double));
619 l_diag = (
double*) malloc((g->
size_y - 1) *
sizeof(double));
620 u_diag = (
double*) malloc((g->
size_y - 1) *
sizeof(double));
622 for (y = 1; y < g->
size_y - 1; y++) {
623 l_diag[y - 1] = -
dt *
DcY(x, y, z) / (2. *
SQ(g->
dy));
625 u_diag[y] = -
dt *
DcY(x, y + 1, z) / (2. *
SQ(g->
dy));
631 u_diag[0] = -0.5 *
dt *
DcY(x, 1, z) /
SQ(g->
dy);
649 l_diag[g->
size_y - 2] = 0.0;
655 for (y = 1; y < g->
size_y - 1; y++) {
689 double const*
const state,
691 double*
const scratch) {
699 (x == 0 || y == 0 || x == g->
size_x - 1 || y == g->
size_y - 1)) {
700 for (z = 0; z < g->
size_z; z++)
713 diag = (
double*) malloc(g->
size_z *
sizeof(
double));
714 l_diag = (
double*) malloc((g->
size_z - 1) *
sizeof(double));
715 u_diag = (
double*) malloc((g->
size_z - 1) *
sizeof(double));
718 for (z = 1; z < g->
size_z - 1; z++) {
719 l_diag[z - 1] = -
dt *
DcZ(x, y, z) / (2. *
SQ(g->
dz));
721 u_diag[z] = -
dt *
DcZ(x, y, z + 1) / (2. *
SQ(g->
dz));
727 u_diag[0] = -0.5 *
dt *
DcZ(x, y, 1) /
SQ(g->
dz);
745 l_diag[g->
size_z - 2] = 0.0;
751 for (z = 1; z < g->
size_z - 1; z++) {
787 double dx = g->
dx, dy = g->
dy, dz = g->
dz;
788 int i,
j,
k, stop_i, stop_j, stop_k;
789 double rate_x = 1. / (dx * dx);
790 double rate_y = 1. / (dy * dy);
791 double rate_z = 1. / (dz * dz);
794 int index, prev_i, prev_j, prev_k, next_i, next_j, next_k;
795 int xpd, xmd, ypd, ymd, zpd, zmd;
796 double div_x, div_y, div_z;
799 stop_i = num_states_x - 1;
800 stop_j = num_states_y - 1;
801 stop_k = num_states_z - 1;
805 prev_i = num_states_y * num_states_z,
806 next_i = num_states_y * num_states_z;
810 div_x = (
i == 0 ||
i == stop_i) ? 2. : 1.;
811 xpd = (
i == stop_i) ?
i :
i + 1;
812 xmd = (
i == 0) ? 1 :
i;
814 for (
j = 0, prev_j =
index + num_states_z, next_j =
index + num_states_z;
817 div_y = (
j == 0 ||
j == stop_j) ? 2. : 1.;
818 ypd = (
j == stop_j) ?
j :
j + 1;
819 ymd = (
j == 0) ? 1 :
j;
821 for (
k = 0, prev_k =
index + 1, next_k =
index + 1;
k < num_states_z;
822 k++,
index++, prev_i++, next_i++, prev_j++, next_j++) {
823 div_z = (
k == 0 ||
k == stop_k) ? 2. : 1.;
824 zpd = (
k == stop_k) ?
k :
k + 1;
825 zmd = (
k == 0) ? 1 :
k;
828 ydot[
index] += rate_x *
835 ydot[
index] += rate_y *
843 ydot[
index] += rate_z *
853 prev_j =
index - num_states_z;
854 next_j = (
j == stop_j - 1) ? prev_j :
index + num_states_z;
856 prev_i =
index - num_states_y * num_states_z;
857 next_i = (
i == stop_i - 1) ? prev_i :
index + num_states_y * num_states_z;
860 for (
i = 0,
index = 0, prev_i = 0, next_i = num_states_y * num_states_z;
i < num_states_x;
862 for (
j = 0, prev_j =
index - num_states_z, next_j =
index + num_states_z;
865 for (
k = 0, prev_k =
index - 1, next_k =
index + 1;
k < num_states_z;
866 k++,
index++, prev_i++, next_i++, prev_j++, next_j++, next_k++, prev_k++) {
867 if (
i == 0 ||
i == stop_i ||
j == 0 ||
j == stop_j ||
k == 0 ||
k == stop_k) {
884 prev_j =
index - num_states_z;
885 next_j =
index + num_states_z;
887 prev_i =
index - num_states_y * num_states_z;
888 next_i =
index + num_states_y * num_states_z;
896 double dx = g->
dx, dy = g->
dy, dz = g->
dz;
897 int i,
j,
k, stop_i, stop_j, stop_k;
898 double rate_x = g->
dc_x / (dx * dx);
899 double rate_y = g->
dc_y / (dy * dy);
900 double rate_z = g->
dc_z / (dz * dz);
904 int index, prev_i, prev_j, prev_k, next_i, next_j, next_k;
907 int xpd, xmd, ypd, ymd, zpd, zmd;
908 double div_x, div_y, div_z;
911 stop_i = num_states_x - 1;
912 stop_j = num_states_y - 1;
913 stop_k = num_states_z - 1;
917 prev_i = num_states_y * num_states_z,
918 next_i = num_states_y * num_states_z;
922 div_x = (
i == 0 ||
i == stop_i) ? 2. : 1.;
923 xpd = (
i == stop_i) ?
i :
i + 1;
924 xmd = (
i == 0) ? 1 :
i;
926 for (
j = 0, prev_j =
index + num_states_z, next_j =
index + num_states_z;
929 div_y = (
j == 0 ||
j == stop_j) ? 2. : 1.;
930 ypd = (
j == stop_j) ?
j :
j + 1;
931 ymd = (
j == 0) ? 1 :
j;
933 for (
k = 0, prev_k =
index + 1, next_k =
index + 1;
k < num_states_z;
934 k++,
index++, prev_i++, next_i++, prev_j++, next_j++) {
935 div_z = (
k == 0 ||
k == stop_k) ? 2. : 1.;
936 zpd = (
k == stop_k) ?
k :
k + 1;
937 zmd = (
k == 0) ? 1 :
k;
941 ydot[
index] += rate_x *
949 ydot[
index] += rate_y *
957 ydot[
index] += rate_z *
966 prev_j =
index - num_states_z;
967 next_j = (
j == stop_j - 1) ? prev_j :
index + num_states_z;
969 prev_i =
index - num_states_y * num_states_z;
970 next_i = (
i == stop_i - 1) ? prev_i :
index + num_states_y * num_states_z;
973 for (
i = 0,
index = 0, prev_i = 0, next_i = num_states_y * num_states_z;
i < num_states_x;
975 for (
j = 0, prev_j =
index - num_states_z, next_j =
index + num_states_z;
978 for (
k = 0, prev_k =
index - 1, next_k =
index + 1;
k < num_states_z;
979 k++,
index++, prev_i++, next_i++, prev_j++, next_j++, next_k++, prev_k++) {
980 if (
i == 0 ||
i == stop_i ||
j == 0 ||
j == stop_j ||
k == 0 ||
k == stop_k) {
985 ydot[
index] += rate_x *
991 ydot[
index] += rate_y *
997 ydot[
index] += rate_z *
1003 prev_j =
index - num_states_z;
1004 next_j =
index + num_states_z;
1006 prev_i =
index - num_states_y * num_states_z;
1007 next_i =
index + num_states_y * num_states_z;
struct ECSAdiDirection * ecs_adi_dir_z
struct ECSAdiDirection * ecs_adi_dir_y
struct ECSAdiDirection * ecs_adi_dir_x
static void ecs_dg_adi_vol_y(ECS_Grid_node *g, double const dt, int const x, int const z, double const *const state, double *const RHS, double *const scratch)
static void ecs_dg_adi_vol_x(ECS_Grid_node *g, const double dt, const int y, const int z, double const *const state, double *const RHS, double *const scratch)
void ecs_set_adi_tort(ECS_Grid_node *g)
static int solve_dd_tridiag(int N, const double *l_diag, const double *diag, const double *u_diag, double *b, double *c)
void _rhs_variable_step_helper_tort(Grid_node *g, double const *const states, double *ydot)
static void ecs_dg_adi_tort_z(ECS_Grid_node *g, double const dt, int const x, int const y, double const *const state, double *const RHS, double *const scratch)
void _rhs_variable_step_helper_vol(Grid_node *g, double const *const states, double *ydot)
static void ecs_dg_adi_tort_x(ECS_Grid_node *g, const double dt, const int y, const int z, double const *const state, double *const RHS, double *const scratch)
static void ecs_dg_adi_vol_z(ECS_Grid_node *g, double const dt, int const x, int const y, double const *const state, double *const RHS, double *const scratch)
void ecs_set_adi_vol(ECS_Grid_node *g)
static void ecs_dg_adi_tort_y(ECS_Grid_node *g, double const dt, int const x, int const z, double const *const state, double *const RHS, double *const scratch)
void(* ecs_dg_adi_dir)(ECS_Grid_node *, const double, const int, const int, double const *const, double *const, double *const)