Canoe
Comprehensive Atmosphere N' Ocean Engine
forward_backward.hpp
Go to the documentation of this file.
1 #ifndef SRC_SNAP_IMPLICIT_FORWARD_BACKWARD_HPP_
2 #define SRC_SNAP_IMPLICIT_FORWARD_BACKWARD_HPP_
3 
4 // C/C++ headers
5 #include <vector>
6 
7 // Eigen headers
8 #include <Eigen/Core>
9 #include <Eigen/Dense>
10 
11 // Athena++ headers
12 #include "communication.hpp"
13 
14 template <typename T1, typename T2>
15 void ImplicitSolver::ForwardSweep(std::vector<T1> &a, std::vector<T1> &b,
16  std::vector<T1> &c, std::vector<T2> &delta,
17  std::vector<T2> &corr, Real dt, int k, int j,
18  int il, int iu) {
19  T1 phi;
20  T2 rhs;
21 
22  if (T2::RowsAtCompileTime == 3) { // partial matrix
23  rhs(0) = du_(IDN, k, j, il);
24  for (int n = 1; n <= NVAPOR; ++n) rhs(0) += du_(n, k, j, il);
25  rhs(0) /= dt;
26  rhs(1) = du_(IVX + mydir_, k, j, il) / dt;
27  rhs(2) = du_(IEN, k, j, il) / dt;
28  rhs -= corr[il];
29  } else { // full matrix
30  rhs(0) = du_(IDN, k, j, il);
31  for (int n = 1; n <= NVAPOR; ++n) rhs(0) += du_(n, k, j, il);
32  rhs(0) /= dt;
33  rhs(1) = du_(IVX + mydir_, k, j, il) / dt;
34  rhs(2) = du_(IVX + (IVY - IVX + mydir_) % 3, k, j, il) / dt;
35  rhs(3) = du_(IVX + (IVZ - IVX + mydir_) % 3, k, j, il) / dt;
36  rhs(4) = du_(IEN, k, j, il) / dt;
37  // if (pmy_hydro->implicit_done != nullptr) {
38  // pmy_hydro->implicit_done->LoadForcingJacobian(phi,k,j,il,mydir_);
39  // rhs -= dt*phi*rhs;
40  // }
41  }
42 
43  if (!first_block) {
44  RecvBuffer(a[il - 1], delta[il - 1], k, j, bblock);
45  a[il] = (a[il] - b[il] * a[il - 1]).inverse().eval();
46  delta[il] = a[il] * (rhs - b[il] * delta[il - 1]);
47  a[il] *= c[il];
48  } else {
49  a[il] = a[il].inverse().eval();
50  delta[il] = a[il] * rhs;
51  a[il] *= c[il];
52  }
53 
54  for (int i = il + 1; i <= iu; ++i) {
55  if (T2::RowsAtCompileTime == 3) { // partial matrix
56  rhs(0) = du_(IDN, k, j, i);
57  for (int n = 1; n <= NVAPOR; ++n) rhs(0) += du_(n, k, j, i);
58  rhs(0) /= dt;
59  rhs(1) = du_(IVX + mydir_, k, j, i) / dt;
60  rhs(2) = du_(IEN, k, j, i) / dt;
61  rhs -= corr[i];
62  } else {
63  rhs(0) = du_(IDN, k, j, i);
64  for (int n = 1; n <= NVAPOR; ++n) rhs(0) += du_(n, k, j, i);
65  rhs(0) /= dt;
66  rhs(1) = du_(IVX + mydir_, k, j, i) / dt;
67  rhs(2) = du_(IVX + (IVY - IVX + mydir_) % 3, k, j, i) / dt;
68  rhs(3) = du_(IVX + (IVZ - IVX + mydir_) % 3, k, j, i) / dt;
69  rhs(4) = du_(IEN, k, j, i) / dt;
70  // if (pmy_hydro->implicit_done != nullptr) {
71  // pmy_hydro->implicit_done->LoadForcingJacobian(phi,k,j,i,mydir_);
72  // rhs -= dt*phi*rhs;
73  // }
74  }
75 
76  a[i] = (a[i] - b[i] * a[i - 1]).inverse().eval();
77  delta[i] = a[i] * (rhs - b[i] * delta[i - 1]);
78  a[i] *= c[i];
79  }
80 
81  SaveCoefficients(a, delta, k, j, il, iu);
82 
83  if (!last_block) SendBuffer(a[iu], delta[iu], k, j, tblock);
84 }
85 
86 template <typename T1, typename T2>
88  std::vector<T2> &delta, int kl,
89  int ku, int jl, int ju, int il,
90  int iu) {
91  for (int k = kl; k <= ku; ++k)
92  for (int j = jl; j <= ju; ++j) {
93  LoadCoefficients(a, delta, k, j, il, iu);
94  if (!last_block) {
95  RecvBuffer(delta[iu + 1], k, j, tblock);
96  delta[iu] -= a[iu] * delta[iu + 1];
97  }
98 
99  // update solutions, i=iu
100  for (int i = iu - 1; i >= il; --i) delta[i] -= a[i] * delta[i + 1];
101 
102  // 7. update conserved variables, i = iu
103  for (int i = il; i <= iu; ++i) {
104  if (T2::RowsAtCompileTime == 3) { // partial matrix
105  du_(IDN, k, j, i) = delta[i](0);
106  du_(IVX + mydir_, k, j, i) = delta[i](1);
107  du_(IEN, k, j, i) = delta[i](2);
108  } else { // full matrix
109  du_(IDN, k, j, i) = delta[i](0);
110  du_(IVX + mydir_, k, j, i) = delta[i](1);
111  du_(IVX + (IVY - IVX + mydir_) % 3, k, j, i) = delta[i](2);
112  du_(IVX + (IVZ - IVX + mydir_) % 3, k, j, i) = delta[i](3);
113  du_(IEN, k, j, i) = delta[i](4);
114  }
115  for (int n = 1; n <= NVAPOR; ++n) du_(IDN, k, j, i) -= du_(n, k, j, i);
116  }
117 
118  if (!first_block) SendBuffer(delta[il], k, j, bblock);
119  }
120 
121 #ifdef MPI_PARALLEL
122  MPI_Status status;
123 
124  if (!last_block && (tblock.snb.rank != Globals::my_rank)) {
125  for (int k = kl; k <= ku; ++k)
126  for (int j = jl; j <= ju; ++j) MPI_Wait(&req_send_data2_[k][j], &status);
127  }
128 
129  if (!first_block && (bblock.snb.rank != Globals::my_rank)) {
130  for (int k = kl; k <= ku; ++k)
131  for (int j = jl; j <= ju; ++j) MPI_Wait(&req_send_data1_[k][j], &status);
132  }
133 #endif
134 }
135 
136 #endif // SRC_SNAP_IMPLICIT_FORWARD_BACKWARD_HPP_
void ForwardSweep(std::vector< T1 > &a, std::vector< T1 > &b, std::vector< T1 > &c, std::vector< T2 > &delta, std::vector< T2 > &corr, Real dt, int k, int j, int il, int iu)
NeighborBlock bblock
void RecvBuffer(T &a, int k, int j, NeighborBlock nb)
NeighborBlock tblock
CoordinateDirection mydir_
void BackwardSubstitution(std::vector< T1 > &a, std::vector< T2 > &delta, int kl, int ku, int jl, int ju, int il, int iu)
void LoadCoefficients(std::vector< T1 > &a, std::vector< T2 > &b, int k, int j, int il, int iu)
AthenaArray< Real > du_
void SaveCoefficients(std::vector< T1 > &a, std::vector< T2 > &b, int k, int j, int il, int iu)
void SendBuffer(T const &a, int k, int j, NeighborBlock nb)