16 auto& wdata = data.
meta();
17 auto& info = data.
info();
18 pp.
get(
"num_points", wdata.num_pts);
19 pp.
get(
"start", wdata.start);
20 pp.
get(
"end", wdata.end);
23 if (!pp.
contains(
"pitch_timetable")) {
25 pp.
get(
"pitch", wdata.pitch);
27 pp.
get(
"airfoil_table", wdata.airfoil_file);
28 pp.
query(
"airfoil_type", wdata.airfoil_type);
29 pp.
queryarr(
"span_locs", wdata.span_locs);
30 pp.
queryarr(
"chord", wdata.chord_inp);
31 bool use_fllc =
false;
32 pp.
query(
"fllc", use_fllc);
35 pp.
query(
"disable_spanwise_gaussian", wdata.gauss_2D);
38 pp.
query(
"normalize_spanwise", wdata.normalize_2D_spanwise);
41 amrex::Vector<int> force_coord_flags_query_inp;
42 pp.
queryarr(
"active_force_dirs", force_coord_flags_query_inp);
43 if (!force_coord_flags_query_inp.empty()) {
45 force_coord_flags_query_inp.size() == AMREX_SPACEDIM);
46 wdata.force_coord_flags = force_coord_flags_query_inp;
51 pp.
query(
"prescribed_uinf", wdata.prescribed_uinf);
54 pp.
query(
"pitch_timetable", wdata.pitch_timetable_file);
55 if (!wdata.pitch_timetable_file.empty()) {
56 std::ifstream ifh(wdata.pitch_timetable_file, std::ios::in);
59 "Cannot find input file: " + wdata.pitch_timetable_file);
61 amrex::Real data_time;
62 amrex::Real data_pitch_deg;
63 ifh.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
64 while (ifh >> data_time) {
65 ifh >> data_pitch_deg;
66 wdata.time_table.push_back(data_time);
67 wdata.pitch_table.push_back(data_pitch_deg);
71 pp.
query(
"motion_type", wdata.motion_type);
74 if (amrex::toLower(wdata.motion_type) ==
"linear") {
76 pp.
get(
"velocity", wdata.vel_tr);
77 }
else if (amrex::toLower(wdata.motion_type) ==
"sine") {
79 pp.
get(
"sine_period", wdata.s_period);
80 pp.
get(
"sine_vector", wdata.s_vector);
81 }
else if (amrex::toLower(wdata.motion_type) !=
"none") {
83 "Invalid FixedWingLine motion type. Valid options are "
84 "none, linear, and sine.");
88 wdata.fllc = std::make_unique<FLLCData>();
94 "Actuator fixed wing requires specification of one or both "
95 "of 'epsilon' or 'epsilon_chord'");
98 AMREX_ALWAYS_ASSERT(wdata.span_locs.size() == wdata.chord_inp.size());
100 amrex::Real max_chord =
101 *std::max_element(wdata.chord_inp.begin(), wdata.chord_inp.end());
102 amrex::Real max_eps =
103 *std::max_element(wdata.eps_inp.begin(), wdata.eps_inp.end());
104 amrex::Real max_epsc = *std::max_element(
105 wdata.epsilon_chord.begin(), wdata.epsilon_chord.end());
106 amrex::Real search_radius =
107 amrex::max(max_eps, max_epsc) * max_chord * 3.0;
108 const auto& p1 = wdata.start;
109 const auto& p2 = wdata.end;
111 amrex::Real minpx = amrex::min(p1.x(), p2.x());
112 amrex::Real maxpx = amrex::max(p1.x(), p2.x());
113 amrex::Real minpy = amrex::min(p1.y(), p2.y());
114 amrex::Real maxpy = amrex::max(p1.y(), p2.y());
115 amrex::Real minpz = amrex::min(p1.z(), p2.z());
116 amrex::Real maxpz = amrex::max(p1.z(), p2.z());
118 if (wdata.gauss_2D) {
121 const auto wspan = wdata.end - wdata.start;
123 bool warn_per{
false};
125 auto per = data.
sim().
mesh().Geom()[0].periodicity();
126 if (std::abs(wspan.x()) >=
127 std::max(std::abs(wspan.y()), std::abs(wspan.z()))) {
128 minpx = data.
sim().
mesh().Geom(0).ProbLoArray()[0];
129 maxpx = data.
sim().
mesh().Geom(0).ProbHiArray()[0];
130 warn_per = !per.isPeriodic(0);
132 }
else if (std::abs(wspan.y()) >= std::abs(wspan.z())) {
133 minpy = data.
sim().
mesh().Geom(0).ProbLoArray()[1];
134 maxpy = data.
sim().
mesh().Geom(0).ProbHiArray()[1];
135 warn_per = !per.isPeriodic(1);
138 minpz = data.
sim().
mesh().Geom(0).ProbLoArray()[2];
139 maxpz = data.
sim().
mesh().Geom(0).ProbHiArray()[2];
140 warn_per = !per.isPeriodic(2);
145 <<
"\nWARNING: fixed_wing_ops: Detected spanwise direction "
147 <<
" is not periodic, though 2D Gaussian is being "
152 if (amrex::toLower(wdata.motion_type) ==
"none") {
153 info.bound_box = amrex::RealBox(
154 minpx - search_radius, minpy - search_radius,
155 minpz - search_radius, maxpx + search_radius,
156 maxpy + search_radius, maxpz + search_radius);
157 }
else if (amrex::toLower(wdata.motion_type) ==
"linear") {
159 constexpr amrex::Real tiny = 1e-8;
161 const bool up_ = wdata.vel_tr.x() > tiny;
162 const amrex::Real up_ext =
163 data.
sim().
mesh().Geom(0).ProbHiArray()[0];
164 const bool um_ = wdata.vel_tr.x() < -tiny;
165 const amrex::Real um_ext =
166 data.
sim().
mesh().Geom(0).ProbLoArray()[0];
167 const bool vp_ = wdata.vel_tr.y() > tiny;
168 const amrex::Real vp_ext =
169 data.
sim().
mesh().Geom(0).ProbHiArray()[1];
170 const bool vm_ = wdata.vel_tr.y() < -tiny;
171 const amrex::Real vm_ext =
172 data.
sim().
mesh().Geom(0).ProbLoArray()[1];
173 const bool wp_ = wdata.vel_tr.z() > tiny;
174 const amrex::Real wp_ext =
175 data.
sim().
mesh().Geom(0).ProbHiArray()[2];
176 const bool wm_ = wdata.vel_tr.z() < -tiny;
177 const amrex::Real wm_ext =
178 data.
sim().
mesh().Geom(0).ProbLoArray()[2];
179 info.bound_box = amrex::RealBox(
180 um_ ? um_ext : minpx - search_radius,
181 vm_ ? vm_ext : minpy - search_radius,
182 wm_ ? wm_ext : minpz - search_radius,
183 up_ ? up_ext : maxpx + search_radius,
184 vp_ ? vp_ext : maxpy + search_radius,
185 wp_ ? wp_ext : maxpz + search_radius);
186 }
else if (amrex::toLower(wdata.motion_type) ==
"sine") {
187 info.bound_box = amrex::RealBox(
188 minpx - wdata.s_vector.x() - search_radius,
189 minpy - wdata.s_vector.y() - search_radius,
190 minpz - wdata.s_vector.z() - search_radius,
191 maxpx + wdata.s_vector.x() + search_radius,
192 maxpy + wdata.s_vector.y() + search_radius,
193 maxpz + wdata.s_vector.z() + search_radius);