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

Kynema-SGF API: /home/runner/work/kynema-sgf/kynema-sgf/src/ocean_waves/relaxation_zones/waves2amr_ops.H Source File
Kynema-SGF API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
waves2amr_ops.H
Go to the documentation of this file.
1#ifndef W2A_WAVES_OPS_H
2#define W2A_WAVES_OPS_H
3
10#include "src/core/FieldRepo.H"
11#include "src/core/field_ops.H"
13#include "AMReX_MultiFabUtil.H"
14#include "AMReX_REAL.H"
15
16using namespace amrex::literals;
17
18#ifdef KYNEMA_SGF_USE_W2A
19namespace {
20int evaluate_read_resize(
21 int& ntime,
22 bool& read_flag,
23 bool& resize_flag,
24 amrex::Real& wtime,
25 amrex::Real& t_last,
26 const int new_ntime,
27 const amrex::Real wtinit,
28 const amrex::Real wdt,
29 const amrex::Real time)
30{
31 // Flag to indicate that data must be read twice for interpolation
32 int double_data = 0;
33 // Check if time indicates reading must take place
34 if (new_ntime != ntime) {
35 // New data is needed - reading should happen
36 read_flag = true;
37 // If time index has proceeded more than 1 step
38 if (new_ntime > ntime + 1) {
39 // Double reading is necessary
40 double_data = 1;
41 }
42 // Time index for reading
43 ntime = new_ntime;
44 // Sim time to go with recorded data
45 wtime = new_ntime * wdt - wtinit;
46 // If double reading is deemed necessary, check for convenience
47 if (double_data == 1 && std::abs(wtime - time) <= 1.0e-10_rt) {
48 // Reading can be done just once, w2a fields replace ow fields
49 double_data = 2;
50 }
51 }
52 // Check if reading must take place for other reasons
53 if (t_last < -1.0e-10_rt) {
54 // Signifies initialization from scratch without waves or a restart
55 read_flag = true;
56 // Resizing needs to happen for the first time
57 resize_flag = true;
58
59 // Confirm that new time is not coincident with modes time step
60 if (std::abs(wtime - time) > 1.0e-10_rt) {
61 // Data must be read before and after wtime
62 double_data = 1;
63 } else {
64 // Data need only be read once, w2a fields will replace ow fields
65 double_data = 2;
66 }
67
68 } else if (std::abs(t_last) < 1.0e-10_rt) {
69 // Signifies initialization with waves
70 read_flag = true;
71 // Resizing needs to happen for the first time
72 resize_flag = true;
73
74 // levelset and velocity fields are up-to-date at t=0
75 // interpolation is ready to go
76 }
77 // Record latest time as 'last' for next timestep
78 t_last = time;
79 // Return flag regarding double reading
80 return double_data;
81}
82
83int update_offset_timestep(const int ntime, const int n0)
84{
85 // Offending timestep (goes too far): ntime + offset
86 // Farthest back timesteps are permitted to go: n0
87 // Subtract offset by offending timestep, add back lower limit
88 // new offset = offset - (ntime + offset) + n0
89 return (-ntime + n0);
90}
91
92void populate_fields_all_levels(
94 amrex::Vector<amrex::Geometry>& geom_all,
95 kynema_sgf::Field& lvs_field,
96 kynema_sgf::Field& vel_field,
97 int ntime_off = 0)
98{
99
100 // Get data from modes
101 bool no_EOF =
102 wdata.is_ocean
103 ? wdata.c_rmodes.get_data(
104 wdata.ntime + wdata.n_offset + ntime_off, wdata.c_mX,
105 wdata.c_mY, wdata.c_mZ, wdata.c_mFS)
106 : wdata.r_rmodes.get_data(
107 wdata.ntime + wdata.n_offset + ntime_off, wdata.r_mX,
108 wdata.r_mY, wdata.r_mZ, wdata.r_mFS, wdata.r_mAdd);
109 // Navigate when end of file is reached
110 if (!no_EOF) {
111 // End of file detected, reset reading
112 wdata.n_offset = update_offset_timestep(wdata.ntime, wdata.n_winit);
113 // Print warning to screen
114 amrex::Print() << "WARNING (waves2amr_ops): end of mode data file "
115 "detected, resetting to beginning of mode data.\n";
116 // Read data again, now from a valid timestep
117 no_EOF = wdata.is_ocean
118 ? wdata.c_rmodes.get_data(
119 wdata.ntime + wdata.n_offset + ntime_off, wdata.c_mX,
120 wdata.c_mY, wdata.c_mZ, wdata.c_mFS)
121 : wdata.r_rmodes.get_data(
122 wdata.ntime + wdata.n_offset + ntime_off, wdata.r_mX,
123 wdata.r_mY, wdata.r_mZ, wdata.r_mFS, wdata.r_mAdd);
124 // If no valid data is detected at this point, abort
125 if (!no_EOF) {
126 amrex::Abort(
127 "waves2amr_ops: end of mode data file detected after "
128 "resetting to beginning; please evaluate HOS_init_time "
129 "or HOS_init_timestep and check the length of the mode "
130 "file.");
131 }
132 }
133
134 // Convert to spatial data in vectors
135 if (wdata.is_ocean) {
136 modes_hosgrid::copy_complex(
137 wdata.n0, wdata.n1, wdata.c_mFS, wdata.c_eta_mptr);
138 modes_hosgrid::populate_hos_eta(
139 wdata.c_rmodes, wdata.plan_vector, wdata.c_eta_mptr,
140 wdata.sp_eta_vec);
141 } else {
142 modes_hosgrid::copy_real(
143 wdata.n0, wdata.n1, wdata.r_mFS, wdata.r_eta_mptr);
144 modes_hosgrid::populate_hos_eta(
145 wdata.r_rmodes, wdata.plan_vector, wdata.r_eta_mptr,
146 wdata.sp_eta_vec);
147 }
148
149 for (int iht = 0; iht < wdata.indvec.size(); ++iht) {
150 // Get sample height
151 amrex::Real ht = wdata.hvec[wdata.indvec[iht]];
152 // Sample velocity
153 if (wdata.is_ocean) {
154 modes_hosgrid::populate_hos_vel(
155 wdata.c_rmodes, ht, wdata.zsl, wdata.c_mX, wdata.c_mY,
156 wdata.c_mZ, wdata.plan_vector, wdata.c_u_mptr, wdata.c_v_mptr,
157 wdata.c_w_mptr, wdata.sp_u_vec, wdata.sp_v_vec, wdata.sp_w_vec,
158 iht * wdata.n0 * wdata.n1);
159 } else {
160 modes_hosgrid::populate_hos_vel(
161 wdata.r_rmodes, ht, wdata.zsl, wdata.r_mX, wdata.r_mY,
162 wdata.r_mZ, wdata.r_mAdd, wdata.plan_vector, wdata.r_u_mptr,
163 wdata.r_v_mptr, wdata.r_w_mptr, wdata.au_mptr, wdata.av_mptr,
164 wdata.aw_mptr, wdata.sp_u_vec, wdata.sp_v_vec, wdata.sp_w_vec,
165 iht * wdata.n0 * wdata.n1);
166 }
167 }
168
169 // Interpolate to fields (vector of MultiFabs)
170 interp_to_mfab::interp_eta_to_levelset_field(
171 wdata.n0_sp, wdata.n1_sp, wdata.dx0, wdata.dx1, wdata.xlo0, wdata.xlo1,
172 wdata.zsl, wdata.is_ocean, wdata.sp_eta_vec, lvs_field.vec_ptrs(),
173 geom_all);
174 interp_to_mfab::interp_velocity_to_field(
175 wdata.n0_sp, wdata.n1_sp, wdata.dx0, wdata.dx1, wdata.xlo0, wdata.xlo1,
176 wdata.is_ocean, wdata.indvec, wdata.hvec, wdata.sp_u_vec,
177 wdata.sp_v_vec, wdata.sp_w_vec, vel_field.vec_ptrs(), geom_all);
178}
179
180void time_interpolate_wave_fields(
181 kynema_sgf::Field& lvs_field,
182 kynema_sgf::Field& vel_field,
183 const kynema_sgf::Field& future_lvs_field,
184 const kynema_sgf::Field& future_vel_field,
185 const amrex::Real t_old,
186 const amrex::Real t_new,
187 const amrex::Real t_future)
188{
189 const amrex::Real b =
190 (t_new - t_old) /
191 (t_future - t_old + std::numeric_limits<amrex::Real>::epsilon());
192 const amrex::Real a = 1.0_rt - b;
194 lvs_field, a, lvs_field, 0, b, future_lvs_field, 0, 0, 1,
195 lvs_field.num_grow());
197 vel_field, a, vel_field, 0, b, future_vel_field, 0, 0, AMREX_SPACEDIM,
198 vel_field.num_grow());
199}
200
201} // namespace
202#endif
203
205
206template <>
208{
210 W2AWaves::DataType& data, const ::kynema_sgf::utils::MultiParser& pp)
211 {
212// Check for W2A initialization
213#ifndef KYNEMA_SGF_USE_W2A
214 // Assert Waves2AMR must be used for initial condition file
215 amrex::Abort(
216 "ocean_waves/W2AWaves: Kynema-SGF was not built with Waves2AMR "
217 "support; associated wave data cannot be processed for relaxation "
218 "zones.");
219
220 amrex::ignore_unused(data, pp);
221#else
222 auto& wdata = data.meta();
223 auto& info = data.info();
224 relaxation_zones::read_inputs(wdata, info, pp);
225
226 if (wdata.current > constants::TIGHT_TOL) {
227 amrex::Abort(
228 "Current is specified as nonzero, but current is not yet "
229 "implemented for W2A Waves.");
230 }
231
232 pp.get("HOS_modes_filename", wdata.modes_file);
233 pp.query("HOS_simulation_is_ocean", wdata.is_ocean);
234 pp.query("HOS_init_timestep", wdata.ntime);
235 if (!pp.contains("HOS_init_timestep")) {
236 pp.query("HOS_init_time", wdata.t_winit);
237 }
238 pp.query("HOS_domain_offset_x", wdata.xlo0);
239 pp.query("HOS_domain_offset_y", wdata.xlo1);
240
241 // Default fftw_plan is deterministic
242 std::string fftw_planner_flag{"estimate"};
243 pp.query("fftw_planner_flag", fftw_planner_flag);
244
245 amrex::Vector<amrex::Real> prob_lo_input(AMREX_SPACEDIM);
246 amrex::ParmParse pp_geom("geometry");
247 pp_geom.getarr("prob_lo", prob_lo_input);
248
249 // Read user inputs to height vector
250 int nheights = 0;
251 int nh_above = 1;
252 amrex::Real dz0 = 0.0_rt;
253 pp.get("number_interp_points_in_z", nheights);
254 pp.get("interp_spacing_at_surface", dz0);
255 pp.query("number_interp_above_surface", nh_above);
256
257 // Initialize mode reader
258 bool file_exists{false};
259 if (wdata.is_ocean) {
260 file_exists = wdata.c_rmodes.initialize(wdata.modes_file, true);
261 } else {
262 file_exists = wdata.r_rmodes.initialize(wdata.modes_file, false);
263 }
264
265 // Abort if file does not exist
266 if (!file_exists) {
267 amrex::Abort(
268 "Waves2AMR ReadInputsOp: modes file requested does not exist");
269 }
270
271 // Get dt of HOS data
272 wdata.dt_modes = wdata.is_ocean ? wdata.c_rmodes.get_dtout()
273 : wdata.r_rmodes.get_dtout();
274
275 // Get initial time and timestep synced
276 if (wdata.t_winit > 0.0_rt) {
277 // If initial time was specified
278 // Get time index near requested time
279 wdata.ntime =
280 wdata.is_ocean
281 ? wdata.c_rmodes.time2step(wdata.t_winit, wdata.ntime)
282 : wdata.r_rmodes.time2step(wdata.t_winit, wdata.ntime);
283 ;
284 // Sync time to time index
285 wdata.t_winit = wdata.dt_modes * wdata.ntime;
286 // Save first timestep
287 wdata.n_winit = wdata.ntime;
288 } else {
289 // If initial timestep is being used
290 wdata.t_winit = wdata.dt_modes * wdata.ntime;
291 // Save first timestep
292 wdata.n_winit = wdata.ntime;
293 }
294
295 amrex::Print() << "OceanWaves: Initializing Waves2AMR profile at time "
296 << wdata.t_winit << ", step " << wdata.n_winit
297 << std::endl;
298
299 // Initialize variables to store modes
300 amrex::Real depth{0.0_rt};
301 if (wdata.is_ocean) {
302 int vsize = wdata.c_rmodes.get_vector_size();
303 amrex::Real initval = 0.0_rt;
304 wdata.c_mX.resize(vsize, initval);
305 wdata.c_mY.resize(vsize, initval);
306 wdata.c_mZ.resize(vsize, initval);
307 wdata.c_mFS.resize(vsize, initval);
308
309 // Get dimensions of data
310 wdata.n0 = wdata.c_rmodes.get_first_fft_dimension();
311 wdata.n1 = wdata.c_rmodes.get_second_fft_dimension();
312 wdata.n0_sp = wdata.c_rmodes.get_first_spatial_dimension();
313 wdata.n1_sp = wdata.c_rmodes.get_second_spatial_dimension();
314 // Get resolution
315 wdata.dx0 = wdata.c_rmodes.get_xlen() / wdata.n0_sp;
316 wdata.dx1 = wdata.c_rmodes.get_ylen() / wdata.n1_sp;
317 // Get depth
318 depth = wdata.c_rmodes.get_depth();
319 // Get dimensional length
320 wdata.dimL = wdata.c_rmodes.get_L();
321 // Get nominal last timestep of data
322 wdata.n_wstop = static_cast<int>(
323 (wdata.c_rmodes.get_Tstop() + 1.0e-8_rt) / wdata.dt_modes);
324
325 amrex::Print()
326 << "OceanWaves: Waves2AMR parameters from HOS-Ocean file: \n"
327 << " nx " << wdata.n0_sp << " dx " << wdata.dx0 << " Lx "
328 << wdata.c_rmodes.get_xlen() << std::endl
329 << " ny " << wdata.n1_sp << " dy " << wdata.dx1 << " Ly "
330 << wdata.c_rmodes.get_ylen() << std::endl
331 << " depth " << depth << std::endl
332 << " output time interval " << wdata.dt_modes
333 << " nominal last time " << wdata.n_wstop * wdata.dt_modes
334 << std::endl;
335 } else {
336 int vsize = wdata.r_rmodes.get_vector_size();
337 int vasize = wdata.r_rmodes.get_addl_vector_size();
338 amrex::Real initval = 0.0_rt;
339 wdata.r_mX.resize(vsize, initval);
340 wdata.r_mY.resize(vsize, initval);
341 wdata.r_mZ.resize(vsize, initval);
342 wdata.r_mFS.resize(vsize, initval);
343 wdata.r_mAdd.resize(vasize, initval);
344
345 // Get dimensions of data
346 wdata.n0 = wdata.r_rmodes.get_first_fft_dimension();
347 wdata.n1 = wdata.r_rmodes.get_second_fft_dimension();
348 wdata.n2 = wdata.r_rmodes.get_third_dimension();
349 wdata.n0_sp = wdata.r_rmodes.get_first_spatial_dimension();
350 wdata.n1_sp = wdata.r_rmodes.get_second_spatial_dimension();
351 // Get resolution (slightly different for NWT)
352 wdata.dx0 = wdata.r_rmodes.get_xlen() / (wdata.n0_sp - 1);
353 wdata.dx1 =
354 wdata.r_rmodes.get_ylen() / amrex::max(wdata.n1_sp - 1, 1);
355 // Get depth
356 depth = wdata.r_rmodes.get_depth();
357 // Get dimensional length
358 wdata.dimL = wdata.r_rmodes.get_L();
359 // Get nominal last timestep of data
360 wdata.n_wstop = static_cast<int>(
361 (wdata.r_rmodes.get_Tstop() + 1.0e-8_rt) / wdata.dt_modes);
362
363 amrex::Print()
364 << "OceanWaves: Waves2AMR parameters from HOS-NWT file: \n"
365 << " nx " << wdata.n0_sp << " dx " << wdata.dx0 << " Lx "
366 << wdata.r_rmodes.get_xlen() << std::endl
367 << " ny " << wdata.n1_sp << " dy " << wdata.dx1 << " Ly "
368 << wdata.r_rmodes.get_ylen() << std::endl
369 << " nz " << wdata.n2 << " depth " << depth << std::endl
370 << " output time interval " << wdata.dt_modes
371 << " nominal last time " << wdata.n_wstop * wdata.dt_modes
372 << std::endl;
373 }
374
375 // Check if stop time is exceeded, introduce offset to ntime
376 if (wdata.ntime + wdata.n_offset > wdata.n_wstop) {
377 // If exceeding stop step, calculate new offset
378 wdata.n_offset = update_offset_timestep(wdata.ntime, wdata.n_winit);
379 // Print warning to screen
380 amrex::Print()
381 << "WARNING (waves2amr_ops): available mode data exceeded, "
382 "resetting to beginning of mode data.\n";
383 }
384
385 // Warning if depth does not correspond to simulation
386 if (std::abs(depth - (wdata.zsl - prob_lo_input[2])) >
387 1.0e-3_rt * depth) {
388 amrex::Print()
389 << "WARNING: Mismatch between water depths from Kynema-SGF "
390 "domain and HOS data interpreted by Waves2AMR. \n ^This "
391 "warning is not a concern when using waves as terrain.\n";
392 }
393
394 // Allocate pointers for FFTW
395 if (wdata.is_ocean) {
396 wdata.c_eta_mptr =
397 modes_hosgrid::allocate_complex(wdata.n0, wdata.n1);
398 wdata.c_u_mptr =
399 modes_hosgrid::allocate_complex(wdata.n0, wdata.n1);
400 wdata.c_v_mptr =
401 modes_hosgrid::allocate_complex(wdata.n0, wdata.n1);
402 wdata.c_w_mptr =
403 modes_hosgrid::allocate_complex(wdata.n0, wdata.n1);
404 } else {
405 wdata.r_eta_mptr = modes_hosgrid::allocate_real(wdata.n0, wdata.n1);
406 wdata.r_u_mptr = modes_hosgrid::allocate_real(wdata.n0, wdata.n1);
407 wdata.r_v_mptr = modes_hosgrid::allocate_real(wdata.n0, wdata.n1);
408 wdata.r_w_mptr = modes_hosgrid::allocate_real(wdata.n0, wdata.n1);
409 wdata.au_mptr = modes_hosgrid::allocate_real(wdata.n0, 1);
410 wdata.av_mptr = modes_hosgrid::allocate_real(wdata.n0, 1);
411 wdata.aw_mptr = modes_hosgrid::allocate_real(wdata.n0, 1);
412 }
413 wdata.plan_out = modes_hosgrid::allocate_real(wdata.n0, wdata.n1);
414
415 // Set up planner flag based on input
416 auto plan_f = modes_hosgrid::planner_flags::estimate;
417 if (fftw_planner_flag == "patient") {
418 plan_f = modes_hosgrid::planner_flags::patient;
419 } else if (fftw_planner_flag == "exhaustive") {
420 plan_f = modes_hosgrid::planner_flags::exhaustive;
421 } else if (fftw_planner_flag == "measure") {
422 plan_f = modes_hosgrid::planner_flags::measure;
423 } else if (!(fftw_planner_flag == "estimate")) {
424 amrex::Print()
425 << "WARNING (waves2amr_ops): invalid fftw_planner_flag "
426 "specified; defaulting to estimate (FFTW_ESTIMATE).\n";
427 }
428 // Set up plan for FFTW
429 if (wdata.is_ocean) {
430 wdata.plan_vector.emplace_back(
431 modes_hosgrid::plan_ifftw(
432 wdata.n0, wdata.n1, wdata.c_eta_mptr, wdata.plan_out,
433 plan_f));
434 } else {
435 modes_hosgrid::plan_ifftw_nwt(
436 wdata.n0, wdata.n1, wdata.plan_vector, wdata.r_eta_mptr,
437 wdata.plan_out, plan_f);
438 }
439
440 // Create height vector for velocity mode conversion before
441 // interpolation, with prob_lo as bottom
442 int flag = interp_to_mfab::create_height_vector(
443 wdata.hvec, nheights, dz0, wdata.zsl, prob_lo_input[2], nh_above);
444 // Fail if flag indicates it should
445 if (flag > 0) {
446 amrex::Abort(
447 "Waves2AMR ReadInputsOp: create_height_vector error, failure "
448 "code " +
449 std::to_string(flag));
450 }
451
452 amrex::Real z_double{0.0_rt};
453 bool found_z_double{false};
454 for (int n = 0; n < wdata.hvec.size() - 1; ++n) {
455 const amrex::Real dz = wdata.hvec[n] - wdata.hvec[n + 1];
456 if (!found_z_double && dz >= 2.0_rt * dz0) {
457 z_double = 0.5_rt * (wdata.hvec[n] + wdata.hvec[n + 1]);
458 found_z_double = true;
459 }
460 }
461
462 amrex::Print()
463 << "OceanWaves: Waves2AMR height vector for interpolation: \n"
464 << " start " << wdata.hvec[0] << " end "
465 << wdata.hvec[wdata.hvec.size() - 1] << " num points "
466 << wdata.hvec.size() << std::endl
467 << " initial dz " << wdata.hvec[0] - wdata.hvec[1]
468 << " first two grown dz "
469 << wdata.hvec[nh_above] - wdata.hvec[nh_above + 1] << " "
470 << wdata.hvec[nh_above + 1] - wdata.hvec[nh_above + 2]
471 << " final dz "
472 << wdata.hvec[wdata.hvec.size() - 2] -
473 wdata.hvec[wdata.hvec.size() - 1]
474 << std::endl;
475
476 if (found_z_double) {
477 amrex::Print()
478 << " interp spacing reaches double that of surface at "
479 << z_double << std::endl;
480 } else {
481 amrex::Print() << " interp spacing remains less than double "
482 "that of surface "
483 << std::endl;
484 }
485
486 // Always get modes on every processor for initialization
487 bool no_EOF =
488 wdata.is_ocean
489 ? wdata.c_rmodes.get_data(
490 wdata.ntime + wdata.n_offset, wdata.c_mX, wdata.c_mY,
491 wdata.c_mZ, wdata.c_mFS)
492 : wdata.r_rmodes.get_data(
493 wdata.ntime + wdata.n_offset, wdata.r_mX, wdata.r_mY,
494 wdata.r_mZ, wdata.r_mFS, wdata.r_mAdd);
495 if (!no_EOF) {
496 // End of file detected, reset reading
497 wdata.n_offset = update_offset_timestep(wdata.ntime, wdata.n_winit);
498 // Print warning to screen
499 amrex::Print()
500 << "WARNING (waves2amr_ops): end of mode data file "
501 "detected, resetting to beginning of mode data.\n";
502 // Read data again, now from a valid timestep
503 no_EOF =
504 wdata.is_ocean
505 ? wdata.c_rmodes.get_data(
506 wdata.ntime + wdata.n_offset, wdata.c_mX, wdata.c_mY,
507 wdata.c_mZ, wdata.c_mFS)
508 : wdata.r_rmodes.get_data(
509 wdata.ntime + wdata.n_offset, wdata.r_mX, wdata.r_mY,
510 wdata.r_mZ, wdata.r_mFS, wdata.r_mAdd);
511 // If no valid data is detected at this point, abort
512 if (!no_EOF) {
513 amrex::Abort(
514 "waves2amr_ops: end of mode data file detected after "
515 "resetting to beginning; please evaluate HOS_init_time "
516 "or HOS_init_timestep and check the length of the mode "
517 "file.");
518 }
519 }
520
521 // Convert modes to spatial data
522 if (wdata.is_ocean) {
523 modes_hosgrid::copy_complex(
524 wdata.n0, wdata.n1, wdata.c_mFS, wdata.c_eta_mptr);
525 wdata.sp_eta_vec.resize(
526 static_cast<size_t>(wdata.n0) * static_cast<size_t>(wdata.n1),
527 0.0_rt);
528 modes_hosgrid::populate_hos_eta(
529 wdata.c_rmodes, wdata.plan_vector, wdata.c_eta_mptr,
530 wdata.sp_eta_vec);
531 // Mesh is not yet created, so get data at every height
532 const auto n_hts = wdata.hvec.size();
533 wdata.sp_u_vec.resize(
534 static_cast<size_t>(wdata.n0 * wdata.n1) * n_hts);
535 wdata.sp_v_vec.resize(
536 static_cast<size_t>(wdata.n0 * wdata.n1) * n_hts);
537 wdata.sp_w_vec.resize(
538 static_cast<size_t>(wdata.n0 * wdata.n1) * n_hts);
539 for (int iht = 0; iht < static_cast<int>(n_hts); ++iht) {
540 // Get sample height
541 amrex::Real ht = wdata.hvec[iht];
542 // Sample velocity
543 modes_hosgrid::populate_hos_vel(
544 wdata.c_rmodes, ht, wdata.zsl, wdata.c_mX, wdata.c_mY,
545 wdata.c_mZ, wdata.plan_vector, wdata.c_u_mptr,
546 wdata.c_v_mptr, wdata.c_w_mptr, wdata.sp_u_vec,
547 wdata.sp_v_vec, wdata.sp_w_vec, iht * wdata.n0 * wdata.n1);
548 }
549 } else {
550 modes_hosgrid::copy_real(
551 wdata.n0, wdata.n1, wdata.r_mFS, wdata.r_eta_mptr);
552 wdata.sp_eta_vec.resize(
553 static_cast<size_t>(wdata.n0) * static_cast<size_t>(wdata.n1),
554 0.0_rt);
555 modes_hosgrid::populate_hos_eta(
556 wdata.r_rmodes, wdata.plan_vector, wdata.r_eta_mptr,
557 wdata.sp_eta_vec);
558 // Mesh is not yet created, so get data at every height
559 const auto n_hts = wdata.hvec.size();
560 wdata.sp_u_vec.resize(
561 static_cast<size_t>(wdata.n0 * wdata.n1) * n_hts);
562 wdata.sp_v_vec.resize(
563 static_cast<size_t>(wdata.n0 * wdata.n1) * n_hts);
564 wdata.sp_w_vec.resize(
565 static_cast<size_t>(wdata.n0 * wdata.n1) * n_hts);
566 for (int iht = 0; iht < static_cast<int>(n_hts); ++iht) {
567 // Get sample height
568 amrex::Real ht = wdata.hvec[iht];
569 // Sample velocity
570 modes_hosgrid::populate_hos_vel(
571 wdata.r_rmodes, ht, wdata.zsl, wdata.r_mX, wdata.r_mY,
572 wdata.r_mZ, wdata.r_mAdd, wdata.plan_vector, wdata.r_u_mptr,
573 wdata.r_v_mptr, wdata.r_w_mptr, wdata.au_mptr,
574 wdata.av_mptr, wdata.aw_mptr, wdata.sp_u_vec,
575 wdata.sp_v_vec, wdata.sp_w_vec, iht * wdata.n0 * wdata.n1);
576 }
577 }
578
579 // Declare fields for HOS
580 auto& w2a_levelset =
581 data.sim().repo().declare_field("w2a_levelset", 1, 3, 2);
582 auto& w2a_velocity = data.sim().repo().declare_field(
583 "w2a_velocity", AMREX_SPACEDIM, 3, 2);
584
585 // Extrapolation can work well when finer data is available
586 w2a_levelset.set_default_fillpatch_bc(data.sim().time());
587 w2a_velocity.set_default_fillpatch_bc(data.sim().time());
588#endif
589 }
590}; // namespace ops
591
592template <>
594{
596 W2AWaves::DataType& data,
597 int level,
598 const amrex::Geometry& geom,
599 bool multiphase_mode)
600 {
601
602#ifdef KYNEMA_SGF_USE_W2A
603 auto& wdata = data.meta();
604
605 auto& sim = data.sim();
606
607 // Fill ow fields, then populate flow fields according to setup
608 auto& ow_levelset = sim.repo().get_field("ow_levelset");
609 auto& ow_velocity = sim.repo().get_field("ow_velocity");
610
611 auto& velocity = sim.repo().get_field("velocity");
612 // Set w2a fields to default values to prep for updates
613 auto& w2a_levelset = sim.repo().get_field("w2a_levelset");
614 auto& w2a_velocity = sim.repo().get_field("w2a_velocity");
615 // Copy current fields to old w2a fields for time interp
616 auto& w2a_lvs_old = w2a_levelset.state(kynema_sgf::FieldState::Old);
617 auto& w2a_vel_old = w2a_velocity.state(kynema_sgf::FieldState::Old);
618
619 Field* levelset{nullptr};
620 if (multiphase_mode) {
621 levelset = &sim.repo().get_field("levelset");
622 }
623
624 const auto& problo = geom.ProbLoArray();
625 const auto& probhi = geom.ProbHiArray();
626 const auto& dx = geom.CellSizeArray();
627
628 // Set t_last to 0.0_rt to signify information read in
629 wdata.t_last = 0.0_rt;
630
631 // indvec is complete upon initialization (all heights every proc)
632 amrex::Vector<int> indvec(wdata.hvec.size());
633 std::iota(indvec.begin(), indvec.end(), 0);
634 // Interpolate to MultiFabs (one level at a time)
635 interp_to_mfab::interp_eta_to_levelset_multifab(
636 wdata.n0_sp, wdata.n1_sp, wdata.dx0, wdata.dx1, wdata.xlo0,
637 wdata.xlo1, wdata.zsl, wdata.is_ocean, wdata.sp_eta_vec,
638 ow_levelset(level), problo, dx);
639 interp_to_mfab::interp_velocity_to_multifab(
640 wdata.n0_sp, wdata.n1_sp, wdata.dx0, wdata.dx1, wdata.xlo0,
641 wdata.xlo1, wdata.is_ocean, indvec, wdata.hvec, wdata.sp_u_vec,
642 wdata.sp_v_vec, wdata.sp_w_vec, ow_velocity(level), problo, dx);
643
644 // Populate flow fields according to intended forcing and init setup
645 const auto& ow_phi = ow_levelset(level).const_arrays();
646 const auto& ow_vel = ow_velocity(level).const_arrays();
647 const auto& vel = velocity(level).arrays();
648 const auto& phi_arrs = multiphase_mode
649 ? (*levelset)(level).arrays()
650 : amrex::MultiArray4<amrex::Real>();
651
652 const auto& w2a_phi = w2a_levelset(level).arrays();
653 const auto& w2a_vel = w2a_velocity(level).arrays();
654 const auto& w2a_phi_o = w2a_lvs_old(level).arrays();
655 const auto& w2a_vel_o = w2a_vel_old(level).arrays();
656
657 const amrex::Real gen_length = wdata.gen_length;
658 const amrex::Real beach_length = wdata.beach_length;
659 const amrex::Real y_length = wdata.zone_length_y;
660 const amrex::Real zero_sea_level = wdata.zsl;
661
662 const bool has_beach = wdata.has_beach && multiphase_mode;
663 const bool init_wave_field = wdata.init_wave_field || !multiphase_mode;
664
665 amrex::MultiFab phi_tmp_fab(
666 velocity(level).boxArray(), velocity(level).DistributionMap(), 1,
667 3);
668 amrex::MultiFab vel_tmp_fab(
669 velocity(level).boxArray(), velocity(level).DistributionMap(),
670 AMREX_SPACEDIM, 3);
671
672 const auto& phi_tmp = phi_tmp_fab.arrays();
673 const auto& vel_tmp = vel_tmp_fab.arrays();
674
675 amrex::ParallelFor(
676 velocity(level), amrex::IntVect(3),
677 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
678 const amrex::Real x = problo[0] + (i + 0.5_rt) * dx[0];
679 const amrex::Real y = problo[1] + (j + 0.5_rt) * dx[1];
680 const amrex::Real z = problo[2] + (k + 0.5_rt) * dx[2];
681
682 // Wave profile
683 const utils::WaveVec wave_sol{
684 ow_vel[nbx](i, j, k, 0), ow_vel[nbx](i, j, k, 1),
685 ow_vel[nbx](i, j, k, 2), ow_phi[nbx](i, j, k) + z};
686 // Quiescent profile
687 const utils::WaveVec quiescent{
688 0.0_rt, 0.0_rt, 0.0_rt, zero_sea_level};
689
690 // Specify initial state for each region of domain
691 const auto bulk = init_wave_field ? wave_sol : quiescent;
692 const auto outlet = has_beach ? quiescent : wave_sol;
693
694 const auto local_profile = utils::harmonize_profiles_2d(
695 x, y, problo[0], gen_length, probhi[0], beach_length,
696 problo[1], probhi[1], y_length, wave_sol, bulk, outlet);
697
698 phi_tmp[nbx](i, j, k) = local_profile[3] - z;
699 vel_tmp[nbx](i, j, k, 0) = local_profile[0];
700 vel_tmp[nbx](i, j, k, 1) = local_profile[1];
701 vel_tmp[nbx](i, j, k, 2) = local_profile[2];
702
703 if (multiphase_mode) {
704 phi_arrs[nbx](i, j, k) = phi_tmp[nbx](i, j, k);
705 }
706
707 // Start old values at w2a solution (for the sake of time
708 // interpolation)
709 w2a_phi_o[nbx](i, j, k) = wave_sol[3] - z;
710 w2a_vel_o[nbx](i, j, k, 0) = wave_sol[0];
711 w2a_vel_o[nbx](i, j, k, 1) = wave_sol[1];
712 w2a_vel_o[nbx](i, j, k, 2) = wave_sol[2];
713
714 // Default w2a values matter for where no updates happen
715 w2a_phi[nbx](i, j, k) = quiescent[3] - z;
716 w2a_vel[nbx](i, j, k, 0) = quiescent[0];
717 w2a_vel[nbx](i, j, k, 1) = quiescent[1];
718 w2a_vel[nbx](i, j, k, 2) = quiescent[2];
719 });
720 amrex::Gpu::streamSynchronize();
721
722 amrex::ParallelFor(
723 velocity(level), amrex::IntVect(2),
724 [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k) {
725 const amrex::Real eps =
726 2.0_rt * std::cbrt(dx[0] * dx[1] * dx[2]);
727 const amrex::Real vof_local =
728 multiphase::levelset_to_vof(i, j, k, eps, phi_tmp[nbx]);
729
730 if (vof_local > 1.0_rt - constants::VOF_TOL) {
731 // Entire cell is liquid
732 vel[nbx](i, j, k, 0) = vel_tmp[nbx](i, j, k, 0);
733 vel[nbx](i, j, k, 1) = vel_tmp[nbx](i, j, k, 1);
734 vel[nbx](i, j, k, 2) = vel_tmp[nbx](i, j, k, 2);
735 } else if (vof_local > 1.0e-3_rt) {
736 // Velocity of liquid becomes velocity of entire cell
737 // Interpolate using cell-centered values to liquid centroid
738 // Consider only z-direction to find centroid
739 const amrex::Real z_cell = problo[2] + (k + 0.5_rt) * dx[2];
740 const amrex::Real z_cell_below = z_cell - dx[2];
741 const amrex::Real z_cell_bottom = z_cell - 0.5_rt * dx[2];
742 const amrex::Real z_liq_center =
743 z_cell_bottom + 0.5_rt * vof_local * dx[2];
744 for (int n = 0; n < AMREX_SPACEDIM; ++n) {
745 vel[nbx](i, j, k, n) =
746 vel_tmp[nbx](i, j, k - 1, n) +
747 (vel_tmp[nbx](i, j, k, n) -
748 vel_tmp[nbx](i, j, k - 1, n)) *
749 ((z_liq_center - z_cell_below) /
750 (z_cell - z_cell_below + constants::EPS));
751 }
752 }
753 });
754 amrex::Gpu::streamSynchronize();
755#else
756 amrex::ignore_unused(data, level, geom, multiphase_mode);
757#endif
758 }
759}; // namespace ocean_waves
760
761template <>
763{
764 void operator()(W2AWaves::DataType& data, const amrex::Real time)
765 {
766
767#ifdef KYNEMA_SGF_USE_W2A
768 auto& wdata = data.meta();
769 auto& sim = data.sim();
770
771 // Update ow fields every time
772 auto& ow_levelset = sim.repo().get_field("ow_levelset");
773 auto& ow_velocity = sim.repo().get_field("ow_velocity");
774 // Update HOS fields when necessary
775 auto& w2a_levelset = sim.repo().get_field("w2a_levelset");
776 auto& w2a_velocity = sim.repo().get_field("w2a_velocity");
777 // Old state of HOS fields used for time interpolation
778 auto& w2a_lvs_old = w2a_levelset.state(kynema_sgf::FieldState::Old);
779 auto& w2a_vel_old = w2a_velocity.state(kynema_sgf::FieldState::Old);
780
781 // Proxy for multiphase mode of ocean waves
782 bool vof_exists = sim.repo().field_exists("vof");
783
784 auto nlevels = sim.repo().num_active_levels();
785 auto geom = sim.mesh().Geom();
786
787 // Get value for time interpolation
788 amrex::Real t_last = wdata.t_last;
789
790 // Check if new HOS data needs to be read
791 bool read_flag = false;
792 // Check if time indicates reading must take place
793 int new_ntime =
794 wdata.is_ocean
795 ? wdata.c_rmodes.time2step(time + wdata.t_winit, wdata.ntime)
796 : wdata.r_rmodes.time2step(time + wdata.t_winit, wdata.ntime);
797 int double_data = evaluate_read_resize(
798 wdata.ntime, read_flag, wdata.resize_flag, wdata.t, wdata.t_last,
799 new_ntime, wdata.t_winit, wdata.dt_modes, time);
800 // Check if stop time is exceeded, introduce offset to ntime
801 if (read_flag) {
802 // Need to only check when reading is occurring
803 if (wdata.ntime + wdata.n_offset > wdata.n_wstop) {
804 // If exceeding stop step, calculate new offset
805 wdata.n_offset =
806 update_offset_timestep(wdata.ntime, wdata.n_winit);
807 // Print warning to screen
808 amrex::Print()
809 << "WARNING (waves2amr_ops): available mode data exceeded, "
810 "resetting to beginning of mode data.\n";
811 }
812 }
813 // Resizing (assuming reading is taking place) must happen after regrid
814 if (wdata.regrid_occurred) {
815 // resize_flag remains true until resizing occurs, but
816 // regrid_occurred resets every timestep
817 wdata.resize_flag = true;
818 }
819
820 // Read HOS data if necessary based on time
821 if (read_flag) {
822
823 amrex::Print() << "OceanWaves: Waves2AMR reading from file: step "
824 << wdata.ntime << std::endl
825 << " last interp time " << t_last << std::endl
826 << " simulation time " << time << std::endl
827 << " new data time " << wdata.t << std::endl
828 << " double data read " << double_data
829 << std::endl;
830
831 if (wdata.resize_flag) {
832 // Reset flag
833 wdata.resize_flag = false;
834 // Flags for indicating overlap, assume none at first
835 bool flag_z = false;
836 bool flag_xlo = false;
837 bool flag_xhi = false;
838 bool flag_ylo = false;
839 bool flag_yhi = false;
840 // Get heights for this processor, check overlap in z
841 flag_z =
842 (interp_to_mfab::get_local_height_indices(
843 wdata.indvec, wdata.hvec, ow_velocity.vec_ptrs(),
844 geom) == 1);
845 // No overlap from heights definitely means no interp
846
847 // Check lateral bounds (in x)
848 flag_xlo =
849 (interp_to_mfab::check_lateral_overlap_lo(
850 wdata.gen_length, 0, ow_velocity.vec_ptrs(), geom) ==
851 1);
852 // No overlap with gen region means no interp, unless ...
853 if (!wdata.has_beach) {
854 // ... if overlap exists here, needing interp
855 flag_xhi =
856 (interp_to_mfab::check_lateral_overlap_hi(
857 wdata.beach_length, 0, ow_velocity.vec_ptrs(),
858 geom) == 1);
859 }
860 // Then in y, if y zones are present
861 if (wdata.zone_length_y > constants::EPS) {
862 flag_ylo =
863 (interp_to_mfab::check_lateral_overlap_lo(
864 wdata.zone_length_y, 1, ow_velocity.vec_ptrs(),
865 geom) == 1);
866 flag_yhi =
867 (interp_to_mfab::check_lateral_overlap_hi(
868 wdata.zone_length_y, 1, ow_velocity.vec_ptrs(),
869 geom) == 1);
870 }
871
872 // Wave generation zones are irrelevant for single-phase mode,
873 // indicated by nonexistence of vof
874 if (!vof_exists) {
875 flag_xlo = true;
876 flag_xhi = true;
877 }
878
879 if (flag_z && (flag_xlo || flag_xhi || flag_ylo || flag_yhi)) {
880 // Interpolation is needed
881 wdata.do_interp = true;
882 // Do resizing
883 wdata.sp_eta_vec.resize(
884 static_cast<size_t>(wdata.n0) *
885 static_cast<size_t>(wdata.n1),
886 0.0_rt);
887 wdata.sp_u_vec.resize(
888 static_cast<size_t>(wdata.n0 * wdata.n1) *
889 wdata.indvec.size());
890 wdata.sp_v_vec.resize(
891 static_cast<size_t>(wdata.n0 * wdata.n1) *
892 wdata.indvec.size());
893 wdata.sp_w_vec.resize(
894 static_cast<size_t>(wdata.n0 * wdata.n1) *
895 wdata.indvec.size());
896 // Sizes will remain constant and need for interpolation
897 // will remain until a regrid occurs
898 } else {
899 // No overlapping with spatial data or no overlapping with
900 // relaxation zones, interpolation can be skipped
901 wdata.do_interp = false;
902 }
903 }
904 // Only perform reading where needed, communicate offset though
905 amrex::ParallelDescriptor::ReduceIntMax(wdata.n_offset);
906
907 // Previous W2A data is more recent than last interpolated data
908 t_last = (wdata.ntime - 1) * wdata.dt_modes;
909
910 if (double_data == 0) {
911 // Previous W2A data needs to be copied into old fields
913 w2a_lvs_old, w2a_levelset, 0, 0, 1,
914 w2a_levelset.num_grow());
916 w2a_vel_old, w2a_velocity, 0, 0, AMREX_SPACEDIM,
917 w2a_velocity.num_grow());
918 } else if (double_data == 1) {
919 // Previous W2A data is unknown, read into old fields
920 if (wdata.do_interp) {
921 populate_fields_all_levels(
922 wdata, geom, w2a_lvs_old, w2a_vel_old, -1);
923 }
924
925 // Average down to get fine information on coarse grid where
926 // possible (may be unnecessary)
927 for (int lev = nlevels - 1; lev > 0; --lev) {
928 amrex::average_down(
929 w2a_vel_old(lev), w2a_vel_old(lev - 1), 0,
930 AMREX_SPACEDIM, sim.mesh().refRatio(lev - 1));
931 amrex::average_down(
932 w2a_lvs_old(lev), w2a_lvs_old(lev - 1), 0, 1,
933 sim.mesh().refRatio(lev - 1));
934 }
935 // Fill patch to get correct ghost cells after average down
936 w2a_vel_old.fillpatch(sim.time().new_time());
937 w2a_lvs_old.fillpatch(sim.time().new_time());
938 }
939 // ow fields cancel when double_data == 2, no modification
940
941 // After possible prior read, now read data for this ntime
942 if (wdata.do_interp) {
943 populate_fields_all_levels(
944 wdata, geom, w2a_levelset, w2a_velocity);
945 }
946
947 // Average down to get fine information on coarse grid where
948 // possible and update ghost cells (may be unnecessary)
949 for (int lev = nlevels - 1; lev > 0; --lev) {
950 amrex::average_down(
951 w2a_velocity(lev), w2a_velocity(lev - 1), 0, AMREX_SPACEDIM,
952 sim.mesh().refRatio(lev - 1));
953 w2a_velocity(lev - 1).FillBoundary(geom[lev - 1].periodicity());
954 amrex::average_down(
955 w2a_levelset(lev), w2a_levelset(lev - 1), 0, 1,
956 sim.mesh().refRatio(lev - 1));
957 w2a_levelset(lev - 1).FillBoundary(geom[lev - 1].periodicity());
958 }
959 }
960
961 // Temporally interpolate at every timestep to get target solution
962 time_interpolate_wave_fields(
963 w2a_lvs_old, w2a_vel_old, w2a_levelset, w2a_velocity, t_last, time,
964 wdata.t);
965 // Copy to ow fields, which may be modified for beach
967 ow_levelset, w2a_lvs_old, 0, 0, 1, ow_levelset.num_grow());
969 ow_velocity, w2a_vel_old, 0, 0, AMREX_SPACEDIM,
970 ow_velocity.num_grow());
971#else
972 amrex::ignore_unused(data, time);
973#endif
974 }
975};
976
977} // namespace kynema_sgf::ocean_waves::ops
978
979#endif /* WAVES2AMR_OPS_H */
FieldRepo & repo()
Return the field repository.
Definition CFDSim.H:76
SimTime & time()
Return simulation time control.
Definition CFDSim.H:66
Definition Field.H:115
const amrex::IntVect & num_grow() const
Ghost cells.
Definition Field.H:139
Field & state(FieldState fstate)
Return field at a different time state.
Definition Field.cpp:118
amrex::Vector< amrex::MultiFab * > vec_ptrs()
Return a vector of MultiFab pointers for all levels.
Definition Field.cpp:146
void set_default_fillpatch_bc(const SimTime &time, amrex::BCType::mathematicalBndryTypes bctype=amrex::BCType::hoextrap)
Definition Field.cpp:539
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
bool field_exists(const std::string &name, FieldState fstate=FieldState::New) const
Query if field uniquely identified by name and time state exists in repository.
Definition FieldRepo.cpp:218
Field & declare_field(const std::string &name, int ncomp=1, int ngrow=0, int nstates=1, FieldLoc floc=FieldLoc::CELL)
Definition FieldRepo.cpp:86
OceanWavesTrait::InfoType & info()
Definition OceanWavesTypes.H:86
OceanWavesTrait::MetaType & meta()
Definition OceanWavesTypes.H:92
CFDSim & sim()
Definition OceanWavesTypes.H:83
void copy(T1 &dst, const T2 &src, const int srccomp, const int dstcomp, const int numcomp, const amrex::IntVect &nghost)
Definition field_ops.H:157
void lincomb(T1 &dst, const amrex::Real a, const T2 &x, const int xcomp, const amrex::Real b, const T3 &y, const int ycomp, const int dstcomp, const int numcomp, const amrex::IntVect &nghost)
Definition field_ops.H:320
@ Old
Same as FieldState::N.
Definition FieldDescTypes.H:23
static constexpr amrex::Real VOF_TOL
Tolerance for vof determining presence of liquid.
Definition constants.H:34
static constexpr amrex::Real TIGHT_TOL
A tight tolerance.
Definition constants.H:17
static constexpr amrex::Real EPS
A number very close to zero.
Definition constants.H:13
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real levelset_to_vof(const int i, const int j, const int k, const amrex::Real eps, amrex::Array4< amrex::Real const > const &phi)
Definition volume_fractions.H:567
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_2d(const amrex::Real x, const amrex::Real y, const amrex::Real left_bdy, const amrex::Real left_length, const amrex::Real right_bdy, const amrex::Real right_length, const amrex::Real lo_y_bdy, const amrex::Real hi_y_bdy, const amrex::Real y_length, const WaveVec left, const WaveVec bulk, const WaveVec right)
Definition wave_utils_K.H:110
bool regrid_occurred
Definition RelaxationZones.H:45
bool has_beach
Definition RelaxationZones.H:41
amrex::Real zone_length_y
Definition RelaxationZones.H:33
amrex::Real zsl
Definition RelaxationZones.H:20
amrex::Real gen_length
Definition RelaxationZones.H:28
bool init_wave_field
Definition RelaxationZones.H:37
amrex::Real current
Definition RelaxationZones.H:35
amrex::Real beach_length
Definition RelaxationZones.H:30
bool resize_flag
Definition W2AWaves.H:85
amrex::Real dx1
Definition W2AWaves.H:29
int n_winit
Definition W2AWaves.H:44
int ntime
Definition W2AWaves.H:42
amrex::Gpu::DeviceVector< amrex::Real > sp_w_vec
Definition W2AWaves.H:88
std::vector< std::complex< amrex::Real > > c_mY
Definition W2AWaves.H:57
std::vector< std::complex< amrex::Real > > c_mX
Definition W2AWaves.H:57
std::string modes_file
Definition W2AWaves.H:19
std::vector< amrex::Real > r_mAdd
Definition W2AWaves.H:58
amrex::Real dt_modes
Definition W2AWaves.H:36
amrex::Real xlo1
Definition W2AWaves.H:32
amrex::Real dx0
Definition W2AWaves.H:28
int n2
Definition W2AWaves.H:23
int n1_sp
Definition W2AWaves.H:26
std::vector< amrex::Real > r_mFS
Definition W2AWaves.H:58
int n1
Definition W2AWaves.H:22
int n0_sp
Definition W2AWaves.H:25
amrex::Real xlo0
Definition W2AWaves.H:31
amrex::Real t_last
Definition W2AWaves.H:52
amrex::Real t_winit
Definition W2AWaves.H:40
std::vector< amrex::Real > r_mX
Definition W2AWaves.H:58
amrex::Gpu::DeviceVector< amrex::Real > sp_eta_vec
Definition W2AWaves.H:87
amrex::Gpu::DeviceVector< amrex::Real > sp_u_vec
Definition W2AWaves.H:87
bool do_interp
Definition W2AWaves.H:83
int n_wstop
Definition W2AWaves.H:46
amrex::Real dimL
Definition W2AWaves.H:34
amrex::Real t
Definition W2AWaves.H:54
int n0
Definition W2AWaves.H:21
amrex::Vector< int > indvec
Definition W2AWaves.H:79
std::vector< std::complex< amrex::Real > > c_mFS
Definition W2AWaves.H:57
bool is_ocean
Definition W2AWaves.H:81
std::vector< std::complex< amrex::Real > > c_mZ
Definition W2AWaves.H:57
std::vector< amrex::Real > r_mZ
Definition W2AWaves.H:58
std::vector< amrex::Real > r_mY
Definition W2AWaves.H:58
int n_offset
Definition W2AWaves.H:48
amrex::Vector< amrex::Real > hvec
Definition W2AWaves.H:77
amrex::Gpu::DeviceVector< amrex::Real > sp_v_vec
Definition W2AWaves.H:87
Definition W2AWaves.H:138
OceanWavesDataHolder< W2AWaves > DataType
Definition W2AWaves.H:141
W2AWavesData MetaType
Definition W2AWaves.H:140
void operator()(W2AWaves::DataType &data, int level, const amrex::Geometry &geom, bool multiphase_mode)
Definition waves2amr_ops.H:595
Definition OceanWavesOps.H:14
void operator()(W2AWaves::DataType &data, const ::kynema_sgf::utils::MultiParser &pp)
Definition waves2amr_ops.H:209
Definition OceanWavesOps.H:11
void operator()(W2AWaves::DataType &data, const amrex::Real time)
Definition waves2amr_ops.H:764