/home/runner/work/kynema/kynema/kynema/src/interfaces/components/aerodynamics.hpp Source File

Kynema API: /home/runner/work/kynema/kynema/kynema/src/interfaces/components/aerodynamics.hpp Source File
Kynema API
A flexible multibody structural dynamics code for wind turbines
Loading...
Searching...
No Matches
aerodynamics.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cassert>
5#include <cmath>
6#include <ranges>
7#include <span>
8#include <vector>
9
12#include "model/node.hpp"
13
15
16double CalculateAngleOfAttack(std::span<const double, 3> v_rel);
17
18std::array<double, 6> CalculateAerodynamicLoad(
19 std::span<double, 3> ref_axis_moment, std::span<const double, 3> v_inflow,
20 std::span<const double, 3> v_motion, std::span<const double> aoa_polar,
21 std::span<const double> cl_polar, std::span<const double> cd_polar,
22 std::span<const double> cm_polar, double chord, double delta_s, double fluid_density,
23 std::span<const double, 3> con_force, std::span<const double, 4> qqr,
24 std::array<double, 3>& v_rel, double& aoa, double& cn, double& ct, double& cm
25);
26
27std::array<double, 3> CalculateConMotionVector(
28 double ac_to_ref_axis_horizontal, double chord_to_ref_axis_vertical
29);
30
31std::vector<double> CalculateJacobianXi(std::span<const double> aero_node_xi);
32
33std::vector<double> CalculateAeroNodeWidths(
34 std::span<const double> jacobian_xi, std::span<const double> jacobian_integration_matrix,
35 std::span<const double> node_x
36);
37
39public:
40 size_t id;
41
42 //--------------------------------------------------------------------------
43 // Node data
44 //--------------------------------------------------------------------------
45
47 std::vector<size_t> node_ids;
48
50 std::vector<std::array<double, 7>> node_u;
51
53 std::vector<std::array<double, 6>> node_v;
54
57 std::vector<std::array<double, 6>> node_f;
58
59 //--------------------------------------------------------------------------
60 // Aerodynamic section data
61 //--------------------------------------------------------------------------
62
64 std::vector<std::array<double, 7>> xr_motion_map;
65
67 std::vector<std::array<double, 7>> u_motion_map;
68
70 std::vector<std::array<double, 6>> v_motion_map;
71
74 std::vector<std::array<double, 4>> qqr_motion_map;
75
78 std::vector<std::array<double, 3>> con_motion;
79
81 std::vector<std::array<double, 3>> x_motion;
82
84 std::vector<std::array<double, 3>> v_motion;
85
88 std::vector<std::array<double, 3>> con_force;
89
91 std::vector<std::array<double, 3>> v_inflow;
92
94 std::vector<std::array<double, 3>> v_rel;
95
96 //--------------------------------------------------------------------------
97 // Aerodynamic section output
98 //--------------------------------------------------------------------------
99
101 std::vector<double> alpha;
102
105 std::vector<double> cn;
106
108 std::vector<double> ct;
109
111 std::vector<double> cm;
112
114 std::vector<std::array<double, 6>> loads;
115
118 std::vector<std::array<double, 3>> ref_axis_moments;
119
120 //--------------------------------------------------------------------------
121 // Aerodynamic section properties
122 //--------------------------------------------------------------------------
123
125 std::vector<double> twist;
126
128 std::vector<double> chord;
129
131 std::vector<double> delta_s;
132
134 std::vector<size_t> polar_size;
135
137 std::vector<std::vector<double>> aoa;
138
140 std::vector<std::vector<double>> cl_polar;
141
143 std::vector<std::vector<double>> cd_polar;
144
146 std::vector<std::vector<double>> cm_polar;
147
148 //--------------------------------------------------------------------------
149 // Interpolation data
150 //--------------------------------------------------------------------------
151
154 std::vector<double> jacobian_xi;
155
157 std::vector<double> motion_interp;
158
161 std::vector<double> shape_deriv_jac;
162
163private:
164 static std::vector<double> ExtractSectionXi(const AerodynamicBodyInput& input);
165
166 static std::vector<double> ExtractBeamNodeXi(
167 const AerodynamicBodyInput& input, std::span<const Node> nodes
168 );
169
170 static std::vector<double> ComputeMotionInterp(
171 std::span<const double> section_xi, std::span<const double> beam_node_xi
172 );
173
174 static std::vector<std::array<double, 7>> ExtractNodeX(
175 const AerodynamicBodyInput& input, std::span<const Node> nodes
176 );
177
178 static void InterpolateQuaternionFromNodesToSections(
179 std::span<std::array<double, 7>> xr, std::span<const std::array<double, 7>> node_x,
180 std::span<const double> interp
181 );
182
183 static std::vector<std::array<double, 7>> InterpolateNodePositionsToSections(
184 const AerodynamicBodyInput& input, std::span<const std::array<double, 7>> node_x,
185 std::span<const double> interp, std::span<const double> section_xi,
186 std::span<const double> beam_node_xi
187 );
188
189 static std::vector<double> ComputeShapeDerivNode(
190 std::span<const double> section_xi, std::span<const double> beam_node_xi
191 );
192
193 static void AddTwistToReferenceLocation(
194 std::vector<std::array<double, 7>>& xr, std::span<const std::array<double, 7>> node_x,
195 const AerodynamicBodyInput& input, std::span<const double> shape_deriv_node
196 );
197
198 static std::vector<std::array<double, 3>> ComputeConMotion(const AerodynamicBodyInput& input);
199
200 static std::vector<double> ComputeShapeDerivJacobian(
201 std::span<const double> jacobian_xi, std::span<const double> beam_node_xi
202 );
203
204 static std::vector<double> ComputeDeltaS(
205 std::span<const std::array<double, 7>> node_x, std::span<const double> jacobian_xi,
206 std::span<const double> shape_deriv_jac
207 );
208
209 template <typename T>
210 static std::vector<std::vector<double>> ExtractPolar(size_t n_sections, T polar_extractor) {
211 auto output = std::vector<std::vector<double>>(n_sections);
212 for (auto section : std::views::iota(0U, n_sections)) {
213 const auto& polar_data = polar_extractor(section);
214 const auto n_polar_points = polar_data.size();
215 output[section].resize(n_polar_points);
216 for (auto polar : std::views::iota(0U, n_polar_points)) {
217 output[section][polar] = polar_data[polar];
218 }
219 }
220 return output;
221 }
222
223 static std::vector<std::array<double, 3>> InitializeConForce(
224 std::span<const std::array<double, 3>> con_motion
225 );
226
227public:
228 AerodynamicBody(const AerodynamicBodyInput& input, std::span<const Node> nodes);
229
230 template <typename DeviceType>
232 // Copy beam node displacements from state
233 for (auto node : std::views::iota(0U, node_u.size())) {
234 for (auto component : std::views::iota(0U, 7U)) {
235 node_u[node][component] = state.q(node_ids[node], component);
236 }
237 }
238
239 // Copy beam node velocities from state
240 for (auto node : std::views::iota(0U, node_v.size())) {
241 for (auto component : std::views::iota(0U, 6U)) {
242 node_v[node][component] = state.v(node_ids[node], component);
243 }
244 }
245
246 InterpolateQuaternionFromNodesToSections(u_motion_map, node_u, motion_interp);
247
248 // Interpolate beam node velocities to aerodynamic sections on the reference axis
249 for (auto i : std::views::iota(0U, v_motion_map.size())) {
250 for (auto component : std::views::iota(0U, 6U)) {
251 v_motion_map[i][component] = 0.;
252 }
253 for (auto j : std::views::iota(0U, node_v.size())) {
254 const auto coeff = motion_interp[(i * node_v.size()) + j];
255 for (auto component : std::views::iota(0U, 6U)) {
256 v_motion_map[i][component] += coeff * node_v[j][component];
257 }
258 }
259 }
260
261 // Calculate global rotation of each section
262 for (auto i : std::views::iota(0U, qqr_motion_map.size())) {
263 const auto xr = Eigen::Quaternion<double>{
264 xr_motion_map[i][3], xr_motion_map[i][4], xr_motion_map[i][5], xr_motion_map[i][6]
265 };
266 const auto u = Eigen::Quaternion<double>{
267 u_motion_map[i][3], u_motion_map[i][4], u_motion_map[i][5], u_motion_map[i][6]
268 };
269 const auto qqr = u * xr;
270 qqr_motion_map[i][0] = qqr.w();
271 qqr_motion_map[i][1] = qqr.x();
272 qqr_motion_map[i][2] = qqr.y();
273 qqr_motion_map[i][3] = qqr.z();
274 }
275
276 // Calculate motion of aerodynamic centers in global coordinates
277 for (auto i : std::views::iota(0U, x_motion.size())) {
278 const auto qqr_mm = Eigen::Quaternion<double>(
279 qqr_motion_map[i][0], qqr_motion_map[i][1], qqr_motion_map[i][2],
280 qqr_motion_map[i][3]
281 );
282 const auto con_m = Eigen::Matrix<double, 3, 1>(con_motion[i].data());
283 const auto qqr_con = qqr_mm._transformVector(con_m);
284
285 for (auto component : std::views::iota(0U, 3U)) {
286 x_motion[i][component] =
287 xr_motion_map[i][component] + u_motion_map[i][component] + qqr_con(component);
288 }
289
290 const auto omega = Eigen::Matrix<double, 3, 1>(&v_motion_map[i][3]);
291 const auto omega_qqr_con = omega.cross(qqr_con);
292 for (auto component : std::views::iota(0U, 3U)) {
293 v_motion[i][component] = v_motion_map[i][component] + omega_qqr_con(component);
294 }
295 }
296
297 auto node_x = std::vector<double>(node_u.size() * 3U);
298 for (auto node : std::views::iota(0U, node_f.size())) {
299 for (auto component : std::views::iota(0U, 3U)) {
300 node_x[(component * node_u.size()) + node] = state.x(node_ids[node], component);
301 }
302 }
303
305 }
306
307 void SetInflowFromVector(std::span<const std::array<double, 3>> inflow_velocity);
308
309 template <typename T>
310 void SetInflowFromFunction(const T& inflow_velocity_function) {
311 for (auto node = 0U; node < v_inflow.size(); ++node) {
312 const auto inflow_velocity = inflow_velocity_function(x_motion[node]);
313 for (auto component = 0U; component < 3U; ++component) {
314 v_inflow[node][component] = inflow_velocity[component];
315 }
316 }
317 }
318
319 void SetAerodynamicLoads(std::span<const std::array<double, 6>> aerodynamic_loads);
320
321 void CalculateAerodynamicLoads(double fluid_density);
322
323 void CalculateNodalLoads();
324
325 template <typename DeviceType>
327 for (auto node : std::views::iota(0U, node_f.size())) {
328 for (auto component : std::views::iota(0U, 6U)) {
329 state.f(node_ids[node], component) += node_f[node][component];
330 }
331 }
332 }
333};
334
336public:
337 std::vector<AerodynamicBody> bodies;
338
339 Aerodynamics(std::span<const AerodynamicBodyInput> inputs, std::span<const Node> nodes);
340
341 template <typename DeviceType>
343 for (auto& body : bodies) {
344 body.CalculateMotion(state);
345 }
346 }
347
349 std::span<const std::vector<std::array<double, 3>>> body_inflow_velocities
350 );
351
352 template <typename T>
353 void SetInflowFromFunction(const T& body_inflow_velocity_function) {
354 for (auto& body : bodies) {
355 body.SetInflowFromFunction(body_inflow_velocity_function);
356 }
357 }
358
359 void SetAerodynamicLoads(std::span<const std::vector<std::array<double, 6>>> body_aero_loads);
360
361 void CalculateAerodynamicLoads(double fluid_density);
362
363 void CalculateNodalLoads();
364
365 template <typename DeviceType>
367 for (auto& body : bodies) {
368 body.AddNodalLoadsToState(state);
369 }
370 }
371};
372} // namespace kynema::interfaces::components
std::vector< std::array< double, 4 > > qqr_motion_map
Total rotation quaternion of beam reference axis at aerodynamic sections (reference + displacement)
Definition aerodynamics.hpp:74
std::vector< std::array< double, 7 > > xr_motion_map
Initial position and orientation of beam reference axis at aerodynamic sections.
Definition aerodynamics.hpp:64
void CalculateNodalLoads()
Definition aerodynamics.cpp:487
std::vector< double > alpha
Angle of attack at aerodynamic sections (output)
Definition aerodynamics.hpp:101
size_t id
Definition aerodynamics.hpp:40
std::vector< size_t > polar_size
Number of points in each aerodynamic polar.
Definition aerodynamics.hpp:134
std::vector< std::array< double, 7 > > node_u
Displacements of the beam nodes (copied from state based on node_ids)
Definition aerodynamics.hpp:50
std::vector< double > cm
Moment coefficient at aerodynamic sections (output)
Definition aerodynamics.hpp:111
std::vector< std::vector< double > > cl_polar
Lift coefficient polar at each aerodynamic section.
Definition aerodynamics.hpp:140
std::vector< std::array< double, 3 > > v_rel
Relative velocity at aerodynamic sections (v_inflow - v_motion) (output)
Definition aerodynamics.hpp:94
void CalculateAerodynamicLoads(double fluid_density)
Definition aerodynamics.cpp:473
void CalculateMotion(const HostState< DeviceType > &state)
Definition aerodynamics.hpp:231
std::vector< std::array< double, 3 > > ref_axis_moments
Total moment about beam reference axis at aerodynamic sections (accounting for AC moment arm and aero...
Definition aerodynamics.hpp:118
std::vector< double > cn
Normal force coefficient at aerodynamic sections (perpendicular to airfoil chord) (output)
Definition aerodynamics.hpp:105
void SetInflowFromVector(std::span< const std::array< double, 3 > > inflow_velocity)
Definition aerodynamics.cpp:446
std::vector< double > twist
Aerodynamic section twist.
Definition aerodynamics.hpp:125
std::vector< std::array< double, 3 > > x_motion
Positions of aerodynamic centers at aerodynamic sections in global coordinates.
Definition aerodynamics.hpp:81
std::vector< double > motion_interp
Flattened matrix to interpolate motion from beam nodes to aerodynamic sections.
Definition aerodynamics.hpp:157
void SetInflowFromFunction(const T &inflow_velocity_function)
Definition aerodynamics.hpp:310
std::vector< std::array< double, 6 > > v_motion_map
Velocities of beam reference axis at aerodynamic sections.
Definition aerodynamics.hpp:70
std::vector< size_t > node_ids
IDs of the beam nodes in this aerodynamic body.
Definition aerodynamics.hpp:47
std::vector< std::array< double, 3 > > v_motion
Velocities of aerodynamic centers at aerodynamic sections in global coordinates.
Definition aerodynamics.hpp:84
std::vector< double > shape_deriv_jac
Flattened matrix to interpolate motion derivatives from beam nodes to aerodynamic sections (used for ...
Definition aerodynamics.hpp:161
std::vector< double > chord
Aerodynamic section chord length.
Definition aerodynamics.hpp:128
std::vector< std::vector< double > > aoa
Angle of attack polar at each aerodynamic section.
Definition aerodynamics.hpp:137
std::vector< std::array< double, 7 > > u_motion_map
Displacements of beam reference axis at aerodynamic sections.
Definition aerodynamics.hpp:67
std::vector< std::vector< double > > cd_polar
Drag coefficient polar at each aerodynamic section.
Definition aerodynamics.hpp:143
void SetAerodynamicLoads(std::span< const std::array< double, 6 > > aerodynamic_loads)
Definition aerodynamics.cpp:454
std::vector< double > ct
Tangent force coefficient at aerodynamic sections (parallel to airfoil chord) (output)
Definition aerodynamics.hpp:108
std::vector< std::array< double, 3 > > con_force
Vectors from aerodynamic center to reference axis at aerodynamic sections in reference configuration ...
Definition aerodynamics.hpp:88
std::vector< std::array< double, 3 > > v_inflow
Inflow velocity at aerodynamic sections.
Definition aerodynamics.hpp:91
std::vector< std::array< double, 6 > > node_f
Aerodynamic forces at the beam nodes with moment arm applied from aerodynamic center to reference axi...
Definition aerodynamics.hpp:57
void AddNodalLoadsToState(HostState< DeviceType > &state)
Definition aerodynamics.hpp:326
std::vector< std::array< double, 3 > > con_motion
Vectors from reference axis to aerodynamic center at aerodynamic sections in reference configuration ...
Definition aerodynamics.hpp:78
std::vector< std::array< double, 6 > > loads
Aerodynamic loads (forces and moments) at aerodynamic centers (output)
Definition aerodynamics.hpp:114
std::vector< double > delta_s
Aerodynamic section width for force/moment calculation.
Definition aerodynamics.hpp:131
std::vector< double > jacobian_xi
Locations of aerodynamic section width boundaries along the beam (used for section width calculation)
Definition aerodynamics.hpp:154
std::vector< std::vector< double > > cm_polar
Moment coefficient polar at each aerodynamic section.
Definition aerodynamics.hpp:146
std::vector< std::array< double, 6 > > node_v
Velocities of the beam nodes (copied from state based on node_ids)
Definition aerodynamics.hpp:53
Definition aerodynamics.hpp:335
void SetInflowFromFunction(const T &body_inflow_velocity_function)
Definition aerodynamics.hpp:353
void SetAerodynamicLoads(std::span< const std::vector< std::array< double, 6 > > > body_aero_loads)
Definition aerodynamics.cpp:527
void CalculateMotion(HostState< DeviceType > &state)
Definition aerodynamics.hpp:342
void AddNodalLoadsToState(HostState< DeviceType > &state)
Definition aerodynamics.hpp:366
std::vector< AerodynamicBody > bodies
Definition aerodynamics.hpp:337
void CalculateAerodynamicLoads(double fluid_density)
Definition aerodynamics.cpp:535
void SetInflowFromVector(std::span< const std::vector< std::array< double, 3 > > > body_inflow_velocities)
Definition aerodynamics.cpp:519
void CalculateNodalLoads()
Definition aerodynamics.cpp:541
Definition aerodynamics.cpp:5
std::array< double, 3 > CalculateConMotionVector(double ac_to_ref_axis_horizontal, double chord_to_ref_axis_vertical)
Definition aerodynamics.cpp:83
std::array< double, 6 > CalculateAerodynamicLoad(std::span< double, 3 > ref_axis_moment, std::span< const double, 3 > v_inflow, std::span< const double, 3 > v_motion, std::span< const double > aoa_polar, std::span< const double > cl_polar, std::span< const double > cd_polar, std::span< const double > cm_polar, double chord, double delta_s, double fluid_density, std::span< const double, 3 > con_force, std::span< const double, 4 > qqr, std::array< double, 3 > &v_rel, double &aoa, double &cn, double &ct, double &cm)
Definition aerodynamics.cpp:11
std::vector< double > CalculateAeroNodeWidths(std::span< const double > jacobian_xi, std::span< const double > jacobian_integration_matrix, std::span< const double > node_x)
Definition aerodynamics.cpp:110
std::vector< double > CalculateJacobianXi(std::span< const double > aero_node_xi)
Definition aerodynamics.cpp:89
double CalculateAngleOfAttack(std::span< const double, 3 > v_rel)
Definition aerodynamics.cpp:7
Host-side mirror of the simulation state for a given time increment.
Definition host_state.hpp:22
HostView< double *[6]> f
Host local copy of external forces.
Definition host_state.hpp:39
HostView< double *[7]> x
Host local copy of current position.
Definition host_state.hpp:27
HostView< double *[6]> v
Host local copy of current velocity.
Definition host_state.hpp:33
HostView< double *[7]> q
Host local copy of current displacement.
Definition host_state.hpp:30
Definition aerodynamics_input.hpp:21