/home/runner/work/kynema-sgf/kynema-sgf/src/equation_systems/AdvOp_Godunov.H Source File

Kynema-SGF API: /home/runner/work/kynema-sgf/kynema-sgf/src/equation_systems/AdvOp_Godunov.H Source File
Kynema-SGF API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
AdvOp_Godunov.H
Go to the documentation of this file.
1#ifndef ADVOP_GODUNOV_H
2#define ADVOP_GODUNOV_H
3
4#include <type_traits>
5
11
12#include "AMReX_Gpu.H"
13#include "AMReX_ParmParse.H"
14#include "AMReX_MultiFabUtil.H"
15#include "hydro_utils.H"
16
18#include "AMReX_REAL.H"
19
20using namespace amrex::literals;
21
22namespace kynema_sgf::pde {
23
27template <typename PDE>
29 PDE,
30 fvm::Godunov,
31 typename std::enable_if_t<std::is_base_of_v<ScalarTransport, PDE>>>
32{
34 CFDSim& /* sim */,
35 PDEFields& fields_in,
36 bool /* has_overset */,
37 bool /* variable density */,
38 bool /* mesh mapping */,
39 bool /* is_anelastic */)
40 : fields(fields_in)
41 , density(fields_in.repo.get_field("density"))
42 , u_mac(fields_in.repo.get_field("u_mac"))
43 , v_mac(fields_in.repo.get_field("v_mac"))
44 , w_mac(fields_in.repo.get_field("w_mac"))
45 , m_flux_x(fields_in.repo.create_scratch_field(
46 PDE::ndim, 0, kynema_sgf::FieldLoc::XFACE))
47 , m_flux_y(fields_in.repo.create_scratch_field(
48 PDE::ndim, 0, kynema_sgf::FieldLoc::YFACE))
49 , m_flux_z(fields_in.repo.create_scratch_field(
50 PDE::ndim, 0, kynema_sgf::FieldLoc::ZFACE))
51 , m_face_x(fields_in.repo.create_scratch_field(
52 PDE::ndim, 0, kynema_sgf::FieldLoc::XFACE))
53 , m_face_y(fields_in.repo.create_scratch_field(
54 PDE::ndim, 0, kynema_sgf::FieldLoc::YFACE))
55 , m_face_z(fields_in.repo.create_scratch_field(
56 PDE::ndim, 0, kynema_sgf::FieldLoc::ZFACE))
57 {
58 amrex::ParmParse pp("incflo");
59 pp.query("godunov_type", godunov_type);
60 pp.query("godunov_use_forces_in_trans", godunov_use_forces_in_trans);
61 if (pp.contains("use_ppm") || pp.contains("use_limiter")) {
62 amrex::Abort(
63 "Godunov: use_ppm and use_limiter are deprecated. Please "
64 "update input file");
65 }
66
67 if (amrex::toLower(godunov_type) == "plm") {
69 } else if (amrex::toLower(godunov_type) == "ppm") {
71 } else if (amrex::toLower(godunov_type) == "ppm_nolim") {
73 amrex::Print() << "WARNING: Using advection type ppm_nolim is not "
74 "recommended. Prefer using weno_z."
75 << '\n';
76 } else if (amrex::toLower(godunov_type) == "bds") {
78 advection_type = "BDS";
79 } else if (
80 amrex::toLower(godunov_type) == "weno" ||
81 amrex::toLower(godunov_type) == "weno_js") {
83 } else if (amrex::toLower(godunov_type) == "weno_z") {
85 } else {
86 amrex::Abort(
87 "Invalid godunov_type specified. For godunov_type select "
88 "between plm, ppm, ppm_nolim, bds, weno_js, and weno_z. If no "
89 "godunov_type is specified, the default weno_z is used.");
90 }
91
92 // Flux calculation used in multiphase portions of domain
93 pp.query("mflux_type", mflux_type);
94 if (amrex::toLower(mflux_type) == "minmod") {
96 } else if (amrex::toLower(mflux_type) == "upwind") {
98 } else {
99 amrex::Abort("Invalid argument entered for mflux_type.");
100 }
101
102 amrex::ParmParse pp_eq{fields_in.field.base_name()};
103 pp_eq.query(
104 "allow_inflow_at_pressure_outflow", m_allow_inflow_on_outflow);
105
106 // TODO: Need iconserv flag to be adjusted???
107 iconserv.resize(PDE::ndim, 1);
108 }
109
111 const FieldState /*unused*/,
112 const amrex::Real /*unused*/,
113 const amrex::Real /*unused*/)
114 {}
115
116 void operator()(const FieldState fstate, const amrex::Real dt)
117 {
118 static_assert(
119 PDE::ndim == 1, "Invalid number of components for scalar");
120 auto& repo = fields.repo;
121 const auto& geom = repo.mesh().Geom();
122
123 const auto& src_term = fields.src_term;
124 // cppcheck-suppress constVariableReference
125 auto& conv_term = fields.conv_term;
126 const auto& dof_field = fields.field.state(fstate);
127 const auto& dof_nph = fields.field.state(kynema_sgf::FieldState::NPH);
128
129 auto& flux_x = *m_flux_x;
130 auto& flux_y = *m_flux_y;
131 auto& flux_z = *m_flux_z;
132 auto& face_x = *m_face_x;
133 auto& face_y = *m_face_y;
134 auto& face_z = *m_face_z;
135
136 // only needed if multiplying by rho below
137 const auto& den = density.state(fstate);
138 const auto& den_nph = density.state(kynema_sgf::FieldState::NPH);
139
140 const bool mphase_vof = repo.field_exists("vof");
141
142 for (int lev = 0; lev < repo.num_active_levels(); ++lev) {
143 amrex::MFItInfo mfi_info;
144 if (amrex::Gpu::notInLaunchRegion()) {
145 mfi_info.EnableTiling(amrex::IntVect(1024, 1024, 1024))
146 .SetDynamic(true);
147 }
148#ifdef AMREX_USE_OMP
149#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
150#endif
151 for (amrex::MFIter mfi(dof_field(lev), mfi_info); mfi.isValid();
152 ++mfi) {
153 const auto& bx = mfi.tilebox();
154 auto rho_arr = den(lev).array(mfi);
155 auto rho_nph_arr = den_nph(lev).array(mfi);
156 auto tra_arr = dof_field(lev).array(mfi);
157 auto tra_nph_arr = dof_nph(lev).array(mfi);
158 amrex::FArrayBox rhotracfab;
159 amrex::Array4<amrex::Real> rhotrac;
160 amrex::FArrayBox rhotrac_nph_fab;
161 amrex::Array4<amrex::Real> rhotrac_nph;
162 amrex::FArrayBox srctrac_over_rho_fab;
163 amrex::Array4<amrex::Real> srctrac_over_rho;
164 const auto& src_arr = src_term(lev).const_array(mfi);
165
166 if (PDE::multiply_rho) {
167 auto rhotrac_box =
168 amrex::grow(bx, fvm::Godunov::nghost_state);
169 auto srctrac_box =
170 amrex::grow(bx, fvm::Godunov::nghost_src);
171 rhotracfab.resize(
172 rhotrac_box, PDE::ndim, amrex::The_Async_Arena());
173 rhotrac = rhotracfab.array();
174 rhotrac_nph_fab.resize(
175 rhotrac_box, PDE::ndim, amrex::The_Async_Arena());
176 rhotrac_nph = rhotrac_nph_fab.array();
177 if (mphase_vof) {
178 srctrac_over_rho_fab.resize(
179 rhotrac_box, PDE::ndim, amrex::The_Async_Arena());
180 srctrac_over_rho = srctrac_over_rho_fab.array();
181 }
182
183 amrex::ParallelFor(
184 rhotrac_box, PDE::ndim,
185 [=] AMREX_GPU_DEVICE(int i, int j, int k, int n) {
186 rhotrac(i, j, k, n) =
187 rho_arr(i, j, k) * tra_arr(i, j, k, n);
188 rhotrac_nph(i, j, k, n) =
189 rho_nph_arr(i, j, k) * tra_nph_arr(i, j, k, n);
190 if (mphase_vof && srctrac_box.contains(i, j, k)) {
191 // Need to remove the effect of the multiply_rho
192 // routine -- the setup is different for
193 // mass-consistent multiphase advection
194 srctrac_over_rho(i, j, k, n) =
195 src_arr(i, j, k, n) / rho_nph_arr(i, j, k);
196 }
197 });
198 }
199
206 amrex::FArrayBox tmpfab(
207 amrex::grow(bx, 1), 1, amrex::The_Async_Arena());
208 tmpfab.setVal<amrex::RunOn::Device>(0.0_rt);
209 const auto& divu = tmpfab.array();
210 const bool is_velocity = false;
211 const bool known_edge_state = false;
212 const bool godunov_use_ppm =
215 int limiter_type;
217 limiter_type = PPM::NoLimiter;
219 limiter_type = PPM::WENOZ;
221 limiter_type = PPM::WENO_JS;
222 } else {
223 limiter_type = PPM::default_limiter;
224 }
225
226 // if state is NPH, then n and n+1 are known, and only
227 // spatial extrapolation is performed
228 const amrex::Real dt_extrap =
229 (fstate == FieldState::NPH) ? 0.0_rt : dt;
230
231 HydroUtils::ComputeFluxesOnBoxFromState(
232 bx, PDE::ndim, mfi,
233 ((PDE::multiply_rho && !mphase_vof) ? rhotrac
234 : tra_arr),
235 ((PDE::multiply_rho && !mphase_vof) ? rhotrac_nph
236 : tra_nph_arr),
237 flux_x(lev).array(mfi), flux_y(lev).array(mfi),
238 flux_z(lev).array(mfi), face_x(lev).array(mfi),
239 face_y(lev).array(mfi), face_z(lev).array(mfi),
240 known_edge_state, u_mac(lev).const_array(mfi),
241 v_mac(lev).const_array(mfi),
242 w_mac(lev).const_array(mfi), divu,
243 ((PDE::multiply_rho && mphase_vof)
244 ? srctrac_over_rho
245 : src_term(lev).const_array(mfi)),
246 geom[lev], dt_extrap, dof_field.bcrec(),
247 dof_field.bcrec_device().data(), iconserv.data(),
248 godunov_use_ppm, godunov_use_forces_in_trans,
250 limiter_type, m_allow_inflow_on_outflow);
251 } else {
252 amrex::Abort("Invalid godunov scheme");
253 }
254 }
255 }
256
257 // Multiphase flux operations
258 if (mphase_vof && PDE::multiply_rho) {
259 // Loop levels
261 repo, PDE::ndim, iconserv, flux_x, flux_y, flux_z, dof_field,
262 dof_nph, src_term, den, den_nph, u_mac, v_mac, w_mac,
263 dof_field.bcrec(), dof_field.bcrec_device().data(), den.bcrec(),
264 den.bcrec_device().data(), dt, mflux_scheme,
266 }
267
268 amrex::Vector<amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>> fluxes(
269 repo.num_active_levels());
270 for (int lev = 0; lev < repo.num_active_levels(); ++lev) {
271 fluxes[lev][0] = &flux_x(lev);
272 fluxes[lev][1] = &flux_y(lev);
273 fluxes[lev][2] = &flux_z(lev);
274 }
275
276 // In order to enforce conservation across coarse-fine boundaries we
277 // must be sure to average down the fluxes before we use them
278 for (int lev = repo.num_active_levels() - 1; lev > 0; --lev) {
279 amrex::IntVect rr =
280 geom[lev].Domain().size() / geom[lev - 1].Domain().size();
281 amrex::average_down_faces(
282 GetArrOfConstPtrs(fluxes[lev]), fluxes[lev - 1], rr,
283 geom[lev - 1]);
284 }
285
286 for (int lev = 0; lev < repo.num_active_levels(); ++lev) {
287#ifdef AMREX_USE_OMP
288#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
289#endif
290 for (amrex::MFIter mfi(dof_field(lev), amrex::TilingIfNotGPU());
291 mfi.isValid(); ++mfi) {
292 const auto& bx = mfi.tilebox();
293
294 HydroUtils::ComputeDivergence(
295 bx, conv_term(lev).array(mfi), flux_x(lev).array(mfi),
296 flux_y(lev).array(mfi), flux_z(lev).array(mfi), PDE::ndim,
297 geom[lev], amrex::Real(-1.0_rt), fluxes_are_area_weighted);
298 }
299 }
300 }
301
307
308 std::unique_ptr<ScratchField> m_flux_x;
309 std::unique_ptr<ScratchField> m_flux_y;
310 std::unique_ptr<ScratchField> m_flux_z;
311 std::unique_ptr<ScratchField> m_face_x;
312 std::unique_ptr<ScratchField> m_face_y;
313 std::unique_ptr<ScratchField> m_face_z;
314
315 amrex::Gpu::DeviceVector<int> iconserv;
316
319 std::string godunov_type{"weno_z"};
320 std::string mflux_type{"upwind"};
321 const bool fluxes_are_area_weighted{false};
324 std::string advection_type{"Godunov"};
325};
326
327} // namespace kynema_sgf::pde
328
329#endif /* ADVOP_GODUNOV_H */
Definition CFDSim.H:55
Definition Field.H:112
const std::string & base_name() const
Base name (without state information)
Definition Field.H:124
FieldLoc
Definition FieldDescTypes.H:29
FieldState
Definition FieldDescTypes.H:16
@ ZFACE
Face-centered in z-direction.
Definition FieldDescTypes.H:34
@ XFACE
Face-centered in x-direction (e.g., face normal velocity)
Definition FieldDescTypes.H:32
@ YFACE
Face-centered in y-direction.
Definition FieldDescTypes.H:33
@ NPH
State at (n + 1/2) (intermediate) timestep.
Definition FieldDescTypes.H:20
scheme
Definition Godunov.H:8
@ BDS
Definition Godunov.H:12
@ PPM
Definition Godunov.H:10
@ UPWIND
Definition Godunov.H:16
@ PLM
Definition Godunov.H:9
@ WENO_JS
Definition Godunov.H:13
@ MINMOD
Definition Godunov.H:15
@ PPM_NOLIM
Definition Godunov.H:11
@ WENOZ
Definition Godunov.H:14
Definition SchemeTraits.H:6
static AMREX_INLINE 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
Definition AdvOp_Godunov.H:22
This test case is intended as an evaluation of the momentum advection scheme.
Definition BCInterface.cpp:10
static constexpr int nghost_src
Number of ghost cells in the source term variable.
Definition SchemeTraits.H:21
static constexpr int nghost_state
Number of ghost in the state variable.
Definition SchemeTraits.H:19
AdvectionOp(CFDSim &, PDEFields &fields_in, bool, bool, bool, bool)
Definition AdvOp_Godunov.H:33
void preadvect(const FieldState, const amrex::Real, const amrex::Real)
Definition AdvOp_Godunov.H:110
void operator()(const FieldState fstate, const amrex::Real dt)
Definition AdvOp_Godunov.H:116
Definition PDEFields.H:27
Field & field
Solution variable (e.g., velocity, temperature)
Definition PDEFields.H:34