19 auto& wdata = data.
meta();
20 auto& info = data.
info();
21 pp.
get(
"num_points", wdata.num_pts);
22 pp.
get(
"start", wdata.start);
23 pp.
get(
"end", wdata.end);
26 if (!pp.
contains(
"pitch_timetable")) {
28 pp.
get(
"pitch", wdata.pitch);
30 pp.
get(
"airfoil_table", wdata.airfoil_file);
31 pp.
query(
"airfoil_type", wdata.airfoil_type);
32 pp.
queryarr(
"span_locs", wdata.span_locs);
33 pp.
queryarr(
"chord", wdata.chord_inp);
34 bool use_fllc =
false;
35 pp.
query(
"fllc", use_fllc);
38 pp.
query(
"disable_spanwise_gaussian", wdata.gauss_2D);
41 pp.
query(
"normalize_spanwise", wdata.normalize_2D_spanwise);
44 amrex::Vector<int> force_coord_flags_query_inp;
45 pp.
queryarr(
"active_force_dirs", force_coord_flags_query_inp);
46 if (!force_coord_flags_query_inp.empty()) {
48 force_coord_flags_query_inp.size() == AMREX_SPACEDIM);
49 wdata.force_coord_flags = force_coord_flags_query_inp;
54 pp.
query(
"prescribed_uinf", wdata.prescribed_uinf);
57 pp.
query(
"pitch_timetable", wdata.pitch_timetable_file);
58 if (!wdata.pitch_timetable_file.empty()) {
59 std::ifstream ifh(wdata.pitch_timetable_file, std::ios::in);
62 "Cannot find input file: " + wdata.pitch_timetable_file);
64 amrex::Real data_time;
65 amrex::Real data_pitch_deg;
66 ifh.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
67 while (ifh >> data_time) {
68 ifh >> data_pitch_deg;
69 wdata.time_table.push_back(data_time);
70 wdata.pitch_table.push_back(data_pitch_deg);
74 pp.
query(
"motion_type", wdata.motion_type);
77 if (amrex::toLower(wdata.motion_type) ==
"linear") {
79 pp.
get(
"velocity", wdata.vel_tr);
80 }
else if (amrex::toLower(wdata.motion_type) ==
"sine") {
82 pp.
get(
"sine_period", wdata.s_period);
83 pp.
get(
"sine_vector", wdata.s_vector);
84 }
else if (amrex::toLower(wdata.motion_type) !=
"none") {
86 "Invalid FixedWingLine motion type. Valid options are "
87 "none, linear, and sine.");
91 wdata.fllc = std::make_unique<FLLCData>();
97 "Actuator fixed wing requires specification of one or both "
98 "of 'epsilon' or 'epsilon_chord'");
101 AMREX_ALWAYS_ASSERT(wdata.span_locs.size() == wdata.chord_inp.size());
103 amrex::Real max_chord =
104 *std::max_element(wdata.chord_inp.begin(), wdata.chord_inp.end());
105 amrex::Real max_eps =
106 *std::max_element(wdata.eps_inp.begin(), wdata.eps_inp.end());
107 amrex::Real max_epsc = *std::max_element(
108 wdata.epsilon_chord.begin(), wdata.epsilon_chord.end());
109 amrex::Real search_radius =
110 amrex::max(max_eps, max_epsc) * max_chord * 3.0_rt;
111 const auto& p1 = wdata.start;
112 const auto& p2 = wdata.end;
114 amrex::Real minpx = amrex::min(p1.x(), p2.x());
115 amrex::Real maxpx = amrex::max(p1.x(), p2.x());
116 amrex::Real minpy = amrex::min(p1.y(), p2.y());
117 amrex::Real maxpy = amrex::max(p1.y(), p2.y());
118 amrex::Real minpz = amrex::min(p1.z(), p2.z());
119 amrex::Real maxpz = amrex::max(p1.z(), p2.z());
121 if (wdata.gauss_2D) {
124 const auto wspan = wdata.end - wdata.start;
126 bool warn_per{
false};
128 auto per = data.
sim().
mesh().Geom()[0].periodicity();
129 if (std::abs(wspan.x()) >=
130 amrex::max<amrex::Real>(
131 std::abs(wspan.y()), std::abs(wspan.z()))) {
132 minpx = data.
sim().
mesh().Geom(0).ProbLoArray()[0];
133 maxpx = data.
sim().
mesh().Geom(0).ProbHiArray()[0];
134 warn_per = !per.isPeriodic(0);
136 }
else if (std::abs(wspan.y()) >= std::abs(wspan.z())) {
137 minpy = data.
sim().
mesh().Geom(0).ProbLoArray()[1];
138 maxpy = data.
sim().
mesh().Geom(0).ProbHiArray()[1];
139 warn_per = !per.isPeriodic(1);
142 minpz = data.
sim().
mesh().Geom(0).ProbLoArray()[2];
143 maxpz = data.
sim().
mesh().Geom(0).ProbHiArray()[2];
144 warn_per = !per.isPeriodic(2);
149 <<
"\nWARNING: fixed_wing_ops: Detected spanwise direction "
151 <<
" is not periodic, though 2D Gaussian is being "
156 if (amrex::toLower(wdata.motion_type) ==
"none") {
157 info.bound_box = amrex::RealBox(
158 minpx - search_radius, minpy - search_radius,
159 minpz - search_radius, maxpx + search_radius,
160 maxpy + search_radius, maxpz + search_radius);
161 }
else if (amrex::toLower(wdata.motion_type) ==
"linear") {
163 constexpr amrex::Real tiny = std::numeric_limits<float>::epsilon();
165 const bool up_ = wdata.vel_tr.x() > tiny;
166 const amrex::Real up_ext =
167 data.
sim().
mesh().Geom(0).ProbHiArray()[0];
168 const bool um_ = wdata.vel_tr.x() < -tiny;
169 const amrex::Real um_ext =
170 data.
sim().
mesh().Geom(0).ProbLoArray()[0];
171 const bool vp_ = wdata.vel_tr.y() > tiny;
172 const amrex::Real vp_ext =
173 data.
sim().
mesh().Geom(0).ProbHiArray()[1];
174 const bool vm_ = wdata.vel_tr.y() < -tiny;
175 const amrex::Real vm_ext =
176 data.
sim().
mesh().Geom(0).ProbLoArray()[1];
177 const bool wp_ = wdata.vel_tr.z() > tiny;
178 const amrex::Real wp_ext =
179 data.
sim().
mesh().Geom(0).ProbHiArray()[2];
180 const bool wm_ = wdata.vel_tr.z() < -tiny;
181 const amrex::Real wm_ext =
182 data.
sim().
mesh().Geom(0).ProbLoArray()[2];
183 info.bound_box = amrex::RealBox(
184 um_ ? um_ext : minpx - search_radius,
185 vm_ ? vm_ext : minpy - search_radius,
186 wm_ ? wm_ext : minpz - search_radius,
187 up_ ? up_ext : maxpx + search_radius,
188 vp_ ? vp_ext : maxpy + search_radius,
189 wp_ ? wp_ext : maxpz + search_radius);
190 }
else if (amrex::toLower(wdata.motion_type) ==
"sine") {
191 info.bound_box = amrex::RealBox(
192 minpx - wdata.s_vector.x() - search_radius,
193 minpy - wdata.s_vector.y() - search_radius,
194 minpz - wdata.s_vector.z() - search_radius,
195 maxpx + wdata.s_vector.x() + search_radius,
196 maxpy + wdata.s_vector.y() + search_radius,
197 maxpz + wdata.s_vector.z() + search_radius);