Canoe
Comprehensive Atmosphere N' Ocean Engine
lmars.cpp
Go to the documentation of this file.
1 // \brief LMARS based on Chen's 2013 paper
3 
4 // C/C++
5 #include <cstring>
6 
7 // Athena++
8 #include <athena/athena.hpp>
9 #include <athena/eos/eos.hpp>
10 #include <athena/hydro/hydro.hpp>
11 
12 // climath
13 #include <climath/core.h> // sqr
14 
15 // canoe
16 #include <impl.hpp>
17 
18 // snap
20 
21 // microphysics
23 
24 void Hydro::RiemannSolver(int const k, int const j, int const il, int const iu,
25  int const ivx, AthenaArray<Real> &wl,
27  const AthenaArray<Real> &dxw) {
28  int ivy = IVX + ((ivx - IVX) + 1) % 3;
29  int ivz = IVX + ((ivx - IVX) + 2) % 3;
30  int dir = ivx - IVX;
31 
32  auto pthermo = Thermodynamics::GetInstance();
33  auto pmicro = pmy_block->pimpl->pmicro;
34 
35  Real rhobar, pbar, cbar, ubar, hl, hr;
36  Real gamma = pmy_block->peos->GetGamma();
37  Real wli[NHYDRO], wri[NHYDRO];
38 
39  for (int i = il; i <= iu; ++i) {
40  // copy local variables
41  for (int n = 0; n < NHYDRO; ++n) {
42  wli[n] = wl(n, i);
43  wri[n] = wr(n, i);
44  }
45  // correction for gamma
46  // left
47  Real fsig = 1., feps = 1.;
48  for (int n = 1; n <= NVAPOR; ++n) {
49  fsig += wli[n] * (pthermo->GetCvRatioMass(n) - 1.);
50  feps += wli[n] * (1. / pthermo->GetMuRatio(n) - 1.);
51  }
52  Real kappal = 1. / (gamma - 1.) * fsig / feps;
53 
54  // right
55  fsig = 1., feps = 1.;
56  for (int n = 1; n <= NVAPOR; ++n) {
57  fsig += wri[n] * (pthermo->GetCvRatioMass(n) - 1.);
58  feps += wri[n] * (1. / pthermo->GetMuRatio(n) - 1.);
59  }
60  Real kappar = 1. / (gamma - 1.) * fsig / feps;
61 
62  // enthalpy
63  hl = wli[IPR] / wli[IDN] * (kappal + 1.) +
64  0.5 * (sqr(wli[ivx]) + sqr(wli[ivy]) + sqr(wli[ivz]));
65  hr = wri[IPR] / wri[IDN] * (kappar + 1.) +
66  0.5 * (sqr(wri[ivx]) + sqr(wri[ivy]) + sqr(wri[ivz]));
67 
68  rhobar = 0.5 * (wli[IDN] + wri[IDN]);
69  cbar = sqrt(0.5 * (1. + (1. / kappar + 1. / kappal) / 2.) *
70  (wli[IPR] + wri[IPR]) / rhobar);
71  pbar = 0.5 * (wli[IPR] + wri[IPR]) +
72  0.5 * (rhobar * cbar) * (wli[ivx] - wri[ivx]);
73  ubar = 0.5 * (wli[ivx] + wri[ivx]) +
74  0.5 / (rhobar * cbar) * (wli[IPR] - wri[IPR]);
75 
76  Real rdl = 1., rdr = 1.;
77  for (int n = 1; n <= NVAPOR; ++n) {
78  rdl -= wli[n];
79  rdr -= wri[n];
80  }
81 
82  if (ubar > 0.) {
83  flx(IDN, k, j, i) = ubar * wli[IDN] * rdl;
84  for (int n = 1; n <= NVAPOR; ++n)
85  flx(n, k, j, i) = ubar * wli[IDN] * wli[n];
86  flx(ivx, k, j, i) = ubar * wli[IDN] * wli[ivx] + pbar;
87  flx(ivy, k, j, i) = ubar * wli[IDN] * wli[ivy];
88  flx(ivz, k, j, i) = ubar * wli[IDN] * wli[ivz];
89  flx(IEN, k, j, i) = ubar * wli[IDN] * hl;
90  } else {
91  flx(IDN, k, j, i) = ubar * wri[IDN] * rdr;
92  for (int n = 1; n <= NVAPOR; ++n)
93  flx(n, k, j, i) = ubar * wri[IDN] * wri[n];
94  flx(ivx, k, j, i) = ubar * wri[IDN] * wri[ivx] + pbar;
95  flx(ivy, k, j, i) = ubar * wri[IDN] * wri[ivy];
96  flx(ivz, k, j, i) = ubar * wri[IDN] * wri[ivz];
97  flx(IEN, k, j, i) = ubar * wri[IDN] * hr;
98  }
99 
100  // sedimentation flux
101  // In Athena++ passive tracer module, the tracer mixing ratio is defined as
102  // the ratio of the density of the tracer to the density of the "dry"
103  // species. This ensures conservation of the tracer concentration even with
104  // condensation However, the first component of the primitive variable is
105  // the "total" density To get the denisty of the dry species, the "dry
106  // mixing ratio" (rdl/rdr) is multiplied
107  for (int n = 0; n < NCLOUD; ++n) {
108  Real vfld = ubar + pmicro->vsedf[dir](n, k, j, i);
109  if (vfld > 0.) {
110  pmicro->mass_flux[dir](n, k, j, i) = vfld * wli[IDN] * rdl;
111  } else {
112  pmicro->mass_flux[dir](n, k, j, i) = vfld * wri[IDN] * rdr;
113  }
114  }
115  }
116 }
static Thermodynamics const * GetInstance()
Return a pointer to the one and only instance of Thermodynamics.
double sqr(double x)
Definition: core.h:14