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