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

Kynema-SGF API: /home/runner/work/kynema-sgf/kynema-sgf/src/ocean_waves/relaxation_zones/linear_waves_ops.H Source File
Kynema-SGF API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
linear_waves_ops.H
Go to the documentation of this file.
1#ifndef LINEAR_WAVES_OPS_H
2#define LINEAR_WAVES_OPS_H
3
9#include "AMReX_REAL.H"
10
11using namespace amrex::literals;
12
14
15template <>
17{
19 LinearWaves::DataType& data, const ::kynema_sgf::utils::MultiParser& pp)
20 {
21 auto& wdata = data.meta();
22 auto& info = data.info();
23 relaxation_zones::read_inputs(wdata, info, pp);
24 // Get gravity, assume negative z
25 amrex::Vector<amrex::Real> gravity{0.0_rt, 0.0_rt, -9.81_rt};
26 amrex::ParmParse pp_incflo("incflo");
27 pp_incflo.queryarr("gravity", gravity);
28 wdata.g = -gravity[2];
29
30 pp.get("wave_length", wdata.wave_length);
31 pp.get("wave_height", wdata.wave_height);
32 pp.query("wave_phase_offset_radians", wdata.wave_phase_offset);
33 if (!pp.contains("wave_phase_offset_radians")) {
34 pp.query("wave_phase_offset_degrees", wdata.wave_phase_offset);
35 wdata.wave_phase_offset *=
36 std::numbers::pi_v<amrex::Real> / 180.0_rt;
37 } else if (pp.contains("wave_phase_offset_degrees")) {
38 amrex::Abort(
39 "ReadInputsOp<LinearWaves> : wave phase offset is specified in "
40 "both radians and degrees. Please use only one.");
41 }
42 }
43};
44
45template <>
47{
50 int level,
51 const amrex::Geometry& geom,
52 bool multiphase_mode)
53 {
54 const auto& wdata = data.meta();
55
56 auto& sim = data.sim();
57
58 Field* levelset{nullptr};
59 if (multiphase_mode) {
60 levelset = &sim.repo().get_field("levelset");
61 }
62 auto& velocity = sim.repo().get_field("velocity");
63
64 const auto& problo = geom.ProbLoArray();
65 const auto& probhi = geom.ProbHiArray();
66 const auto& dx = geom.CellSizeArray();
67
68 const auto& vel = velocity(level).arrays();
69 const auto& phi_arrs = multiphase_mode
70 ? (*levelset)(level).arrays()
71 : amrex::MultiArray4<amrex::Real>();
72
73 const amrex::Real zero_sea_level = wdata.zsl;
74 const amrex::Real gen_length = wdata.gen_length;
75 const amrex::Real beach_length = wdata.beach_length;
76 const amrex::Real g = wdata.g;
77 const bool has_beach = wdata.has_beach && multiphase_mode;
78 const bool init_wave_field = wdata.init_wave_field || !multiphase_mode;
79
80 const amrex::Real wave_height = wdata.wave_height;
81 const amrex::Real wave_length = wdata.wave_length;
82 const amrex::Real phase_offset = wdata.wave_phase_offset;
83 const amrex::Real water_depth = wdata.water_depth;
84 const amrex::Real current = wdata.current;
85
86 amrex::ParallelFor(
87 velocity(level), amrex::IntVect(3),
88 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
89 const amrex::Real x = problo[0] + ((i + 0.5_rt) * dx[0]);
90 const amrex::Real z = problo[2] + ((k + 0.5_rt) * dx[2]);
91
92 const amrex::Real wave_number =
93 2.0_rt * std::numbers::pi_v<amrex::Real> / wave_length;
94 const amrex::Real omega = std::pow(
95 wave_number * g * std::tanh(wave_number * water_depth),
96 0.5_rt);
97 const amrex::Real phase = (wave_number * x) - phase_offset;
98
99 // Wave profile
100 const amrex::Real eta_w =
101 (wave_height / 2.0_rt * std::cos(phase)) + zero_sea_level;
102 const amrex::Real u_w =
103 omega * wave_height / 2.0_rt *
104 std::cosh(
105 wave_number * (z - zero_sea_level + water_depth)) /
106 std::sinh(wave_number * water_depth) * std::cos(phase);
107 const amrex::Real v_w = 0.0_rt;
108 const amrex::Real w_w =
109 omega * wave_height / 2.0_rt *
110 std::sinh(
111 wave_number * (z - zero_sea_level + water_depth)) /
112 std::sinh(wave_number * water_depth) * std::sin(phase);
113 const utils::WaveVec wave_sol{u_w, v_w, w_w, eta_w};
114
115 // Quiescent profile
116 const utils::WaveVec quiescent{
117 0.0_rt, 0.0_rt, 0.0_rt, zero_sea_level};
118
119 // Specify initial state for each region of domain
120 const auto bulk = init_wave_field ? wave_sol : quiescent;
121 const auto outlet = has_beach ? quiescent : wave_sol;
122
123 const auto local_profile = utils::harmonize_profiles_1d(
124 x, problo[0], gen_length, probhi[0], beach_length, wave_sol,
125 bulk, outlet);
126
127 const amrex::Real phi = local_profile[3] - z;
128 const amrex::Real cell_length_2D =
129 std::sqrt((dx[0] * dx[0]) + (dx[2] * dx[2]));
130
131 if (phi + cell_length_2D >= 0) {
132 vel[nbx](i, j, k, 0) = current + local_profile[0];
133 vel[nbx](i, j, k, 1) = local_profile[1];
134 vel[nbx](i, j, k, 2) = local_profile[2];
135 }
136 if (multiphase_mode) {
137 phi_arrs[nbx](i, j, k) = phi;
138 }
139 });
140 amrex::Gpu::streamSynchronize();
141 }
142};
143
144template <>
146{
147 void operator()(LinearWaves::DataType& data, const amrex::Real time)
148 {
149 const auto& wdata = data.meta();
150
151 auto& sim = data.sim();
152
153 auto& ow_levelset = sim.repo().get_field("ow_levelset");
154 auto& ow_velocity = sim.repo().get_field("ow_velocity");
155
156 auto nlevels = sim.repo().num_active_levels();
157 auto geom = sim.mesh().Geom();
158
159 for (int lev = 0; lev < nlevels; ++lev) {
160 const auto& problo = geom[lev].ProbLoArray();
161 const auto& dx = geom[lev].CellSizeArray();
162
163 const auto& phi = ow_levelset(lev).arrays();
164 const auto& vel = ow_velocity(lev).arrays();
165
166 const amrex::Real wave_height = wdata.wave_height;
167 const amrex::Real wave_length = wdata.wave_length;
168 const amrex::Real phase_offset = wdata.wave_phase_offset;
169 const amrex::Real water_depth = wdata.water_depth;
170 const amrex::Real zero_sea_level = wdata.zsl;
171 const amrex::Real g = wdata.g;
172 const amrex::Real current = wdata.current;
173
174 amrex::ParallelFor(
175 ow_velocity(lev), amrex::IntVect(3),
176 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
177 const amrex::Real x = amrex::max<amrex::Real>(
178 problo[0], problo[0] + ((i + 0.5_rt) * dx[0]));
179 const amrex::Real z = problo[2] + ((k + 0.5_rt) * dx[2]);
180
181 const amrex::Real wave_number =
182 2.0_rt * std::numbers::pi_v<amrex::Real> / wave_length;
183 const amrex::Real omega = std::pow(
184 wave_number * g * std::tanh(wave_number * water_depth),
185 0.5_rt);
186 const amrex::Real phase =
187 (wave_number * (x - (current * time))) -
188 (omega * time) - phase_offset;
189
190 const amrex::Real eta =
191 (wave_height / 2.0_rt * std::cos(phase)) +
192 zero_sea_level;
193
194 phi[nbx](i, j, k) = eta - z;
195
196 const amrex::Real cell_length_2D =
197 std::sqrt((dx[0] * dx[0]) + (dx[2] * dx[2]));
198 if (phi[nbx](i, j, k) + cell_length_2D >= 0) {
199 vel[nbx](i, j, k, 0) =
200 (omega * wave_height / 2.0_rt *
201 std::cosh(
202 wave_number *
203 (z - zero_sea_level + water_depth)) /
204 std::sinh(wave_number * water_depth) *
205 std::cos(phase)) +
206 current;
207 vel[nbx](i, j, k, 1) = 0.0_rt;
208 vel[nbx](i, j, k, 2) =
209 omega * wave_height / 2.0_rt *
210 std::sinh(
211 wave_number *
212 (z - zero_sea_level + water_depth)) /
213 std::sinh(wave_number * water_depth) *
214 std::sin(phase);
215 } else {
216 vel[nbx](i, j, k, 0) = 0.0_rt;
217 vel[nbx](i, j, k, 1) = 0.0_rt;
218 vel[nbx](i, j, k, 2) = 0.0_rt;
219 }
220 });
221 }
222 amrex::Gpu::streamSynchronize();
223 }
224};
225
226} // namespace kynema_sgf::ocean_waves::ops
227
228#endif /* LINEAR_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
Definition OceanWavesOps.H:8
void read_inputs(RelaxZonesBaseData &wdata, OceanWavesInfo &, const ::kynema_sgf::utils::MultiParser &pp)
Definition relaxation_zones_ops.cpp:17
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
phase
Definition BoundaryPlane.H:21
Definition LinearWaves.H:19
OceanWavesDataHolder< LinearWaves > DataType
Definition LinearWaves.H:22
void operator()(LinearWaves::DataType &data, int level, const amrex::Geometry &geom, bool multiphase_mode)
Definition linear_waves_ops.H:48
Definition OceanWavesOps.H:14
void operator()(LinearWaves::DataType &data, const ::kynema_sgf::utils::MultiParser &pp)
Definition linear_waves_ops.H:18
Definition OceanWavesOps.H:11
void operator()(LinearWaves::DataType &data, const amrex::Real time)
Definition linear_waves_ops.H:147