@@ -25,7 +25,6 @@ void read_inputs(
25
25
pp.query (" relax_zone_gen_length" , wdata.gen_length );
26
26
if (pp.contains (" relax_zone_out_length" )) {
27
27
wdata.has_beach = false ;
28
- wdata.has_outprofile = true ;
29
28
wdata.init_wave_field = true ;
30
29
pp.query (" relax_zone_out_length" , wdata.beach_length );
31
30
} else {
@@ -34,6 +33,7 @@ void read_inputs(
34
33
pp.query (" numerical_beach_length_factor" , wdata.beach_length_factor );
35
34
pp.query (" initialize_wave_field" , wdata.init_wave_field );
36
35
}
36
+ pp.query (" relax_zone_length_y" , wdata.zone_length_y );
37
37
38
38
pp.query (" current" , wdata.current );
39
39
@@ -120,17 +120,21 @@ void apply_relaxation_zones(CFDSim& sim, const RelaxZonesBaseData& wdata)
120
120
const amrex::Real gen_length = wdata.gen_length ;
121
121
const amrex::Real beach_length = wdata.beach_length ;
122
122
const amrex::Real beach_length_factor = wdata.beach_length_factor ;
123
+ const amrex::Real zone_length_y = wdata.zone_length_y ;
124
+ const bool has_zone_y = zone_length_y > constants::EPS;
123
125
const amrex::Real zsl = wdata.zsl ;
124
126
const amrex::Real current = wdata.current ;
125
127
const bool has_beach = wdata.has_beach ;
126
- const bool has_outprofile = wdata.has_outprofile ;
127
128
128
129
amrex::ParallelFor (
129
130
velocity (lev), amrex::IntVect (0 ),
130
131
[=] AMREX_GPU_DEVICE (int nbx, int i, int j, int k) noexcept {
131
132
const amrex::Real x = amrex::min (
132
133
amrex::max (problo[0 ] + (i + 0.5 ) * dx[0 ], problo[0 ]),
133
134
probhi[0 ]);
135
+ const amrex::Real y = amrex::min (
136
+ amrex::max (problo[1 ] + (j + 0.5 ) * dx[1 ], problo[1 ]),
137
+ probhi[1 ]);
134
138
const amrex::Real z = amrex::min (
135
139
amrex::max (problo[2 ] + (k + 0.5 ) * dx[2 ], problo[2 ]),
136
140
probhi[2 ]);
@@ -141,128 +145,96 @@ void apply_relaxation_zones(CFDSim& sim, const RelaxZonesBaseData& wdata)
141
145
const auto target_volfrac = target_volfrac_arrs[nbx];
142
146
const auto target_vel = target_vel_arrs[nbx];
143
147
148
+ // Skip if in or near terrain
144
149
bool in_or_near_terrain{false };
145
150
if (terrain_exists) {
146
151
in_or_near_terrain =
147
152
(terrain_blank_flags[nbx](i, j, k) == 1 ||
148
153
terrain_drag_flags[nbx](i, j, k) == 1 );
149
154
}
150
155
151
- // Generation region
152
- if (x <= problo[0 ] + gen_length && !in_or_near_terrain) {
153
- const amrex::Real Gamma =
154
- utils::gamma_generate (x - problo[0 ], gen_length);
155
- // Get bounded new vof, incorporate with increment
156
+ // Get gamma for each possible direction
157
+ const amrex::Real Gamma_xlo =
158
+ utils::gamma_generate (x - problo[0 ], gen_length);
159
+ const amrex::Real Gamma_xhi = utils::gamma_absorb (
160
+ x - (probhi[0 ] - beach_length), beach_length,
161
+ beach_length_factor);
162
+ amrex::Real Gamma_ylo = 1 .;
163
+ amrex::Real Gamma_yhi = 1 .;
164
+ if (has_zone_y) {
165
+ Gamma_ylo =
166
+ utils::gamma_generate (y - problo[1 ], zone_length_y);
167
+ Gamma_yhi = utils::gamma_absorb (
168
+ y - (probhi[1 ] - zone_length_y), zone_length_y, 1.0 );
169
+ }
170
+ const amrex::Real Gamma = std::min (
171
+ std::min (Gamma_xhi, Gamma_xlo),
172
+ std::min (Gamma_yhi, Gamma_ylo));
173
+
174
+ // Skip if Gamma is close enough to 1
175
+ bool outside_zones = Gamma + constants::EPS >= 1 .;
176
+
177
+ if (!(outside_zones || in_or_near_terrain)) {
178
+ // Create wave vector for generation, numerical beach
179
+ const utils::WaveVec wave_sol{
180
+ target_vel (i, j, k, 0 ), target_vel (i, j, k, 1 ),
181
+ target_vel (i, j, k, 2 ), target_volfrac (i, j, k)};
182
+ const utils::WaveVec quiescent{
183
+ current, 0.0 , 0.0 ,
184
+ utils::free_surface_to_vof (zsl, z, dx[2 ])};
185
+ const auto outlet = has_beach ? quiescent : wave_sol;
186
+
187
+ // Check for in beach, needed for velocity forcing
188
+ const bool in_beach =
189
+ has_beach && x + beach_length >= probhi[0 ];
190
+
191
+ // Harmonize between inlet/bulk profile and outlet profile
192
+ const auto target_profile = utils::harmonize_profiles_1d (
193
+ x, problo[0 ], gen_length, probhi[0 ], beach_length,
194
+ wave_sol, wave_sol, outlet);
195
+
196
+ // Nudge solution toward target
156
197
amrex::Real new_vof = utils::combine_linear (
157
- Gamma, target_volfrac (i, j, k) , volfrac (i, j, k));
198
+ Gamma, target_profile[ 3 ] , volfrac (i, j, k));
158
199
new_vof = (new_vof > 1 . - vof_tiny)
159
200
? 1.0
160
201
: (new_vof < vof_tiny ? 0.0 : new_vof);
161
202
const amrex::Real dvf = new_vof - volfrac (i, j, k);
162
203
volfrac (i, j, k) += rampf * dvf;
163
- // Force liquid velocity only if target vof present
164
- const amrex::Real fvel_liq =
204
+ // Liquid velocity forced only where velocity is known
205
+ // - in most of domain, that is where target vof is nonzero
206
+ // - in numerical beach, that is anywhere
207
+ amrex::Real fvel_liq =
165
208
(target_volfrac (i, j, k) > vof_tiny) ? 1.0 : 0.0 ;
209
+ fvel_liq = in_beach ? 1.0 : fvel_liq;
166
210
amrex::Real rho_ = rho1 * volfrac (i, j, k) +
167
211
rho2 * (1.0 - volfrac (i, j, k));
168
212
for (int n = 0 ; n < vel.ncomp ; ++n) {
169
213
// Get updated liquid velocity
170
214
amrex::Real vel_liq = vel (i, j, k, n);
171
215
const amrex::Real dvel_liq =
172
216
utils::combine_linear (
173
- Gamma, target_vel (i, j, k, n) , vel_liq) -
217
+ Gamma, target_profile[n] , vel_liq) -
174
218
vel_liq;
175
219
vel_liq += rampf * fvel_liq * dvel_liq;
176
220
// If liquid was added, that liquid has target_vel
177
221
amrex::Real integrated_vel_liq =
178
222
volfrac (i, j, k) * vel_liq;
179
223
integrated_vel_liq +=
180
224
rampf * fvel_liq * amrex::max (0.0 , dvf) *
181
- (target_vel (i, j, k, n) - vel (i, j, k, n));
225
+ (target_profile[n] - vel (i, j, k, n));
182
226
// Update overall velocity using momentum
183
227
vel (i, j, k, n) =
184
228
(rho1 * integrated_vel_liq +
185
229
rho2 * (1 . - volfrac (i, j, k)) * vel (i, j, k, n)) /
186
230
rho_;
187
231
}
188
- }
189
- // Outlet region
190
- if (x + beach_length >= probhi[0 ] && !in_or_near_terrain) {
191
- const amrex::Real Gamma = utils::gamma_absorb (
192
- x - (probhi[0 ] - beach_length), beach_length,
193
- beach_length_factor);
194
- // Numerical beach (sponge layer)
195
- if (has_beach) {
196
- // Get bounded new vof, save increment
197
- amrex::Real new_vof = utils::combine_linear (
198
- Gamma, utils::free_surface_to_vof (zsl, z, dx[2 ]),
199
- volfrac (i, j, k));
200
- new_vof = (new_vof > 1 . - vof_tiny)
201
- ? 1.0
202
- : (new_vof < vof_tiny ? 0.0 : new_vof);
203
- const amrex::Real dvf = new_vof - volfrac (i, j, k);
204
- volfrac (i, j, k) = new_vof;
205
- // Conserve momentum when density changes
206
- amrex::Real rho_ = rho1 * volfrac (i, j, k) +
207
- rho2 * (1.0 - volfrac (i, j, k));
208
- // Target vel is current, 0, 0
209
- amrex::Real out_vel{0.0 };
210
- for (int n = 0 ; n < vel.ncomp ; ++n) {
211
- if (n == 0 ) {
212
- out_vel = current;
213
- } else {
214
- out_vel = 0.0 ;
215
- }
216
- const amrex::Real vel_liq = utils::combine_linear (
217
- Gamma, out_vel, vel (i, j, k, n));
218
- amrex::Real integrated_vel_liq =
219
- volfrac (i, j, k) * vel_liq;
220
- integrated_vel_liq += amrex::max (0.0 , dvf) *
221
- (out_vel - vel (i, j, k, n));
222
- vel (i, j, k, n) = (rho1 * integrated_vel_liq +
223
- rho2 * (1 . - volfrac (i, j, k)) *
224
- vel (i, j, k, n)) /
225
- rho_;
226
- }
227
- }
228
- // Forcing to wave profile instead
229
- if (has_outprofile) {
230
- // Same steps as in wave generation region
231
- amrex::Real new_vof = utils::combine_linear (
232
- Gamma, target_volfrac (i, j, k), volfrac (i, j, k));
233
- new_vof = (new_vof > 1 . - vof_tiny)
234
- ? 1.0
235
- : (new_vof < vof_tiny ? 0.0 : new_vof);
236
- const amrex::Real dvf = new_vof - volfrac (i, j, k);
237
- volfrac (i, j, k) += dvf;
238
- const amrex::Real fvel_liq =
239
- (target_volfrac (i, j, k) > vof_tiny) ? 1.0 : 0.0 ;
240
- amrex::Real rho_ = rho1 * volfrac (i, j, k) +
241
- rho2 * (1.0 - volfrac (i, j, k));
242
- for (int n = 0 ; n < vel.ncomp ; ++n) {
243
- amrex::Real vel_liq = vel (i, j, k, n);
244
- const amrex::Real dvel_liq =
245
- utils::combine_linear (
246
- Gamma, target_vel (i, j, k, n), vel_liq) -
247
- vel_liq;
248
- vel_liq += rampf * fvel_liq * dvel_liq;
249
- amrex::Real integrated_vel_liq =
250
- volfrac (i, j, k) * vel_liq;
251
- integrated_vel_liq +=
252
- rampf * fvel_liq * amrex::max (0.0 , dvf) *
253
- (target_vel (i, j, k, n) - vel (i, j, k, n));
254
- vel (i, j, k, n) = (rho1 * integrated_vel_liq +
255
- rho2 * (1 . - volfrac (i, j, k)) *
256
- vel (i, j, k, n)) /
257
- rho_;
258
- }
259
- }
260
- }
261
232
262
- // Make sure that density is updated before entering the
263
- // solution
264
- rho (i, j, k) =
265
- rho1 * volfrac (i, j, k) + rho2 * (1 . - volfrac (i, j, k));
233
+ // Make sure that density is updated before entering the
234
+ // solution
235
+ rho (i, j, k) = rho1 * volfrac (i, j, k) +
236
+ rho2 * (1 . - volfrac (i, j, k));
237
+ }
266
238
});
267
239
}
268
240
amrex::Gpu::streamSynchronize ();
0 commit comments