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 = std::numeric_limits<float>::epsilon();
164 const bool up_ = wdata.vel_tr.x() > tiny;
165 const amrex::Real up_ext =
166 data.
sim().
mesh().Geom(0).ProbHiArray()[0];
167 const bool um_ = wdata.vel_tr.x() < -tiny;
168 const amrex::Real um_ext =
169 data.
sim().
mesh().Geom(0).ProbLoArray()[0];
170 const bool vp_ = wdata.vel_tr.y() > tiny;
171 const amrex::Real vp_ext =
172 data.
sim().
mesh().Geom(0).ProbHiArray()[1];
173 const bool vm_ = wdata.vel_tr.y() < -tiny;
174 const amrex::Real vm_ext =
175 data.
sim().
mesh().Geom(0).ProbLoArray()[1];
176 const bool wp_ = wdata.vel_tr.z() > tiny;
177 const amrex::Real wp_ext =
178 data.
sim().
mesh().Geom(0).ProbHiArray()[2];
179 const bool wm_ = wdata.vel_tr.z() < -tiny;
180 const amrex::Real wm_ext =
181 data.
sim().
mesh().Geom(0).ProbLoArray()[2];
182 info.bound_box = amrex::RealBox(
183 um_ ? um_ext : minpx - search_radius,
184 vm_ ? vm_ext : minpy - search_radius,
185 wm_ ? wm_ext : minpz - search_radius,
186 up_ ? up_ext : maxpx + search_radius,
187 vp_ ? vp_ext : maxpy + search_radius,
188 wp_ ? wp_ext : maxpz + search_radius);
189 }
else if (amrex::toLower(wdata.motion_type) ==
"sine") {
190 info.bound_box = amrex::RealBox(
191 minpx - wdata.s_vector.x() - search_radius,
192 minpy - wdata.s_vector.y() - search_radius,
193 minpz - wdata.s_vector.z() - search_radius,
194 maxpx + wdata.s_vector.x() + search_radius,
195 maxpy + wdata.s_vector.y() + search_radius,
196 maxpz + wdata.s_vector.z() + search_radius);