/home/runner/work/kynema-sgf/kynema-sgf/src/ocean_waves/relaxation_zones/stokes_waves_ops.H Source File

Kynema-SGF API: /home/runner/work/kynema-sgf/kynema-sgf/src/ocean_waves/relaxation_zones/stokes_waves_ops.H Source File
Kynema-SGF API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
stokes_waves_ops.H
Go to the documentation of this file.
1#ifndef STOKES_WAVES_OPS_H
2#define STOKES_WAVES_OPS_H
3
11#include "AMReX_REAL.H"
12
13using namespace amrex::literals;
14
16
17template <>
19{
21 StokesWaves::DataType& data, const ::kynema_sgf::utils::MultiParser& pp)
22 {
23 auto& wdata = data.meta();
24 auto& info = data.info();
25 relaxation_zones::read_inputs(wdata, info, pp);
26
27 // Get gravity, assume negative z
28 amrex::Vector<amrex::Real> gravity{0.0_rt, 0.0_rt, -9.81_rt};
29 amrex::ParmParse pp_incflo("incflo");
30 pp_incflo.queryarr("gravity", gravity);
31 wdata.g = -gravity[2];
32
33 if (wdata.current > constants::TIGHT_TOL) {
34 amrex::Abort(
35 "Current is specified as nonzero, but current is not yet "
36 "implemented for Stokes Waves.");
37 }
38
39 // Get wave attributes
40 pp.get("wave_height", wdata.wave_height);
41 pp.get("order", wdata.order);
42 if (pp.contains("wave_length")) {
43 pp.get("wave_length", wdata.wave_length);
44 } else {
45 // Wave length will be calculated using wave period
46 amrex::Real wave_period = 1.0_rt;
47 pp.get("wave_period", wave_period);
48 // User can specify a different order for wavelength calculation,
49 // e.g., an order of 1 will use the linear dispersion relation.
50 // Default is to use the same order as the waves themselves.
51 int order_lambda = wdata.order;
52 pp.query("stokes_wavelength_order", order_lambda);
53 // Get user-specified convergence criteria, if supplied
54 amrex::Real tol_lambda = 1.0e-10_rt;
55 int itmax_lambda = 40;
56 pp.query("stokes_wavelength_tolerance", tol_lambda);
57 pp.query("stokes_wavelength_iter_max", itmax_lambda);
58 wdata.wave_length = relaxation_zones::stokes_wave_length(
59 wave_period, wdata.water_depth, wdata.wave_height, order_lambda,
60 wdata.g, tol_lambda, itmax_lambda);
61 // Abort if wave length is negative
62 if (wdata.wave_length < 0.0_rt) {
63 if (wdata.wave_length == -1) {
64 amrex::Print() << "Stokes wave length too close to 0.\n";
65 }
66 if (wdata.wave_length == -2) {
67 amrex::Print() << "Stokes wave length is not a number.\n";
68 }
69 if (wdata.wave_length == -3) {
70 amrex::Print() << "Stokes wave length calculation used "
71 "maximum iterations before converging.\n";
72 }
73 amrex::Abort(
74 "Failed to properly calculate a wave length in "
75 "stokes_waves_ops.H");
76 } else {
77 amrex::Print() << "Stokes wave length calculated to be "
78 << wdata.wave_length << " m.\n";
79 }
80 }
81 pp.query("wave_phase_offset_radians", wdata.wave_phase_offset);
82 if (!pp.contains("wave_phase_offset_radians")) {
83 pp.query("wave_phase_offset_degrees", wdata.wave_phase_offset);
84 wdata.wave_phase_offset *=
85 std::numbers::pi_v<amrex::Real> / 180.0_rt;
86 } else if (pp.contains("wave_phase_offset_degrees")) {
87 amrex::Abort(
88 "ReadInputsOp<StokesWaves> : wave phase offset is specified in "
89 "both radians and degrees. Please use only one.");
90 }
91 }
92};
93
94template <>
96{
99 int level,
100 const amrex::Geometry& geom,
101 bool multiphase_mode)
102 {
103 const auto& wdata = data.meta();
104
105 auto& sim = data.sim();
106 Field* levelset{nullptr};
107 if (multiphase_mode) {
108 levelset = &sim.repo().get_field("levelset");
109 }
110 // cppcheck-suppress constVariableReference
111 auto& velocity = sim.repo().get_field("velocity");
112 const auto& problo = geom.ProbLoArray();
113 const auto& probhi = geom.ProbHiArray();
114 const auto& dx = geom.CellSizeArray();
115
116 const auto& vel = velocity(level).arrays();
117 const auto& phi_arrs = multiphase_mode
118 ? (*levelset)(level).arrays()
119 : amrex::MultiArray4<amrex::Real>();
120
121 const amrex::Real wave_height = wdata.wave_height;
122 const amrex::Real wave_length = wdata.wave_length;
123 const amrex::Real phase_offset = wdata.wave_phase_offset;
124 const amrex::Real water_depth = wdata.water_depth;
125 const amrex::Real zero_sea_level = wdata.zsl;
126 const amrex::Real gen_length = wdata.gen_length;
127 const amrex::Real beach_length = wdata.beach_length;
128 const amrex::Real g = wdata.g;
129 const int order = wdata.order;
130 const bool has_beach = wdata.has_beach && multiphase_mode;
131 const bool init_wave_field = wdata.init_wave_field || !multiphase_mode;
132
133 amrex::ParallelFor(
134 velocity(level), amrex::IntVect(3),
135 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
136 const amrex::Real x = problo[0] + ((i + 0.5_rt) * dx[0]);
137 const amrex::Real z = problo[2] + ((k + 0.5_rt) * dx[2]);
138
139 // Wave profile
140 amrex::Real eta_w{0.0_rt}, u_w{0.0_rt}, v_w{0.0_rt},
141 w_w{0.0_rt};
143 order, wave_length, water_depth, wave_height,
144 zero_sea_level, g, x, z, 0.0_rt, phase_offset,
146 w_w);
147 const utils::WaveVec wave_sol{u_w, v_w, w_w, eta_w};
148
149 // Quiescent profile
150 const utils::WaveVec quiescent{
151 0.0_rt, 0.0_rt, 0.0_rt, zero_sea_level};
152
153 // Specify initial state for each region of domain
154 const auto bulk = init_wave_field ? wave_sol : quiescent;
155 const auto outlet = has_beach ? quiescent : wave_sol;
156
157 const auto local_profile = utils::harmonize_profiles_1d(
158 x, problo[0], gen_length, probhi[0], beach_length, wave_sol,
159 bulk, outlet);
160
161 const amrex::Real phi = local_profile[3] - z;
162 const amrex::Real cell_length_2D =
163 std::sqrt((dx[0] * dx[0]) + (dx[2] * dx[2]));
164 if (phi + cell_length_2D >= 0) {
165 vel[nbx](i, j, k, 0) = local_profile[0];
166 vel[nbx](i, j, k, 1) = local_profile[1];
167 vel[nbx](i, j, k, 2) = local_profile[2];
168 }
169 if (multiphase_mode) {
170 phi_arrs[nbx](i, j, k) = phi;
171 }
172 });
173 amrex::Gpu::streamSynchronize();
174 }
175};
176
177template <>
179{
180 void operator()(StokesWaves::DataType& data, const amrex::Real time)
181 {
182 const auto& wdata = data.meta();
183
184 auto& sim = data.sim();
185
186 // cppcheck-suppress constVariableReference
187 auto& ow_levelset = sim.repo().get_field("ow_levelset");
188 // cppcheck-suppress constVariableReference
189 auto& ow_velocity = sim.repo().get_field("ow_velocity");
190
191 auto nlevels = sim.repo().num_active_levels();
192 auto geom = sim.mesh().Geom();
193
194 for (int lev = 0; lev < nlevels; ++lev) {
195 const auto& problo = geom[lev].ProbLoArray();
196 const auto& dx = geom[lev].CellSizeArray();
197
198 const auto& phi = ow_levelset(lev).arrays();
199 const auto& vel = ow_velocity(lev).arrays();
200
201 const amrex::Real wave_height = wdata.wave_height;
202 const amrex::Real wave_length = wdata.wave_length;
203 const amrex::Real phase_offset = wdata.wave_phase_offset;
204 const amrex::Real water_depth = wdata.water_depth;
205 const amrex::Real zero_sea_level = wdata.zsl;
206 const amrex::Real g = wdata.g;
207 const int order = wdata.order;
208
209 amrex::ParallelFor(
210 ow_velocity(lev), amrex::IntVect(3),
211 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
212 const amrex::Real x = amrex::max<amrex::Real>(
213 problo[0], problo[0] + ((i + 0.5_rt) * dx[0]));
214 const amrex::Real z = problo[2] + ((k + 0.5_rt) * dx[2]);
215
216 amrex::Real eta{0.0_rt}, u_w{0.0_rt}, v_w{0.0_rt},
217 w_w{0.0_rt};
218
220 order, wave_length, water_depth, wave_height,
221 zero_sea_level, g, x, z, time, phase_offset,
223 w_w);
224
225 phi[nbx](i, j, k) = eta - z;
226 const amrex::Real cell_length_2D =
227 std::sqrt((dx[0] * dx[0]) + (dx[2] * dx[2]));
228 if (phi[nbx](i, j, k) + cell_length_2D >= 0) {
229 // Wave velocity within a cell of interface
230 vel[nbx](i, j, k, 0) = u_w;
231 vel[nbx](i, j, k, 1) = v_w;
232 vel[nbx](i, j, k, 2) = w_w;
233 } else {
234 vel[nbx](i, j, k, 0) = 0.;
235 vel[nbx](i, j, k, 1) = 0.;
236 vel[nbx](i, j, k, 2) = 0.;
237 }
238 });
239 }
240 amrex::Gpu::streamSynchronize();
241 }
242};
243
244} // namespace kynema_sgf::ocean_waves::ops
245
246#endif /* STOKES_WAVES_OPS_H */
FieldRepo & repo()
Return the field repository.
Definition CFDSim.H:76
Definition Field.H:112
FieldRepo & repo() const
FieldRepo instance that manages this field.
Definition Field.H:161
Field & get_field(const std::string &name, FieldState fstate=FieldState::New) const
Definition FieldRepo.cpp:152
int num_active_levels() const
Total number of levels currently active in the AMR mesh.
Definition FieldRepo.H:351
OceanWavesTrait::InfoType & info()
Definition OceanWavesTypes.H:86
OceanWavesTrait::MetaType & meta()
Definition OceanWavesTypes.H:92
CFDSim & sim()
Definition OceanWavesTypes.H:83
static constexpr amrex::Real LARGE_NUM
A large positive number.
Definition constants.H:29
static constexpr amrex::Real LOW_NUM
A large negative number.
Definition constants.H:25
static constexpr amrex::Real TIGHT_TOL
A tight tolerance.
Definition constants.H:17
Definition OceanWavesOps.H:8
AMREX_FORCE_INLINE amrex::Real stokes_wave_length(const amrex::Real T, const amrex::Real d, const amrex::Real H, const int order, const amrex::Real g, const amrex::Real tol, const int iter_max)
Definition stokes_waves_K.H:28
void read_inputs(RelaxZonesBaseData &wdata, OceanWavesInfo &, const ::kynema_sgf::utils::MultiParser &pp)
Definition relaxation_zones_ops.cpp:16
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void stokes_waves(int stokes_order, amrex::Real wavelength, amrex::Real water_depth, amrex::Real wave_height, amrex::Real zsl, amrex::Real g, amrex::Real x, amrex::Real z, amrex::Real time, amrex::Real phase_offset, amrex::Real hyp_lo_limit, amrex::Real hyp_hi_limit, amrex::Real &eta, amrex::Real &u_w, amrex::Real &v_w, amrex::Real &w_w)
Definition stokes_waves_K.H:278
amrex::GpuArray< amrex::Real, 4 > WaveVec
Definition wave_utils_K.H:14
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE WaveVec harmonize_profiles_1d(const amrex::Real x, const amrex::Real left_bdy, const amrex::Real left_length, const amrex::Real right_bdy, const amrex::Real right_length, const WaveVec left, const WaveVec bulk, const WaveVec right)
Definition wave_utils_K.H:77
Definition StokesWaves.H:20
OceanWavesDataHolder< StokesWaves > DataType
Definition StokesWaves.H:23
void operator()(StokesWaves::DataType &data, int level, const amrex::Geometry &geom, bool multiphase_mode)
Definition stokes_waves_ops.H:97
Definition OceanWavesOps.H:14
void operator()(StokesWaves::DataType &data, const ::kynema_sgf::utils::MultiParser &pp)
Definition stokes_waves_ops.H:20
Definition OceanWavesOps.H:11
void operator()(StokesWaves::DataType &data, const amrex::Real time)
Definition stokes_waves_ops.H:180