/home/runner/work/amr-wind/amr-wind/amr-wind/wind_energy/actuator/wing/wing_ops.H Source File

AMR-Wind API: /home/runner/work/amr-wind/amr-wind/amr-wind/wind_energy/actuator/wing/wing_ops.H Source File
AMR-Wind API v0.1.0
CFD solver for wind plant simulations
Loading...
Searching...
No Matches
wing_ops.H
Go to the documentation of this file.
1#ifndef WING_OPS_H
2#define WING_OPS_H
3
12
13namespace amr_wind::actuator {
14namespace wing {
15
16// Initialize core data structures when modeling fixed wings
17void init_data_structures(WingBaseData& /*wdata*/, ActGrid& /*grid*/);
18
20 const std::string& /*ncfile*/,
21 const WingBaseData& /*meta*/,
22 const ActInfo& /*info*/,
23 const ActGrid& /*grid*/);
24
25void write_netcdf(
26 const std::string& /*ncfile*/,
27 const WingBaseData& /*meta*/,
28 const ActInfo& /*info*/,
29 const ActGrid& /*grid*/,
30 const amrex::Real /*time*/);
31
32void refresh_wing_position(VecList& vpoints, VecList fpoints, const int npts);
33
35 VecList& points,
36 vs::Vector& vtr,
37 const int npts,
38 const amrex::Real tn,
39 const amrex::Real tnp1,
40 const std::string& motion,
41 const amrex::Real period,
42 const vs::Vector svec);
43
44template <typename T>
45ComponentView make_component_view(typename T::DataType& data)
46{
47 auto& grid = data.grid();
48 auto& meta = data.meta();
49 ComponentView view;
50 view.pos = ::amr_wind::utils::slice(grid.pos, 0, meta.num_pts);
51 view.vel_pos = ::amr_wind::utils::slice(grid.vel_pos, 0, meta.num_pts);
52 view.force = ::amr_wind::utils::slice(grid.force, 0, meta.num_pts);
53 view.epsilon = ::amr_wind::utils::slice(grid.epsilon, 0, meta.num_pts);
54 view.orientation =
55 ::amr_wind::utils::slice(grid.orientation, 0, meta.num_pts);
56 view.chord = ::amr_wind::utils::slice(meta.chord, 0, meta.num_pts);
57 view.vel_rel = ::amr_wind::utils::slice(meta.vel_rel, 0, meta.num_pts);
58 view.vel = ::amr_wind::utils::slice(grid.vel, 0, meta.num_pts);
59
60 return view;
61}
62
63} // namespace wing
64
65namespace ops {
66
67template <typename T>
69airfoil_lookup(typename T::DataType& data);
70
71template <typename ActTrait, typename SrcTrait>
73{
74 static constexpr bool update_pos = true;
75 static constexpr bool update_vel = true;
76 static constexpr bool compute_force = true;
77 static constexpr bool process_outputs = true;
78};
79
80template <typename ActTrait>
82 ActTrait,
84 typename std::enable_if_t<
85 std::is_base_of_v<WingType, ActTrait> &&
86 UseDefaultOp<ActTrait, ActSrcLine>::update_pos>>
87{
88 void operator()(typename ActTrait::DataType& data)
89 {
90 // Put wing at current (time n) position from force points
91 auto& grid = data.grid();
92 const int npts = data.meta().num_pts;
93 actuator::wing::refresh_wing_position(grid.vel_pos, grid.pos, npts);
94 }
95};
96
97template <typename ActTrait>
99 ActTrait,
101 typename std::enable_if_t<
102 std::is_base_of_v<WingType, ActTrait> &&
103 UseDefaultOp<ActTrait, ActSrcLine>::update_vel>>
104{
105
106 void operator()(typename ActTrait::DataType& data)
107 {
108 auto& meta = data.meta();
109 if (meta.fllc) {
110 FLLCOp()(meta.component_view, *(meta.fllc));
111 }
112 }
113};
114
115template <typename ActTrait>
117 ActTrait,
119 typename std::enable_if_t<
120 std::is_base_of_v<WingType, ActTrait> &&
121 UseDefaultOp<ActTrait, ActSrcLine>::compute_force>>
122{
123 void operator()(typename ActTrait::DataType& data)
124 {
125 auto& grid = data.grid();
126 auto& wdata = data.meta();
127 const int npts = wdata.num_pts;
128 const auto& dx = wdata.dx;
129 const auto& chord = wdata.chord;
130 const auto& aflookup = airfoil_lookup<ActTrait>(data);
131 const auto& time = data.sim().time();
132
133 // Move force points to location at n+1
134 // Also, get velocity of actuator from n to n+1
135 // (will be unchanged for "none" and "linear" motion)
137 grid.pos, wdata.vel_tr, npts, time.current_time(), time.new_time(),
138 wdata.motion_type, wdata.s_period, wdata.s_vector);
139
140 // Build the local reference frame
141 const vs::Vector wspan = wdata.end - wdata.start;
142
143 // Use the global coord to orient the blade
144 // The default is for inflow in the x direction
145 const auto blade_y = wspan.unit();
146 const auto blade_z = (wdata.blade_x.unit() ^ blade_y).unit();
147 // Ensure orthogonality for new reference frame
148 const auto blade_x = (blade_y ^ blade_z).unit();
149
150 // Calculate the aoa based on the pitch actuation table if supplied
151 // (interpolate pitch angle at step n+1/2) or the initial pitch angle
152 if (!wdata.pitch_timetable_file.empty()) {
153 const auto time_interp =
154 (time.current_time() + time.new_time()) / 2.0;
155 wdata.pitch = amr_wind::interp::linear_angle(
156 wdata.time_table, wdata.pitch_table, time_interp, 360.);
157 amrex::Print() << "Wing Ops: Current wing pitch (at time "
158 << time_interp << " s) is " << wdata.pitch
159 << " degrees.\n";
160 // Recalculate transformation matrix and update on grid struct
161 auto tmat = vs::quaternion(wspan, wdata.pitch);
162 grid.orientation.assign(npts, tmat);
163 }
164
165 // Get flags for each coordinate of force and put in vs::Vector
166 const vs::Vector force_coord_flags_vec = {
167 (amrex::Real)wdata.force_coord_flags[0],
168 (amrex::Real)wdata.force_coord_flags[1],
169 (amrex::Real)wdata.force_coord_flags[2]};
170
171 // Calculate the local force using sampled velocity (at n)
172 amrex::Real total_lift = 0.0;
173 amrex::Real total_drag = 0.0;
174 for (int ip = 0; ip < npts; ++ip) {
175
176 // Wind vector is relative to actuator motion
177 vs::Vector windvector;
178 windvector[0] = (grid.vel[ip] - wdata.vel_tr) & blade_x;
179 windvector[1] = 0;
180 windvector[2] = (grid.vel[ip] - wdata.vel_tr) & blade_z;
181
182 const auto vmag = vs::mag(windvector);
183 const auto aoa = std::atan2(windvector[2], windvector[0]) +
184 amr_wind::utils::radians(wdata.pitch);
185
186 // Get Cl, Cd values
187 amrex::Real cl, cd;
188 aflookup(aoa, cl, cd);
189
190 // Calculate factor for qval: 0.5 * Uinf * Uinf * dx
191 // but replace velocity magnitude if specified
192 auto qfac =
193 (wdata.prescribed_uinf < 0.0)
194 ? 0.5 * vmag * vmag
195 : 0.5 * wdata.prescribed_uinf * wdata.prescribed_uinf;
196 // Length scale in spanwise direction
197 if (wdata.gauss_2D && wdata.normalize_2D_spanwise) {
198 // Do not multiply by a length scale, but divide by number of
199 // points because the Gaussians of each point all overlap
200 qfac /= (amrex::Real)npts;
201 // Convert 3D Gaussian factor to 2D factor
202 constexpr amrex::Real G2D_from_3D =
203 0.31830988618379067 / 0.17958712212516656;
204 qfac *= G2D_from_3D;
205 // Get rid of epsilon in spanwise direction
206 const amrex::Real eps_span = grid.epsilon[ip][1];
207 qfac *= eps_span;
208 } else {
209 // 3D implementation: multiply by spanwise dx
210 qfac *= dx[ip];
211 }
212
213 const auto qval = qfac * chord[ip];
214 const auto lift = qval * cl;
215 const auto drag = qval * cd;
216
217 // Determine unit vector parallel and perpendicular to velocity
218 const auto drag_dir =
219 (blade_x * windvector.x() + blade_z * windvector.z()).unit();
220 const auto lift_dir = (drag_dir ^ blade_y).unit();
221
222 // Compute force on fluid from this section of wing
223 grid.force[ip] = -(lift_dir * lift + drag * drag_dir);
224
225 // In global coords, zero disabled force components
226 grid.force[ip] *= force_coord_flags_vec;
227
228 // Assign values for output
229 wdata.vel_rel[ip] = windvector;
230 wdata.aoa[ip] = amr_wind::utils::degrees(aoa);
231 wdata.cl[ip] = cl;
232 wdata.cd[ip] = cd;
233
234 total_lift += lift;
235 total_drag += drag;
236 }
237
238 wdata.lift = total_lift;
239 wdata.drag = total_drag;
240
241 if (wdata.fllc) {
242 if (!(wdata.fllc->initialized) &&
243 (time.current_time() > wdata.fllc->fllc_start_time)) {
244 wdata.component_view =
246 data);
247 fllc_init(
248 *(wdata.fllc.get()), wdata.component_view,
249 wdata.epsilon_chord[0]);
250 }
251 }
252 }
253};
254
255template <typename ActTrait, typename SrcTrait>
257 ActTrait,
258 SrcTrait,
259 typename std::enable_if_t<
260 std::is_base_of_v<WingType, ActTrait> &&
261 UseDefaultOp<ActTrait, ActSrcLine>::process_outputs>>
262{
263private:
264 typename ActTrait::DataType& m_data;
265
266 std::string m_out_dir;
267 std::string m_nc_filename;
268 int m_out_freq{10};
269
270public:
271 explicit ProcessOutputsOp(typename ActTrait::DataType& data) : m_data(data)
272 {}
273
275 {
276 pp.query("output_frequency", m_out_freq);
277 }
278
279 void prepare_outputs(const std::string& out_dir)
280 {
281 m_nc_filename = out_dir + "/" + m_data.info().label + ".nc";
283 m_nc_filename, m_data.meta(), m_data.info(), m_data.grid());
284 }
285
287 {
288 const auto& time = m_data.sim().time();
289 const int tidx = time.time_index();
290 if (tidx % m_out_freq != 0) {
291 return;
292 }
293
295 m_nc_filename, m_data.meta(), m_data.info(), m_data.grid(),
296 time.new_time());
297 }
298};
299
300} // namespace ops
301} // namespace amr_wind::actuator
302
303#endif /* WING_OPS_H */
Definition MultiParser.H:18
void query(const std::string &name, vs::Vector &value) const
Definition MultiParser.H:57
const AirfoilTraits< T >::AirfoilLookup & airfoil_lookup(typename T::DataType &data)
void new_wing_position_velocity(VecList &points, vs::Vector &vtr, const int npts, const amrex::Real tn, const amrex::Real tnp1, const std::string &motion, const amrex::Real period, const vs::Vector svec)
Definition wing_ops.cpp:161
void refresh_wing_position(VecList &vpoints, VecList fpoints, const int npts)
Definition wing_ops.cpp:151
ComponentView make_component_view(typename T::DataType &data)
Definition wing_ops.H:45
void init_data_structures(WingBaseData &wdata, ActGrid &grid)
Definition wing_ops.cpp:10
void prepare_netcdf_file(const std::string &ncfile, const WingBaseData &meta, const ActInfo &info, const ActGrid &grid)
Definition wing_ops.cpp:49
void write_netcdf(const std::string &ncfile, const WingBaseData &meta, const ActInfo &info, const ActGrid &grid, const amrex::Real time)
Definition wing_ops.cpp:111
Definition ActParser.H:6
void fllc_init(FLLCData &data, const ComponentView &view, const amrex::Real eps_chord)
Initialize FLLC data structure. This should be called at the end of the first ComputeForceOp to ensur...
Definition FLLC.cpp:6
amrex::Vector< amr_wind::vs::Vector > VecList
Definition actuator_types.H:62
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::iterator_traits< C2 >::value_type linear_angle(const C1 xbegin, const C1 xend, const C2 yinp, const typename std::iterator_traits< C1 >::value_type &xout, const typename std::iterator_traits< C1 >::value_type &upper_bound)
Definition linear_interpolation.H:213
Slice< T > slice(std::vector< T > &vec, const size_t start, const size_t count)
Definition Slice.H:66
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real degrees(const amrex::Real rad_val)
Convert from radians to degrees.
Definition trig_ops.H:42
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real radians(const amrex::Real deg_val)
Convert from degrees to radians.
Definition trig_ops.H:35
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Tensor quaternion(const Vector &axis, const amrex::Real angle)
Definition tensorI.H:215
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T mag(const TensorT< T > &t)
Definition tensorI.H:182
VectorT< amrex::Real > Vector
Definition vector.H:148
Definition actuator_types.H:38
AirfoilTable AirfoilLookup
Definition AirfoilTable.H:80
Definition actuator_types.H:126
VecSlice vel
Definition actuator_types.H:133
VecSlice epsilon
Definition actuator_types.H:129
VecSlice vel_rel
Definition actuator_types.H:134
VecSlice force
Definition actuator_types.H:128
TensorSlice orientation
Definition actuator_types.H:130
RealSlice chord
Definition actuator_types.H:136
VecSlice pos
Definition actuator_types.H:127
VecSlice vel_pos
Definition actuator_types.H:132
This struct will operate on a blade/wing. The velocity from the simulation is corrected using the Fil...
Definition FLLCOp.H:17
Definition actuator_ops.H:61
Definition actuator_ops.H:71
Definition actuator_ops.H:43
Definition actuator_ops.H:54
static constexpr bool update_vel
Definition wing_ops.H:75
static constexpr bool compute_force
Definition wing_ops.H:76
static constexpr bool process_outputs
Definition wing_ops.H:77
static constexpr bool update_pos
Definition wing_ops.H:74
Definition vector.H:13
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T & z() &noexcept
Definition vector.H:99
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T & x() &noexcept
Definition vector.H:97
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE VectorT< T > unit() const
Return the unit vector parallel to this vector.
Definition vector.H:92
iterator end() noexcept
Definition vector.H:142