Canoe
Comprehensive Atmosphere N' Ocean Engine
change_to_perturbation.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/hydro/hydro.hpp>
8 #include <athena/stride_iterator.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  // Need to integrate upwards
42  MeshBlock *pmb = pmy_block_;
43  Coordinates *pco = pmb->pcoord;
44 
45  Real grav = -pmb->phydro->hsrc.GetG1(); // positive downward pointing
47  int is = pmb->is, ie = pmb->ie;
48  if (grav == 0.) return;
49 
50  std::stringstream msg;
51  if (NGHOST < 3) {
52  msg << "### FATAL ERROR in function [Hydro::DecomposePressure]" << std::endl
53  << "number of ghost cells (NGHOST) must be at least 3" << std::endl;
54  ATHENA_ERROR(msg);
55  }
56 
57  FindNeighbors();
58 
59  if (!has_top_neighbor) {
60  // isothermal extrapolation
61  for (int k = kl; k <= ku; ++k)
62  for (int j = jl; j <= ju; ++j) {
63  Real RdTv = w(IPR, k, j, ie) / w(IDN, k, j, ie);
64  psf_(k, j, ie + 1) =
65  w(IPR, k, j, ie) * exp(-grav * pco->dx1f(ie) / (2 * RdTv));
66  }
67  } else {
68  RecvBuffer(psf_, kl, ku, jl, ju, ie + 1, ie + NGHOST + 1, tblock);
69  }
70  IntegrateDownwards(psf_, w, pco, grav, kl, ku, jl, ju, is, ie);
71 
72  // populate ghost cells
73  SendBuffer(psf_, kl, ku, jl, ju);
74 
75  // boundary condition
76  if (pmb->pbval->block_bcs[inner_x1] == BoundaryFlag::reflect) {
77  for (int k = kl; k <= ku; ++k)
78  for (int j = jl; j <= ju; ++j)
79  for (int i = 1; i <= NGHOST; ++i)
80  psf_(k, j, is - i) = psf_(k, j, is + i);
81  } else if (pmb->pbval->block_bcs[inner_x1] == BoundaryFlag::outflow) {
82  IntegrateDownwards(psf_, w, pco, 0., kl, ku, jl, ju, is - NGHOST, is - 1);
83  }
84 
85  if (pmb->pbval->block_bcs[outer_x1] == BoundaryFlag::reflect) {
86  for (int k = kl; k <= ku; ++k)
87  for (int j = jl; j <= ju; ++j)
88  for (int i = 1; i <= NGHOST; ++i)
89  psf_(k, j, ie + i + 1) = psf_(k, j, ie + 1 - i);
90  } else if (pmb->pbval->block_bcs[outer_x1] == BoundaryFlag::outflow) {
91  IntegrateUpwards(psf_, w, pco, 0., kl, ku, jl, ju, ie + 1, ie + NGHOST);
92  }
93 
94  if (has_bot_neighbor)
95  RecvBuffer(psf_, kl, ku, jl, ju, is - NGHOST, is, bblock);
96 
97  // decompose pressure and density
98  PopulateBotEntropy(w, kl, ku, jl, ju);
99  for (int k = kl; k <= ku; ++k)
100  for (int j = jl; j <= ju; ++j) {
101  // 1. change density and pressure (including ghost cells)
102  for (int i = is - NGHOST; i <= ie + NGHOST; ++i) {
103  // save pressure and density
104  pres_(k, j, i) = w(IPR, k, j, i);
105  dens_(k, j, i) = w(IDN, k, j, i);
106 
107  // interpolate hydrostatic pressure, prevent divided by zero
108  Real psv, dsv;
109  if (fabs(psf_(k, j, i) - psf_(k, j, i + 1)) < 1.E-6)
110  psv = (psf_(k, j, i) + psf_(k, j, i + 1)) / 2.;
111  else
112  psv = (psf_(k, j, i) - psf_(k, j, i + 1)) /
113  log(psf_(k, j, i) / psf_(k, j, i + 1));
114  dsv = pow(psv, 1. / entropy_(0, k, j)) *
115  exp(-entropy_(1, k, j) / entropy_(0, k, j));
116 
117  // change pressure/density to pertubation quantities
118  w(IPR, k, j, i) -= psv;
119  w(IDN, k, j, i) -= dsv;
120  }
121  }
122 
123  /* debug
124  if (Globals::my_rank == 0) {
125  //int km = (kl + ku)/2;
126  //int jm = (jl + ju)/2;
127  int km = kl;
128  int jm = jl;
129  std::cout << "my.gid = " << pmb->gid << std::endl;
130  std::cout << "bblock.gid = " << bblock.snb.gid << std::endl;
131  std::cout << "===== k = " << km << " j = " << jm << std::endl;
132  for (int i = is - NGHOST; i <= ie + NGHOST; ++i) {
133  if (i == is)
134  std::cout << "-------- ";
135  if (i == 0)
136  std::cout << "i = " << "-1/2 ";
137  else if (i == 1)
138  std::cout << "i = " << "+1/2 ";
139  else
140  std::cout << "i = " << i-1 << "+1/2 ";
141  std::cout << "psf = " << psf_(km,jm,i) << std::endl;
142  std::cout << "i = " << i << " ";
143  std::cout << " pre = " << w(IPR,km,jm,i)
144  << " den = " << w(IDN,km,jm,i) << std::endl;
145  if (i == ie)
146  std::cout << "-------- ";
147  if (i == ie + NGHOST) {
148  std::cout << "i = " << i+1 << "+1/2 ";
149  std::cout << "psf = " << psf_(km,jm,i+1) << std::endl;
150  }
151  }
152  std::cout << "==========" << std::endl;
153  }*/
154 
155  // finish send top pressure
157 }
158 
160  AthenaArray<Real> &wl,
161  AthenaArray<Real> &wr, int k, int j,
162  int il, int iu) {
163  MeshBlock *pmb = pmy_block_;
164  Hydro *phydro = pmb->phydro;
166  int is = pmb->is, ie = pmb->ie;
167  if (phydro->hsrc.GetG1() == 0.) return;
168 
169  for (int i = is - NGHOST; i <= ie + NGHOST; ++i) {
170  w(IPR, k, j, i) = pres_(k, j, i);
171  w(IDN, k, j, i) = dens_(k, j, i);
172  }
173 
174  for (int i = il; i <= iu; ++i) {
175  wr(IPR, i) += psf_(k, j, i);
176  if (wr(IPR, i) < 0.) wr(IPR, i) = psf_(k, j, i);
177 
178  wl(IPR, i) += psf_(k, j, i);
179  if (wl(IPR, i) < 0.) wl(IPR, i) = psf_(k, j, i);
180 
181  Real dsf = pow(psf_(k, j, i), 1. / entropy_(0, k, j)) *
182  exp(-entropy_(1, k, j) / entropy_(0, k, j));
183 
184  wr(IDN, i) += dsf;
185  if (wr(IDN, i) < 0.) wr(IDN, i) = dsf;
186 
187  wl(IDN, i) += dsf;
188  if (wl(IDN, i) < 0.) wl(IDN, i) = dsf;
189  }
190 
191  /* debug
192  //int km = (pmb->ks + pmb->ke)/2, jm = (pmb->js + pmb->je)/2;
193  int km = pmb->ks-1, jm = pmb->js-1;
194  if (Globals::my_rank == 1 && km == k & jm == j) {
195  std::cout << "my.gid = " << pmb->gid << std::endl;
196  std::cout << "bblock.gid = " << bblock.snb.gid << std::endl;
197  std::cout << "===== k = " << km << " j = " << jm << std::endl;
198  for (int i = il; i <= iu; ++i) {
199  if (i == is)
200  std::cout << "-------- ";
201  if (i == 0)
202  std::cout << "i = " << "-1/2 ";
203  else if (i == 1)
204  std::cout << "i = " << "+1/2 ";
205  else
206  std::cout << "i = " << i-1 << "+1/2 ";
207  std::cout << "psf = " << psf_(km,jm,i)
208  << " wl(IPR) = " << wl(IPR,i)
209  << " wr(IPR) = " << wr(IPR,i)
210  << " wl(IDN) = " << wl(IDN,i)
211  << " wr(IDN) = " << wr(IDN,i)
212  << std::endl;
213  std::cout << "i = " << i << " ";
214  std::cout << " pre = " << w(IPR,km,jm,i) << " den = " << w(IDN,km,jm,i) <<
215  std::endl; if (i == ie) std::cout << "-------- "; if (i == ie + NGHOST) {
216  std::cout << "i = " << i+1 << "+1/2 ";
217  std::cout << "psf = " << psf_(km,jm,i+1) << std::endl;
218  }
219  }
220  std::cout << "==========" << std::endl;
221  }*/
222 }
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)
void RecvBuffer(AthenaArray< Real > &psf, int kl, int ku, int jl, int ju, int il, int iu, NeighborBlock nb)
AthenaArray< Real > psf_
NeighborBlock tblock
MeshBlock * pmy_block_
AthenaArray< Real > pres_
AthenaArray< Real > dens_
NeighborBlock bblock
void WaitToFinishSend()
void SendBuffer(AthenaArray< Real > const &psf, int kl, int ku, int jl, int ju)
AthenaArray< Real > entropy_
void FindNeighbors()
void RestoreFromPerturbation(AthenaArray< Real > &w, AthenaArray< Real > &wl, AthenaArray< Real > &wr, int k, int j, int il, int iu)
void ChangeToPerturbation(AthenaArray< Real > &w, int kl, int ku, int jl, int ju)
void PopulateBotEntropy(AthenaArray< Real > const &w, int kl, int ku, int jl, int ju)
static Thermodynamics const * GetInstance()
Return a pointer to the one and only instance of Thermodynamics.
Real GetRd() const
Real Rd
Definition: straka.cpp:66