Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
60ad11e
skeleton for Flather
mbkuhn Aug 21, 2026
8d4f33f
starting to do averages
mbkuhn Aug 21, 2026
01873d8
now for any lateral boundary
mbkuhn Aug 21, 2026
e1e9dd7
vof is assumed
mbkuhn Aug 21, 2026
04c9bb6
include terrain feature
mbkuhn Aug 21, 2026
9482b90
include averages within boundary
mbkuhn Aug 21, 2026
abb35b7
compute water height as well
mbkuhn Aug 21, 2026
f846972
basic Flather velocity calculation
mbkuhn Aug 22, 2026
ff8f933
refactor and add unit test
mbkuhn Aug 24, 2026
1521ee9
start to update unit test
mbkuhn Aug 24, 2026
b64c6a4
changes from unit testing - works with multiple levels
mbkuhn Aug 24, 2026
8fdf9d5
make unit test a little harder
mbkuhn Aug 24, 2026
7fe2099
only use interior values of mask array - now passes boundary unit test
mbkuhn Aug 24, 2026
edcdb78
forgot to resize some of the arrays
mbkuhn Aug 25, 2026
28a6ba5
remove unnecessary variable
mbkuhn Aug 25, 2026
2e7a201
start to make changes to do subsequent field fillpatch boundaries
mbkuhn Aug 25, 2026
e8583fe
fix check inside set_default_fillpatch_bc
mbkuhn Aug 25, 2026
75b1a6d
don't mess up sibling fields. Not sure exactly what to do instead
mbkuhn Aug 25, 2026
b7eb413
get the indices right for cell centers in set_velocity
mbkuhn Aug 25, 2026
2eeb191
remove offsets for domain lo, that's always 0
mbkuhn Aug 25, 2026
857cda3
restrict to normal components
mbkuhn Aug 25, 2026
c15a9f3
found the bug!!!!
mbkuhn Aug 26, 2026
a201171
use idx_max better
mbkuhn Aug 26, 2026
312b4ee
avoid using Flather modification if it is going to pull in gas
mbkuhn Aug 26, 2026
c340b53
remove unnecessary check for velocity field
mbkuhn Aug 26, 2026
4b3e266
- always reference field, not mfab
mbkuhn Aug 26, 2026
cba4321
separate internal and boundary calcs so that the correct data is used
mbkuhn Aug 26, 2026
eadcb57
give non-const access to multi-level vector
mbkuhn Aug 26, 2026
de6060a
make field for averaging depend on incoming state
mbkuhn Aug 27, 2026
a6cebe9
state considerations for vof
mbkuhn Aug 27, 2026
c6de51f
use mac velocities for averaging calculations when appropriate
mbkuhn Aug 27, 2026
0f266fb
remove unused field, add some const
mbkuhn Aug 27, 2026
6016005
make sure to not mess up the states with mac fields
mbkuhn Aug 27, 2026
8866f12
average over the correct indices for face velocities
mbkuhn Aug 27, 2026
ff491d4
include shifts to cell-centered data when operating on face fields (m…
mbkuhn Aug 27, 2026
b5a521a
use prescribed velocity as starting point for inflow
mbkuhn Aug 27, 2026
d5ab8b5
forgot conditional for mac fields
mbkuhn Aug 27, 2026
7ef2018
update final conditional
mbkuhn Aug 28, 2026
77ddffc
formatting
mbkuhn Aug 28, 2026
57d3d48
Merge branch 'main' into flather_bc
mbkuhn Aug 28, 2026
34ececc
address unused variables
mbkuhn Sep 1, 2026
8f06842
addressed missed _rt
mbkuhn Sep 1, 2026
8f098d6
remove redundant cast
mbkuhn Sep 1, 2026
7407202
address some more unused variables
mbkuhn Sep 1, 2026
f4d1cee
prescribe Flather vel uniformly if averaged_vel is under a threshold;…
mbkuhn Sep 1, 2026
7b461d0
fix dangling reference
mbkuhn Sep 1, 2026
33db42d
get unit tests to pass
mbkuhn Sep 1, 2026
5b41688
scaling should only apply to liquid
mbkuhn Sep 1, 2026
859def0
avoid modifying mixed outflow cells - modify unit test later
mbkuhn Sep 2, 2026
d78c389
add another outflow case
mbkuhn Sep 2, 2026
1ad9fae
maybe this will help with convergence
mbkuhn Sep 2, 2026
c61c64b
update unit test
mbkuhn Sep 3, 2026
1c573cb
prevent inflow at outflow
mbkuhn Sep 3, 2026
5b6ab03
expand outputs to include boundary cells
mbkuhn Sep 3, 2026
3607683
correct phase switch for multiphase cells
mbkuhn Sep 3, 2026
20b4821
avoid dividing by 0, override multiphase velocity with Flather veloci…
mbkuhn Sep 3, 2026
ffcd7a2
more conditionals
mbkuhn Sep 3, 2026
dadd7ea
address case where boundary_h = 0
mbkuhn Sep 3, 2026
1fac42a
put a check against large scales
mbkuhn Sep 3, 2026
33d93ab
basic outflow if boundary_h is too small
mbkuhn Sep 4, 2026
8fbdb04
another edge case?
mbkuhn Sep 4, 2026
7cbfc12
correct conditional
mbkuhn Sep 4, 2026
ad0f3fc
try a limit on the scale
mbkuhn Sep 4, 2026
0fed0f0
try overriding interior instead
mbkuhn Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,7 @@ void BoundaryPlane::initialize_data()
if (m_repo.field_exists(fname)) {
auto& fld = m_repo.get_field(fname);
if (m_io_mode == io_mode::input) {
fld.register_fill_patch_op<PlaneFillInflow>(
m_mesh, m_time, *this);
fld.add_fill_patch_op<PlaneFillInflow>(m_mesh, m_time, *this);
}
m_fields.emplace_back(&fld);
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/boundary_conditions/field_boundary_fill/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ target_sources(${kynema_sgf_lib_name}
OceanWavesBoundary.cpp
PlaneFillInflow.cpp
BoundaryPlane.cpp
FillFlather.cpp
Flather.cpp
FillMPL.cpp
ModulatedPowerLaw.cpp
)
60 changes: 60 additions & 0 deletions src/boundary_conditions/field_boundary_fill/FillFlather.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef FILLFLATHER_H
#define FILLFLATHER_H

#include "src/core/FieldFillPatchOps.H"
#include "src/core/FieldBCOps.H"
#include "src/boundary_conditions/field_boundary_fill/Flather.H"

namespace kynema_sgf {

/** Fill patch operator that applies Flather boundary updates. */
class FillFlather : public FieldFillPatchOps<FieldBCDirichlet>
{
public:
FillFlather(
Field& field,
const amrex::AmrCore& mesh,
const SimTime& time,
Flather& flather);

~FillFlather() override;

void fillpatch(
int lev,
amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& nghost,
FieldState fstate = FieldState::New) override;

void fillpatch_sibling_fields(
int lev,
amrex::Real time,
amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& mfabs,
amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& ffabs,
amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& cfabs,
const amrex::IntVect& nghost,
const amrex::Vector<amrex::BCRec>& bcrec,
const amrex::Vector<amrex::BCRec>& /* unused */,
FieldState fstate = FieldState::New) override;

void fillpatch_from_coarse(
int lev,
amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& nghost,
FieldState fstate = FieldState::New) override;

void fillphysbc(
int lev,
amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& nghost,
FieldState fstate = FieldState::New) override;

protected:
Flather& m_flather;
};

} // namespace kynema_sgf

#endif /* FILLFLATHER_H */
75 changes: 75 additions & 0 deletions src/boundary_conditions/field_boundary_fill/FillFlather.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <utility>

#include "src/boundary_conditions/field_boundary_fill/FillFlather.H"

namespace kynema_sgf {

FillFlather::FillFlather(
Field& field,
const amrex::AmrCore& mesh,
const SimTime& time,
Flather& flather)
: FieldFillPatchOps<FieldBCDirichlet>(
field, mesh, time, FieldInterpolator::CellConsLinear)
, m_flather(flather)
{}

FillFlather::~FillFlather() = default;

void FillFlather::fillpatch(
const int lev,
const amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& /* nghost */,
const FieldState fstate)
{
if (m_field.base_name() == "velocity") {
m_flather.update_flather_variables(lev, fstate);
m_flather.set_velocity(lev, time, m_field, mfab);
}
}

void FillFlather::fillpatch_from_coarse(
const int lev,
const amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& /* nghost */,
const FieldState fstate)
{
if (m_field.base_name() == "velocity") {
m_flather.update_flather_variables(lev, fstate);
m_flather.set_velocity(lev, time, m_field, mfab);
}
}

void FillFlather::fillphysbc(
const int lev,
const amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& /* nghost */,
const FieldState fstate)
{
if (m_field.base_name() == "velocity") {
m_flather.update_flather_variables(lev, fstate);
m_flather.set_velocity(lev, time, m_field, mfab);
}
}

void FillFlather::fillpatch_sibling_fields(
const int lev,
const amrex::Real time,
amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& mfabs,
amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& /* ffabs */,
amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& /* cfabs */,
const amrex::IntVect& /* nghost */,
const amrex::Vector<amrex::BCRec>& /* bcrec */,
const amrex::Vector<amrex::BCRec>& /* unused */,
const FieldState fstate)
{
m_flather.update_flather_variables(lev, fstate, true);
for (int i = 0; std::cmp_less(i, mfabs.size()); ++i) {
m_flather.set_velocity(lev, time, m_field, *mfabs[i], 0, i);
}
}

} // namespace kynema_sgf
72 changes: 30 additions & 42 deletions src/boundary_conditions/field_boundary_fill/FillMPL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ void FillMPL::fillpatch(
const int lev,
const amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& nghost,
const FieldState fstate)
const amrex::IntVect& /* nghost */,
const FieldState /* fstate */)
{
FieldFillPatchOps<FieldBCDirichlet>::fillpatch(
lev, time, mfab, nghost, fstate);

if (m_field.base_name() == "velocity") {
m_abl_mpl.set_velocity(lev, time, m_field, mfab);
} else if (m_field.base_name() == "temperature") {
Expand All @@ -37,12 +34,9 @@ void FillMPL::fillpatch_from_coarse(
const int lev,
const amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& nghost,
const FieldState fstate)
const amrex::IntVect& /* nghost */,
const FieldState /* fstate */)
{
FieldFillPatchOps<FieldBCDirichlet>::fillpatch_from_coarse(
lev, time, mfab, nghost, fstate);

if (m_field.base_name() == "velocity") {
m_abl_mpl.set_velocity(lev, time, m_field, mfab);
} else if (m_field.base_name() == "temperature") {
Expand All @@ -54,12 +48,9 @@ void FillMPL::fillphysbc(
const int lev,
const amrex::Real time,
amrex::MultiFab& mfab,
const amrex::IntVect& nghost,
const FieldState fstate)
const amrex::IntVect& /* nghost */,
const FieldState /* fstate */)
{
FieldFillPatchOps<FieldBCDirichlet>::fillphysbc(
lev, time, mfab, nghost, fstate);

if (m_field.base_name() == "velocity") {
m_abl_mpl.set_velocity(lev, time, m_field, mfab);
} else if (m_field.base_name() == "temperature") {
Expand All @@ -78,39 +69,36 @@ void FillMPL::fillpatch_sibling_fields(
const amrex::Vector<amrex::BCRec>& /* unused */,
const FieldState fstate)
{
if (m_field.base_name() == "velocity") {
// For an ABL MPL, we first just foextrap the mac velocities
amrex::Vector<amrex::BCRec> lbcrec(m_field.num_comp());
const auto& ibctype = m_field.bc_type();
for (amrex::OrientationIter oit; oit != nullptr; ++oit) {
auto ori = oit();
const auto side = ori.faceDir();
const auto bct = ibctype[ori];
const int dir = ori.coordDir();
for (int i = 0; i < m_field.num_comp(); ++i) {
if ((bct == BC::mass_inflow) ||
(bct == BC::mass_inflow_outflow)) {
if (side == amrex::Orientation::low) {
lbcrec[i].setLo(dir, amrex::BCType::foextrap);
} else {
lbcrec[i].setHi(dir, amrex::BCType::foextrap);
}
// For an ABL MPL, we first just foextrap the mac velocities
amrex::Vector<amrex::BCRec> lbcrec(m_field.num_comp());
const auto& ibctype = m_field.bc_type();
for (amrex::OrientationIter oit; oit != nullptr; ++oit) {
auto ori = oit();
const auto side = ori.faceDir();
const auto bct = ibctype[ori];
const int dir = ori.coordDir();
for (int i = 0; i < m_field.num_comp(); ++i) {
if ((bct == BC::mass_inflow) || (bct == BC::mass_inflow_outflow)) {
if (side == amrex::Orientation::low) {
lbcrec[i].setLo(dir, amrex::BCType::foextrap);
} else {
if (side == amrex::Orientation::low) {
lbcrec[i].setLo(dir, bcrec[i].lo(dir));
} else {
lbcrec[i].setHi(dir, bcrec[i].hi(dir));
}
lbcrec[i].setHi(dir, amrex::BCType::foextrap);
}
} else {
if (side == amrex::Orientation::low) {
lbcrec[i].setLo(dir, bcrec[i].lo(dir));
} else {
lbcrec[i].setHi(dir, bcrec[i].hi(dir));
}
}
}
}

FieldFillPatchOps<FieldBCDirichlet>::fillpatch_sibling_fields(
lev, time, mfabs, ffabs, cfabs, nghost, lbcrec, lbcrec, fstate);
FieldFillPatchOps<FieldBCDirichlet>::fillpatch_sibling_fields(
lev, time, mfabs, ffabs, cfabs, nghost, lbcrec, lbcrec, fstate);

for (int i = 0; std::cmp_less(i, mfabs.size()); i++) {
m_abl_mpl.set_velocity(lev, time, m_field, *mfabs[i], 0, i);
}
for (int i = 0; std::cmp_less(i, mfabs.size()); i++) {
m_abl_mpl.set_velocity(lev, time, m_field, *mfabs[i], 0, i);
}
}

Expand Down
107 changes: 107 additions & 0 deletions src/boundary_conditions/field_boundary_fill/Flather.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#ifndef FLATHER_H
#define FLATHER_H

#include "src/core/Field.H"
#include "src/core/IntField.H"
#include "src/CFDSim.H"
#include "src/boundary_conditions/field_boundary_fill/FieldBoundary.H"
#include "src/utilities/MultiLevelVector.H"
#include "src/utilities/trig_ops.H"
#include "AMReX_REAL.H"
#include <limits>

using namespace amrex::literals;

namespace kynema_sgf {

/** Flather-style open boundary for velocity
*
* This boundary reads current boundary ghost-cell values and adjacent interior
* values, computes a blended target, and writes updated boundary values.
*/
class Flather : public FieldBoundary::Register<Flather>
{
public:
static std::string identifier() { return "Flather"; }

explicit Flather(CFDSim& sim);

void post_init_actions() override;

void pre_advance_work() override;

void post_advance_work() override {}

void set_velocity(
int lev,
amrex::Real time,
const Field& fld,
amrex::MultiFab& mfab,
int dcomp = 0,
int orig_comp = 0) const override;

void update_flather_variables(const int lev, const FieldState fstate)
{
compute_boundary_z_averages(lev, fstate, false);
}

void update_flather_variables(
const int lev, const FieldState fstate, const bool use_mac_fields)
{
compute_boundary_z_averages(lev, fstate, use_mac_fields);
}

void accumulate_boundary(
int current_level,
int idir,
int phase_switch,
bool is_low,
MultiLevelVector& out_uvec,
MultiLevelVector& out_hvec,
bool sample_boundary,
FieldState fstate,
bool use_mac_fields = false) const;

private:
void compute_internal_z_averages();
void compute_boundary_z_averages(
int lev, FieldState fstate, bool use_mac_fields = false);

const CFDSim& m_sim;
const kynema_sgf::SimTime& m_time;
const FieldRepo& m_repo;
const amrex::AmrCore& m_mesh;
Field& m_velocity;
const Field& m_u_mac;
const Field& m_v_mac;
const Field& m_vof;
const IntField* m_terrain_blank{nullptr};
amrex::Vector<amrex::Real> m_gravity{0.0_rt, 0.0_rt, -9.81_rt};
amrex::Real m_rho1{1000.0_rt};
amrex::Real m_rho2{1.0_rt};

MultiLevelVector m_xlo_uliq{FieldLoc::CELL};
MultiLevelVector m_xhi_uliq{FieldLoc::CELL};
MultiLevelVector m_ylo_uliq{FieldLoc::CELL};
MultiLevelVector m_yhi_uliq{FieldLoc::CELL};
MultiLevelVector m_xlo_umix{FieldLoc::CELL};
MultiLevelVector m_xhi_umix{FieldLoc::CELL};
MultiLevelVector m_ylo_umix{FieldLoc::CELL};
MultiLevelVector m_yhi_umix{FieldLoc::CELL};
MultiLevelVector m_xlo_bnd_uvof{FieldLoc::CELL};
MultiLevelVector m_xhi_bnd_uvof{FieldLoc::CELL};
MultiLevelVector m_ylo_bnd_uvof{FieldLoc::CELL};
MultiLevelVector m_yhi_bnd_uvof{FieldLoc::CELL};
MultiLevelVector m_xlo_h_avg{FieldLoc::CELL};
MultiLevelVector m_xhi_h_avg{FieldLoc::CELL};
MultiLevelVector m_ylo_h_avg{FieldLoc::CELL};
MultiLevelVector m_yhi_h_avg{FieldLoc::CELL};
MultiLevelVector m_xlo_bnd_h_avg{FieldLoc::CELL};
MultiLevelVector m_xhi_bnd_h_avg{FieldLoc::CELL};
MultiLevelVector m_ylo_bnd_h_avg{FieldLoc::CELL};
MultiLevelVector m_yhi_bnd_h_avg{FieldLoc::CELL};
};

} // namespace kynema_sgf

#endif /* FLATHER_H */
Loading
Loading