21 auto& wdata = data.
meta();
22 auto& info = data.
info();
23 pp.
get(
"num_points", wdata.num_pts);
24 pp.
get(
"start", wdata.start);
25 pp.
get(
"end", wdata.end);
28 if (!pp.
contains(
"pitch_timetable")) {
30 pp.
get(
"pitch", wdata.pitch);
32 pp.
get(
"airfoil_table", wdata.airfoil_file);
33 pp.
query(
"airfoil_type", wdata.airfoil_type);
34 pp.
queryarr(
"span_locs", wdata.span_locs);
35 pp.
queryarr(
"chord", wdata.chord_inp);
36 bool use_fllc =
false;
37 pp.
query(
"fllc", use_fllc);
40 pp.
query(
"disable_spanwise_gaussian", wdata.gauss_2D);
43 pp.
query(
"normalize_spanwise", wdata.normalize_2D_spanwise);
46 amrex::Vector<int> force_coord_flags_query_inp;
47 pp.
queryarr(
"active_force_dirs", force_coord_flags_query_inp);
48 if (!force_coord_flags_query_inp.empty()) {
50 force_coord_flags_query_inp.size() == AMREX_SPACEDIM);
51 wdata.force_coord_flags = force_coord_flags_query_inp;
56 pp.
query(
"prescribed_uinf", wdata.prescribed_uinf);
59 pp.
query(
"pitch_timetable", wdata.pitch_timetable_file);
60 if (!wdata.pitch_timetable_file.empty()) {
61 std::ifstream ifh(wdata.pitch_timetable_file, std::ios::in);
64 "Cannot find input file: " + wdata.pitch_timetable_file);
66 amrex::Real data_time;
67 amrex::Real data_pitch_deg;
68 ifh.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
69 while (ifh >> data_time) {
70 ifh >> data_pitch_deg;
71 wdata.time_table.push_back(data_time);
72 wdata.pitch_table.push_back(data_pitch_deg);
76 pp.
query(
"motion_type", wdata.motion_type);
79 if (amrex::toLower(wdata.motion_type) ==
"linear") {
81 pp.
get(
"velocity", wdata.vel_tr);
82 }
else if (amrex::toLower(wdata.motion_type) ==
"sine") {
84 pp.
get(
"sine_period", wdata.s_period);
85 pp.
get(
"sine_vector", wdata.s_vector);
86 }
else if (amrex::toLower(wdata.motion_type) !=
"none") {
88 "Invalid FixedWingLine motion type. Valid options are "
89 "none, linear, and sine.");
93 wdata.fllc = std::make_unique<FLLCData>();
99 "Actuator fixed wing requires specification of one or both "
100 "of 'epsilon' or 'epsilon_chord'");
103 AMREX_ALWAYS_ASSERT(wdata.span_locs.size() == wdata.chord_inp.size());
105 amrex::Real max_chord = *std::ranges::max_element(wdata.chord_inp);
106 amrex::Real max_eps = *std::ranges::max_element(wdata.eps_inp);
107 amrex::Real max_epsc = *std::ranges::max_element(wdata.epsilon_chord);
108 amrex::Real search_radius =
109 amrex::max(max_eps, max_epsc) * max_chord * 3.0_rt;
110 const auto& p1 = wdata.start;
111 const auto& p2 = wdata.end;
113 amrex::Real minpx = amrex::min(p1.x(), p2.x());
114 amrex::Real maxpx = amrex::max(p1.x(), p2.x());
115 amrex::Real minpy = amrex::min(p1.y(), p2.y());
116 amrex::Real maxpy = amrex::max(p1.y(), p2.y());
117 amrex::Real minpz = amrex::min(p1.z(), p2.z());
118 amrex::Real maxpz = amrex::max(p1.z(), p2.z());
120 if (wdata.gauss_2D) {
123 const auto wspan = wdata.end - wdata.start;
125 bool warn_per{
false};
127 auto per = data.
sim().
mesh().Geom()[0].periodicity();
128 if (std::abs(wspan.x()) >=
129 amrex::max<amrex::Real>(
130 std::abs(wspan.y()), std::abs(wspan.z()))) {
131 minpx = data.
sim().
mesh().Geom(0).ProbLoArray()[0];
132 maxpx = data.
sim().
mesh().Geom(0).ProbHiArray()[0];
133 warn_per = !per.isPeriodic(0);
135 }
else if (std::abs(wspan.y()) >= std::abs(wspan.z())) {
136 minpy = data.
sim().
mesh().Geom(0).ProbLoArray()[1];
137 maxpy = data.
sim().
mesh().Geom(0).ProbHiArray()[1];
138 warn_per = !per.isPeriodic(1);
141 minpz = data.
sim().
mesh().Geom(0).ProbLoArray()[2];
142 maxpz = data.
sim().
mesh().Geom(0).ProbHiArray()[2];
143 warn_per = !per.isPeriodic(2);
148 <<
"\nWARNING: fixed_wing_ops: Detected spanwise direction "
150 <<
" is not periodic, though 2D Gaussian is being "
155 if (amrex::toLower(wdata.motion_type) ==
"none") {
156 info.bound_box = amrex::RealBox(
157 minpx - search_radius, minpy - search_radius,
158 minpz - search_radius, maxpx + search_radius,
159 maxpy + search_radius, maxpz + search_radius);
160 }
else if (amrex::toLower(wdata.motion_type) ==
"linear") {
162 constexpr amrex::Real tiny =
163 std::numeric_limits<amrex::Real>::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);