1#ifndef TWOPHASETRANSPORT_H
2#define TWOPHASETRANSPORT_H
7#include "AMReX_ParmParse.H"
10using namespace amrex::literals;
22 static std::string
identifier() {
return "TwoPhaseTransport"; }
27 amrex::ParmParse pp(
"transport");
28 pp.query(
"viscosity_fluid1",
m_mu1);
29 pp.query(
"viscosity_fluid2",
m_mu2);
30 pp.query(
"laminar_prandtl_fluid1",
m_Pr1);
31 pp.query(
"laminar_prandtl_fluid2",
m_Pr2);
32 pp.query(
"turbulent_prandtl",
m_Prt);
35 if (pp.contains(
"viscosity")) {
37 <<
"WARNING: single-phase viscosity has been specified but "
38 "will not be used! (TwoPhaseTransport)\n";
40 if (pp.contains(
"laminar_prandtl")) {
42 <<
"WARNING: single-phase laminar_prandtl has been specified "
43 "but will not be used! (TwoPhaseTransport)\n";
47 amrex::ParmParse pp_boussinesq_buoyancy(
"BoussinesqBuoyancy");
48 amrex::ParmParse pp_abl(
"ABL");
49 if (pp.contains(
"thermal_expansion_coefficient")) {
51 if (pp_boussinesq_buoyancy.contains(
"thermal_expansion_coeff")) {
53 <<
"WARNING: BoussinesqBuoyancy.thermal_expansion_coeff "
54 "option has been deprecated in favor of "
55 "transport.thermal_expansion_coefficient. Ignoring the "
56 "BoussinesqBuoyancy option in favor of the transport "
60 }
else if (pp_boussinesq_buoyancy.contains(
"thermal_expansion_coeff")) {
62 <<
"WARNING: BoussinesqBuoyancy.thermal_expansion_coeff option "
63 "has been deprecated in favor of "
64 "transport.thermal_expansion_coefficient. Please replace "
67 pp_boussinesq_buoyancy.get(
71 if (pp.contains(
"reference_temperature")) {
73 if (pp_boussinesq_buoyancy.contains(
"reference_temperature")) {
75 <<
"WARNING: BoussinesqBuoyancy.reference_temperature "
76 "option has been deprecated in favor of "
77 "transport.reference_temperature. Ignoring the "
78 "BoussinesqBuoyancy option in favor of the transport "
81 }
else if (pp_abl.contains(
"reference_temperature")) {
83 <<
"WARNING: ABL.reference_temperature "
84 "option has been deprecated in favor of "
85 "transport.reference_temperature. Ignoring the "
86 "ABL option in favor of the transport "
90 }
else if (pp_boussinesq_buoyancy.contains(
"reference_temperature")) {
92 <<
"WARNING: BoussinesqBuoyancy.reference_temperature option "
93 "has been deprecated in favor of "
94 "transport.reference_temperature. Please replace "
97 pp_boussinesq_buoyancy.get(
99 }
else if (pp_abl.contains(
"reference_temperature")) {
100 amrex::Print() <<
"WARNING: ABL.reference_temperature option "
101 "has been deprecated in favor of "
102 "transport.reference_temperature. Please replace "
118 amrex::ParmParse pp(
"transport");
119 const std::string key = scalar_name +
"_laminar_schmidt";
120 amrex::Real lam_schmidt = 1.0_rt;
121 pp.query(key, lam_schmidt);
127 amrex::ParmParse pp(
"transport");
128 const std::string key = scalar_name +
"_turbulent_schmidt";
129 amrex::Real turb_schmidt = 1.0_rt;
130 pp.query(key, turb_schmidt);
135 std::unique_ptr<ScratchField>
mu()
override
138 auto mu =
m_repo.create_scratch_field(1, m_ngrow);
143 const auto& vof =
m_repo.get_field(
"vof");
145 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
146 const auto& volfrac_arrs = vof(lev).const_arrays();
147 const auto& visc_arrs = (*mu)(lev).arrays();
148 const amrex::Real mu1 =
m_mu1;
149 const amrex::Real mu2 =
m_mu2;
151 (*
mu)(lev),
mu->num_grow(),
152 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k) {
153 visc_arrs[nbx](i, j, k) =
154 (mu1 * volfrac_arrs[nbx](i, j, k)) +
155 (mu2 * (1.0_rt - volfrac_arrs[nbx](i, j, k)));
158 amrex::Gpu::streamSynchronize();
162 const auto& levelset =
m_repo.get_field(
"levelset");
163 const auto& geom =
m_repo.mesh().Geom();
165 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
166 const auto& dx = geom[lev].CellSizeArray();
167 const auto& visc_arrs = (*mu)(lev).arrays();
168 const auto& phi_arrs = levelset(lev).const_arrays();
169 const amrex::Real eps =
170 std::cbrt(2.0_rt * dx[0] * dx[1] * dx[2]);
171 const amrex::Real mu1 =
m_mu1;
172 const amrex::Real mu2 =
m_mu2;
175 (*
mu)(lev),
mu->num_grow(),
176 [=] AMREX_GPU_DEVICE(
int nbx,
int i,
int j,
int k) {
177 amrex::Real smooth_heaviside;
178 if (phi_arrs[nbx](i, j, k) > eps) {
179 smooth_heaviside = 1.0_rt;
180 }
else if (phi_arrs[nbx](i, j, k) < -eps) {
181 smooth_heaviside = 0.0_rt;
185 (1.0_rt + phi_arrs[nbx](i, j, k) / eps +
186 1.0_rt / std::numbers::pi_v<amrex::Real> *
188 phi_arrs[nbx](i, j, k) *
189 std::numbers::pi_v<amrex::Real> /
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> /
261 visc_arrs[nbx](i, j, k) =
262 (mu1 / Pr1 * smooth_heaviside) +
263 (mu2 / Pr2 * (1.0_rt - smooth_heaviside));
267 amrex::Gpu::streamSynchronize();
271 std::unique_ptr<ScratchField>
276 amrex::Real inv_schmidt = 1.0_rt / lam_schmidt;
278 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
279 (*diff)(lev).mult(inv_schmidt);
286 [[nodiscard]] std::unique_ptr<ScratchField>
beta()
const override
288 auto beta =
m_repo.create_scratch_field(1, m_ngrow);
289 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
291#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
293 for (amrex::MFIter mfi((*
beta)(lev)); mfi.isValid(); ++mfi) {
294 const auto& bx = mfi.tilebox();
295 const auto& beta_arr = (*beta)(lev).array(mfi);
305 const amrex::MFIter& mfi,
306 const amrex::Box& bx,
307 const amrex::Array4<amrex::Real>&
beta)
const override
312 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
313 beta(i, j, k) = beta_val;
315 }
else if (
m_repo.field_exists(
"reference_temperature")) {
316 const auto& temp0 =
m_repo.get_field(
"reference_temperature");
317 const auto& temp0_arr = temp0(lev).const_array(mfi);
318 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
319 beta(i, j, k) = 1.0_rt / temp0_arr(i, j, k);
323 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
324 beta(i, j, k) = beta_val;
330 const auto& vof =
m_repo.get_field(
"vof");
331 const auto& vof_arr = vof(lev).const_array(mfi);
332 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
334 beta(i, j, k) = 0.0_rt;
338 const auto& levelset =
m_repo.get_field(
"levelset");
339 const auto& dx =
m_repo.mesh().Geom(lev).CellSizeArray();
340 const auto& phi_arr = levelset(lev).const_array(mfi);
341 const amrex::Real eps = std::cbrt(2.0_rt * dx[0] * dx[1] * dx[2]);
342 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
343 amrex::Real smooth_heaviside;
344 if (phi_arr(i, j, k) > eps) {
345 smooth_heaviside = 1.0_rt;
346 }
else if (phi_arr(i, j, k) < -eps) {
347 smooth_heaviside = 0.0_rt;
351 (1.0_rt + phi_arr(i, j, k) / eps +
352 1.0_rt / std::numbers::pi_v<amrex::Real> *
355 std::numbers::pi_v<amrex::Real> / eps));
357 beta(i, j, k) *= (1.0_rt - smooth_heaviside);
368 [[nodiscard]] std::unique_ptr<ScratchField>
ref_theta()
const override
371 amrex::Abort(
"Reference temperature was not set");
375 for (
int lev = 0; lev <
m_repo.num_active_levels(); ++lev) {
377#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
379 for (amrex::MFIter mfi((*
ref_theta)(lev)); mfi.isValid(); ++mfi) {
380 const auto& bx = mfi.tilebox();
381 const auto& ref_theta_arr = (*ref_theta)(lev).array(mfi);
391 const amrex::MFIter& mfi,
392 const amrex::Box& bx,
393 const amrex::Array4<amrex::Real>&
ref_theta)
const override
396 amrex::Abort(
"Reference temperature was not set");
399 if (
m_repo.field_exists(
"reference_temperature")) {
400 auto& temp0 =
m_repo.get_field(
"reference_temperature");
401 const auto& temp0_arr = temp0(lev).const_array(mfi);
402 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
407 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
444 amrex::Abort(
"TwoPhaseTransport requires MultiPhase physics");
447 return multiphase.interface_capturing_method();
Definition FieldRepo.H:86
Definition MultiPhase.H:31
amrex::Real laminar_prandtl1() const
Definition TwoPhaseTransport.H:111
std::unique_ptr< ScratchField > ref_theta() const override
Return the reference temperature.
Definition TwoPhaseTransport.H:368
amrex::Real reference_temperature() const override
Definition TwoPhaseTransport.H:362
amrex::Real m_Prt
Turbulent Prandtl number.
Definition TwoPhaseTransport.H:433
std::unique_ptr< ScratchField > beta() const override
Return the thermal expansion coefficient.
Definition TwoPhaseTransport.H:286
std::unique_ptr< ScratchField > mu() override
Return the dynamic visocity field.
Definition TwoPhaseTransport.H:135
std::unique_ptr< ScratchField > scalar_diffusivity(const std::string &scalar_name) override
Definition TwoPhaseTransport.H:272
void ref_theta_impl(const int lev, const amrex::MFIter &mfi, const amrex::Box &bx, const amrex::Array4< amrex::Real > &ref_theta) const override
Compute the reference temperature.
Definition TwoPhaseTransport.H:389
amrex::Real turbulent_prandtl() const
Definition TwoPhaseTransport.H:114
InterfaceCapturingMethod get_iface_method() const
Definition TwoPhaseTransport.H:441
amrex::Real m_reference_temperature
Reference temperature.
Definition TwoPhaseTransport.H:439
amrex::Real m_Pr1
Phase 1 (liquid) Prandtl number.
Definition TwoPhaseTransport.H:427
~TwoPhaseTransport() override=default
void beta_impl(const int lev, const amrex::MFIter &mfi, const amrex::Box &bx, const amrex::Array4< amrex::Real > &beta) const override
Compute the thermal expansion coefficient.
Definition TwoPhaseTransport.H:303
static constexpr bool constant_properties
Definition TwoPhaseTransport.H:20
TwoPhaseTransport(const CFDSim &sim)
Definition TwoPhaseTransport.H:24
amrex::Real m_constant_beta
Constant thermal expansion coefficient.
Definition TwoPhaseTransport.H:436
amrex::Real laminar_prandtl2() const
Definition TwoPhaseTransport.H:112
amrex::Real m_mu1
Phase 1 (liquid) dynamic molecular viscosity.
Definition TwoPhaseTransport.H:421
FieldRepo & m_repo
Reference to the field repository (for creating scratch fields)
Definition TwoPhaseTransport.H:415
static std::string identifier()
Definition TwoPhaseTransport.H:22
amrex::Real m_mu2
Phase 2 (gas) dynamic molecular viscosity.
Definition TwoPhaseTransport.H:424
static amrex::Real turbulent_schmidt(const std::string &scalar_name)
Definition TwoPhaseTransport.H:125
amrex::Real m_Pr2
Phase 2 (gas) Prandtl number.
Definition TwoPhaseTransport.H:430
static amrex::Real laminar_schmidt(const std::string &scalar_name)
Definition TwoPhaseTransport.H:116
const PhysicsMgr & m_physics_mgr
Reference to the physics manager.
Definition TwoPhaseTransport.H:418
std::unique_ptr< ScratchField > alpha() override
Return the thermal diffusivity field (later divided by density, though)
Definition TwoPhaseTransport.H:203
static constexpr amrex::Real TIGHT_TOL
A tight tolerance.
Definition constants.H:17
Definition height_functions.H:8
InterfaceCapturingMethod
Definition MultiPhase.H:25
@ VOF
Volume of fluid.
Definition MultiPhase.H:26
@ LS
Levelset.
Definition MultiPhase.H:27