45#ifndef PECLET_FLOW_VOF_ENERGY_ADVECT_HPP
46#define PECLET_FLOW_VOF_ENERGY_ADVECT_HPP
49#include <Kokkos_Core.hpp>
66 throw std::invalid_argument(
67 "peclet::flow::vof::VofEnergyAdvector: both phase rho*c_p must be > 0");
71 len_ =
static_cast<long>(e_.
x) * e_.
y * e_.
z;
74 T_ =
SField(
"vof::energyT", len_);
75 Tw_ =
SField(
"vof::energyTw", len_);
114 throw std::runtime_error(
"peclet::flow::vof::VofEnergyAdvector: init() was never called");
116 throw std::runtime_error(
"peclet::flow::vof::VofEnergyAdvector: no `exchange` hook");
118 throw std::runtime_error(
119 "peclet::flow::vof::VofEnergyAdvector: cut-cell geometry is not composed with the "
120 "consistent energy transport at this rung (enable_phase_change already refuses a solid)");
123 const double dth = dt / w.h();
124 w.freezeDilationFlag();
125 w.timedExchange([&] {
exchange(T_); });
127 for (
int s = 0; s < 3; ++s) {
128 const int d =
perm[s];
130 w.computeFluxes(d, dth);
131 w.applySweep(d, dth);
133 w.exchangeTimed(w.colour());
134 w.timedExchange([&] {
exchange(T_); });
140 const I3 e = e_, n = n_;
143 double mn = 0.0, mx = 0.0;
145 MD pol(
SExec(), {g, g, g}, {g + n.x, g + n.y, g + n.z});
146 Kokkos::parallel_reduce(
147 "vof::energy::min",
pol,
148 KOKKOS_LAMBDA(
int x,
int y,
int z,
double& a) { a = Kokkos::fmin(a, T(
L3(x, y, z, e))); },
149 Kokkos::Min<double>(
mn));
150 Kokkos::parallel_reduce(
151 "vof::energy::max",
pol,
152 KOKKOS_LAMBDA(
int x,
int y,
int z,
double& a) { a = Kokkos::fmax(a, T(
L3(x, y, z, e))); },
153 Kokkos::Max<double>(mx));
172 const I3 e = e_, n = n_;
175 d == 0 ? 1 : (d == 1 ?
static_cast<long>(e_.
x) :
static_cast<long>(e_.
x) * e_.
y);
180 SField T = T_,
Tw = Tw_, fl = w.faceFlux(), u = w.faceVel(d), c = w.colour();
181 const double rg = rcpG_,
rl = rcpL_;
184 Kokkos::parallel_for(
187 const long i =
L3(x, y, z, e);
188 const double aP = u(i) * dth,
aM = u(i -
sd) * dth;
189 const double FP = fl(i), FM = fl(i -
sd);
192 const double ti = T(i);
200 const double wP = 0.5 - 0.5 * Kokkos::fabs(
aP),
wM = 0.5 - 0.5 * Kokkos::fabs(
aM);
210 const double cl = Kokkos::fmin(Kokkos::fmax(c(i), 0.0), 1.0);
221 I3 n_{0, 0, 0}, e_{0, 0, 0};
224 double rcpG_ = 1.0, rcpL_ = 1.0;
flow — VoF rung V1: Weymouth & Yue (2010) directionally-split, exactly volume-conserving geometric ad...
void setPhaseRcp(double g, double l)
void extrema(double &lo, double &hi) const
Min/max of the transported temperature over the inner region (a boundedness read-out).
SField temperature() const
The transported temperature on the advector's block (inner cells mirror the solver's scalar).
std::function< void(SField)> exchange
Ghost policy for the temperature — the halo/periodic exchange plus the block's non-periodic zero-grad...
void advect(WyAdvector &w, double dt, long step)
One consistent colour + energy Weymouth-Yue step.
void init(const WyAdvector &w, double rcpG, double rcpL)
bool energyMuscl
MinMod-limited donor reconstruction of the face temperature, instead of the DEFAULT plain donor-cell ...
void energyUpdate(WyAdvector &w, int d, double dth)
The DEVIATION form of the update, and it is not cosmetic.
Weymouth-Yue split advection of a colour field on an extended (inner + ghost) block.
flow — VoF rung V2b (WO-K): momentum-consistent transport of rho^c u_c on the half-shifted (MAC) mome...
constexpr int kWySweepPerm[6][3]
The six permutations of (x, y, z), cycled by step index so no direction is systematically favoured (p...
double vofMinmod(double a, double b)
double pcPhaseMix(double vg, double vl, double c)
Linear-in-C phase property (k, rho c_p), written so that C = 0 and C = 1 return the endpoint EXACTLY ...
long L3(int x, int y, int z, I3 e)
Kokkos::DefaultExecutionSpace SExec
Kokkos::View< double *, SMem > SField
flow — VoF phase change (Part II, rungs P0/P1): the container-free kernel set.
flow — the multidimensional iteration policies: iteration order follows storage.
static double perm(const std::vector< double > &gsdf, const BlockDecomposer< 3 > &dec, int rank, bool amg, int levels, MPI_Comm comm)