Canoe
Comprehensive Atmosphere N' Ocean Engine
change_to_entropy.cpp
Go to the documentation of this file.
1 // C/C++ headers
2 #include <iomanip>
3 #include <sstream>
4 
5 // Athena++ headers
6 #include <athena/coordinates/coordinates.hpp>
7 #include <athena/eos/eos.hpp>
8 #include <athena/hydro/hydro.hpp>
9 
10 // utils
11 #include <utils/ndarrays.hpp>
12 
13 // canoe
14 #include <impl.hpp>
15 
16 // snap
17 #include "../thermodynamics/thermodynamics.hpp"
18 #include "decomposition.hpp"
19 
21  Coordinates *pco, Real grav, int kl, int ku,
22  int jl, int ju, int il, int iu) {
23  for (int k = kl; k <= ku; ++k)
24  for (int j = jl; j <= ju; ++j)
25  for (int i = il; i <= iu; ++i)
26  psf(k, j, i + 1) = psf(k, j, i) + grav * w(IDN, k, j, i) * pco->dx1f(i);
27 }
28 
30  AthenaArray<Real> const &w, Coordinates *pco,
31  Real grav, int kl, int ku, int jl, int ju,
32  int il, int iu) {
33  for (int k = kl; k <= ku; ++k)
34  for (int j = jl; j <= ju; ++j)
35  for (int i = iu; i >= il; --i)
36  psf(k, j, i) = psf(k, j, i + 1) - grav * w(IDN, k, j, i) * pco->dx1f(i);
37 }
38 
40  int jl, int ju) {
41  MeshBlock *pmb = pmy_block_;
42  Coordinates *pco = pmb->pcoord;
43  auto pthermo = Thermodynamics::GetInstance();
44 
45  // positive in the x-increasing direction
46  Real grav = pmb->phydro->hsrc.GetG1();
47  Real gamma = pmb->peos->GetGamma();
48  Real Rd = pthermo->GetRd();
49 
50  int is = pmb->is, ie = pmb->ie;
51  if (grav == 0.) return;
52 
53  FindNeighbors();
54 
55  if (has_top_neighbor) {
56  RecvFromTop(psf_, kl, ku, jl, ju);
57  } else {
58  // isothermal extrapolation to find the pressure at top boundary
59  for (int k = kl; k <= ku; ++k)
60  for (int j = jl; j <= ju; ++j) {
61  Real RdTv = w(IPR, k, j, ie) / w(IDN, k, j, ie);
62  psf_(k, j, ie + 1) =
63  w(IPR, k, j, ie) * exp(grav * pco->dx1f(ie) / (2 * RdTv));
64  }
65  }
66  IntegrateDownwards(psf_, w, pco, grav, kl, ku, jl, ju, is, ie);
67 
68  // populate ghost cells
69  if (has_bot_neighbor) SendToBottom(psf_, kl, ku, jl, ju);
70 
71  // boundary condition
72  if (pmb->pbval->block_bcs[inner_x1] == BoundaryFlag::reflect) {
73  IntegrateDownwards(psf_, w, pco, -grav, kl, ku, jl, ju, is - NGHOST,
74  is - 1);
75  } else { // block boundary
76  IntegrateDownwards(psf_, w, pco, grav, kl, ku, jl, ju, is - NGHOST, is - 1);
77  }
78 
79  if (pmb->pbval->block_bcs[outer_x1] == BoundaryFlag::reflect) {
80  IntegrateUpwards(psf_, w, pco, -grav, kl, ku, jl, ju, ie + 1, ie + NGHOST);
81  } else { // block boundary
82  IntegrateUpwards(psf_, w, pco, grav, kl, ku, jl, ju, ie + 1, ie + NGHOST);
83  }
84 
85  // decompose pressure and density
86  for (int k = kl; k <= ku; ++k)
87  for (int j = jl; j <= ju; ++j) {
88  // 1. change density and pressure (including ghost cells)
89  for (int i = is - NGHOST; i <= ie + NGHOST; ++i) {
90  // interpolate hydrostatic pressure, prevent divided by zero
91  if (fabs(psf_(k, j, i) - psf_(k, j, i + 1)) < 1.E-6)
92  psv_(k, j, i) = 0.5 * (psf_(k, j, i) + psf_(k, j, i + 1));
93  else
94  psv_(k, j, i) = (psf_(k, j, i) - psf_(k, j, i + 1)) /
95  log(psf_(k, j, i) / psf_(k, j, i + 1));
96 
97  // calculate local polytropic index
98  Real fsig = 1., feps = 1.;
99  for (int n = 1; n <= NVAPOR; ++n) {
100  fsig += w(n, k, j, i) * (pthermo->GetCvRatioMass(n) - 1.);
101  feps += w(n, k, j, i) * (1. / pthermo->GetMuRatio(n) - 1.);
102  }
103  gamma_(k, j, i) = 1. + (gamma - 1.) * feps / fsig;
104 
105  // change density to entropy
106  w(IDN, k, j, i) =
107  log(w(IPR, k, j, i)) - gamma_(k, j, i) * log(w(IDN, k, j, i));
108 
109  // change pressure to pertubation
110  w(IPR, k, j, i) -= psv_(k, j, i);
111  }
112 
113  // 2. adjust bottom boundary condition
114  if (pmb->pbval->block_bcs[inner_x1] == BoundaryFlag::outflow) {
115  for (int i = is - NGHOST; i < is; ++i) {
116  w(IDN, k, j, i) = w(IDN, k, j, is);
117  w(IPR, k, j, i) = w(IPR, k, j, is);
118  }
119  }
120 
121  // 3. adjust top boundary condition
122  if (pmb->pbval->block_bcs[outer_x1] == BoundaryFlag::outflow) {
123  for (int i = ie + 1; i <= ie + NGHOST; ++i) {
124  w(IDN, k, j, i) = w(IDN, k, j, ie);
125  w(IPR, k, j, i) = w(IPR, k, j, ie);
126  }
127  }
128  }
129 
130  // finish send top pressure
131 #ifdef MPI_PARALLEL
132  MPI_Status status;
133  if (has_bot_neighbor && (bblock.snb.rank != Globals::my_rank))
134  MPI_Wait(&req_send_bot_, &status);
135 #endif
136 }
137 
139  AthenaArray<Real> &wl,
140  AthenaArray<Real> &wr, int k, int j,
141  int il, int iu) {
142  MeshBlock *pmb = pmy_block_;
143  Hydro *phydro = pmb->phydro;
144  auto pthermo = Thermodynamics::GetInstance();
145 
146  Real Rd = pthermo->GetRd();
147  Real grav = phydro->hsrc.GetG1();
148  int is = pmb->is, ie = pmb->ie;
149  if (grav == 0.) return;
150 
151  for (int i = is - NGHOST; i <= ie + NGHOST; ++i) {
152  w(IPR, k, j, i) += psv_(k, j, i);
153  w(IDN, k, j, i) =
154  exp((log(w(IPR, k, j, i)) - w(IDN, k, j, i)) / gamma_(k, j, i));
155  }
156 
157  for (int i = il; i <= iu; ++i) {
158  wr(IPR, i) += psf_(k, j, i);
159  if (wr(IPR, i) < 0.) wr(IPR, i) = psf_(k, j, i);
160 
161  wl(IPR, i) += psf_(k, j, i);
162  if (wl(IPR, i) < 0.) wl(IPR, i) = psf_(k, j, i);
163 
164  wl(IDN, i) = exp((log(wl(IPR, i)) - wl(IDN, i)) / gamma_(k, j, i - 1));
165  wr(IDN, i) = exp((log(wr(IPR, i)) - wr(IDN, i)) / gamma_(k, j, i));
166  }
167 }
void IntegrateDownwards(AthenaArray< Real > &psf, AthenaArray< Real > const &w, Coordinates *pco, Real grav, int kl, int ku, int jl, int ju, int il, int iu)
void IntegrateUpwards(AthenaArray< Real > &psf, AthenaArray< Real > const &w, Coordinates *pco, Real grav, int kl, int ku, int jl, int ju, int il, int iu)
AthenaArray< Real > psf_
AthenaArray< Real > gamma_
MeshBlock * pmy_block_
void ChangeToEntropy(AthenaArray< Real > &w, int kl, int ku, int jl, int ju)
void RecvFromTop(AthenaArray< Real > &psf, int kl, int ku, int jl, int ju)
NeighborBlock bblock
AthenaArray< Real > psv_
void RestoreFromEntropy(AthenaArray< Real > &w, AthenaArray< Real > &wl, AthenaArray< Real > &wr, int k, int j, int il, int iu)
void FindNeighbors()
void SendToBottom(AthenaArray< Real > const &psf, int kl, int ku, int jl, int ju)
static Thermodynamics const * GetInstance()
Return a pointer to the one and only instance of Thermodynamics.
Real Rd
Definition: straka.cpp:66