/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 auto& velocity = sim.repo().get_field("velocity");
111 const auto& problo = geom.ProbLoArray();
112 const auto& probhi = geom.ProbHiArray();
113 const auto& dx = geom.CellSizeArray();
114
115 const auto& vel = velocity(level).arrays();
116 const auto& phi_arrs = multiphase_mode
117 ? (*levelset)(level).arrays()
118 : amrex::MultiArray4<amrex::Real>();
119
120 const amrex::Real wave_height = wdata.wave_height;
121 const amrex::Real wave_length = wdata.wave_length;
122 const amrex::Real phase_offset = wdata.wave_phase_offset;
123 const amrex::Real water_depth = wdata.water_depth;
124 const amrex::Real zero_sea_level = wdata.zsl;
125 const amrex::Real gen_length = wdata.gen_length;
126 const amrex::Real beach_length = wdata.beach_length;
127 const amrex::Real g = wdata.g;
128 const int order = wdata.order;
129 const bool has_beach = wdata.has_beach && multiphase_mode;
130 const bool init_wave_field = wdata.init_wave_field || !multiphase_mode;
131
132 amrex::ParallelFor(
133 velocity(level), amrex::IntVect(3),
134 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
135 const amrex::Real x = problo[0] + ((i + 0.5_rt) * dx[0]);
136 const amrex::Real z = problo[2] + ((k + 0.5_rt) * dx[2]);
137
138 // Wave profile
139 amrex::Real eta_w{0.0_rt}, u_w{0.0_rt}, v_w{0.0_rt},
140 w_w{0.0_rt};
142 order, wave_length, water_depth, wave_height,
143 zero_sea_level, g, x, z, 0.0_rt, phase_offset,
145 w_w);
146 const utils::WaveVec wave_sol{u_w, v_w, w_w, eta_w};
147
148 // Quiescent profile
149 const utils::WaveVec quiescent{
150 0.0_rt, 0.0_rt, 0.0_rt, zero_sea_level};
151
152 // Specify initial state for each region of domain
153 const auto bulk = init_wave_field ? wave_sol : quiescent;
154 const auto outlet = has_beach ? quiescent : wave_sol;
155
156 const auto local_profile = utils::harmonize_profiles_1d(
157 x, problo[0], gen_length, probhi[0], beach_length, wave_sol,
158 bulk, outlet);
159
160 const amrex::Real phi = local_profile[3] - z;
161 const amrex::Real cell_length_2D =
162 std::sqrt((dx[0] * dx[0]) + (dx[2] * dx[2]));
163 if (phi + cell_length_2D >= 0) {
164 vel[nbx](i, j, k, 0) = local_profile[0];
165 vel[nbx](i, j, k, 1) = local_profile[1];
166 vel[nbx](i, j, k, 2) = local_profile[2];
167 }
168 if (multiphase_mode) {
169 phi_arrs[nbx](i, j, k) = phi;
170 }
171 });
172 amrex::Gpu::streamSynchronize();
173 }
174};
175
176template <>
178{
179 void operator()(StokesWaves::DataType& data, const amrex::Real time)
180 {
181 const auto& wdata = data.meta();
182
183 auto& sim = data.sim();
184
185 auto& ow_levelset = sim.repo().get_field("ow_levelset");
186 auto& ow_velocity = sim.repo().get_field("ow_velocity");
187
188 auto nlevels = sim.repo().num_active_levels();
189 auto geom = sim.mesh().Geom();
190
191 for (int lev = 0; lev < nlevels; ++lev) {
192 const auto& problo = geom[lev].ProbLoArray();
193 const auto& dx = geom[lev].CellSizeArray();
194
195 const auto& phi = ow_levelset(lev).arrays();
196 const auto& vel = ow_velocity(lev).arrays();
197
198 const amrex::Real wave_height = wdata.wave_height;
199 const amrex::Real wave_length = wdata.wave_length;
200 const amrex::Real phase_offset = wdata.wave_phase_offset;
201 const amrex::Real water_depth = wdata.water_depth;
202 const amrex::Real zero_sea_level = wdata.zsl;
203 const amrex::Real g = wdata.g;
204 const int order = wdata.order;
205
206 amrex::ParallelFor(
207 ow_velocity(lev), amrex::IntVect(3),
208 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
209 const amrex::Real x = amrex::max<amrex::Real>(
210 problo[0], problo[0] + ((i + 0.5_rt) * dx[0]));
211 const amrex::Real z = problo[2] + ((k + 0.5_rt) * dx[2]);
212
213 amrex::Real eta{0.0_rt}, u_w{0.0_rt}, v_w{0.0_rt},
214 w_w{0.0_rt};
215
217 order, wave_length, water_depth, wave_height,
218 zero_sea_level, g, x, z, time, phase_offset,
220 w_w);
221
222 phi[nbx](i, j, k) = eta - z;
223 const amrex::Real cell_length_2D =
224 std::sqrt((dx[0] * dx[0]) + (dx[2] * dx[2]));
225 if (phi[nbx](i, j, k) + cell_length_2D >= 0) {
226 // Wave velocity within a cell of interface
227 vel[nbx](i, j, k, 0) = u_w;
228 vel[nbx](i, j, k, 1) = v_w;
229 vel[nbx](i, j, k, 2) = w_w;
230 } else {
231 vel[nbx](i, j, k, 0) = 0.;
232 vel[nbx](i, j, k, 1) = 0.;
233 vel[nbx](i, j, k, 2) = 0.;
234 }
235 });
236 }
237 amrex::Gpu::streamSynchronize();
238 }
239};
240
241} // namespace kynema_sgf::ocean_waves::ops
242
243#endif /* STOKES_WAVES_OPS_H */
FieldRepo & repo()
Return the field repository.
Definition CFDSim.H:76
Definition Field.H:115
FieldRepo & repo() const
FieldRepo instance that manages this field.
Definition Field.H:164
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:17
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:283
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:179