ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SolverUtils.H
Go to the documentation of this file.
1 /**
2  * \file ERF_SolverUtils.H
3  */
4 #ifndef ERF_SOLVER_UTILS_H_
5 #define ERF_SOLVER_UTILS_H_
6 
7 #include "AMReX_LO_BCTYPES.H"
8 
9 using namespace amrex;
10 
11 /**
12  * Define the domain boundary conditions for the (optional) Poisson solve
13  * if we want to enforce that the initial conditions satisfy the constraint
14  *
15  * @param lev_geom Geometry used to identify periodic low-side boundaries
16  * @param l_domain_bc_type Domain boundary-condition names
17  * @return Low-side linear-operator boundary condition in each direction
18  */
19 inline Array<LinOpBCType,AMREX_SPACEDIM>
20 get_lo_projection_bc (Geometry const& lev_geom,
21  Array<std::string,2*AMREX_SPACEDIM> l_domain_bc_type)
22 {
23  amrex::Array<amrex::LinOpBCType,AMREX_SPACEDIM> r;
24  for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
25  if ( lev_geom.isPeriodic(dir) )
26  {
27  r[dir] = LinOpBCType::Periodic;
28  } else {
29  auto bc_type = l_domain_bc_type[Orientation(dir,Orientation::low)];
30  if (bc_type == "Outflow" || bc_type == "Open") {
31  r[dir] = LinOpBCType::Dirichlet;
32  } else {
33  r[dir] = LinOpBCType::Neumann;
34  }
35  }
36  }
37  return r;
38 }
39 
40 /**
41  * Define high-side domain boundary conditions for the projection solve.
42  *
43  * @param lev_geom Geometry used to identify periodic high-side boundaries
44  * @param l_domain_bc_type Domain boundary-condition names
45  * @return High-side linear-operator boundary condition in each direction
46  */
47 inline Array<LinOpBCType,AMREX_SPACEDIM>
48 get_hi_projection_bc (Geometry const& lev_geom,
49  Array<std::string,2*AMREX_SPACEDIM> l_domain_bc_type)
50 {
51  amrex::Array<amrex::LinOpBCType,AMREX_SPACEDIM> r;
52  for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
53  if ( lev_geom.isPeriodic(dir) )
54  {
55  r[dir] = LinOpBCType::Periodic;
56  } else {
57  auto bc_type = l_domain_bc_type[Orientation(dir,Orientation::high)];
58  if (bc_type == "Outflow" || bc_type == "Open") {
59  r[dir] = LinOpBCType::Dirichlet;
60  } else {
61  r[dir] = LinOpBCType::Neumann;
62  }
63  }
64  }
65  return r;
66 }
67 
68 #ifdef ERF_USE_FFT
69 
70 /**
71  * Define FFT boundary conditions on the specified solve box.
72  *
73  * @param lev_geom Geometry for the full level domain
74  * @param l_domain_bc_type Domain boundary-condition names
75  * @param bounding_box Box covered by the FFT solve
76  * @param use_real_bcs Whether real lateral boundary conditions are active
77  * @return Low/high FFT boundary-condition pair in each direction
78  */
79 inline Array<std::pair<FFT::Boundary,FFT::Boundary>,AMREX_SPACEDIM>
80 get_fft_bc (Geometry const& lev_geom,
81  Array<std::string,2*AMREX_SPACEDIM> l_domain_bc_type,
82  Box const& bounding_box, bool use_real_bcs) noexcept
83 {
84  Array<std::pair<FFT::Boundary,FFT::Boundary>,AMREX_SPACEDIM> r;
85 
86  FFT::Boundary first, second;
87 
88  for (int dir = 0; dir <= 2; dir++)
89  {
90  auto bc_type_lo = l_domain_bc_type[Orientation(dir,Orientation::low)];
91  if ( lev_geom.isPeriodic(dir) &&
92  (lev_geom.Domain().smallEnd(dir) == bounding_box.smallEnd(dir)) )
93  {
94  first = FFT::Boundary::periodic;
95  // amrex::Print() << "SETTING FIRST OF " << dir << " TO PERIODIC " << std::endl;
96  }
97 
98  else if ( (lev_geom.Domain().smallEnd(dir) == bounding_box.smallEnd(dir)) &&
99  (bc_type_lo == "Outflow" || bc_type_lo == "Open") && (dir == 2 || !use_real_bcs) )
100  {
101  first = FFT::Boundary::odd;
102  // amrex::Print() << "SETTING FIRST OF " << dir << " TO ODD " << std::endl;
103  }
104 
105  else
106  {
107  first = FFT::Boundary::even;
108  // amrex::Print() << "SETTING FIRST OF " << dir << " TO EVEN " << std::endl;
109  }
110 
111  auto bc_type_hi = l_domain_bc_type[Orientation(dir,Orientation::high)];
112  if ( lev_geom.isPeriodic(dir) &&
113  (lev_geom.Domain().bigEnd(dir) == bounding_box.bigEnd(dir)) )
114  {
115  second = FFT::Boundary::periodic;
116  // amrex::Print() << "SETTING SECOND OF " << dir << " TO PERIODIC " << std::endl;
117  }
118 
119  else if ( (lev_geom.Domain().bigEnd(dir) == bounding_box.bigEnd(dir)) &&
120  (bc_type_hi == "Outflow" || bc_type_hi == "Open") && (dir == 2 || !use_real_bcs) )
121  {
122  second = FFT::Boundary::odd;
123  // amrex::Print() << "SETTING SECOND OF " << dir << " TO ODD " << std::endl;
124  }
125 
126  else
127  {
128  second = FFT::Boundary::even;
129  // amrex::Print() << "SETTING SECOND OF " << dir << " TO EVEN " << std::endl;
130  }
131 
132  r[dir] = std::make_pair(first,second);
133 
134  } // dir
135 
136  return r;
137 }
138 #endif
139 #endif
Array< LinOpBCType, AMREX_SPACEDIM > get_lo_projection_bc(Geometry const &lev_geom, Array< std::string, 2 *AMREX_SPACEDIM > l_domain_bc_type)
Definition: ERF_SolverUtils.H:20
Array< LinOpBCType, AMREX_SPACEDIM > get_hi_projection_bc(Geometry const &lev_geom, Array< std::string, 2 *AMREX_SPACEDIM > l_domain_bc_type)
Definition: ERF_SolverUtils.H:48
Definition: ERF_ConsoleIO.cpp:15
amrex::GpuArray< Face, 2 *AMREX_SPACEDIM > Boundary
Definition: ERF_WallThermodynamics.H:34