Skip to content

Commit 3e23581

Browse files
mukul1992marchdf
andauthored
Inflow-outflow boundary condition (#1066)
--------- Co-authored-by: Marc T. Henry de Frahan <marchdf@gmail.com>
1 parent ff277fc commit 3e23581

24 files changed

+522
-31
lines changed

amr-wind/boundary_conditions/BCInterface.H

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public:
4949
virtual void operator()(const amrex::Real value = 0.0);
5050

5151
//! User-defined functions for Dirichlet-type boundaries
52-
std::pair<const std::string, const std::string> get_dirichlet_udfs();
52+
amrex::Array<const std::string, 3> get_dirichlet_udfs();
5353

5454
protected:
5555
//! Setup AMReX mathematical BC types

amr-wind/boundary_conditions/BCInterface.cpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "amr-wind/boundary_conditions/BCInterface.H"
22
#include "amr-wind/core/FieldRepo.H"
33
#include "amr-wind/boundary_conditions/FixedGradientBC.H"
4+
#include "amr-wind/boundary_conditions/MassInflowOutflowBC.H"
45
#include "AMReX_ParmParse.H"
56

67
namespace amr_wind {
@@ -64,6 +65,8 @@ void BCIface::read_bctype()
6465
ibctype[ori] = BC::pressure_outflow;
6566
} else if ((bcstr == "mass_inflow") || (bcstr == "mi")) {
6667
ibctype[ori] = BC::mass_inflow;
68+
} else if ((bcstr == "mass_inflow_outflow") || (bcstr == "mio")) {
69+
ibctype[ori] = BC::mass_inflow_outflow;
6770
} else if ((bcstr == "no_slip_wall") || (bcstr == "nsw")) {
6871
ibctype[ori] = BC::no_slip_wall;
6972
} else if ((bcstr == "slip_wall") || (bcstr == "sw")) {
@@ -100,18 +103,27 @@ void BCIface::set_bcfuncs()
100103
if (bct == BC::fixed_gradient) {
101104
m_field.register_custom_bc<FixedGradientBC>(ori);
102105
}
106+
107+
if ((m_field.name() == "velocity") // only velocity for now
108+
&& (bct == BC::mass_inflow_outflow)) {
109+
110+
m_field.register_custom_bc<MassInflowOutflowBC>(ori);
111+
}
103112
}
104113
}
105114

106-
std::pair<const std::string, const std::string> BCIface::get_dirichlet_udfs()
115+
amrex::Array<const std::string, 3> BCIface::get_dirichlet_udfs()
107116
{
108117
const auto& fname = m_field.name();
109118
const auto& bctype = m_field.bc_type();
110119
const std::string inflow_key = fname + ".inflow_type";
120+
const std::string inflow_outflow_key = fname + ".inflow_outflow_type";
111121
const std::string wall_key = fname + ".wall_type";
112122
std::string inflow_udf{"ConstDirichlet"};
123+
std::string inflow_outflow_udf{"ConstDirichlet"};
113124
std::string wall_udf{"ConstDirichlet"};
114125
bool has_inflow_udf = false;
126+
bool has_inflow_outflow_udf = false;
115127
bool has_wall_udf = false;
116128

117129
for (amrex::OrientationIter oit; oit != nullptr; ++oit) {
@@ -135,6 +147,22 @@ std::pair<const std::string, const std::string> BCIface::get_dirichlet_udfs()
135147
}
136148
}
137149

150+
if (bct == BC::mass_inflow_outflow) {
151+
if (pp.contains(inflow_outflow_key.c_str())) {
152+
std::string val;
153+
pp.get(inflow_outflow_key.c_str(), val);
154+
155+
if (has_inflow_outflow_udf && (inflow_outflow_udf != val)) {
156+
amrex::Abort(
157+
"BC: Inflow-outflow UDF must be same for all "
158+
"inflow-outflow faces");
159+
} else {
160+
inflow_outflow_udf = val;
161+
has_inflow_outflow_udf = true;
162+
}
163+
}
164+
}
165+
138166
if (bct == BC::slip_wall) {
139167
if (pp.contains(wall_key.c_str())) {
140168
std::string val;
@@ -151,7 +179,7 @@ std::pair<const std::string, const std::string> BCIface::get_dirichlet_udfs()
151179
}
152180
}
153181

154-
return {inflow_udf, wall_udf};
182+
return {inflow_udf, inflow_outflow_udf, wall_udf};
155183
}
156184

157185
void BCVelocity::set_bcrec()
@@ -194,6 +222,15 @@ void BCVelocity::set_bcrec()
194222
}
195223
break;
196224

225+
case BC::mass_inflow_outflow:
226+
m_field.set_inout_bndry();
227+
if (side == amrex::Orientation::low) {
228+
set_bcrec_lo(dir, amrex::BCType::direction_dependent);
229+
} else {
230+
set_bcrec_hi(dir, amrex::BCType::direction_dependent);
231+
}
232+
break;
233+
197234
case BC::slip_wall:
198235
case BC::wall_model:
199236
if (side == amrex::Orientation::low) {
@@ -287,6 +324,15 @@ void BCScalar::set_bcrec()
287324
}
288325
break;
289326

327+
case BC::mass_inflow_outflow:
328+
m_field.set_inout_bndry();
329+
if (side == amrex::Orientation::low) {
330+
set_bcrec_lo(dir, amrex::BCType::direction_dependent);
331+
} else {
332+
set_bcrec_hi(dir, amrex::BCType::direction_dependent);
333+
}
334+
break;
335+
290336
case BC::slip_wall:
291337
case BC::wall_model:
292338
case BC::fixed_gradient:
@@ -310,15 +356,18 @@ void BCScalar::read_values()
310356
auto& bcval = m_field.bc_values();
311357
const int ndim = m_field.num_comp();
312358
const auto udfs = get_dirichlet_udfs();
313-
const auto const_dirichlet_inflow = udfs.first == "ConstDirichlet";
359+
const auto const_dirichlet_inflow = udfs[0] == "ConstDirichlet";
360+
const auto const_dirichlet_inflow_outflow = udfs[1] == "ConstDirichlet";
314361

315362
for (amrex::OrientationIter oit; oit != nullptr; ++oit) {
316363
auto ori = oit();
317364
const auto& bcid = bcnames[ori];
318365
const auto bct = bctype[ori];
319366

320367
amrex::ParmParse pp(bcid);
321-
if ((bct == BC::mass_inflow) && (const_dirichlet_inflow)) {
368+
if (((bct == BC::mass_inflow) && (const_dirichlet_inflow)) ||
369+
((bct == BC::mass_inflow_outflow) &&
370+
(const_dirichlet_inflow_outflow))) {
322371
pp.getarr(fname.c_str(), bcval[ori], 0, ndim);
323372
} else {
324373
pp.queryarr(fname.c_str(), bcval[ori], 0, ndim);

amr-wind/boundary_conditions/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ target_sources(${amr_wind_lib_name}
44
BCInterface.cpp
55
FixedGradientBC.cpp
66
scalar_bcs.cpp
7+
MassInflowOutflowBC.cpp
78
)
89

910
add_subdirectory(wall_models)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef MASSINFLOWOUTFLOWBC_H
2+
#define MASSINFLOWOUTFLOWBC_H
3+
4+
#include "amr-wind/core/FieldBCOps.H"
5+
#include "amr-wind/core/FieldRepo.H"
6+
7+
#include "AMReX_Orientation.H"
8+
9+
namespace amr_wind {
10+
11+
/** Custom Neumann fills for the inflow-outflow BC
12+
* \ingroup field_bc
13+
*
14+
* Used to fill the outflow boundary cells for mass-inflow-outflow BC
15+
*/
16+
class MassInflowOutflowBC : public FieldBCIface
17+
{
18+
public:
19+
MassInflowOutflowBC(Field& field, amrex::Orientation ori);
20+
21+
void operator()(Field& field, const FieldState /*rho_state*/) override;
22+
23+
private:
24+
Field& m_field;
25+
26+
amrex::Orientation m_ori;
27+
};
28+
29+
} // namespace amr_wind
30+
31+
#endif /* MASSINFLOWOUTFLOWBC_H */
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
#include "amr-wind/boundary_conditions/MassInflowOutflowBC.H"
3+
4+
namespace amr_wind {
5+
6+
MassInflowOutflowBC::MassInflowOutflowBC(Field& field, amrex::Orientation ori)
7+
: m_field(field), m_ori(ori)
8+
{}
9+
10+
void MassInflowOutflowBC::operator()(
11+
Field& /*field*/, const FieldState /*rho_state*/)
12+
{
13+
const auto& repo = m_field.repo();
14+
const auto& velocity = repo.get_field("velocity");
15+
const int ncomp = m_field.num_comp();
16+
const int idim = m_ori.coordDir();
17+
const auto islow = m_ori.isLow();
18+
const auto ishigh = m_ori.isHigh();
19+
const int nlevels = m_field.repo().num_active_levels();
20+
const amrex::IntVect iv_dir = {
21+
static_cast<int>(idim == 0), static_cast<int>(idim == 1),
22+
static_cast<int>(idim == 2)};
23+
24+
for (int lev = 0; lev < nlevels; ++lev) {
25+
const auto& domain = repo.mesh().Geom(lev).Domain();
26+
27+
amrex::MFItInfo mfi_info{};
28+
if (amrex::Gpu::notInLaunchRegion()) {
29+
mfi_info.SetDynamic(true);
30+
}
31+
#ifdef AMREX_USE_OMP
32+
#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
33+
#endif
34+
for (amrex::MFIter mfi(m_field(lev), mfi_info); mfi.isValid(); ++mfi) {
35+
auto bx = mfi.validbox();
36+
bx.grow(
37+
{static_cast<int>(idim != 0), static_cast<int>(idim != 1),
38+
static_cast<int>(idim != 2)});
39+
const auto& bc_a = m_field(lev).array(mfi);
40+
const auto& vel = velocity(lev).array(mfi);
41+
42+
if (islow && (bx.smallEnd(idim) == domain.smallEnd(idim))) {
43+
amrex::ParallelFor(
44+
amrex::bdryLo(bx, idim),
45+
[=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
46+
const amrex::IntVect iv = {i, j, k};
47+
const amrex::IntVect ivm = iv - iv_dir;
48+
if (vel(ivm[0], ivm[1], ivm[2], idim) < 0) {
49+
for (int n = 0; n < ncomp; n++) {
50+
bc_a(ivm[0], ivm[1], ivm[2], n) =
51+
bc_a(i, j, k, n);
52+
}
53+
}
54+
});
55+
}
56+
57+
if (ishigh && (bx.bigEnd(idim) == domain.bigEnd(idim))) {
58+
amrex::ParallelFor(
59+
amrex::bdryHi(bx, idim),
60+
[=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
61+
const amrex::IntVect iv = {i, j, k};
62+
const amrex::IntVect ivm = iv - iv_dir;
63+
if (vel(i, j, k, idim) > 0) {
64+
for (int n = 0; n < ncomp; n++) {
65+
bc_a(i, j, k, n) =
66+
bc_a(ivm[0], ivm[1], ivm[2], n);
67+
}
68+
}
69+
});
70+
}
71+
}
72+
}
73+
}
74+
75+
} // namespace amr_wind

amr-wind/boundary_conditions/scalar_bcs.H

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ void register_scalar_dirichlet(
2929
Field& field,
3030
const amrex::AmrCore& mesh,
3131
const SimTime& time,
32-
const std::pair<const std::string, const std::string>& udfs);
32+
const amrex::Array<const std::string, 3>& udfs);
3333

3434
} // namespace amr_wind::scalar_bc
3535

amr-wind/boundary_conditions/scalar_bcs.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ void register_scalar_dirichlet(
55
Field& field,
66
const amrex::AmrCore& mesh,
77
const SimTime& time,
8-
const std::pair<const std::string, const std::string>& udfs)
8+
const amrex::Array<const std::string, 3>& udfs)
99
{
10-
const std::string inflow_udf = udfs.first;
11-
const std::string wall_udf = udfs.second;
10+
const std::string& inflow_udf = udfs[0];
11+
const std::string& inflow_outflow_udf = udfs[1];
12+
const std::string& wall_udf = udfs[2];
1213

13-
if ((inflow_udf == "ConstDirichlet") && (wall_udf == "ConstDirichlet")) {
14+
if ((inflow_udf == "ConstDirichlet") &&
15+
(inflow_outflow_udf == "ConstDirichlet") &&
16+
(wall_udf == "ConstDirichlet")) {
1417
return;
1518
}
1619

@@ -19,7 +22,14 @@ void register_scalar_dirichlet(
1922
"Scalar BC: Only constant dirichlet supported for Wall BC");
2023
}
2124

22-
register_inflow_scalar_dirichlet<ConstDirichlet>(
23-
field, inflow_udf, mesh, time);
25+
if (inflow_udf != "ConstDirichlet") {
26+
register_inflow_scalar_dirichlet<ConstDirichlet>(
27+
field, inflow_udf, mesh, time);
28+
}
29+
30+
if (inflow_outflow_udf != "ConstDirichlet") {
31+
register_inflow_scalar_dirichlet<ConstDirichlet>(
32+
field, inflow_outflow_udf, mesh, time);
33+
}
2434
}
2535
} // namespace amr_wind::scalar_bc

amr-wind/boundary_conditions/velocity_bcs.H

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "amr-wind/physics/udfs/BurggrafLid.H"
1111
#include "amr-wind/physics/udfs/Rankine.H"
1212
#include "amr-wind/physics/udfs/CustomVelocity.H"
13+
#include "amr-wind/physics/udfs/TwoLayer.H"
1314

1415
namespace amr_wind::vel_bc {
1516

@@ -40,6 +41,10 @@ void register_inflow_vel_dirichlet(
4041
using InflowOp = BCOpCreator<udf::CustomVelocity, WallOp>;
4142
field.register_fill_patch_op<FieldFillPatchOps<InflowOp>>(
4243
mesh, time, InflowOp(field));
44+
} else if (inflow_udf == "TwoLayer") {
45+
using InflowOp = BCOpCreator<udf::TwoLayer, WallOp>;
46+
field.register_fill_patch_op<FieldFillPatchOps<InflowOp>>(
47+
mesh, time, InflowOp(field));
4348
} else {
4449
amrex::Abort("Velocity BC: Invalid dirichlet BC type = " + inflow_udf);
4550
}
@@ -49,12 +54,15 @@ void register_velocity_dirichlet(
4954
Field& field,
5055
const amrex::AmrCore& mesh,
5156
const SimTime& time,
52-
const std::pair<const std::string, const std::string>& udfs)
57+
const amrex::Array<const std::string, 3>& udfs)
5358
{
54-
const std::string inflow_udf = udfs.first;
55-
const std::string wall_udf = udfs.second;
59+
const std::string& inflow_udf = udfs[0];
60+
const std::string& inflow_outflow_udf = udfs[1];
61+
const std::string& wall_udf = udfs[2];
5662

57-
if ((inflow_udf == "ConstDirichlet") && (wall_udf == "ConstDirichlet")) {
63+
if ((inflow_udf == "ConstDirichlet") &&
64+
(inflow_outflow_udf == "ConstDirichlet") &&
65+
(wall_udf == "ConstDirichlet")) {
5866
return;
5967
}
6068

@@ -63,8 +71,15 @@ void register_velocity_dirichlet(
6371
"Velocity BC: Only constant dirichlet supported for Wall BC");
6472
}
6573

66-
register_inflow_vel_dirichlet<ConstDirichlet>(
67-
field, inflow_udf, mesh, time);
74+
if (inflow_udf != "ConstDirichlet") {
75+
register_inflow_vel_dirichlet<ConstDirichlet>(
76+
field, inflow_udf, mesh, time);
77+
}
78+
79+
if (inflow_outflow_udf != "ConstDirichlet") {
80+
register_inflow_vel_dirichlet<ConstDirichlet>(
81+
field, inflow_outflow_udf, mesh, time);
82+
}
6883
}
6984

7085
} // namespace amr_wind::vel_bc

amr-wind/core/Field.H

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,12 @@ public:
396396
inline bool& in_uniform_space() { return m_mesh_mapped; }
397397
inline bool in_uniform_space() const { return m_mesh_mapped; }
398398

399+
//! Check if any of the boundaries is a mass-inflow-outflow
400+
inline bool has_inout_bndry() const { return m_inout_bndry; }
401+
402+
//! Set the inout_bndry flag
403+
void set_inout_bndry() { m_inout_bndry = true; }
404+
399405
protected:
400406
Field(
401407
FieldRepo& repo,
@@ -425,6 +431,9 @@ protected:
425431

426432
//! Flag to track mesh mapping (to uniform space) of field
427433
bool m_mesh_mapped{false};
434+
435+
//! Flag to indicate whether any of the boundaries is mass-inflow-outflow
436+
bool m_inout_bndry{false};
428437
};
429438

430439
} // namespace amr_wind

0 commit comments

Comments
 (0)