/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 <algorithm>
4#include <array>
5#include <cassert>
6#include <cmath>
7#include <ranges>
8#include <span>
9#include <vector>
10
16#include "model/node.hpp"
17
19
20double CalculateAngleOfAttack(std::span<const double, 3> v_rel);
21
22std::array<double, 6> CalculateAerodynamicLoad(
23 std::span<double, 3> ref_axis_moment, std::span<const double, 3> v_inflow,
24 std::span<const double, 3> v_motion, std::span<const double> aoa_polar,
25 std::span<const double> cl_polar, std::span<const double> cd_polar,
26 std::span<const double> cm_polar, double chord, double delta_s, double fluid_density,
27 std::span<const double, 3> con_force, std::span<const double, 4> qqr
28);
29
30std::array<double, 3> CalculateConMotionVector(
31 double ac_to_ref_axis_horizontal, double chord_to_ref_axis_vertical
32);
33
34std::vector<double> CalculateJacobianXi(std::span<const double> aero_node_xi);
35
36std::vector<double> CalculateAeroNodeWidths(
37 std::span<const double> jacobian_xi, std::span<const double> jacobian_integration_matrix,
38 std::span<const double> node_x
39);
40
42public:
43 size_t id;
44
45 std::vector<size_t> node_ids;
46 std::vector<std::array<double, 7>> node_u;
47 std::vector<std::array<double, 6>> node_v;
48 std::vector<std::array<double, 6>> node_f;
49
50 std::vector<std::array<double, 7>> xr_motion_map;
51 std::vector<std::array<double, 7>> u_motion_map;
52 std::vector<std::array<double, 6>> v_motion_map;
53 std::vector<std::array<double, 4>> qqr_motion_map;
54 std::vector<std::array<double, 3>> con_motion;
55 std::vector<std::array<double, 3>> x_motion;
56 std::vector<std::array<double, 3>> v_motion;
57
58 std::vector<std::array<double, 3>> con_force;
59 std::vector<std::array<double, 6>> loads;
60 std::vector<std::array<double, 3>> ref_axis_moments;
61
62 std::vector<double> jacobian_xi;
63 std::vector<std::array<double, 3>> v_inflow;
64 std::vector<std::array<double, 3>> v_rel;
65 std::vector<double> twist;
66 std::vector<double> chord;
67 std::vector<double> delta_s;
68 std::vector<size_t> polar_size;
69 std::vector<std::vector<double>> aoa;
70 std::vector<std::vector<double>> cl;
71 std::vector<std::vector<double>> cd;
72 std::vector<std::vector<double>> cm;
73
74 std::vector<double> motion_interp;
75 std::vector<double> shape_deriv_jac;
76
77private:
78 static std::vector<double> ExtractSectionXi(const AerodynamicBodyInput& input);
79
80 static std::vector<double> ExtractBeamNodeXi(
81 const AerodynamicBodyInput& input, std::span<const Node> nodes
82 );
83
84 static std::vector<double> ComputeMotionInterp(
85 std::span<const double> section_xi, std::span<const double> beam_node_xi
86 );
87
88 static std::vector<std::array<double, 7>> ExtractNodeX(
89 const AerodynamicBodyInput& input, std::span<const Node> nodes
90 );
91
92 static void InterpolateQuaternionFromNodesToSections(
93 std::span<std::array<double, 7>> xr, std::span<const std::array<double, 7>> node_x,
94 std::span<const double> interp
95 );
96
97 static std::vector<std::array<double, 7>> InterpolateNodePositionsToSections(
98 const AerodynamicBodyInput& input, std::span<const std::array<double, 7>> node_x,
99 std::span<const double> interp, std::span<const double> section_xi,
100 std::span<const double> beam_node_xi
101 );
102
103 static std::vector<double> ComputeShapeDerivNode(
104 std::span<const double> section_xi, std::span<const double> beam_node_xi
105 );
106
107 static void AddTwistToReferenceLocation(
108 std::vector<std::array<double, 7>>& xr, std::span<const std::array<double, 7>> node_x,
109 const AerodynamicBodyInput& input, std::span<const double> shape_deriv_node
110 );
111
112 static std::vector<std::array<double, 3>> ComputeConMotion(const AerodynamicBodyInput& input);
113
114 static std::vector<double> ComputeShapeDerivJacobian(
115 std::span<const double> jacobian_xi, std::span<const double> beam_node_xi
116 );
117
118 static std::vector<double> ComputeDeltaS(
119 std::span<const std::array<double, 7>> node_x, std::span<const double> jacobian_xi,
120 std::span<const double> shape_deriv_jac
121 );
122
123 template <typename T>
124 static std::vector<std::vector<double>> ExtractPolar(size_t n_sections, T polar_extractor) {
125 auto output = std::vector<std::vector<double>>(n_sections);
126 for (auto section = 0U; section < n_sections; ++section) {
127 const auto& polar_data = polar_extractor(section);
128 const auto n_polar_points = polar_data.size();
129 output[section].resize(n_polar_points);
130 for (auto polar = 0U; polar < n_polar_points; ++polar) {
131 output[section][polar] = polar_data[polar];
132 }
133 }
134 return output;
135 }
136
137 static std::vector<std::array<double, 3>> InitializeConForce(
138 std::span<const std::array<double, 3>> con_motion
139 );
140
141public:
142 AerodynamicBody(const AerodynamicBodyInput& input, std::span<const Node> nodes);
143
144 template <typename DeviceType>
146 // Copy beam node displacements from state
147 for (auto node = 0U; node < node_u.size(); ++node) {
148 for (auto component = 0U; component < 7U; ++component) {
149 node_u[node][component] = state.q(node_ids[node], component);
150 }
151 }
152
153 // Copy beam node velocities from state
154 for (auto node = 0U; node < node_v.size(); ++node) {
155 for (auto component = 0U; component < 6U; ++component) {
156 node_v[node][component] = state.v(node_ids[node], component);
157 }
158 }
159
160 InterpolateQuaternionFromNodesToSections(u_motion_map, node_u, motion_interp);
161
162 // Interpolate beam node velocities to aerodynamic sections on the reference axis
163 for (auto i = 0U; i < v_motion_map.size(); ++i) {
164 for (auto component = 0U; component < 6U; ++component) {
165 v_motion_map[i][component] = 0.;
166 }
167 for (auto j = 0U; j < node_v.size(); ++j) {
168 const auto coeff = motion_interp[i * node_v.size() + j];
169 for (auto component = 0U; component < 6U; ++component) {
170 v_motion_map[i][component] += coeff * node_v[j][component];
171 }
172 }
173 }
174
175 // Calculate global rotation of each section
176 for (auto i = 0U; i < qqr_motion_map.size(); ++i) {
177 const auto xr = std::array{
178 xr_motion_map[i][3], xr_motion_map[i][4], xr_motion_map[i][5], xr_motion_map[i][6]
179 };
180 const auto u = std::array{
181 u_motion_map[i][3], u_motion_map[i][4], u_motion_map[i][5], u_motion_map[i][6]
182 };
183 const auto qqr = math::QuaternionCompose(xr, u);
184 for (auto component = 0U; component < 4U; ++component) {
185 qqr_motion_map[i][component] = qqr[component];
186 }
187 }
188
189 // Calculate motion of aerodynamic centers in global coordinates
190 for (auto i = 0U; i < x_motion.size(); ++i) {
191 const auto qqr_con = math::RotateVectorByQuaternion(qqr_motion_map[i], con_motion[i]);
192
193 for (auto component = 0U; component < 3U; ++component) {
194 x_motion[i][component] =
195 xr_motion_map[i][component] + u_motion_map[i][component] + qqr_con[component];
196 }
197
198 const auto omega =
199 std::array{v_motion_map[i][3], v_motion_map[i][4], v_motion_map[i][5]};
200 const auto omega_qqr_con = math::CrossProduct(omega, qqr_con);
201 for (auto component = 0U; component < 3U; ++component) {
202 v_motion[i][component] = v_motion_map[i][component] + omega_qqr_con[component];
203 }
204 }
205
206 auto node_x = std::vector<double>(node_u.size() * 3U);
207 for (auto node = 0U; node < node_u.size(); ++node) {
208 for (auto component = 0U; component < 3U; ++component) {
209 node_x[component * node_u.size() + node] = state.x(node_ids[node], component);
210 }
211 }
212
214 }
215
216 void SetInflowFromVector(std::span<const std::array<double, 3>> inflow_velocity);
217
218 template <typename T>
219 void SetInflowFromFunction(const T& inflow_velocity_function) {
220 for (auto node = 0U; node < v_inflow.size(); ++node) {
221 const auto inflow_velocity = inflow_velocity_function(x_motion[node]);
222 for (auto component = 0U; component < 3U; ++component) {
223 v_inflow[node][component] = inflow_velocity[component];
224 }
225 }
226 }
227
228 void SetAerodynamicLoads(std::span<const std::array<double, 6>> aerodynamic_loads);
229
230 void CalculateAerodynamicLoads(double fluid_density);
231
232 void CalculateNodalLoads();
233
234 template <typename DeviceType>
236 for (auto node = 0U; node < node_f.size(); ++node) {
237 for (auto component = 0U; component < 6U; ++component) {
238 state.f(node_ids[node], component) += node_f[node][component];
239 }
240 }
241 }
242};
243
245public:
246 std::vector<AerodynamicBody> bodies;
247
248 Aerodynamics(std::span<const AerodynamicBodyInput> inputs, std::span<const Node> nodes);
249
250 template <typename DeviceType>
252 for (auto& body : bodies) {
253 body.CalculateMotion(state);
254 }
255 }
256
258 std::span<const std::vector<std::array<double, 3>>> body_inflow_velocities
259 );
260
261 template <typename T>
262 void SetInflowFromFunction(const T& body_inflow_velocity_function) {
263 for (auto& body : bodies) {
264 body.SetInflowFromFunction(body_inflow_velocity_function);
265 }
266 }
267
268 void SetAerodynamicLoads(std::span<const std::vector<std::array<double, 6>>> body_aero_loads);
269
270 void CalculateAerodynamicLoads(double fluid_density);
271
272 void CalculateNodalLoads();
273
274 template <typename DeviceType>
276 for (auto& body : bodies) {
277 body.AddNodalLoadsToState(state);
278 }
279 }
280};
281} // namespace kynema::interfaces::components
std::vector< std::array< double, 4 > > qqr_motion_map
Definition aerodynamics.hpp:53
std::vector< std::array< double, 7 > > xr_motion_map
Definition aerodynamics.hpp:50
void CalculateNodalLoads()
Definition aerodynamics.cpp:493
size_t id
Definition aerodynamics.hpp:43
std::vector< size_t > polar_size
Definition aerodynamics.hpp:68
std::vector< std::array< double, 7 > > node_u
Definition aerodynamics.hpp:46
std::vector< std::vector< double > > cd
Definition aerodynamics.hpp:71
std::vector< std::array< double, 3 > > v_rel
Definition aerodynamics.hpp:64
void CalculateAerodynamicLoads(double fluid_density)
Definition aerodynamics.cpp:480
void CalculateMotion(const HostState< DeviceType > &state)
Definition aerodynamics.hpp:145
std::vector< std::vector< double > > cm
Definition aerodynamics.hpp:72
std::vector< std::array< double, 3 > > ref_axis_moments
Definition aerodynamics.hpp:60
void SetInflowFromVector(std::span< const std::array< double, 3 > > inflow_velocity)
Definition aerodynamics.cpp:458
std::vector< double > twist
Definition aerodynamics.hpp:65
std::vector< std::array< double, 3 > > x_motion
Definition aerodynamics.hpp:55
std::vector< double > motion_interp
Definition aerodynamics.hpp:74
void SetInflowFromFunction(const T &inflow_velocity_function)
Definition aerodynamics.hpp:219
std::vector< std::array< double, 6 > > v_motion_map
Definition aerodynamics.hpp:52
std::vector< std::vector< double > > cl
Definition aerodynamics.hpp:70
std::vector< size_t > node_ids
Definition aerodynamics.hpp:45
std::vector< std::array< double, 3 > > v_motion
Definition aerodynamics.hpp:56
std::vector< double > shape_deriv_jac
Definition aerodynamics.hpp:75
std::vector< double > chord
Definition aerodynamics.hpp:66
std::vector< std::vector< double > > aoa
Definition aerodynamics.hpp:69
std::vector< std::array< double, 7 > > u_motion_map
Definition aerodynamics.hpp:51
void SetAerodynamicLoads(std::span< const std::array< double, 6 > > aerodynamic_loads)
Definition aerodynamics.cpp:466
std::vector< std::array< double, 3 > > con_force
Definition aerodynamics.hpp:58
std::vector< std::array< double, 3 > > v_inflow
Definition aerodynamics.hpp:63
std::vector< std::array< double, 6 > > node_f
Definition aerodynamics.hpp:48
void AddNodalLoadsToState(HostState< DeviceType > &state)
Definition aerodynamics.hpp:235
std::vector< std::array< double, 3 > > con_motion
Definition aerodynamics.hpp:54
std::vector< std::array< double, 6 > > loads
Definition aerodynamics.hpp:59
std::vector< double > delta_s
Definition aerodynamics.hpp:67
std::vector< double > jacobian_xi
Definition aerodynamics.hpp:62
std::vector< std::array< double, 6 > > node_v
Definition aerodynamics.hpp:47
Definition aerodynamics.hpp:244
void SetInflowFromFunction(const T &body_inflow_velocity_function)
Definition aerodynamics.hpp:262
void SetAerodynamicLoads(std::span< const std::vector< std::array< double, 6 > > > body_aero_loads)
Definition aerodynamics.cpp:535
void CalculateMotion(HostState< DeviceType > &state)
Definition aerodynamics.hpp:251
void AddNodalLoadsToState(HostState< DeviceType > &state)
Definition aerodynamics.hpp:275
std::vector< AerodynamicBody > bodies
Definition aerodynamics.hpp:246
void CalculateAerodynamicLoads(double fluid_density)
Definition aerodynamics.cpp:543
void SetInflowFromVector(std::span< const std::vector< std::array< double, 3 > > > body_inflow_velocities)
Definition aerodynamics.cpp:527
void CalculateNodalLoads()
Definition aerodynamics.cpp:549
Definition aerodynamics.cpp:3
std::array< double, 3 > CalculateConMotionVector(double ac_to_ref_axis_horizontal, double chord_to_ref_axis_vertical)
Definition aerodynamics.cpp:97
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)
Definition aerodynamics.cpp:9
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:124
std::vector< double > CalculateJacobianXi(std::span< const double > aero_node_xi)
Definition aerodynamics.cpp:103
double CalculateAngleOfAttack(std::span< const double, 3 > v_rel)
Definition aerodynamics.cpp:5
KOKKOS_INLINE_FUNCTION void CrossProduct(const VectorType &a, const VectorType &b, const VectorType &c)
Calculate the cross product between two vector views.
Definition vector_operations.hpp:40
KOKKOS_INLINE_FUNCTION void QuaternionCompose(const Quaternion1 &q1, const Quaternion2 &q2, QuaternionN &qn)
Composes (i.e. multiplies) two quaternions and stores the result in a third quaternion.
Definition quaternion_operations.hpp:204
KOKKOS_INLINE_FUNCTION void RotateVectorByQuaternion(const Quaternion &q, const View1 &v, const View2 &v_rot)
Rotates provided vector by provided unit quaternion and returns the result.
Definition quaternion_operations.hpp:120
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