/home/runner/work/amr-wind/amr-wind/amr-wind/transport_models/TwoPhaseTransport.H Source File

AMR-Wind API: /home/runner/work/amr-wind/amr-wind/amr-wind/transport_models/TwoPhaseTransport.H Source File
AMR-Wind API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
TwoPhaseTransport.H
Go to the documentation of this file.
1#ifndef TWOPHASETRANSPORT_H
2#define TWOPHASETRANSPORT_H
3
6#include "AMReX_ParmParse.H"
7
8namespace amr_wind::transport {
9
14{
15public:
16 static constexpr bool constant_properties = false;
17
18 static std::string identifier() { return "TwoPhaseTransport"; }
19
20 explicit TwoPhaseTransport(CFDSim& sim) : m_sim(sim), m_repo(sim.repo())
21 {
22 auto& physics_mgr = m_sim.physics_manager();
23 if (!physics_mgr.contains("MultiPhase")) {
24 amrex::Abort("TwoPhaseTransport requires MultiPhase physics");
25 }
26 auto& multiphase = physics_mgr.get<MultiPhase>();
28
29 amrex::ParmParse pp("transport");
30 pp.query("viscosity_fluid1", m_mu1);
31 pp.query("viscosity_fluid2", m_mu2);
32 pp.query("laminar_prandtl_fluid1", m_Pr1);
33 pp.query("laminar_prandtl_fluid2", m_Pr2);
34 pp.query("turbulent_prandtl", m_Prt);
35
36 // Check for single-phase quantities and warn
37 if (pp.contains("viscosity")) {
38 amrex::Print()
39 << "WARNING: single-phase viscosity has been specified but "
40 "will not be used! (TwoPhaseTransport)\n";
41 }
42 if (pp.contains("laminar_prandtl")) {
43 amrex::Print()
44 << "WARNING: single-phase laminar_prandtl has been specified "
45 "but will not be used! (TwoPhaseTransport)\n";
46 }
47 }
48
49 ~TwoPhaseTransport() override = default;
50
51 inline amrex::Real laminar_prandtl1() const { return m_Pr1; }
52 inline amrex::Real laminar_prandtl2() const { return m_Pr2; }
53
54 inline amrex::Real turbulent_prandtl() const { return m_Prt; }
55
56 static inline amrex::Real laminar_schmidt(const std::string& scalar_name)
57 {
58 amrex::ParmParse pp("transport");
59 const std::string key = scalar_name + "_laminar_schmidt";
60 amrex::Real lam_schmidt = 1.0;
61 pp.query(key.c_str(), lam_schmidt);
62 return lam_schmidt;
63 }
64
65 static inline amrex::Real turbulent_schmidt(const std::string& scalar_name)
66 {
67 amrex::ParmParse pp("transport");
68 const std::string key = scalar_name + "_turbulent_schmidt";
69 amrex::Real turb_schmidt = 1.0;
70 pp.query(key.c_str(), turb_schmidt);
71 return turb_schmidt;
72 }
73
75 inline std::unique_ptr<ScratchField> mu() override
76 {
77 // Select the interface capturing method
78 auto mu = m_repo.create_scratch_field(1, 1);
79
81
82 const auto& vof = m_repo.get_field("vof");
83
84 for (int lev = 0; lev < m_repo.num_active_levels(); ++lev) {
85 for (amrex::MFIter mfi((*mu)(lev)); mfi.isValid(); ++mfi) {
86 const auto& vbx = mfi.growntilebox();
87 const auto& volfrac = vof(lev).const_array(mfi);
88 const auto& visc = (*mu)(lev).array(mfi);
89 const amrex::Real mu1 = m_mu1;
90 const amrex::Real mu2 = m_mu2;
91 amrex::ParallelFor(
92 vbx,
93 [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
94 visc(i, j, k) = mu1 * volfrac(i, j, k) +
95 mu2 * (1.0 - volfrac(i, j, k));
96 });
97 }
98 }
99
101
102 const auto& levelset = m_repo.get_field("levelset");
103 const auto& geom = m_repo.mesh().Geom();
104
105 for (int lev = 0; lev < m_repo.num_active_levels(); ++lev) {
106 for (amrex::MFIter mfi((*mu)(lev)); mfi.isValid(); ++mfi) {
107 const auto& vbx = mfi.growntilebox();
108 const auto& dx = geom[lev].CellSizeArray();
109 const auto& visc = (*mu)(lev).array(mfi);
110 const auto& phi = levelset(lev).const_array(mfi);
111 const amrex::Real eps =
112 std::cbrt(2. * dx[0] * dx[1] * dx[2]);
113 const amrex::Real mu1 = m_mu1;
114 const amrex::Real mu2 = m_mu2;
115 amrex::ParallelFor(
116 vbx,
117 [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
118 amrex::Real smooth_heaviside;
119 if (phi(i, j, k) > eps) {
120 smooth_heaviside = 1.0;
121 } else if (phi(i, j, k) < -eps) {
122 smooth_heaviside = 0.;
123 } else {
124 smooth_heaviside =
125 0.5 *
126 (1.0 + phi(i, j, k) / eps +
127 1.0 / M_PI *
128 std::sin(phi(i, j, k) * M_PI / eps));
129 }
130 visc(i, j, k) = mu1 * smooth_heaviside +
131 mu2 * (1.0 - smooth_heaviside);
132 });
133 }
134 }
135 }
136 return mu;
137 }
138
140 inline std::unique_ptr<ScratchField> alpha() override
141 {
142 // Select the interface capturing method
143 auto alpha = m_repo.create_scratch_field(1, 1);
144
146
147 const auto& vof = m_repo.get_field("vof");
148
149 for (int lev = 0; lev < m_repo.num_active_levels(); ++lev) {
150 for (amrex::MFIter mfi((*alpha)(lev)); mfi.isValid(); ++mfi) {
151 const auto& vbx = mfi.growntilebox();
152 const auto& volfrac = vof(lev).const_array(mfi);
153 const auto& thdiff = (*alpha)(lev).array(mfi);
154 const amrex::Real mu1 = m_mu1;
155 const amrex::Real mu2 = m_mu2;
156 const amrex::Real Pr1 = m_Pr1;
157 const amrex::Real Pr2 = m_Pr2;
158 amrex::ParallelFor(
159 vbx,
160 [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
161 thdiff(i, j, k) =
162 mu1 / Pr1 * volfrac(i, j, k) +
163 mu2 / Pr2 * (1.0 - volfrac(i, j, k));
164 });
165 }
166 }
167
169
170 const auto& levelset = m_repo.get_field("levelset");
171 const auto& geom = m_repo.mesh().Geom();
172
173 for (int lev = 0; lev < m_repo.num_active_levels(); ++lev) {
174 for (amrex::MFIter mfi((*alpha)(lev)); mfi.isValid(); ++mfi) {
175 const auto& vbx = mfi.growntilebox();
176 const auto& dx = geom[lev].CellSizeArray();
177 const auto& visc = (*alpha)(lev).array(mfi);
178 const auto& phi = levelset(lev).const_array(mfi);
179 const amrex::Real eps =
180 std::cbrt(2. * dx[0] * dx[1] * dx[2]);
181 const amrex::Real mu1 = m_mu1;
182 const amrex::Real mu2 = m_mu2;
183 const amrex::Real Pr1 = m_Pr1;
184 const amrex::Real Pr2 = m_Pr2;
185 amrex::ParallelFor(
186 vbx,
187 [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
188 amrex::Real smooth_heaviside;
189 if (phi(i, j, k) > eps) {
190 smooth_heaviside = 1.0;
191 } else if (phi(i, j, k) < -eps) {
192 smooth_heaviside = 0.;
193 } else {
194 smooth_heaviside =
195 0.5 *
196 (1.0 + phi(i, j, k) / eps +
197 1.0 / M_PI *
198 std::sin(phi(i, j, k) * M_PI / eps));
199 }
200 visc(i, j, k) =
201 mu1 / Pr1 * smooth_heaviside +
202 mu2 / Pr2 * (1.0 - smooth_heaviside);
203 });
204 }
205 }
206 }
207 return alpha;
208 }
209
210 inline std::unique_ptr<ScratchField>
211 scalar_diffusivity(const std::string& scalar_name) override
212 {
213 amrex::Real lam_schmidt = laminar_schmidt(scalar_name);
214
215 amrex::Real inv_schmidt = 1.0 / lam_schmidt;
216 auto diff = mu();
217 for (int lev = 0; lev < m_repo.num_active_levels(); ++lev) {
218 (*diff)(lev).mult(inv_schmidt);
219 }
220
221 return diff;
222 }
223
224private:
227
230
233
235 amrex::Real m_mu1{1.0e-3};
236
238 amrex::Real m_mu2{1.0e-5};
239
241 amrex::Real m_Pr1{7.2};
242
244 amrex::Real m_Pr2{0.7};
245
247 amrex::Real m_Prt{1.0};
248};
249
250} // namespace amr_wind::transport
251
252#endif /* TWOPHASETRANSPORT_H */
Definition CFDSim.H:47
PhysicsMgr & physics_manager()
Definition CFDSim.H:68
Definition FieldRepo.H:86
std::unique_ptr< ScratchField > create_scratch_field(const std::string &name, const int ncomp=1, const int nghost=0, const FieldLoc floc=FieldLoc::CELL) const
Definition FieldRepo.cpp:302
Field & get_field(const std::string &name, const FieldState fstate=FieldState::New) const
Definition FieldRepo.cpp:149
int num_active_levels() const noexcept
Total number of levels currently active in the AMR mesh.
Definition FieldRepo.H:361
const amrex::AmrCore & mesh() const
Return a reference to the underlying AMR mesh instance.
Definition FieldRepo.H:358
Definition MultiPhase.H:27
InterfaceCapturingMethod interface_capturing_method()
Definition MultiPhase.cpp:80
T & get()
Return a concrete physics instance.
Definition Physics.H:104
Definition TransportModel.H:29
Definition TwoPhaseTransport.H:14
amrex::Real laminar_prandtl1() const
Definition TwoPhaseTransport.H:51
InterfaceCapturingMethod m_ifacetype
Interface capturing method variable.
Definition TwoPhaseTransport.H:232
amrex::Real m_Prt
Turbulent Prandtl number.
Definition TwoPhaseTransport.H:247
CFDSim & m_sim
Reference to the CFD sim.
Definition TwoPhaseTransport.H:226
std::unique_ptr< ScratchField > mu() override
Return the dynamic visocity field.
Definition TwoPhaseTransport.H:75
std::unique_ptr< ScratchField > scalar_diffusivity(const std::string &scalar_name) override
Scalar diffusivity based on Schmidt number.
Definition TwoPhaseTransport.H:211
amrex::Real turbulent_prandtl() const
Definition TwoPhaseTransport.H:54
TwoPhaseTransport(CFDSim &sim)
Definition TwoPhaseTransport.H:20
amrex::Real m_Pr1
Phase 1 (liquid) Prandtl number.
Definition TwoPhaseTransport.H:241
static constexpr bool constant_properties
Definition TwoPhaseTransport.H:16
amrex::Real laminar_prandtl2() const
Definition TwoPhaseTransport.H:52
amrex::Real m_mu1
Phase 1 (liquid) dynamic molecular viscosity.
Definition TwoPhaseTransport.H:235
FieldRepo & m_repo
Reference to the field repository (for creating scratch fields)
Definition TwoPhaseTransport.H:229
static std::string identifier()
Definition TwoPhaseTransport.H:18
amrex::Real m_mu2
Phase 2 (gas) dynamic molecular viscosity.
Definition TwoPhaseTransport.H:238
static amrex::Real turbulent_schmidt(const std::string &scalar_name)
Definition TwoPhaseTransport.H:65
amrex::Real m_Pr2
Phase 2 (gas) Prandtl number.
Definition TwoPhaseTransport.H:244
static amrex::Real laminar_schmidt(const std::string &scalar_name)
Definition TwoPhaseTransport.H:56
std::unique_ptr< ScratchField > alpha() override
Return the thermal diffusivity field (later divided by density, though)
Definition TwoPhaseTransport.H:140
Definition ConstTransport.H:7
InterfaceCapturingMethod
Definition MultiPhase.H:21