/home/runner/work/amr-wind/amr-wind/amr-wind/equation_systems/vof/vof_momentum_flux.H Source File

AMR-Wind API: /home/runner/work/amr-wind/amr-wind/amr-wind/equation_systems/vof/vof_momentum_flux.H Source File
AMR-Wind API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
vof_momentum_flux.H
Go to the documentation of this file.
1#ifndef VOF_MOMENTUM_FLUX_H
2#define VOF_MOMENTUM_FLUX_H
3
5#include "AMReX_REAL.H"
6
7using namespace amrex::literals;
8
9namespace amr_wind::multiphase {
10
11static inline void hybrid_fluxes(
12 const FieldRepo& repo,
13 const int ncomp,
14 const amrex::Gpu::DeviceVector<int>& iconserv,
15 ScratchField& flux_x,
16 ScratchField& flux_y,
17 ScratchField& flux_z,
18 const Field& dof_field,
19 const Field& dof_nph,
20 const Field& src_term,
21 const Field& rho_o,
22 const Field& rho_nph,
23 const Field& u_mac,
24 const Field& v_mac,
25 const Field& w_mac,
26 amrex::Vector<amrex::BCRec> const& velbc,
27 amrex::BCRec const* velbc_d,
28 amrex::Vector<amrex::BCRec> const& rhobc,
29 amrex::BCRec const* rhobc_d,
30 const amrex::Real dt,
31 godunov::scheme mflux_scheme,
32 bool allow_inflow_on_outflow,
33 bool use_forces_in_trans,
34 bool pre_multiplied_src_term = false)
35{
36 // Get geometry
37 const auto& geom = repo.mesh().Geom();
38 // Get advected alpha fields
39 // At this point in the solve, they have been converted to advected density
40 const auto& advrho_x = repo.get_field("advalpha_x");
41 const auto& advrho_y = repo.get_field("advalpha_y");
42 const auto& advrho_z = repo.get_field("advalpha_z");
43 // Get VOF
44 const auto& vof = repo.get_field("vof").state(amr_wind::FieldState::Old);
45
46 // Create scratch arrays for local flux storage
47 auto ftmp_x =
49 auto ftmp_y =
51 auto ftmp_z =
53
54 auto face_x =
56 auto face_y =
58 auto face_z =
60
61 // Create iconserv = 0 array for density, avoid multiplication by face vel
62 amrex::Gpu::DeviceVector<int> idnsty;
63 idnsty.resize(1, -1);
64
65 for (int lev = 0; lev < repo.num_active_levels(); ++lev) {
66 // Set up temporary arrays for fluxes that will replace other quantities
67 // form multifab for transport variable and source term
68 amrex::MultiFab q(
69 dof_field(lev).boxArray(), dof_field(lev).DistributionMap(), ncomp,
71 amrex::MultiFab::Copy(
72 q, dof_field(lev), 0, 0, ncomp, fvm::Godunov::nghost_state);
73 amrex::MultiFab fq(
74 src_term(lev).boxArray(), src_term(lev).DistributionMap(), ncomp,
76 amrex::MultiFab::Copy(
77 fq, src_term(lev), 0, 0, ncomp, fvm::Godunov::nghost_src);
78
79 for (int idim = 0; idim < dof_field.num_comp(); ++idim) {
80 amrex::MultiFab::Multiply(
81 q, rho_o(lev), 0, idim, 1, fvm::Godunov::nghost_state);
82 if (!pre_multiplied_src_term) {
83 amrex::MultiFab::Multiply(
84 fq, rho_o(lev), 0, idim, 1, fvm::Godunov::nghost_src);
85 }
86 }
87
88 amrex::MultiFab frho(
89 src_term(lev).boxArray(), src_term(lev).DistributionMap(), 1,
91 frho.setVal(0.0_rt);
92
93 // Set up temporary arrays for NPH at boundaries
94 amrex::MultiFab q_nph(
95 dof_field(lev).boxArray(), dof_field(lev).DistributionMap(), ncomp,
97 amrex::MultiFab::Copy(
98 q_nph, dof_nph(lev), 0, 0, ncomp, fvm::Godunov::nghost_state);
99 // Density at NPH is fully calculated a priori
100 // Multiply to get momentum at NPH
101 for (int idim = 0; idim < dof_field.num_comp(); ++idim) {
102 amrex::MultiFab::Multiply(q_nph, rho_nph(lev), 0, idim, 1, 1);
103 }
104
105 std::string advection_type = "Godunov";
106 int limiter_type = PPM::UPWIND; // default
107 if (mflux_scheme == godunov::scheme::MINMOD) {
108 limiter_type = PPM::MINMOD;
109 } else if (mflux_scheme != godunov::scheme::UPWIND) {
110 amrex::Abort("Unknown limiter type in vof_momentum_flux.H");
111 }
112
113 const bool known_edge_state = false;
114 const bool godunov_use_ppm = true;
115 const bool is_velocity = false;
116 const bool fluxes_are_area_weighted = false;
117
118 amrex::MFItInfo mfi_info;
119 if (amrex::Gpu::notInLaunchRegion()) {
120 mfi_info.EnableTiling(amrex::IntVect(1024, 1024, 1024))
121 .SetDynamic(true);
122 }
123#ifdef AMREX_USE_OMP
124#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
125#endif
126 for (amrex::MFIter mfi(dof_field(lev), mfi_info); mfi.isValid();
127 ++mfi) {
128 const auto& bx = mfi.tilebox();
129
130 // Arrays for easy reference (w for working array)
131 auto F_x = flux_x(lev).array(mfi);
132 auto F_y = flux_y(lev).array(mfi);
133 auto F_z = flux_z(lev).array(mfi);
134 auto Fw_x = (*ftmp_x)(lev).array(mfi);
135 auto Fw_y = (*ftmp_y)(lev).array(mfi);
136 auto Fw_z = (*ftmp_z)(lev).array(mfi);
137
138 // Temporary divu
139 amrex::FArrayBox divufab(
140 amrex::grow(bx, 1), 1, amrex::The_Async_Arena());
141 divufab.setVal<amrex::RunOn::Device>(0.0_rt);
142 const auto& divu = divufab.array();
143
144 // Compute momentum flux quantities (multiplied by face velocity)
145 HydroUtils::ComputeFluxesOnBoxFromState(
146 bx, ncomp, mfi, q.const_array(mfi), q_nph.const_array(mfi),
147 Fw_x, Fw_y, Fw_z, (*face_x)(lev).array(mfi),
148 (*face_y)(lev).array(mfi), (*face_z)(lev).array(mfi),
149 known_edge_state, u_mac(lev).const_array(mfi),
150 v_mac(lev).const_array(mfi), w_mac(lev).const_array(mfi), divu,
151 fq.const_array(mfi), geom[lev], dt, velbc, velbc_d,
152 iconserv.data(), godunov_use_ppm, use_forces_in_trans,
153 is_velocity, fluxes_are_area_weighted, advection_type,
154 limiter_type, allow_inflow_on_outflow);
155
156 const auto& bxg1 = amrex::grow(bx, 1);
157 const auto& xbx = amrex::surroundingNodes(bx, 0);
158 const auto& ybx = amrex::surroundingNodes(bx, 1);
159 const auto& zbx = amrex::surroundingNodes(bx, 2);
160
161 // Where interface is present, replace current momentum flux
162 // quantities with those from mflux_scheme
163 auto volfrac = vof(lev).const_array(mfi);
164 amrex::ParallelFor(
165 bxg1, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
166 bool vf_i = multiphase::interface_band(i, j, k, volfrac);
167 // Fluxes in each direction, check with flag too
168 if (xbx.contains(i, j, k)) {
169 bool vf_nb =
170 multiphase::interface_band(i - 1, j, k, volfrac);
171 if (vf_i || vf_nb) {
172 for (int n = 0; n < ncomp; ++n) {
173 F_x(i, j, k, n) = Fw_x(i, j, k, n);
174 }
175 }
176 }
177 if (ybx.contains(i, j, k)) {
178 bool vf_nb =
179 multiphase::interface_band(i, j - 1, k, volfrac);
180 if (vf_i || vf_nb) {
181 for (int n = 0; n < ncomp; ++n) {
182 F_y(i, j, k, n) = Fw_y(i, j, k, n);
183 }
184 }
185 }
186 if (zbx.contains(i, j, k)) {
187 bool vf_nb =
188 multiphase::interface_band(i, j, k - 1, volfrac);
189 if (vf_i || vf_nb) {
190 for (int n = 0; n < ncomp; ++n) {
191 F_z(i, j, k, n) = Fw_z(i, j, k, n);
192 }
193 }
194 }
195 });
196
197 // Compute density flux quantities (not multiplied by face velocity)
198 HydroUtils::ComputeFluxesOnBoxFromState(
199 bx, 1, mfi, rho_o(lev).const_array(mfi), Fw_x, Fw_y, Fw_z,
200 (*face_x)(lev).array(mfi), (*face_y)(lev).array(mfi),
201 (*face_z)(lev).array(mfi), known_edge_state,
202 u_mac(lev).const_array(mfi), v_mac(lev).const_array(mfi),
203 w_mac(lev).const_array(mfi), divu, frho.const_array(mfi),
204 geom[lev], dt, rhobc, rhobc_d, idnsty.data(), godunov_use_ppm,
205 use_forces_in_trans, is_velocity, fluxes_are_area_weighted,
206 advection_type, limiter_type, allow_inflow_on_outflow);
207
208 // At this point in the solve, these are advected
209 auto ar_x = advrho_x(lev).const_array(mfi);
210 auto ar_y = advrho_y(lev).const_array(mfi);
211 auto ar_z = advrho_z(lev).const_array(mfi);
212
213 // When interface is present, divide by interpolated density to get
214 // Favre-averaged flux value. Multiply all fluxes with advected
215 // face density to create mass-consistent fluxes
216 amrex::ParallelFor(
217 bxg1, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
218 bool vf_i = multiphase::interface_band(i, j, k, volfrac);
219 // Fluxes in each direction, check with flag too
220 if (xbx.contains(i, j, k)) {
221 bool vf_nb =
222 multiphase::interface_band(i - 1, j, k, volfrac);
223 for (int n = 0; n < ncomp; ++n) {
224 if (vf_i || vf_nb) {
225 F_x(i, j, k, n) /= Fw_x(i, j, k, 0);
226 }
227 F_x(i, j, k, n) *= ar_x(i, j, k);
228 }
229 }
230 if (ybx.contains(i, j, k)) {
231 bool vf_nb =
232 multiphase::interface_band(i, j - 1, k, volfrac);
233 for (int n = 0; n < ncomp; ++n) {
234 if (vf_i || vf_nb) {
235 F_y(i, j, k, n) /= Fw_y(i, j, k, 0);
236 }
237 F_y(i, j, k, n) *= ar_y(i, j, k);
238 }
239 }
240 if (zbx.contains(i, j, k)) {
241 bool vf_nb =
242 multiphase::interface_band(i, j, k - 1, volfrac);
243 for (int n = 0; n < ncomp; ++n) {
244 if (vf_i || vf_nb) {
245 F_z(i, j, k, n) /= Fw_z(i, j, k, 0);
246 }
247 F_z(i, j, k, n) *= ar_z(i, j, k);
248 }
249 }
250 });
251 }
252 }
253}
254} // namespace amr_wind::multiphase
255
256#endif
Definition Field.H:116
int num_comp() const
Number of components for this field.
Definition Field.H:134
Field & state(const FieldState fstate)
Return field at a different time state.
Definition Field.cpp:117
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:305
Field & get_field(const std::string &name, const FieldState fstate=FieldState::New) const
Definition FieldRepo.cpp:152
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 ScratchField.H:30
@ ZFACE
Face-centered in z-direction.
Definition FieldDescTypes.H:32
@ XFACE
Face-centered in x-direction (e.g., face normal velocity)
Definition FieldDescTypes.H:30
@ YFACE
Face-centered in y-direction.
Definition FieldDescTypes.H:31
@ Old
Same as FieldState::N.
Definition FieldDescTypes.H:21
Definition height_functions.H:8
static void hybrid_fluxes(const FieldRepo &repo, const int ncomp, const amrex::Gpu::DeviceVector< int > &iconserv, ScratchField &flux_x, ScratchField &flux_y, ScratchField &flux_z, const Field &dof_field, const Field &dof_nph, const Field &src_term, const Field &rho_o, const Field &rho_nph, const Field &u_mac, const Field &v_mac, const Field &w_mac, amrex::Vector< amrex::BCRec > const &velbc, amrex::BCRec const *velbc_d, amrex::Vector< amrex::BCRec > const &rhobc, amrex::BCRec const *rhobc_d, const amrex::Real dt, godunov::scheme mflux_scheme, bool allow_inflow_on_outflow, bool use_forces_in_trans, bool pre_multiplied_src_term=false)
Definition vof_momentum_flux.H:11
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool interface_band(const int i, const int j, const int k, amrex::Array4< amrex::Real const > const &volfrac, const int n_band=1, const amrex::Real tiny=constants::TIGHT_TOL) noexcept
Definition volume_fractions.H:503
scheme
Definition Godunov.H:11
@ UPWIND
Definition Godunov.H:11
@ MINMOD
Definition Godunov.H:11
static constexpr int nghost_state
Number of ghost in the state variable.
Definition SchemeTraits.H:19
static constexpr int nghost_src
Number of ghost cells in the source term variable.
Definition SchemeTraits.H:21