Skip to content

Commit 38d1b9f

Browse files
authored
Underwater terrain-aware wave forcing (Exawind#1475)
* turn off apply_relaxation_zones where terrain blanking (or terrain drag forcing) happens * modify ow boundary for underwater terrain * add regression test
1 parent 4f11d0b commit 38d1b9f

File tree

6 files changed

+2291
-8
lines changed

6 files changed

+2291
-8
lines changed

amr-wind/ocean_waves/boundary_ops/OceanWavesBoundary.H

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define OCEANWAVESBOUNDARY_H
33

44
#include "amr-wind/core/Field.H"
5+
#include "amr-wind/core/IntField.H"
56
#include "amr-wind/CFDSim.H"
67
#include "AMReX_Gpu.H"
78
#include <AMReX_BndryRegister.H>
@@ -61,10 +62,17 @@ private:
6162
const amrex::AmrCore& m_mesh;
6263
Field& m_ow_velocity;
6364
Field& m_ow_vof;
65+
IntField* m_terrain_blank_ptr{nullptr};
6466

6567
// Should be active unless boundary planes are used
6668
bool m_activate_ow_bndry{true};
6769

70+
// Check for single-phase simulation
71+
bool m_vof_exists{true};
72+
73+
// Check for terrain
74+
bool m_terrain_exists{false};
75+
6876
// Store time corresponding to current boundary data
6977
amrex::Real m_bndry_time{0.0};
7078

amr-wind/ocean_waves/boundary_ops/OceanWavesBoundary.cpp

+49-6
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,20 @@ void OceanWavesBoundary::post_init_actions()
4242
m_repo.get_field("velocity")
4343
.register_fill_patch_op<OceanWavesFillInflow>(
4444
m_mesh, m_time, *this);
45-
if (m_repo.field_exists("vof")) {
45+
m_vof_exists = m_repo.field_exists("vof");
46+
if (m_vof_exists) {
4647
m_repo.get_field("vof")
4748
.register_fill_patch_op<OceanWavesFillInflow>(
4849
m_mesh, m_time, *this);
4950
m_repo.get_field("density")
5051
.register_fill_patch_op<OceanWavesFillInflow>(
5152
m_mesh, m_time, *this);
5253
}
54+
55+
m_terrain_exists = m_repo.int_field_exists("terrain_blank");
56+
if (m_terrain_exists) {
57+
m_terrain_blank_ptr = &m_repo.get_int_field("terrain_blank");
58+
}
5359
}
5460
}
5561

@@ -73,6 +79,8 @@ void OceanWavesBoundary::set_velocity(
7379
const int nghost = 1;
7480
const auto& domain = geom.growPeriodicDomain(nghost);
7581

82+
const bool terrain_and_vof_exist = m_terrain_exists && m_vof_exists;
83+
7684
for (amrex::OrientationIter oit; oit != nullptr; ++oit) {
7785
auto ori = oit();
7886
if ((bctype[ori] != BC::mass_inflow) &&
@@ -85,10 +93,14 @@ void OceanWavesBoundary::set_velocity(
8593
const auto& dbx = ori.isLow() ? amrex::adjCellLo(domain, idir, nghost)
8694
: amrex::adjCellHi(domain, idir, nghost);
8795

96+
auto shift_to_interior =
97+
amrex::IntVect::TheDimensionVector(idir) * (ori.isLow() ? 1 : -1);
98+
8899
for (amrex::MFIter mfi(mfab); mfi.isValid(); ++mfi) {
89100
auto gbx = amrex::grow(mfi.validbox(), nghost);
90-
const auto& bx =
91-
utils::face_aware_boundary_box_intersection(gbx, dbx, ori);
101+
amrex::IntVect shift_to_cc = {0, 0, 0};
102+
const auto& bx = utils::face_aware_boundary_box_intersection(
103+
shift_to_cc, gbx, dbx, ori);
92104
if (!bx.ok()) {
93105
continue;
94106
}
@@ -98,12 +110,25 @@ void OceanWavesBoundary::set_velocity(
98110
const auto& arr = mfab[mfi].array();
99111
const int numcomp = mfab.nComp();
100112

113+
const auto terrain_blank_flags =
114+
terrain_and_vof_exist
115+
? (*m_terrain_blank_ptr)(lev).const_array(mfi)
116+
: amrex::Array4<int const>();
117+
101118
amrex::ParallelFor(
102119
bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
120+
const amrex::IntVect iv{i, j, k};
103121
for (int n = 0; n < numcomp; n++) {
104-
if (targ_vof(i, j, k) > constants::TIGHT_TOL) {
105-
arr(i, j, k, dcomp + n) =
106-
targ_arr(i, j, k, orig_comp + n);
122+
if (targ_vof(iv) > constants::TIGHT_TOL) {
123+
arr(iv, dcomp + n) = targ_arr(iv, orig_comp + n);
124+
}
125+
if (terrain_and_vof_exist) {
126+
// Terrain-blanked adjacent cell means 0 velocity
127+
if (terrain_blank_flags(
128+
iv + shift_to_cc + shift_to_interior) ==
129+
1) {
130+
arr(iv, dcomp + n) = 0.0;
131+
}
107132
}
108133
}
109134
});
@@ -225,6 +250,7 @@ void OceanWavesBoundary::set_inflow_sibling_velocity(
225250

226251
BL_PROFILE("amr-wind::OceanWavesBoundary::set_inflow_sibling_velocity");
227252

253+
const bool terrain_and_vof_exist = m_terrain_exists && m_vof_exists;
228254
const auto& bctype = fld.bc_type();
229255
const auto& geom = fld.repo().mesh().Geom(lev);
230256

@@ -238,6 +264,10 @@ void OceanWavesBoundary::set_inflow_sibling_velocity(
238264

239265
const int idir = ori.coordDir();
240266
const auto& domain_box = geom.Domain();
267+
268+
auto shift_to_interior =
269+
amrex::IntVect::TheDimensionVector(idir) * (ori.isLow() ? 1 : -1);
270+
241271
for (int fdir = 0; fdir < AMREX_SPACEDIM; ++fdir) {
242272

243273
// Only face-normal velocities populated here
@@ -268,6 +298,11 @@ void OceanWavesBoundary::set_inflow_sibling_velocity(
268298
const auto& targ_arr = m_ow_velocity(lev).const_array(mfi);
269299
const auto& marr = mfab[mfi].array();
270300

301+
const auto terrain_blank_flags =
302+
terrain_and_vof_exist
303+
? (*m_terrain_blank_ptr)(lev).const_array(mfi)
304+
: amrex::Array4<int const>();
305+
271306
amrex::ParallelFor(
272307
bx, [=] AMREX_GPU_DEVICE(
273308
const int i, const int j, const int k) noexcept {
@@ -277,6 +312,14 @@ void OceanWavesBoundary::set_inflow_sibling_velocity(
277312
if (targ_vof(cc_iv) > constants::TIGHT_TOL) {
278313
marr(i, j, k, 0) = targ_arr(cc_iv, fdir);
279314
}
315+
if (terrain_and_vof_exist) {
316+
// Terrain-blanked boundary-adjacent cell should set
317+
// boundary velocity to 0
318+
if (terrain_blank_flags(
319+
cc_iv + shift_to_interior) == 1) {
320+
marr(i, j, k, 0) = 0.0;
321+
}
322+
}
280323
});
281324
}
282325
}

amr-wind/ocean_waves/relaxation_zones/relaxation_zones_ops.cpp

+25-2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ void apply_relaxation_zones(CFDSim& sim, const RelaxZonesBaseData& wdata)
9191
auto& velocity = sim.repo().get_field("velocity");
9292
auto& density = sim.repo().get_field("density");
9393

94+
amr_wind::IntField* terrain_blank_ptr{nullptr};
95+
amr_wind::IntField* terrain_drag_ptr{nullptr};
96+
const bool terrain_exists = sim.repo().int_field_exists("terrain_blank");
97+
// Get fields to prevent forcing in or near underwater terrain
98+
if (terrain_exists) {
99+
terrain_blank_ptr = &sim.repo().get_int_field("terrain_blank");
100+
terrain_drag_ptr = &sim.repo().get_int_field("terrain_drag");
101+
}
102+
94103
for (int lev = 0; lev < nlevels; ++lev) {
95104
const auto& dx = geom[lev].CellSizeArray();
96105
const auto& problo = geom[lev].ProbLoArray();
@@ -101,6 +110,13 @@ void apply_relaxation_zones(CFDSim& sim, const RelaxZonesBaseData& wdata)
101110
const auto target_volfrac_arrs = ow_vof(lev).const_arrays();
102111
const auto target_vel_arrs = ow_vel(lev).const_arrays();
103112

113+
const auto terrain_blank_flags =
114+
terrain_exists ? (*terrain_blank_ptr)(lev).const_arrays()
115+
: amrex::MultiArray4<int const>();
116+
const auto terrain_drag_flags =
117+
terrain_exists ? (*terrain_drag_ptr)(lev).const_arrays()
118+
: amrex::MultiArray4<int const>();
119+
104120
const amrex::Real gen_length = wdata.gen_length;
105121
const amrex::Real beach_length = wdata.beach_length;
106122
const amrex::Real beach_length_factor = wdata.beach_length_factor;
@@ -125,8 +141,15 @@ void apply_relaxation_zones(CFDSim& sim, const RelaxZonesBaseData& wdata)
125141
const auto target_volfrac = target_volfrac_arrs[nbx];
126142
const auto target_vel = target_vel_arrs[nbx];
127143

144+
bool in_or_near_terrain{false};
145+
if (terrain_exists) {
146+
in_or_near_terrain =
147+
(terrain_blank_flags[nbx](i, j, k) == 1 ||
148+
terrain_drag_flags[nbx](i, j, k) == 1);
149+
}
150+
128151
// Generation region
129-
if (x <= problo[0] + gen_length) {
152+
if (x <= problo[0] + gen_length && !in_or_near_terrain) {
130153
const amrex::Real Gamma =
131154
utils::gamma_generate(x - problo[0], gen_length);
132155
// Get bounded new vof, incorporate with increment
@@ -164,7 +187,7 @@ void apply_relaxation_zones(CFDSim& sim, const RelaxZonesBaseData& wdata)
164187
}
165188
}
166189
// Outlet region
167-
if (x + beach_length >= probhi[0]) {
190+
if (x + beach_length >= probhi[0] && !in_or_near_terrain) {
168191
const amrex::Real Gamma = utils::gamma_absorb(
169192
x - (probhi[0] - beach_length), beach_length,
170193
beach_length_factor);

test/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ add_test_re(ow_linear)
254254
add_test_re(ow_linear_init_waves)
255255
add_test_re(ow_stokes)
256256
add_test_re(ow_current_wing)
257+
add_test_re(ow_current_bathymetry)
257258
add_test_re(scalar_advection_uniform)
258259
add_test_re(scalar_advection_refined)
259260
add_test_re(freestream_bds)

0 commit comments

Comments
 (0)