9 #include <configure.hpp>
16 #include <athena/athena.hpp>
17 #include <athena/coordinates/coordinates.hpp>
18 #include <athena/globals.hpp>
19 #include <athena/hydro/hydro.hpp>
20 #include <athena/mesh/mesh.hpp>
21 #include <athena/stride_iterator.hpp>
24 #include <application/application.hpp>
25 #include <application/exceptions.hpp>
43 Application::Logger app(
"inversion");
44 app->Log(
"Initializing ProfileInversion");
49 Vectorize<int>(pin->GetString(
"inversion", name +
".variables").c_str());
54 Xstd_[IDN] = pin->GetReal(
"inversion", name +
".tem.std");
56 pin->GetReal(
"inversion", name +
".tem.corr.km") * 1.E3;
57 app->Log(name +
"::temperature std" + std::to_string(
Xstd_[IDN]));
58 app->Log(name +
"::temperature correlation length" +
59 std::to_string(
Xlen_[0]));
61 Xstd_[m] = pin->GetReal(
"inversion", name +
".qvapor" +
62 std::to_string(m) +
".std.gkg") /
65 Xlen_[m] = pin->GetReal(
"inversion", name +
".qvapor" +
66 std::to_string(m) +
".corr.km") *
68 snprintf(buf,
sizeof(buf),
69 "%s::vapor %d standard deviation = ", name.c_str(), m);
70 app->Log(buf + std::to_string(
Xstd_[m]));
71 snprintf(buf,
sizeof(buf),
72 "%s::vapor %d correlation length = ", name.c_str(), m);
73 app->Log(buf + std::to_string(
Xlen_[m]));
78 chi_ = pin->GetOrAddReal(
"inversion", name +
".chi", 0.0);
82 Vectorize<Real>(pin->GetString(
"inversion", name +
".PrSample").c_str());
85 app->Log(name +
"::number of input dimension = " + std::to_string(ndim));
89 Real pmax = pin->GetReal(
"inversion", name +
".Pmax");
90 Real pmin = pin->GetReal(
"inversion", name +
".Pmin");
91 if (pmax < (
plevel_.front() + 1.E-6))
92 throw RuntimeError(
"ProfileInversion",
93 "Pmax < " + std::to_string(
plevel_.front()));
95 if (pmin > (
plevel_.back() - 1.E-6))
96 throw RuntimeError(
"ProfileInversion",
97 "Pmin > " + std::to_string(
plevel_.back()));
112 int nwalker = pmb->block_size.nx3;
115 if ((nwalker < 2) && pmb->pmy_mesh->nlim > 0) {
116 throw RuntimeError(
"ProfileInversion",
"nwalker (nx3) must be at least 2");
128 Application::Logger app(
"inversion");
131 app->Log(
"Initializing random positions for walkers");
133 unsigned int seed =
time(NULL) + Globals::my_rank;
136 Real reference_pressure =
pmy_block_->pcoord->GetReferencePressure();
137 for (
int n = 0; n < nwalker; ++n) {
139 for (
auto m :
idx_) {
140 for (
int i = 0; i < nsample; ++i)
142 (1. * rand_r(&seed) / RAND_MAX - 0.5) *
Xstd_[m] *
153 Application::Logger app(
"inversion");
154 app->Log(
"UpdateHydro");
158 NewCArray(XpSample, 1 + NVAPOR, nsample + 2);
159 std::fill(*XpSample, *XpSample + (1 + NVAPOR) * (nsample + 2), 0.);
164 for (
auto m :
idx_) {
166 snprintf(buf,
sizeof(buf),
"%s.tema.K",
GetName().c_str());
168 snprintf(buf,
sizeof(buf),
"%s.qvapor%da.gkg",
GetName().c_str(), m);
170 std::string str = pin->GetString(
"problem", buf);
171 std::vector<Real> qa = Vectorize<Real>(str.c_str(),
" ,");
173 if (qa.size() != nsample) {
174 throw ValueError(
"UpdateHydro", buf, qa.size(), nsample);
178 for (
int i = 1; i <= nsample; ++i) {
179 XpSample[m][i] = qa[i - 1] / 1.E3;
182 for (
int k = ks; k <= ke; ++k) {
187 for (
int n = 0; n < NHYDRO; ++n)
188 for (
int i = is; i <= ie; ++i) {
189 phydro->w(n, k, js - 1, i) = phydro->w(n, k,
ju_, i);
198 int jl,
int ju)
const {
199 Application::Logger app(
"inversion");
200 app->Log(
"Updating profiles at k = " + std::to_string(k));
202 if (ju - jl !=
idx_.size()) {
203 throw RuntimeError(
"UpdateProfiles",
204 "Number of allocations in x2 should be " +
205 std::to_string(
idx_.size() + 1));
210 int nlayer = ie - is + 1;
213 std::vector<Real> zlev(nsample);
214 Real P0 =
pmy_block_->pcoord->GetReferencePressure();
215 Real H0 =
pmy_block_->pcoord->GetPressureScaleHeight();
217 for (
int i = 0; i < nsample; ++i) {
218 zlev[i] = -H0 * log(
plevel_[i] / P0);
223 std::vector<Real> stdAll(nlayer);
224 std::vector<Real> stdSample(nsample);
229 for (
int n = 0; n < NHYDRO; ++n)
230 for (
int j = jl;
j <= ju; ++
j)
231 for (
int i = is; i <= ie; ++i)
232 phydro->w(n, k,
j, i) = phydro->w(n, k, jl - 1, i);
236 Real
Rd = pthermo->GetRd();
239 app->Log(
"Update profiles");
240 auto pcoord = pmb->pcoord;
241 for (
size_t n = 0; n <
idx_.size(); ++n) {
245 for (
int i = is; i <= ie; ++i)
246 stdAll[i - is] =
Xstd_[m] * pow(exp(pcoord->x1v(i) / H0),
chi_);
248 for (
int i = 0; i < nsample; ++i)
249 stdSample[i] =
Xstd_[m] * pow(exp(zlev[i] / H0),
chi_);
252 nlayer, XpSample[m], zlev.data(), stdSample.data(), nsample,
255 for (
int i = is; i <= ie; ++i) {
256 Real
temp = pthermo->GetTemp(pmb, k, jn, i);
259 if (pcoord->x1v(i) < zlev[0] || pcoord->x1v(i) > zlev[nsample - 1])
264 if (
temp + Xp[m][i - is] < 0.) {
267 temp += Xp[m][i - is];
269 phydro->w(IDN, k, jn, i) = phydro->w(IPR, k, jn, i) /
270 (
Rd *
temp * pthermo->RovRd(pmb, k, jn, i));
272 phydro->w(m, k, jn, i) += Xp[m][i - is];
273 phydro->w(m, k, jn, i) =
std::max(phydro->w(m, k, jn, i), 0.);
274 phydro->w(m, k, jn, i) =
std::min(phydro->w(m, k, jn, i), 1.);
281 Real *temp1d =
new Real[nlayer];
283 for (
int i = is; i <= ie; ++i) {
285 temp1d[i - is] = pthermo->GetTemp(pmb, k, jl - 1, i);
287 for (
size_t n = 0; n <
idx_.size(); ++n) {
292 temp1d[i - is] = pthermo->GetTemp(pmb, k, jn, i);
294 phydro->w(m, k, ju, i) = phydro->w(m, k, jn, i);
299 phydro->w(IDN, k, ju, i) =
300 phydro->w(IPR, k, ju, i) /
301 (
Rd * temp1d[i - is] * pthermo->RovRd(pmb, k, ju, i));
312 Application::Logger app(
"inversion");
313 app->Log(
"doing convective adjustment");
322 for (
int i = is + 1; i <= ie; ++i) {
323 auto &air = ac[i - is - 1];
324 air.ToMoleFraction();
326 Real dlnp = log(phydro->w(IPR, k, ju, i) / phydro->w(IPR, k, ju, i - 1));
329 air.ToMassFraction();
332 phydro->w(IDN, k, ju, i) =
std::min(air.w[IDN], phydro->w(IDN, k, ju, i));
335 for (
int n = 1; n <= NVAPOR; ++n) {
336 Real rh = pthermo->RelativeHumidity(pmb, n, k, ju, i);
337 if (rh > 1.) phydro->w(n, k, ju, i) /= rh;
void InitializeChain(int nstep, int nwalker, int ndim, int nvalue)
MeshBlock const * pmy_block_
pointer to parent MeshBlock
std::string GetName() const
void UpdateHydro(Hydro *phydro, ParameterInput *pin) const override
void InitializePositions() override
std::vector< Real > plevel_
void ConvectiveAdjustment(Hydro *phydro, int k, int ju) const
ProfileInversion(MeshBlock *pmb, ParameterInput *pin, std::string name)
void UpdateProfiles(Hydro *phydro, Real **XpSample, int k, int jl, int ju) const
static Thermodynamics const * GetInstance()
Return a pointer to the one and only instance of Thermodynamics.
double min(double x1, double x2, double x3)
double max(double x1, double x2, double x3)
double gp_predict(KernelFunction_t kernel, double *arr2, double const *x2, double const *s2, int n2, double const *arr1, double const *x1, double const *s1, int n1, double len)
double SquaredExponential(double x1, double x2, double l, double s1s2=1.)
AirParcel gather_from_primitive(MeshBlock const *pmb, int k, int j, int i)
void NewCArray(T **&a, int n1, int n2)