REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_init_bcs.cpp
Go to the documentation of this file.
1#include <AMReX_Vector.H>
2#include <AMReX_BC_TYPES.H>
3#include <AMReX_ParmParse.H>
4
5#include <REMORA.H>
6
7using namespace amrex;
8
10{
11 auto f_set_var_bc = [this] (ParmParse& pp, int bcvar_type, Orientation ori, std::string bc_type_string) {
12 if (bc_type_string == "symmetry")
13 {
14 phys_bc_type[bcvar_type][ori] = REMORA_BC::symmetry;
15 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
16 domain_bc_type[ori] = "Symmetry";
17 }
18 else if (bc_type_string == "outflow")
19 {
20 phys_bc_type[bcvar_type][ori] = REMORA_BC::outflow;
21 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
22 domain_bc_type[ori] = "Outflow";
23 }
24 else if (bc_type_string == "inflow")
25 {
26 phys_bc_type[bcvar_type][ori] = REMORA_BC::inflow;
27 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
28 domain_bc_type[ori] = "Inflow";
29
30 if (bcvar_type == BCVars::xvel_bc || bcvar_type == BCVars::yvel_bc ||
31 bcvar_type == BCVars::zvel_bc) {
32 std::vector<Real> v;
33 pp.getarr("velocity", v, 0, AMREX_SPACEDIM);
34 m_bc_extdir_vals[bcvar_type][ori] = v[bcvar_type - BCVars::xvel_bc];
35 } else if (bcvar_type == BCVars::Scalar_bc_comp) {
36 Real scalar_in = 0.;
37 if (pp.query("scalar", scalar_in))
39 }
40 }
41 else if (bc_type_string == "noslipwall")
42 {
43 phys_bc_type[bcvar_type][ori] = REMORA_BC::no_slip_wall;
44 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
45 domain_bc_type[ori] = "NoSlipWall";
46
47 if (bcvar_type == BCVars::xvel_bc || bcvar_type == BCVars::yvel_bc ||
48 bcvar_type == BCVars::zvel_bc) {
49 std::vector<Real> v;
50
51 // The values of m_bc_extdir_vals default to 0.
52 // But if we find "velocity" in the inputs file, use those values instead.
53 if (pp.queryarr("velocity", v, 0, AMREX_SPACEDIM))
54 {
55 v[ori.coordDir()] = 0.0_rt;
56 m_bc_extdir_vals[bcvar_type][ori] = v[bcvar_type - BCVars::xvel_bc];
57 }
58 }
59 }
60 else if (bc_type_string == "slipwall")
61 {
62 phys_bc_type[bcvar_type][ori] = REMORA_BC::slip_wall;
63 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
64 domain_bc_type[ori] = "SlipWall";
65 }
66 else if (bc_type_string == "clamped")
67 {
68 phys_bc_type[bcvar_type][ori] = REMORA_BC::clamped;
69 phys_bc_need_data[bdy_index[bcvar_type]][ori] = true;
70 domain_bc_type[ori] = "Clamped";
71 }
72 else if (bc_type_string == "chapman")
73 {
74 phys_bc_type[bcvar_type][ori] = REMORA_BC::chapman;
75 phys_bc_need_data[bdy_index[bcvar_type]][ori] = true;
76 domain_bc_type[ori] = "Chapman";
77
78 if (bcvar_type != BCVars::zeta_bc) {
79 amrex::Abort("Chapman BC can only be applied to zeta");
80 }
81 }
82 else if (bc_type_string == "flather")
83 {
84 phys_bc_type[bcvar_type][ori] = REMORA_BC::flather;
85 phys_bc_need_data[bdy_index[bcvar_type]][ori] = true;
86 domain_bc_type[ori] = "Flather";
87
88 if (!(bcvar_type == BCVars::ubar_bc || bcvar_type == BCVars::vbar_bc)) {
89 amrex::Abort("Flather BC can only be applied to ubar or vbar");
90 }
91 }
92 else if (bc_type_string == "orlanski_rad")
93 {
94 phys_bc_type[bcvar_type][ori] = REMORA_BC::orlanski_rad;
95 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
96 domain_bc_type[ori] = "Orlanski Radiation";
97 }
98 else if (bc_type_string == "orlanski_rad_nudg")
99 {
101 phys_bc_need_data[bdy_index[bcvar_type]][ori] = true;
102 domain_bc_type[ori] = "Orlanski Radiation with nudging";
103 }
104 else if (bc_type_string == "periodic")
105 {
106 if (!geom[0].isPeriodic(ori.coordDir())) {
107 amrex::Abort("Periodic boundary specified in a non-periodic direction");
108 }
109 phys_bc_type[bcvar_type][ori] = REMORA_BC::periodic;
110 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
111 domain_bc_type[ori] = "Periodic";
112 }
113 else
114 {
115 phys_bc_type[bcvar_type][ori] = REMORA_BC::undefined;
116 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
117 }
118
119 if (geom[0].isPeriodic(ori.coordDir()))
120 {
121 domain_bc_type[ori] = "Periodic";
122 if (phys_bc_type[bcvar_type][ori] == REMORA_BC::undefined)
123 {
124 phys_bc_type[bcvar_type][ori] = REMORA_BC::periodic;
125 phys_bc_need_data[bdy_index[bcvar_type]][ori] = false;
126 } else if (phys_bc_type[bcvar_type][ori] != REMORA_BC::periodic) {
127 amrex::Abort("Wrong BC type for periodic boundary");
128 }
129 }
130
131 if (phys_bc_type[bcvar_type][ori] == REMORA_BC::undefined)
132 {
133 amrex::Print() << "BC Type specified for fac is " << bc_type_string << std::endl;
134 amrex::Abort("This BC type is unknown");
135 }
136 };
137
138 auto f_by_side = [this, &f_set_var_bc] (std::string const& bcid, Orientation ori)
139 {
140 ParmParse pp("remora.bc."+bcid);
141 std::string bc_type_in = "null";
142 // Default z directions to slipwall
143 if (bcid=="zlo" or bcid=="zhi") bc_type_in = "slipwall";
144 pp.query("type", bc_type_in);
145 std::string bc_type = amrex::toLower(bc_type_in);
146
147 for (int icomp=0; icomp<BCVars::NumTypes; icomp++) {
148 f_set_var_bc(pp, icomp, ori, bc_type);
149 }
150 };
151
152 auto f_by_var = [this, &f_set_var_bc] (std::string const& varname, int bcvar_type)
153 {
154 amrex::Vector<Orientation> orientations = {Orientation(Direction::x,Orientation::low), Orientation(Direction::y,Orientation::high),Orientation(Direction::x,Orientation::high),Orientation(Direction::y,Orientation::low)}; // west, south, east, north [matches ROMS]
155 std::vector<std::string> bc_types = {"null","null","null","null"};
156 ParmParse pp("remora.bc."+varname);
157 std::string bc_type_in = "null";
158 // default zvel to outflow
159 if (bcvar_type == BCVars::zvel_bc) {
160 bc_types = {"outflow","outflow","outflow","outflow"};
161 for (int i=0; i<4; i++) {
162 auto ori = orientations[i];
163 if (geom[0].isPeriodic(ori.coordDir())) {
164 bc_types[i] = "periodic";
165 }
166 }
167 }
168 pp.queryarr("type", bc_types);
169 AMREX_ASSERT(bc_types.size() == 4);
170 for (int i=0; i<4; i++) {
171 std::string bc_type = amrex::toLower(bc_types[i]);
172 auto ori = orientations[i];
173 f_set_var_bc(pp, bcvar_type, ori, bc_type);
174 }
175 };
176
185
186 for (OrientationIter oit; oit; ++oit) {
187 Orientation ori = oit();
188 // These are simply defaults for Dirichlet faces -- they should be over-written below if needed
189 m_bc_extdir_vals[BCVars::Temp_bc_comp ][ori] = 1.e19_rt;
190 m_bc_extdir_vals[BCVars::Salt_bc_comp ][ori] = 1.e20_rt;
192
193 m_bc_extdir_vals[BCVars::xvel_bc][ori] = 0.0_rt; // default
194 m_bc_extdir_vals[BCVars::yvel_bc][ori] = 0.0_rt;
195 m_bc_extdir_vals[BCVars::zvel_bc][ori] = 0.0_rt;
196
197 m_bc_extdir_vals[BCVars::ubar_bc][ori] = 0.0_rt; // default
198 m_bc_extdir_vals[BCVars::vbar_bc][ori] = 0.0_rt;
201 }
202
203 // Whether to specify boundary conditions by variable (then side).
204 // Alternative is to do it by side by indicating keywords that indicate multiple variables
205 set_bcs_by_var = false;
206
207 ParmParse pp("remora");
208 pp.query("boundary_per_variable", set_bcs_by_var);
209 if (!set_bcs_by_var) {
210 f_by_side("xlo", Orientation(Direction::x,Orientation::low));
211 f_by_side("xhi", Orientation(Direction::x,Orientation::high));
212 f_by_side("ylo", Orientation(Direction::y,Orientation::low));
213 f_by_side("yhi", Orientation(Direction::y,Orientation::high));
214 } else {
215 f_by_var("temp", BCVars::Temp_bc_comp);
216 f_by_var("salt", BCVars::Salt_bc_comp);
217 f_by_var("scalar", BCVars::Scalar_bc_comp);
218 f_by_var("u", BCVars::xvel_bc);
219 f_by_var("v", BCVars::yvel_bc);
220 f_by_var("w", BCVars::zvel_bc);
221 f_by_var("ubar", BCVars::ubar_bc);
222 f_by_var("vbar", BCVars::vbar_bc);
223 f_by_var("zeta", BCVars::zeta_bc);
224 f_by_var("tke", BCVars::tke_bc);
225 }
226
227 // Always specify z direction by side keyword
228 f_by_side("zlo", Orientation(Direction::z,Orientation::low));
229 f_by_side("zhi", Orientation(Direction::z,Orientation::high));
230
231 // *****************************************************************************
232 //
233 // Here we translate the physical boundary conditions -- one type per face --
234 // into logical boundary conditions for each velocity component
235 //
236 // *****************************************************************************
237 {
238 domain_bcs_type.resize(AMREX_SPACEDIM+NCONS+8);
239 domain_bcs_type_d.resize(AMREX_SPACEDIM+NCONS+8);
240
241 for (OrientationIter oit; oit; ++oit) {
242 Orientation ori = oit();
243 int dir = ori.coordDir();
244 Orientation::Side side = ori.faceDir();
245 // only do this for xvel and yvel
246 for (int i = 0; i < 2; i++) {
247 auto const bct = phys_bc_type[BCVars::xvel_bc+i][ori];
248 if ( bct == REMORA_BC::symmetry )
249 {
250 if (side == Orientation::low) {
252 if (i==1)
254 } else {
256 if (i==1)
258 }
259 }
260 else if (bct == REMORA_BC::outflow)
261 {
262 if (side == Orientation::low) {
264 } else {
266 }
267 }
268 else if (bct == REMORA_BC::inflow)
269 {
270 if (side == Orientation::low) {
272 } else {
274 }
275 }
276 else if (bct == REMORA_BC::no_slip_wall)
277 {
278 if (side == Orientation::low) {
280 } else {
282 }
283 }
284 else if (bct == REMORA_BC::slip_wall)
285 {
286 if (side == Orientation::low) {
288 if (i==1) {
289 // Only normal direction has ext_dir
291 }
292
293 } else {
295 if (i==1) {
296 // Only normal direction has ext_dir
298 }
299 }
300 }
301 else if (bct == REMORA_BC::periodic)
302 {
303 if (side == Orientation::low) {
305 } else {
307 }
308 }
309 else if (bct == REMORA_BC::clamped)
310 {
311 if (side == Orientation::low) {
313 } else {
315 }
316 }
317 else if (bct == REMORA_BC::orlanski_rad)
318 {
319 if (side == Orientation::low) {
321 } else {
323 }
324 }
325 else if (bct == REMORA_BC::orlanski_rad_nudge)
326 {
327 if (side == Orientation::low) {
329 } else {
331 }
332 }
333 else
334 {
335 amrex::Abort("Velocity boundary condition not validly specified");
336 }
337 }
338
339 // Always set zvel_bc to foextrap
340 if (side == Orientation::low) {
342 } else {
344 }
345 }
346 }
347
348 // *****************************************************************************
349 //
350 // Here we translate the physical boundary conditions -- one type per face --
351 // into logical boundary conditions for each cell-centered variable
352 //
353 // *****************************************************************************
354 {
355 for (OrientationIter oit; oit; ++oit) {
356 Orientation ori = oit();
357 int dir = ori.coordDir();
358 Orientation::Side side = ori.faceDir();
359 for (int i = 0; i < NCONS; i++) {
360 auto const bct = phys_bc_type[BCVars::cons_bc+i][ori];
361 if ( bct == REMORA_BC::symmetry )
362 {
363 if (side == Orientation::low) {
365 } else {
367 }
368 }
369 else if ( bct == REMORA_BC::outflow)
370 {
371 if (side == Orientation::low) {
373 } else {
375 }
376 }
377 else if ( bct == REMORA_BC::no_slip_wall)
378 {
379 if (side == Orientation::low) {
381 } else {
383 }
384 }
385 else if (bct == REMORA_BC::slip_wall)
386 {
387 if (side == Orientation::low) {
389 } else {
391 }
392 }
393 else if (bct == REMORA_BC::inflow)
394 {
395 if (side == Orientation::low) {
397 } else {
399 }
400 }
401 else if (bct == REMORA_BC::periodic)
402 {
403 if (side == Orientation::low) {
405 } else {
407 }
408 }
409 else if ( bct == REMORA_BC::clamped)
410 {
411 if (side == Orientation::low) {
413 } else {
415 }
416 }
417 else if ( bct == REMORA_BC::orlanski_rad)
418 {
419 if (side == Orientation::low) {
421 } else {
423 }
424 }
425 else if ( bct == REMORA_BC::orlanski_rad_nudge)
426 {
427 if (side == Orientation::low) {
429 } else {
431 }
432 }
433 else
434 {
435 amrex::Abort("Scalar/tracer boundary condition not validly specified");
436 }
437 }
438 }
439 }
440
441 // *****************************************************************************
442 //
443 // Here we translate the physical boundary conditions -- one type per face --
444 // into logical boundary conditions for ubar and vbar. Also add simplified
445 // 2d boundary condition (corresponding to BCs in bc_2d.F
446 //
447 // *****************************************************************************
448 {
449 for (OrientationIter oit; oit; ++oit) {
450 Orientation ori = oit();
451 int dir = ori.coordDir();
452 Orientation::Side side = ori.faceDir();
453 for (int i = 0; i < 2; i++) {
454 auto const bct = phys_bc_type[BCVars::ubar_bc+i][ori];
455 if ( bct == REMORA_BC::symmetry )
456 {
457 if (side == Orientation::low) {
460 if (i==1 and dir!=2) {
463 }
464 } else {
467 if (i==1 and dir!=2) {
470 }
471 }
472 }
473 else if (bct == REMORA_BC::outflow)
474 {
475 if (side == Orientation::low) {
478 } else {
481 }
482 }
483 else if (bct == REMORA_BC::inflow)
484 {
485 if (side == Orientation::low) {
488 } else {
491 }
492 }
493 else if (bct == REMORA_BC::no_slip_wall)
494 {
495 if (side == Orientation::low) {
498 } else {
501 }
502 }
503 else if (bct == REMORA_BC::slip_wall)
504 {
505 if (side == Orientation::low) {
508 if (i==1 and dir!=2) {
509 // Only normal direction has ext_dir
512 }
513
514 } else {
517 if (i==1 and dir!=2) {
518 // Only normal direction has ext_dir
521 }
522 }
523 }
524 else if (bct == REMORA_BC::periodic)
525 {
526 if (side == Orientation::low) {
529 } else {
532 }
533 }
534 else if (bct == REMORA_BC::clamped)
535 {
536 if (side == Orientation::low) {
539 } else {
542 }
543 }
544 else if (bct == REMORA_BC::flather)
545 {
546 if (side == Orientation::low) {
549 if (i==1 and dir!=2) {
550 // Only normal direction has Flather
553 }
554
555 } else {
558 if (i==1 and dir!=2) {
559 // Only normal direction has Flather
562 }
563 }
564 }
565 else
566 {
567 amrex::Abort("ubar or vbar boundary condition not validly specified");
568 }
569 }
570 }
571 }
572
573 // *****************************************************************************
574 //
575 // Here we translate the physical boundary conditions -- one type per face --
576 // into logical boundary conditions for zeta and tke
577 //
578 // *****************************************************************************
579 {
580 for (OrientationIter oit; oit; ++oit) {
581 Orientation ori = oit();
582 int dir = ori.coordDir();
583 Orientation::Side side = ori.faceDir();
584 for (int i = 0; i < 2; i++) {
585 auto const bct = phys_bc_type[BCVars::zeta_bc+i][ori];
586 if ( bct == REMORA_BC::symmetry )
587 {
588 if (side == Orientation::low) {
590 } else {
592 }
593 }
594 else if ( bct == REMORA_BC::outflow)
595 {
596 if (side == Orientation::low) {
598 } else {
600 }
601 }
602 else if ( bct == REMORA_BC::no_slip_wall)
603 {
604 if (side == Orientation::low) {
606 } else {
608 }
609 }
610 else if (bct == REMORA_BC::slip_wall)
611 {
612 if (side == Orientation::low) {
614 } else {
616 }
617 }
618 else if (bct == REMORA_BC::inflow)
619 {
620 if (side == Orientation::low) {
622 } else {
624 }
625 }
626 else if (bct == REMORA_BC::periodic)
627 {
628 if (side == Orientation::low) {
630 } else {
632 }
633 }
634 else if (bct == REMORA_BC::chapman)
635 {
636 if (side == Orientation::low) {
638 } else {
640 }
641 }
642 else if ( bct == REMORA_BC::clamped)
643 {
644 if (side == Orientation::low) {
646 } else {
648 }
649 }
650 else
651 {
652 amrex::Abort("Free surface (zeta) boundary condition not validly specified");
653 }
654 }
655 }
656 }
657
658 // *****************************************************************************
659 //
660 // Here we define a boundary condition that will foextrap while respecting periodicity
661 // This is used as a "null BC"
662 //
663 // *****************************************************************************
664 {
665 for (OrientationIter oit; oit; ++oit) {
666 Orientation ori = oit();
667 int dir = ori.coordDir();
668 Orientation::Side side = ori.faceDir();
669 if (side == Orientation::low) {
671 } else {
673 }
674 }
675 }
676
677 // *****************************************************************************
678 //
679 // Here we define a boundary condition that will unconditionally foextrap
680 //
681 // *****************************************************************************
682 {
683 for (OrientationIter oit; oit; ++oit) {
684 Orientation ori = oit();
685 int dir = ori.coordDir();
686 Orientation::Side side = ori.faceDir();
687 if (side == Orientation::low) {
689 } else {
691 }
692 }
693 }
694
695
696#ifdef AMREX_USE_GPU
697 Gpu::htod_memcpy
698 (domain_bcs_type_d.data(), domain_bcs_type.data(),
699 sizeof(amrex::BCRec)*(NCONS+AMREX_SPACEDIM+8));
700#else
701 std::memcpy
702 (domain_bcs_type_d.data(), domain_bcs_type.data(),
703 sizeof(amrex::BCRec)*(NCONS+AMREX_SPACEDIM+8));
704#endif
705}
706
@ orlanski_rad_nudge
#define NCONS
void init_bcs()
Read in boundary parameters from input file and set up data structures.
amrex::Vector< amrex::BCRec > domain_bcs_type
vector (over BCVars) of BCRecs
Definition REMORA.H:1120
bool set_bcs_by_var
whether to set boundary conditions by variable rather than just by side
Definition REMORA.H:1105
amrex::GpuArray< amrex::GpuArray< REMORA_BC, AMREX_SPACEDIM *2 >, BCVars::NumTypes > phys_bc_type
Array holding the "physical" boundary condition types (e.g. "inflow")
Definition REMORA.H:1131
amrex::Vector< int > bdy_index
Container to connect boundary data being read in boundary condition containers.
Definition REMORA.H:1140
amrex::Array< amrex::Array< amrex::Real, AMREX_SPACEDIM *2 >, AMREX_SPACEDIM+NCONS+8 > m_bc_extdir_vals
Array holding the Dirichlet values at walls which need them.
Definition REMORA.H:1128
amrex::Array< std::string, 2 *AMREX_SPACEDIM > domain_bc_type
Array of strings describing domain boundary conditions.
Definition REMORA.H:1125
amrex::GpuArray< amrex::GpuArray< bool, AMREX_SPACEDIM *2 >, BdyVars::NumTypes+1 > phys_bc_need_data
These are flags that indicate whether we need to read in boundary data from file.
Definition REMORA.H:1134
amrex::Gpu::DeviceVector< amrex::BCRec > domain_bcs_type_d
GPU vector (over BCVars) of BCRecs.
Definition REMORA.H:1122