Canoe
Comprehensive Atmosphere N' Ocean Engine
radiation.cpp
Go to the documentation of this file.
1 // C/C++ headers
2 #include <fstream>
3 #include <sstream>
4 #include <stdexcept>
5 #include <utility>
6 
7 // external
8 #include <yaml-cpp/yaml.h>
9 
10 // application
11 #include <application/application.hpp>
12 #include <application/exceptions.hpp>
13 
14 // athena
15 #include <athena/coordinates/coordinates.hpp>
16 #include <athena/hydro/hydro.hpp>
17 #include <athena/mesh/mesh.hpp>
18 #include <athena/parameter_input.hpp>
19 
20 // climath
21 #include <climath/core.h>
22 
23 // utils
24 #include <utils/vectorize.hpp>
25 
26 // canoe
27 #include <common.hpp>
28 #include <impl.hpp>
29 
30 // harp
31 #include "radiation.hpp"
32 #include "radiation_band.hpp"
33 #include "rt_solvers.hpp"
34 
35 const std::string Radiation::input_key = "radiation_config";
36 
37 Radiation::Radiation(MeshBlock *pmb, ParameterInput *pin) {
38  Application::Logger app("harp");
39  app->Log("Initialize Radiation");
40 
41  // dimensions
42  int ncells1 = pmb->ncells1;
43  int ncells2 = pmb->ncells2;
44  int ncells3 = pmb->ncells3;
45 
46  // radiation flags
48  pin->GetOrAddString("radiation", "flags", "")));
49 
50  // radiation bands
52 
53  // incoming radiation direction (mu, phi) in degrees
54  std::string str = pin->GetOrAddString("radiation", "indir", "(0.,0.)");
56 
57  // radiation configuration
58  int nstr = pin->GetOrAddInteger("radiation", "nstr", 8);
59  int nuphi = pin->GetOrAddInteger("radiation", "nuphi", 1);
60  int numu = pin->GetOrAddInteger("radiation", "numu", 1);
61 
62  for (auto &p : bands_) {
63  // outgoing radiation direction (mu,phi) in degrees
64  if (pin->DoesParameterExist("radiation", p->GetName() + ".outdir")) {
65  auto str = pin->GetString("radiation", p->GetName() + ".outdir");
66  p->SetOutgoingRays(RadiationHelper::parse_radiation_directions(str));
67  } else if (pin->DoesParameterExist("radiation", "outdir")) {
68  auto str = pin->GetString("radiation", "outdir");
69  p->SetOutgoingRays(RadiationHelper::parse_radiation_directions(str));
70  }
71 
72  // allocate memory
73  p->Resize(ncells1, ncells2, ncells3, nstr);
74  p->ResizeSolver(ncells1 - 2 * NGHOST, nstr, nuphi, numu);
75  }
76 
77  // output radiance
78  int nout = GetNumOutgoingRays();
79  if (nout > 0) {
80  radiance.NewAthenaArray(nout, ncells3, ncells2);
81  // set band toa
82  int n = 0;
83  for (auto &p : bands_) {
84  p->btoa.InitWithShallowSlice(radiance, 3, n, p->GetNumOutgoingRays());
85  n += p->GetNumOutgoingRays();
86  }
87  }
88 
89  // output flux
90  flxup.NewAthenaArray(bands_.size(), ncells3, ncells2, ncells1 + 1);
91  flxdn.NewAthenaArray(bands_.size(), ncells3, ncells2, ncells1 + 1);
92 
93  for (int n = 0; n < bands_.size(); ++n) {
94  bands_[n]->bflxup.InitWithShallowSlice(flxup, 4, n, 1);
95  bands_[n]->bflxup.InitWithShallowSlice(flxdn, 4, n, 1);
96  }
97 
98  // time control
99  SetCooldownTime(pin->GetOrAddReal("radiation", "dt", 0.));
100 }
101 
103  Application::Logger app("harp");
104  app->Log("Destroy Radiation");
105 }
106 
107 RadiationBandPtr Radiation::GetBandByName(std::string const &name) const {
108  for (auto &band : bands_) {
109  if (band->GetName() == name) {
110  return band;
111  }
112  }
113  throw NotFoundError("GetBand", "Band " + name);
114 }
115 
117  size_t num = 0;
118  for (auto &p : bands_) {
119  num += p->GetNumOutgoingRays();
120  }
121  return num;
122 }
123 
124 void Radiation::CalRadiativeFlux(MeshBlock const *pmb, int k, int j, int il,
125  int iu) {
126  auto pcoord = pmb->pcoord;
127 
129 
130  Real grav = -pmb->phydro->hsrc.GetG1();
131 
132  for (auto &p : bands_) {
133  // iu ~= ie + 1
134  p->SetSpectralProperties(ac, pcoord, grav, k, j);
135  p->CalBandFlux(pmb, k, j, il, iu);
136  }
137 }
138 
139 void Radiation::CalRadiance(MeshBlock const *pmb, int k, int j) {
140  Application::Logger app("harp");
141  app->Log("CalRadiance");
142 
143  auto pcoord = pmb->pcoord;
144 
146 
147  Real grav = -pmb->phydro->hsrc.GetG1();
148 
149  for (auto &p : bands_) {
150  // iu ~= ie + 1
151  p->SetSpectralProperties(ac, pcoord, grav, k, j);
152  p->CalBandRadiance(pmb, k, j);
153  }
154 }
155 
156 void Radiation::AddRadiativeFlux(Hydro *phydro, int k, int j, int il,
157  int iu) const {
158  // x1-flux divergence
159  for (size_t b = 0; b < bands_.size(); ++b) {
160 #pragma omp simd
161  for (int i = il; i <= iu; ++i)
162  phydro->flux[X1DIR](IEN, k, j, i) +=
163  flxup(b, k, j, i) - flxdn(b, k, j, i);
164  }
165 }
166 
167 size_t Radiation::RestartDataSizeInBytes(Mesh const *pm) const {
168  return flxup.GetSizeInBytes() + flxdn.GetSizeInBytes();
169 }
170 
171 void Radiation::DumpRestartData(char *pdst) const {
172  int offset = 0;
173 
174  std::memcpy(pdst + offset, flxup.data(), flxup.GetSizeInBytes());
175  offset += flxup.GetSizeInBytes();
176  std::memcpy(pdst + offset, flxdn.data(), flxdn.GetSizeInBytes());
177  offset += flxdn.GetSizeInBytes();
178 }
179 
181 size_t Radiation::LoadRestartData(char *psrc) {
182  Application::Logger app("harp");
183  app->Log("Radiation restarted");
184  int offset = 0;
185 
186  std::memcpy(flxup.data(), psrc + offset, flxup.GetSizeInBytes());
187  offset += flxup.GetSizeInBytes();
188  std::memcpy(flxdn.data(), psrc + offset, flxdn.GetSizeInBytes());
189  offset += flxdn.GetSizeInBytes();
190 
191  return offset;
192 }
193 
194 namespace RadiationHelper {
195 std::vector<Direction> parse_radiation_directions(std::string str) {
196  std::vector<std::string> dstr = Vectorize<std::string>(str.c_str());
197  int nray = dstr.size();
198 
199  std::vector<Direction> ray(nray);
200 
201  auto jt = dstr.begin();
202  for (auto it = ray.begin(); it != ray.end(); ++it, ++jt) {
203  it->phi = 0.;
204  sscanf(jt->c_str(), "(%lf,%lf)", &it->mu, &it->phi);
205  it->mu = cos(deg2rad(it->mu));
206  it->phi = deg2rad(it->phi);
207  }
208 
209  return ray;
210 }
211 
212 uint64_t parse_radiation_flags(std::string str) {
213  uint64_t flags = 0LL;
214  std::stringstream msg;
215 
216  std::vector<std::string> dstr = Vectorize<std::string>(str.c_str(), " ,");
217  for (int i = 0; i < dstr.size(); ++i) {
218  if (dstr[i] == "static") {
219  flags &= !RadiationFlags::Dynamic;
220  } else if (dstr[i] == "dynamic") {
221  flags |= RadiationFlags::Dynamic;
222  } else if (dstr[i] == "bin") {
223  flags &= !RadiationFlags::LineByLine;
224  } else if (dstr[i] == "lbl") {
226  } else if (dstr[i] == "ck") {
228  } else if (dstr[i] == "planck") {
229  flags |= RadiationFlags::Planck;
230  } else if (dstr[i] == "star") {
231  flags |= RadiationFlags::Star;
232  } else if (dstr[i] == "spher") {
233  flags |= RadiationFlags::Sphere;
234  } else if (dstr[i] == "only") {
235  flags |= RadiationFlags::FluxOnly;
236  } else if (dstr[i] == "normalize") {
237  flags |= RadiationFlags::Normalize;
238  } else if (dstr[i] == "write_bin_radiance") {
240  } else {
241  msg << "flag:" << dstr[i] << "unrecognized" << std::endl;
242  throw RuntimeError("parse_radiation_flags", msg.str());
243  }
244 
245  // check flags consistency
246  if ((flags & RadiationFlags::LineByLine) &&
247  (flags & RadiationFlags::CorrelatedK)) {
248  msg << "ck cannot be used with lbl." << std::endl;
249  throw RuntimeError("parse_radiation_flags", msg.str());
250  }
251  }
252 
253  return flags;
254 }
255 
256 void get_phase_momentum(Real *pmom, int iphas, Real gg, int npmom) {
257  pmom[0] = 1.;
258  for (int k = 1; k < npmom; k++) pmom[k] = 0.;
259 
260  switch (iphas) {
261  case 0: // HENYEY_GREENSTEIN
262  if (gg <= -1. || gg >= 1.)
263  std::cout << "getmom--bad input variable gg" << std::endl;
264  for (int k = 1; k <= npmom; k++) pmom[k] = pow(gg, (Real)k);
265  break;
266 
267  case 1: // RAYLEIGH
268  pmom[2] = 0.1;
269  break;
270  }
271 }
272 
273 } // namespace RadiationHelper
std::vector< AirParcel > AirColumn
Definition: air_parcel.hpp:121
void SetCooldownTime(Real cooldown)
void SetFlag(uint64_t flag)
static RadiationBandContainer CreateFrom(ParameterInput *pin, std::string key)
AthenaArray< Real > flxdn
downward flux of all bands
Definition: radiation.hpp:35
Radiation(MeshBlock *pmb, ParameterInput *pin)
Definition: radiation.cpp:37
size_t RestartDataSizeInBytes(Mesh const *pm) const override
Definition: radiation.cpp:167
std::vector< Direction > rayInput_
incomming rays
Definition: radiation.hpp:79
std::shared_ptr< RadiationBand > GetBandByName(std::string const &name) const
Get band by name.
Definition: radiation.cpp:107
void CalRadiativeFlux(MeshBlock const *pmb, int k, int j, int il, int iu)
Calculate the radiative flux.
Definition: radiation.cpp:124
std::vector< RadiationBandPtr > bands_
all radiation bands
Definition: radiation.hpp:76
void DumpRestartData(char *pdst) const override
Definition: radiation.cpp:171
AthenaArray< Real > flxup
upward flux of all bands
Definition: radiation.hpp:32
size_t LoadRestartData(char *psrt) override
Definition: radiation.cpp:181
size_t GetNumOutgoingRays() const
Get total number of incoming rays.
Definition: radiation.cpp:116
static const std::string input_key
radiation input key in the input file [radiation_config]
Definition: radiation.hpp:26
void CalRadiance(MeshBlock const *pmb, int k, int j)
Calculate the radiance.
Definition: radiation.cpp:139
void AddRadiativeFlux(Hydro *phydro, int k, int j, int il, int iu) const
Add the radiative flux to hydro energy flux.
Definition: radiation.cpp:156
AthenaArray< Real > radiance
radiance of all bands
Definition: radiation.hpp:29
double deg2rad(double phi)
Definition: core.h:41
AirParcel gather_from_primitive(MeshBlock const *pmb, int k, int j, int i)
Definition: air_parcel.cpp:507
const uint64_t Sphere
Definition: radiation.hpp:92
const uint64_t Dynamic
Definition: radiation.hpp:87
const uint64_t WriteBinRadiance
Definition: radiation.hpp:95
const uint64_t Star
Definition: radiation.hpp:91
const uint64_t LineByLine
Definition: radiation.hpp:88
const uint64_t FluxOnly
Definition: radiation.hpp:93
const uint64_t Normalize
Definition: radiation.hpp:94
const uint64_t Planck
Definition: radiation.hpp:90
const uint64_t CorrelatedK
Definition: radiation.hpp:89
std::vector< Direction > parse_radiation_directions(std::string str)
Definition: radiation.cpp:195
uint64_t parse_radiation_flags(std::string str)
Definition: radiation.cpp:212
void get_phase_momentum(Real *pmom, int iphas, Real gg, int npmom)
Definition: radiation.cpp:256
std::shared_ptr< RadiationBand > RadiationBandPtr