1#ifndef TWOPHASETRANSPORT_H
2#define TWOPHASETRANSPORT_H
8#include "AMReX_ParmParse.H"
11using namespace amrex::literals;
23 static std::string
identifier() {
return "TwoPhaseTransport"; }
28 amrex::ParmParse pp(
"transport");
29 pp.query(
"viscosity_fluid1",
m_mu1);
30 pp.query(
"viscosity_fluid2",
m_mu2);
31 pp.query(
"laminar_prandtl_fluid1",
m_Pr1);
32 pp.query(
"laminar_prandtl_fluid2",
m_Pr2);
33 pp.query(
"turbulent_prandtl",
m_Prt);
36 if (pp.contains(
"viscosity")) {
38 <<
"WARNING: single-phase viscosity has been specified but "
39 "will not be used! (TwoPhaseTransport)\n";
41 if (pp.contains(
"laminar_prandtl")) {
43 <<
"WARNING: single-phase laminar_prandtl has been specified "
44 "but will not be used! (TwoPhaseTransport)\n";
48 amrex::ParmParse pp_boussinesq_buoyancy(
"BoussinesqBuoyancy");
49 amrex::ParmParse pp_abl(
"ABL");
50 if (pp.contains(
"thermal_expansion_coefficient")) {
52 if (pp_boussinesq_buoyancy.contains(
"thermal_expansion_coeff")) {
54 <<
"WARNING: BoussinesqBuoyancy.thermal_expansion_coeff "
55 "option has been deprecated in favor of "
56 "transport.thermal_expansion_coefficient. Ignoring the "
57 "BoussinesqBuoyancy option in favor of the transport "
61 }
else if (pp_boussinesq_buoyancy.contains(
"thermal_expansion_coeff")) {
63 <<
"WARNING: BoussinesqBuoyancy.thermal_expansion_coeff option "
64 "has been deprecated in favor of "
65 "transport.thermal_expansion_coefficient. Please replace "
68 pp_boussinesq_buoyancy.get(
72 if (pp.contains(
"reference_temperature")) {
74 if (pp_boussinesq_buoyancy.contains(
"reference_temperature")) {
76 <<
"WARNING: BoussinesqBuoyancy.reference_temperature "
77 "option has been deprecated in favor of "
78 "transport.reference_temperature. Ignoring the "
79 "BoussinesqBuoyancy option in favor of the transport "
82 }
else if (pp_abl.contains(
"reference_temperature")) {
84 <<
"WARNING: ABL.reference_temperature "
85 "option has been deprecated in favor of "
86 "transport.reference_temperature. Ignoring the "
87 "ABL option in favor of the transport "
91 }
else if (pp_boussinesq_buoyancy.contains(
"reference_temperature")) {
93 <<
"WARNING: BoussinesqBuoyancy.reference_temperature option "
94 "has been deprecated in favor of "
95 "transport.reference_temperature. Please replace "
98 pp_boussinesq_buoyancy.get(
100 }
else if (pp_abl.contains(
"reference_temperature")) {
101 amrex::Print() <<
"WARNING: ABL.reference_temperature option "
102 "has been deprecated in favor of "
103 "transport.reference_temperature. Please replace "
119 amrex::ParmParse pp(
"transport");
120 const std::string key = scalar_name +
"_laminar_schmidt";
121 amrex::Real lam_schmidt = 1.0_rt;
122 pp.query(key, lam_schmidt);
128 amrex::ParmParse pp(
"transport");
129 const std::string key = scalar_name +
"_turbulent_schmidt";
130 amrex::Real turb_schmidt = 1.0_rt;
131 pp.query(key, turb_schmidt);
136 std::unique_ptr<ScratchField>
mu()
override
139 auto mu =
m_repo.create_scratch_field(1, m_ngrow);
144 const auto& vof =
m_repo.get_field(
"vof");
146 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
147 const auto& volfrac_arrs = vof(lev).const_arrays();
148 const auto& visc_arrs = (*mu)(lev).arrays();
149 const amrex::Real mu1 =
m_mu1;
150 const amrex::Real mu2 =
m_mu2;
152 (*
mu)(lev),
mu->num_grow(),
153 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k) {
154 visc_arrs[nbx](i, j, k) =
155 (mu1 * volfrac_arrs[nbx](i, j, k)) +
156 (mu2 * (1.0_rt - volfrac_arrs[nbx](i, j, k)));
159 amrex::Gpu::streamSynchronize();
163 const auto& levelset =
m_repo.get_field(
"levelset");
164 const auto& geom =
m_repo.mesh().Geom();
166 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
167 const auto& dx = geom[lev].CellSizeArray();
168 const auto& visc_arrs = (*mu)(lev).arrays();
169 const auto& phi_arrs = levelset(lev).const_arrays();
170 const amrex::Real eps =
171 std::cbrt(2.0_rt * dx[0] * dx[1] * dx[2]);
172 const amrex::Real mu1 =
m_mu1;
173 const amrex::Real mu2 =
m_mu2;
176 (*
mu)(lev),
mu->num_grow(),
177 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k) {
178 amrex::Real smooth_heaviside;
179 if (phi_arrs[nbx](i, j, k) > eps) {
180 smooth_heaviside = 1.0_rt;
181 }
else if (phi_arrs[nbx](i, j, k) < -eps) {
182 smooth_heaviside = 0.0_rt;
186 (1.0_rt + (phi_arrs[nbx](i, j, k) / eps) +
187 (1.0_rt / std::numbers::pi_v<amrex::Real> *
189 phi_arrs[nbx](i, j, k) *
190 std::numbers::pi_v<amrex::Real> / eps)));
192 visc_arrs[nbx](i, j, k) =
193 (mu1 * smooth_heaviside) +
194 (mu2 * (1.0_rt - smooth_heaviside));
197 amrex::Gpu::streamSynchronize();
203 std::unique_ptr<ScratchField>
alpha()
override
206 auto alpha =
m_repo.create_scratch_field(1, m_ngrow);
211 const auto& vof =
m_repo.get_field(
"vof");
213 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
214 const auto& volfrac_arrs = vof(lev).const_arrays();
215 const auto& thdiff_arrs = (*alpha)(lev).arrays();
216 const amrex::Real mu1 =
m_mu1;
217 const amrex::Real mu2 =
m_mu2;
218 const amrex::Real Pr1 =
m_Pr1;
219 const amrex::Real Pr2 =
m_Pr2;
222 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k) {
223 thdiff_arrs[nbx](i, j, k) =
224 (mu1 / Pr1 * volfrac_arrs[nbx](i, j, k)) +
225 (mu2 / Pr2 * (1.0_rt - volfrac_arrs[nbx](i, j, k)));
230 const auto& levelset =
m_repo.get_field(
"levelset");
231 const auto& geom =
m_repo.mesh().Geom();
233 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
234 const auto& dx = geom[lev].CellSizeArray();
235 const auto& visc_arrs = (*alpha)(lev).arrays();
236 const auto& phi_arrs = levelset(lev).const_arrays();
237 const amrex::Real eps =
238 std::cbrt(2.0_rt * dx[0] * dx[1] * dx[2]);
239 const amrex::Real mu1 =
m_mu1;
240 const amrex::Real mu2 =
m_mu2;
241 const amrex::Real Pr1 =
m_Pr1;
242 const amrex::Real Pr2 =
m_Pr2;
245 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k) {
246 amrex::Real smooth_heaviside;
247 if (phi_arrs[nbx](i, j, k) > eps) {
248 smooth_heaviside = 1.0_rt;
249 }
else if (phi_arrs[nbx](i, j, k) < -eps) {
250 smooth_heaviside = 0.0_rt;
254 (1.0_rt + (phi_arrs[nbx](i, j, k) / eps) +
255 (1.0_rt / std::numbers::pi_v<amrex::Real> *
257 phi_arrs[nbx](i, j, k) *
258 std::numbers::pi_v<amrex::Real> / eps)));
260 visc_arrs[nbx](i, j, k) =
261 (mu1 / Pr1 * smooth_heaviside) +
262 (mu2 / Pr2 * (1.0_rt - smooth_heaviside));
266 amrex::Gpu::streamSynchronize();
270 std::unique_ptr<ScratchField>
275 amrex::Real inv_schmidt = 1.0_rt / lam_schmidt;
277 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
278 (*diff)(lev).mult(inv_schmidt);
285 [[nodiscard]] std::unique_ptr<ScratchField>
beta()
const override
287 auto beta =
m_repo.create_scratch_field(1, m_ngrow);
288 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
299 void beta_fill(
const int lev, amrex::MultiFab& beta_mf)
const override
303 }
else if (
m_repo.field_exists(
"reference_temperature")) {
304 const auto& temp0 =
m_repo.get_field(
"reference_temperature");
305 auto const& beta_arrs = beta_mf.arrays();
306 auto const& temp0_arrs = temp0(lev).const_arrays();
308 beta_mf, amrex::IntVect(0), 1,
309 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k,
int) {
310 beta_arrs[nbx](i, j, k) = 1.0_rt / temp0_arrs[nbx](i, j, k);
312 amrex::Gpu::streamSynchronize();
319 const auto& vof =
m_repo.get_field(
"vof");
320 auto const& beta_arrs = beta_mf.arrays();
321 auto const& vof_arrs = vof(lev).const_arrays();
323 beta_mf, amrex::IntVect(0), 1,
324 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k,
int) {
326 beta_arrs[nbx](i, j, k) = 0.0_rt;
329 amrex::Gpu::streamSynchronize();
331 const auto& levelset =
m_repo.get_field(
"levelset");
332 const auto& dx =
m_repo.mesh().Geom(lev).CellSizeArray();
333 const amrex::Real eps = std::cbrt(2.0_rt * dx[0] * dx[1] * dx[2]);
334 auto const& beta_arrs = beta_mf.arrays();
335 auto const& phi_arrs = levelset(lev).const_arrays();
337 beta_mf, amrex::IntVect(0), 1,
338 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k,
int) {
339 amrex::Real smooth_heaviside;
340 if (phi_arrs[nbx](i, j, k) > eps) {
341 smooth_heaviside = 1.0_rt;
342 }
else if (phi_arrs[nbx](i, j, k) < -eps) {
343 smooth_heaviside = 0.0_rt;
347 (1.0_rt + (phi_arrs[nbx](i, j, k) / eps) +
348 (1.0_rt / std::numbers::pi_v<amrex::Real> *
350 phi_arrs[nbx](i, j, k) *
351 std::numbers::pi_v<amrex::Real> / eps)));
353 beta_arrs[nbx](i, j, k) *= (1.0_rt - smooth_heaviside);
355 amrex::Gpu::streamSynchronize();
363 amrex::Abort(
"Reference temperature was not set");
366 if (
m_repo.field_exists(
"reference_temperature")) {
367 const auto& temp0 =
m_repo.get_field(
"reference_temperature");
368 amrex::MultiFab::Copy(ref_theta_mf, temp0(lev), 0, 0, 1, 0);
375 [[nodiscard]] std::unique_ptr<ScratchField>
ref_theta()
const override
378 amrex::Abort(
"Reference temperature was not set");
382 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
419 amrex::Abort(
"TwoPhaseTransport requires MultiPhase physics");
422 return multiphase.interface_capturing_method();
Definition FieldRepo.H:86
Definition MultiPhase.H:31
static amrex::Real turbulent_schmidt(const std::string &scalar_name)
Definition TwoPhaseTransport.H:126
~TwoPhaseTransport() override=default
InterfaceCapturingMethod get_iface_method() const
Definition TwoPhaseTransport.H:416
amrex::Real reference_temperature() const override
Definition TwoPhaseTransport.H:294
std::unique_ptr< ScratchField > beta() const override
Return the thermal expansion coefficient.
Definition TwoPhaseTransport.H:285
amrex::Real laminar_prandtl1() const
Definition TwoPhaseTransport.H:112
amrex::Real m_Pr1
Phase 1 (liquid) Prandtl number.
Definition TwoPhaseTransport.H:402
void beta_fill(const int lev, amrex::MultiFab &beta_mf) const override
Definition TwoPhaseTransport.H:299
std::unique_ptr< ScratchField > mu() override
Return the dynamic visocity field.
Definition TwoPhaseTransport.H:136
std::unique_ptr< ScratchField > alpha() override
Return the thermal diffusivity field (later divided by density, though)
Definition TwoPhaseTransport.H:203
FieldRepo & m_repo
Reference to the field repository (for creating scratch fields)
Definition TwoPhaseTransport.H:390
TwoPhaseTransport(const CFDSim &sim)
Definition TwoPhaseTransport.H:25
const PhysicsMgr & m_physics_mgr
Reference to the physics manager.
Definition TwoPhaseTransport.H:393
amrex::Real m_constant_beta
Constant thermal expansion coefficient.
Definition TwoPhaseTransport.H:411
amrex::Real turbulent_prandtl() const
Definition TwoPhaseTransport.H:115
amrex::Real m_reference_temperature
Reference temperature.
Definition TwoPhaseTransport.H:414
std::unique_ptr< ScratchField > ref_theta() const override
Return the reference temperature.
Definition TwoPhaseTransport.H:375
static std::string identifier()
Definition TwoPhaseTransport.H:23
amrex::Real m_mu2
Phase 2 (gas) dynamic molecular viscosity.
Definition TwoPhaseTransport.H:399
static amrex::Real laminar_schmidt(const std::string &scalar_name)
Definition TwoPhaseTransport.H:117
void ref_theta_fill(const int lev, amrex::MultiFab &ref_theta_mf) const override
Definition TwoPhaseTransport.H:360
amrex::Real m_mu1
Phase 1 (liquid) dynamic molecular viscosity.
Definition TwoPhaseTransport.H:396
std::unique_ptr< ScratchField > scalar_diffusivity(const std::string &scalar_name) override
Definition TwoPhaseTransport.H:271
static constexpr bool constant_properties
Definition TwoPhaseTransport.H:21
amrex::Real m_Pr2
Phase 2 (gas) Prandtl number.
Definition TwoPhaseTransport.H:405
amrex::Real laminar_prandtl2() const
Definition TwoPhaseTransport.H:113
amrex::Real m_Prt
Turbulent Prandtl number.
Definition TwoPhaseTransport.H:408
static constexpr amrex::Real VOF_TOL
Tolerance for vof determining presence of liquid.
Definition constants.H:34
Definition height_functions.H:8
InterfaceCapturingMethod
Definition MultiPhase.H:25
@ VOF
Volume of fluid.
Definition MultiPhase.H:26
@ LS
Levelset.
Definition MultiPhase.H:27