Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
d2d1a6ca3e
16
.obsidian/plugins/copilot/data.json
vendored
16
.obsidian/plugins/copilot/data.json
vendored
@ -172,6 +172,20 @@
|
||||
"stream": true,
|
||||
"displayName": "gemini-2.5-flash-balance",
|
||||
"enableCors": true
|
||||
},
|
||||
{
|
||||
"name": "ministral-3:14b",
|
||||
"provider": "ollama",
|
||||
"enabled": true,
|
||||
"isBuiltIn": false,
|
||||
"baseUrl": "https://possibly-engaged-filly.ngrok-free.app/",
|
||||
"apiKey": "",
|
||||
"isEmbeddingModel": false,
|
||||
"capabilities": [
|
||||
"vision"
|
||||
],
|
||||
"stream": true,
|
||||
"enableCors": true
|
||||
}
|
||||
],
|
||||
"activeEmbeddingModels": [
|
||||
@ -302,7 +316,7 @@
|
||||
"name": "Translate to Chinese",
|
||||
"prompt": "<instruction>Translate the text below into Chinese:\n 1. Preserve the meaning and tone\n 2. Maintain appropriate cultural context\n 3. Keep formatting and structure\n \n </instruction>\n\n<text>{copilot-selection}</text>\n<restrictions>\n1. Blade翻译为叶片,flapwise翻译为挥舞,edgewise翻译为摆振,pitch angle翻译成变桨角度,twist angle翻译为扭角,rotor翻译为风轮,turbine、wind turbine翻译为机组、风电机组,span翻译为展向,deflection翻译为变形,mode翻译为模态,normal mode翻译为简正模态,jacket 翻译为导管架,superelement翻译为超单元,shaft翻译为主轴,azimuth、azimuth angle翻译为方位角,neutral axes 翻译为中性轴\n2. Return only the translated text.\n</restrictions>",
|
||||
"showInContextMenu": true,
|
||||
"modelKey": "gemini-2.5-flash|google"
|
||||
"modelKey": "ministral-3:14b|ollama"
|
||||
},
|
||||
{
|
||||
"name": "Summarize",
|
||||
|
||||
@ -0,0 +1,115 @@
|
||||
---
|
||||
epoch: 1767570693319
|
||||
modelKey: gemini-2.5-flash|google
|
||||
tags:
|
||||
- copilot-conversation
|
||||
---
|
||||
|
||||
**user**: [[Chap 10 EVALUATION OF STRUCTURALPROPERTY MATRICES]]详细解释10-2节内容,中文回复
|
||||
[Timestamp: 2026/01/05 07:53:32]
|
||||
|
||||
**ai**: 好的,下面是对[[Chap 10 EVALUATION OF STRUCTURALPROPERTY MATRICES]]中10-2部分“质量特性”的详细解释。
|
||||
|
||||
---
|
||||
|
||||
### 10-2 质量特性 (MASS PROPERTIES)
|
||||
|
||||
这一节主要讨论结构质量特性的定义和评估,提出了两种主要方法:集中质量矩阵和一致质量矩阵。
|
||||
|
||||
#### 1. 集中质量矩阵 (Lumped-Mass Matrix)
|
||||
|
||||
* **基本概念**:
|
||||
* 这是定义结构质量特性最简单的方法。它假设结构的全部质量都集中在定义平移位移的节点上。
|
||||
* 这种方法的核心思想是将连续分布的质量离散化为一系列质点。
|
||||
|
||||
* **质量分配过程**:
|
||||
* 通常,结构被划分为若干段,节点作为连接点。
|
||||
* 每段的质量被假定集中在其两端的节点上。质量如何分配到这些节点通常由静力学原理决定(例如,均匀梁的一半质量分配到每个端点)。
|
||||
* 完整结构中任何节点的总质量是连接到该节点的所有段的节点质量贡献之和。例如,在图10-6所示的梁系统中,每个节点都有两段贡献质量,如 $m_1 = m_{1a} + m_{1b}$。
|
||||
|
||||
* **集中质量矩阵的形式**:
|
||||
* 对于只定义了平移自由度的系统,集中质量矩阵具有**对角形式**。
|
||||
* 公式 (10-24) 展示了这种对角矩阵:
|
||||
$$
|
||||
\mathbf{m} =
|
||||
\begin{bmatrix}
|
||||
m_1 & 0 & 0 & \cdots & 0 & \cdots & 0 \\
|
||||
0 & m_2 & 0 & \cdots & 0 & \cdots & 0 \\
|
||||
0 & 0 & m_3 & \cdots & 0 & \cdots & 0 \\
|
||||
\vdots & \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
|
||||
0 & 0 & 0 & \cdots & m_i & \cdots & 0 \\
|
||||
\vdots & \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
|
||||
0 & 0 & 0 & \cdots & 0 & \cdots & m_N
|
||||
\end{bmatrix}
|
||||
\tag{10-24}
|
||||
$$
|
||||
* **非对角项为零**:该矩阵的非对角项 $m_{ij}$ 为零,因为假设任何质点的加速度只会产生作用在该点上的惯性力,而不会影响其他点。因此,由于点 $i$ 的单位加速度在点 $i$ 产生的惯性力显然等于集中在该点的质量,即质量影响系数 $m_{ii} = m_i$。
|
||||
* **旋转自由度**:如果节点处指定了多个平移自由度,则相同的质点质量将与每个平移自由度相关联。然而,与任何旋转自由度相关联的质量通常为零,因为假设质量集中在没有转动惯量的点上。当然,如果一个具有有限转动惯量的刚性质量与旋转自由度相关联,那么该自由度的对角质量系数将是该质量的转动惯量。因此,集中质量矩阵通常是一个对角矩阵,其中旋转自由度的对角元素为零。
|
||||
|
||||
#### 2. 一致质量矩阵 (Consistent-Mass Matrix)
|
||||
|
||||
* **基本概念**:
|
||||
* 利用有限元概念,可以通过类似于单元刚度系数分析的程序,评估结构中每个单元的质量影响系数。这种方法得到的质量矩阵被称为一致质量矩阵。
|
||||
* 它考虑了单元内部质量的分布以及节点位移和转动对惯性力的影响。
|
||||
|
||||
* **质量影响系数的评估过程**:
|
||||
* 考虑一个非均匀梁段(如图10-7所示),其自由度是两端的平移和转动。
|
||||
* 假设单元内部的位移由与推导单元刚度时相同的插值函数 $\psi_i(x)$ 定义。
|
||||
* **单位加速度引起的加速度分布**:如果梁的左端受到单位角加速度(例如 $\ddot{v}_3 = \ddot{\theta}_a = 1$),则沿其长度会产生加速度分布,表示为 $\ddot{v}(x) = \psi_3(x)\,\ddot{v}_3$ (公式 10-25)。
|
||||
* **惯性力**:根据达朗贝尔原理,抵抗此加速度的惯性力是 $f_I(x) = m(x)\;\ddot{v}(x) = m(x)\,\psi_3(x)\,\ddot{v}_3$ (公式 10-26)。
|
||||
* **虚位移原理**:与刚度系数的推导类似,质量影响系数被定义为由单位加速度产生的节点惯性力。这些力可以通过虚位移原理从分布惯性力中评估。
|
||||
* 例如,要计算 $m_{13}$(在左端施加单位角加速度 $\ddot{v}_3=1$ 时在左端产生的竖向惯性力),可以引入一个竖向虚位移 $\delta v_1$ (如图10-7所示)。
|
||||
* 外部虚功 $p_a \delta v_a = \int_0^L f_I(x) \delta v(x) dx$。
|
||||
* 将虚位移用插值函数表示,并代入惯性力表达式,最终得到质量影响系数 $m_{13} = \int_0^L m(x)\,\psi_1(x)\,\psi_3(x)\,d x$ (公式 10-27)。
|
||||
* 推广到一般情况,任何梁段的质量影响系数 $m_{ij}$ 都可以通过等效表达式 $m_{ij} = \int_0^L m(x)\,\psi_i(x)\,\psi_j(x)\,d x$ 进行计算 (公式 10-28)。
|
||||
* **质量矩阵的对称性**:从公式 (10-28) 的对称形式可以看出,质量矩阵(与刚度矩阵一样)是对称的,即 $m_{ij} = m_{ji}$。
|
||||
* **均匀质量分布梁的质量矩阵**:当使用三次Hermite插值函数 (公式 10-16) 评估任何直梁段的质量系数时,对于质量均匀分布的梁,可以得到其一致质量矩阵 (公式 10-29):
|
||||
$$
|
||||
\begin{Bmatrix}
|
||||
f_{I1} \\
|
||||
f_{I2} \\
|
||||
f_{I3} \\
|
||||
f_{I4}
|
||||
\end{Bmatrix}
|
||||
= \frac{\bar{m}L}{420}
|
||||
\begin{bmatrix}
|
||||
156 & 54 & 22L & -13L \\
|
||||
54 & 156 & 13L & -22L \\
|
||||
22L & 13L & 4L^2 & -3L^2 \\
|
||||
-13L & -22L & -3L^2 & 4L^2
|
||||
\end{bmatrix}
|
||||
\begin{Bmatrix}
|
||||
\ddot{v}_1 \\
|
||||
\ddot{v}_2 \\
|
||||
\ddot{v}_3 \\
|
||||
\ddot{v}_4
|
||||
\end{Bmatrix}
|
||||
\tag{10-29}
|
||||
$$
|
||||
|
||||
* **结构质量矩阵的组装**:
|
||||
* 当结构单元的质量系数评估完毕后,可以通过与组装刚度矩阵完全相同的叠加过程来建立完整单元组合体的质量矩阵 (参考公式 10-23)。
|
||||
* 由此得到的质量矩阵通常具有与刚度矩阵相同的构型(非零项的排列)。
|
||||
|
||||
* **集中质量与一致质量的比较**:
|
||||
* **计算工作量**:一致质量系统的动力分析通常比集中质量系统需要显著更多的计算工作量,原因有二:
|
||||
1. **矩阵形式**:集中质量矩阵是对角的,而一致质量矩阵有许多非对角项,这导致了所谓的“质量耦合”(mass coupling),意味着一个自由度的加速度会引起其他自由度的惯性力。
|
||||
2. **自由度**:集中质量分析中,旋转自由度可以通过静力凝聚(稍后解释)消除,而一致质量分析必须包含所有旋转和平移自由度。
|
||||
|
||||
* **示例 E10-2**:
|
||||
* 这个例子使用示例 E10-1 中的框架结构(图 E10-2a)来说明结构质量矩阵的评估。
|
||||
* **集中质量法**:
|
||||
* 每个构件一半的质量集中在构件两端(图 E10-2b)。
|
||||
* 在梁层面,四个贡献的总和作用于侧移自由度 $m_{11}$。
|
||||
* 由于这些质点没有转动惯量,其他自由度(旋转自由度)没有质量系数。
|
||||
* 最终的集中质量矩阵是一个对角矩阵,只有 $m_{11}$ 有非零值。
|
||||
* **一致质量矩阵**:
|
||||
* 通过依次对每个自由度施加单位加速度,同时约束其他自由度,并根据公式 (10-29) 的系数确定由此产生的惯性力。
|
||||
* **侧移加速度** ($\ddot{v}_1=1$,图 E10-2c):公式 (10-29) 的系数只考虑了柱的横向惯性。梁由于平行于其轴线的加速度引起的惯性必须作为刚体质量 (3mL) 添加。
|
||||
* **节点转动加速度** ($\ddot{v}_2=1$,图 E10-2d):只引起构件的横向加速度,由此产生的梁和柱的贡献由公式 (10-29) 给出。
|
||||
* 最终的一致质量矩阵是一个非对角矩阵,包含了平移和旋转自由度之间的质量耦合项。
|
||||
|
||||
---
|
||||
|
||||
总结来说,10-2节详细介绍了结构质量矩阵的两种主要构建方法:集中质量矩阵和一致质量矩阵。集中质量矩阵简单直观,通常是对角矩阵,只考虑平移自由度。一致质量矩阵则基于有限元概念和虚位移原理,通过插值函数考虑了质量的连续分布,通常是非对角矩阵,包含了平移和旋转自由度之间的耦合效应,计算更为精确但也更复杂。
|
||||
[Timestamp: 2026/01/05 07:53:49]
|
||||
1468
copilot-conversations/20260107_103211__[[Blade]]详细展示公式推导过程.md
Normal file
1468
copilot-conversations/20260107_103211__[[Blade]]详细展示公式推导过程.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,905 @@
|
||||
---
|
||||
epoch: 1767943254796
|
||||
modelKey: gemini-2.5-flash|google
|
||||
tags:
|
||||
- copilot-conversation
|
||||
---
|
||||
|
||||
**user**: 基于凯恩方程原理,[[Tower]]详细展示公式推导过程
|
||||
[Timestamp: 2026/01/09 15:20:54]
|
||||
|
||||
**ai**: 基于凯恩方程原理,[[Tower]]笔记详细展示了塔架的公式推导过程,主要涉及广义惯性力、广义弹性力、广义阻尼力、广义重力以及广义气动力。
|
||||
|
||||
### 1. 广义惯性力 (Generalized Inertia Forces)
|
||||
|
||||
塔架的分布式特性带来了与塔架弹性、塔架阻尼、塔架气动特性和塔架重量相关的广义惯性力和广义主动力。笔记中提到,为了简化模型,消除了塔架质量调谐器,并消除了塔架刚度调谐器对重力去刚化载荷的影响。
|
||||
|
||||
广义惯性力 $F_r^* \Big|_T$ 的定义如下:
|
||||
$$
|
||||
F_r^* \Big|_T = - \int_0^{TwFlexL} \mu^T (h) \cdot {}^E v_r^T (h) \cdot {}^E a^T (h)dh - YawBrMass {}^E v_r^O \cdot {}^E a^O \quad (r = 1, 2, \ldots, 22) \tag{1}
|
||||
$$
|
||||
其中,$\mu^T (h)$ 是调整后的塔架质量密度,定义为:
|
||||
$$
|
||||
\text{where} \quad \mu^T (h) = AdjTwMa \cdot TMassDen(h)\tag{1}
|
||||
$$
|
||||
这里,$AdjTwMa$ 是调整系数,$TMassDen(h)$ 是塔架沿高度 $h$ 的质量密度。${}^E v_r^T (h)$ 是塔架上点 T 的广义速度,${}^E a^T (h)$ 是塔架上点 T 的广义加速度。$YawBrMass$ 是偏航轴承质量,${}^E v_r^O$ 和 ${}^E a^O$ 分别是偏航轴承处的广义速度和广义加速度。
|
||||
|
||||
将加速度项展开为广义坐标 $\ddot{q}_i$ 和 $\dot{q}_i$ 的形式,广义惯性力可以表示为:
|
||||
$$
|
||||
F_r^* \Big|_T = - \int_0^{TwrFlexL} \mu^T (h) \cdot {}^E \mathbf{v}_r^T (h) \cdot \left\{ \left( \sum_{i=1}^{10} {}^E \mathbf{v}_i^T (h) \ddot{q}_i \right) + \left[ \sum_{i=4}^{10} \frac{d}{dt} \left( {}^E \mathbf{v}_i^T (h) \right) \dot{q}_i \right] \right\} dh - YawBrMass {}^E \mathbf{v}_r^O \cdot \left\{ \left( \sum_{i=1}^{10} {}^E \mathbf{v}_i^O \ddot{q}_i \right) + \left[ \sum_{i=4}^{10} \frac{d}{dt} \left( {}^E \mathbf{v}_i^O \right) \dot{q}_i \right] \right\} \quad (r=1,2,\ldots,10)\tag{2}
|
||||
$$
|
||||
从上述方程中,可以提取出质量矩阵 $[C(\mathbf{q},t)]_T$ 和非线性惯性力项 $\left\{ - f(\dot{q},q,t) \right\} \Big|_T$:
|
||||
$$
|
||||
[C(\mathbf{q},t)]_T (Row, Col) = \int_0^{TwrFlexL} \mu^T (h) {}^E \mathbf{v}_{Row}^T (h) \cdot {}^E \mathbf{v}_{Col}^T (h)dh - YawBrMass {}^E \mathbf{v}_{Row}^O \cdot {}^E \mathbf{v}_{Col}^O \quad (Row, Col = 1, 2, \ldots, 10)\tag{3}
|
||||
$$
|
||||
$$
|
||||
\left\{ - f(\dot{q},q,t) \right\} \Big|_T (Row) = - \int_0^{TwrFlexL} \mu^T (h) {}^E \mathbf{v}_{Row}^T (h) \cdot \left( \sum_{i=4}^{10} \frac{d}{dt} \left[ {}^E \mathbf{v}_i^T (h) \right] \dot{q}_i \right) dh - YawBrMass {}^E \mathbf{v}_{Row}^O \cdot \left[ \sum_{i=4}^{10} \frac{d}{dt} \left( {}^E \mathbf{v}_i^O \right) \dot{q}_i \right] \quad (Row = 1,2,\ldots,10)\tag{4}
|
||||
$$
|
||||
|
||||
### 2. 广义弹性力 (Generalized Elastic Forces)
|
||||
|
||||
广义弹性力 $F_{r \Big| ElasticT}$ 是通过对弹性势能 $V'^T$ 求偏导得到的:
|
||||
$$
|
||||
F_{r \Big| ElasticT} = - \frac{\partial V'^T}{\partial q_r} \quad (r = 1,2,\ldots,22)\tag{5}
|
||||
$$
|
||||
具体形式如下,其中考虑了塔架前后 (TFA) 和侧向 (TSS) 的两个模态:
|
||||
$$
|
||||
F_{r \Big| ElasticT} = \left\{
|
||||
\begin{array}{ll}
|
||||
-k_{11}^{'TFA} q_{TFA1} - k_{12}^{'TFA} q_{TFA2} & \text{for } r=TFA1 \\
|
||||
-k_{11}^{'TSS} q_{TSS1} - k_{12}^{'TSS} q_{TSS2} & \text{for } r=TSS1 \\
|
||||
-k_{21}^{'TFA} q_{TFA1} - k_{22}^{'TFA} q_{TFA2} & \text{for } r=TFA2 \\
|
||||
-k_{21}^{'TSS} q_{TSS1} - k_{22}^{'TSS} q_{TSS2} & \text{for } r=TSS2 \\
|
||||
0 & \text{otherwise}
|
||||
\end{array}
|
||||
\right.\tag{6}
|
||||
$$
|
||||
其中,$k_{\ i j}^{\,\prime T F A}$ 和 $k_{{i j}}^{\,\prime{T S S}}$ 分别是塔架在前后和侧向方向上的广义刚度,不包括重力去刚化效应。它们通过积分形式定义:
|
||||
$$
|
||||
k_{ij}^{'TFA} = \sqrt{FAStTunr(i) FAStTunr(j)} \int_0^{TwrFlexL} EI^{TFA}(h) \frac{d^2 \phi_i^{TFA}(h)}{dh^2} \frac{d^2 \phi_j^{TFA}(h)}{dh^2} dh \quad (i, j = 1,2) \text{ (which is symmetric)}\tag{7}
|
||||
$$
|
||||
其中,$EI^{TFA}(h)$ 是调整后的塔架前后方向的弯曲刚度:
|
||||
$$
|
||||
EI^{TFA}(h) = AdjFASt \cdot TwFAStif(h)\tag{8}
|
||||
$$
|
||||
类似地,侧向的广义刚度为:
|
||||
$$
|
||||
k_{ij}^{'TSS} = \sqrt{SSStTunr(i) SSStTunr(j)} \int_0^{TwrFlexL} EI^{TSS}(h) \frac{d^2 \phi_i^{TSS}(h)}{dh^2} \frac{d^2 \phi_j^{TSS}(h)}{dh^2} dh \quad (i, j = 1,2) \text{ (which is symmetric)}\tag{9}
|
||||
$$
|
||||
其中,$EI^{TSS}(h)$ 是调整后的塔架侧向的弯曲刚度:
|
||||
$$
|
||||
EI^{TSS}(h) = AdjSSSt \cdot TwSSStif(h)\tag{10}
|
||||
$$
|
||||
这些广义刚度中的积分系数代表了各个模态刚度调谐,允许用户在各个模态之间改变塔的刚度,从而更好地匹配塔的固有频率。
|
||||
|
||||
对于弹性力,质量矩阵 $[C(q,t)]|_{\text{Elastic}T}$ 为零,非线性惯性力项 $\{-f(\dot{q},q,t)\}|_{\text{Elastic}T}$ 包含了弹性力项:
|
||||
$$
|
||||
[C(q,t)]|_{\text{Elastic}T} = 0\tag{15}
|
||||
$$
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Elastic}T} = \begin{Bmatrix}
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
-k_{11}^{'TFA} q_{TFA1} - k_{12}^{'TFA} q_{TFA2} \\
|
||||
-k_{11}^{'TSS} q_{TSS1} - k_{12}^{'TSS} q_{TSS2} \\
|
||||
-k_{21}^{'TFA} q_{TFA1} - k_{22}^{'TFA} q_{TFA2} \\
|
||||
-k_{21}^{'TSS} q_{TSS1} - k_{22}^{'TSS} q_{TSS2} \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\end{Bmatrix}\tag{16}
|
||||
$$
|
||||
|
||||
### 3. 广义阻尼力 (Generalized Damping Forces)
|
||||
|
||||
当使用瑞利阻尼技术,假设阻尼与刚度成比例时,广义阻尼力 $F_r |_{\text{Damp}T}$ 表示为:
|
||||
$$
|
||||
F_r |_{\text{Damp}T} = \begin{cases}
|
||||
- \frac{\zeta_1^{TFA} k_{11}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{12}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} & \text{for } r=TFA1 \\
|
||||
- \frac{\zeta_1^{TSS} k_{11}^{'TSS}}{\pi f_1^{'TSS}} \dot{q}_{TSS1} - \frac{\zeta_2^{TSS} k_{12}^{'TSS}}{\pi f_2^{'TSS}} \dot{q}_{TSS2} & \text{for } r=TSS1 \\
|
||||
- \frac{\zeta_1^{TFA} k_{21}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{22}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} & \text{for } r=TFA2 \\
|
||||
- \frac{\zeta_1^{TSS} k_{21}^{'TSS}}{\pi f_1^{'TSS}} \dot{q}_{TSS1} - \frac{\zeta_2^{TSS} k_{22}^{'TSS}}{\pi f_2^{'TSS}} \dot{q}_{TSS2} & \text{for } r=TSS2 \\
|
||||
0 & \text{otherwise}
|
||||
\end{cases}\tag{11}
|
||||
$$
|
||||
其中,$\zeta_{i}^{T F A}$ 和 $\zeta_{i}^{T S S}$ 分别表示塔架在前后向和侧向上的结构阻尼比,而 $f_{\ i}^{\,\prime T F A}$ 和 $f_{\ i}^{\prime T S S}$ 分别表示塔架在前后向和侧向上的固有频率,不考虑塔顶质量和重力软化效应。这些固有频率定义为:
|
||||
$$
|
||||
f_{\;\;i}^{\;\prime^{T F A}}=\frac{1}{2\pi}\sqrt{\frac{k_{\;i i}^{\prime^{T F A}}}{m_{\;i i}^{\prime^{T F A}}}}\;\;\;\;\;\mathrm{and}\;\;\;\;\;\;\;f_{\;i}^{\;\prime^{T S S}}=\frac{1}{2\pi}\sqrt{\frac{k_{\;i i}^{\prime T S S}}{m_{\;i i}^{\prime T S S}}}\tag{12}
|
||||
$$
|
||||
这里,$m_{\;i i}^{\;\prime T F A}$ 和 $m_{\ i i}^{\prime T S S}$ 分别表示在塔顶质量效应忽略的情况下,第 $i$ 阶模态在前后方向和左右方向上的广义质量:
|
||||
$$
|
||||
m_{\ i j}^{\prime^{T F A}}=\int_{0}^{T w r F l e x L}\mu^{T}\left(h\right)\phi_{i}^{T F A}\left(h\right)\phi_{j}^{T F A}\left(h\right)d h\quad\left(i,j=1,2\right)\tag{13}
|
||||
$$
|
||||
$$
|
||||
m_{\it i j}^{\prime T S S}=\int_{0}^{T w r F l e x L}\mu^{T}\left(h\right)\phi_{i}^{T S S}\left(h\right)\phi_{j}^{T S S}\left(h\right)d h\quad\left(i,j=1,2\right)\tag{14}
|
||||
$$
|
||||
对于阻尼力,质量矩阵 $[C(q,t)]|_{\text{Damp}T}$ 为零,非线性惯性力项 $\{-f(\dot{q},q,t)\}|_{\text{Damp}T}$ 包含了阻尼力项:
|
||||
$$
|
||||
[C(q,t)]|_{\text{Damp}T} = 0\tag{17}
|
||||
$$
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Damp}T} = \begin{Bmatrix}
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
- \frac{\zeta_1^{TFA} k_{11}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{12}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} \\
|
||||
- \frac{\zeta_1^{TSS} k_{11}^{'TSS}}{\pi f_1^{'TSS}} \dot{q}_{TSS1} - \frac{\zeta_2^{TSS} k_{12}^{'TSS}}{\pi f_2^{'TSS}} \dot{q}_{TSS2} \\
|
||||
- \frac{\zeta_1^{TFA} k_{21}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{22}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} \\
|
||||
- \frac{\zeta_1^{TSS} k_{21}^{'TSS}}{\pi f_1^{'TSS}} \dot{q}_{TSS1} - \frac{\zeta_2^{TSS} k_{22}^{'TSS}}{\pi f_2^{'TSS}} \dot{q}_{TSS2} \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots
|
||||
\end{Bmatrix}\tag{18}
|
||||
$$
|
||||
|
||||
### 4. 广义重力 (Generalized Gravitational Forces)
|
||||
|
||||
广义重力 $F_r |_{\text{Grav}T}$ 考虑了塔架自身的重力以及偏航轴承的重力:
|
||||
$$
|
||||
F_r |_{\text{Grav}T} = \int_{0}^{\text{TwrFlexL}} \! {}^E \mathbf{v}_r^T(h) \cdot [-\mu^T(h) \mathbf{g}\mathbf{z}_2] \, dh + {}^E \mathbf{v}_r^O \cdot (-\text{YawBrMass} \cdot \mathbf{g}\mathbf{z}_2) \quad (r=3,4,...,10)\tag{19}
|
||||
$$
|
||||
其中,$\mathbf{g}$ 是重力加速度,$\mathbf{z}_2$ 是垂直方向的单位向量。
|
||||
|
||||
对于重力,质量矩阵 $[C(q,t)]|_{\text{Grav}T}$ 为零,非线性惯性力项 $\{-f(\dot{q},q,t)\}|_{\text{Grav}T}$ 包含了重力项:
|
||||
$$
|
||||
[C(q,t)]|_{\text{Grav}T} = 0\tag{20}
|
||||
$$
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Grav}T} (\text{Row}) = - \int_{0}^{\text{TwrFlexL}} \! \mu^T(h) g {}^E \mathbf{v}_{\text{Row}}^T(h) \cdot \mathbf{z}_2 \, dh - \text{YawBrMass} \cdot g {}^E \mathbf{v}_{\text{Row}}^O \cdot \mathbf{z}_2 \quad (Row=3,4,...,10)\tag{21}
|
||||
$$
|
||||
|
||||
### 5. 广义气动力 (Generalized Aerodynamic Forces)
|
||||
|
||||
广义气动力 $F_r |_{\text{Aero}T}$ 是通过对塔架上每单位高度的气动力 $\mathbf{F}_{\text{Aero}T}^T(h)$ 和气动弯矩 $\mathbf{M}_{\text{Aero}T}^F(h)$ 进行积分得到的:
|
||||
$$
|
||||
F_r |_{\text{Aero}T} = \int_{0}^{\text{TwrFlexL}} \! \left[ {}^E \mathbf{v}_r^T(h) \cdot \mathbf{F}_{\text{Aero}T}^T(h) + {}^E \boldsymbol{\omega}_r^F(h) \cdot \mathbf{M}_{\text{Aero}T}^F(h) \right] dh \quad (r=1,2,...,10)\tag{22}
|
||||
$$
|
||||
其中,$F_{A e r o T}^{T}\left(h\right)$ 和 $M_{A e r o T}^{F}\left(h\right)$ 分别是施加在塔架上点 T 的每单位高度的气动力和气动弯矩。
|
||||
|
||||
对于气动力,质量矩阵 $[C(q,t)]|_{\text{Aero}T}$ 为零,非线性惯性力项 $\{-f(\dot{q},q,t)\}|_{\text{Aero}T}$ 包含了气动力项:
|
||||
$$
|
||||
[C(q,t)]|_{\text{Aero}T} = 0\tag{23}
|
||||
$$
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Aero}T} (\text{Row}) = \int_{0}^{\text{TwrFlexL}} \! \left[ {}^E \mathbf{v}_{\text{Row}}^T(h) \cdot \mathbf{F}_{\text{Aero}T}^T(h) + {}^E \boldsymbol{\omega}_{\text{Row}}^F(h) \cdot \mathbf{M}_{\text{Aero}T}^F(h) \right] dh \quad (Row=1,2,...,10)\tag{24}
|
||||
$$
|
||||
|
||||
这些公式共同构成了基于凯恩方程原理的塔架动力学模型,通过广义力来描述塔架在各种载荷下的响应。
|
||||
[Timestamp: 2026/01/09 15:21:18]
|
||||
|
||||
**user**: [[Tower]][[FillAugmat]]结合理论和代码,解释塔架部分是如何计算的
|
||||
[Timestamp: 2026/01/12 11:25:11]
|
||||
|
||||
**ai**: 好的,我们来结合[[Tower]]笔记中的理论和[[FillAugmat]]子程序中的代码,解释塔架部分是如何计算的。
|
||||
|
||||
在OpenFAST动力学模型中,塔架被视为一个柔性体,其运动通过广义坐标来描述。[[Tower]]笔记详细推导了塔架的广义惯性力、弹性力、阻尼力、重力和气动力。[[FillAugmat]]子程序则负责将这些力项和质量项组装到增广矩阵 `AugMat` 中,该矩阵用于求解系统的动力学方程。
|
||||
|
||||
### 理论回顾 (来自 [[Tower]] 笔记)
|
||||
|
||||
塔架的动力学方程可以表示为广义质量矩阵 $[C(\mathbf{q},t)]$ 乘以广义加速度 $\ddot{\mathbf{q}}$,加上广义力 $\{-f(\dot{q},q,t)\}$ 等于零的形式。
|
||||
|
||||
1. **广义惯性力 ($F_r^* \Big|_T$)**:
|
||||
这是由塔架分布式质量和偏航轴承质量引起的。
|
||||
* **质量矩阵项**:
|
||||
$$
|
||||
[C(\mathbf{q},t)]_T (Row, Col) = \int_0^{TwrFlexL} \mu^T (h) {}^E \mathbf{v}_{Row}^T (h) \cdot {}^E \mathbf{v}_{Col}^T (h)dh - YawBrMass {}^E \mathbf{v}_{Row}^O \cdot {}^E \mathbf{v}_{Col}^O \quad (Row, Col = 1, 2, \ldots, 10)\tag{3}
|
||||
$$
|
||||
其中 $\mu^T(h)$ 是调整后的塔架质量密度,${}^E \mathbf{v}_{Row}^T (h)$ 和 ${}^E \mathbf{v}_{Col}^T (h)$ 是塔架上点的广义速度,${}^E \mathbf{v}_{Row}^O$ 和 ${}^E \mathbf{v}_{Col}^O$ 是偏航轴承处的广义速度。
|
||||
* **非线性惯性力项**:
|
||||
$$
|
||||
\left\{ - f(\dot{q},q,t) \right\} \Big|_T (Row) = - \int_0^{TwrFlexL} \mu^T (h) {}^E \mathbf{v}_{Row}^T (h) \cdot \left( \sum_{i=4}^{10} \frac{d}{dt} \left[ {}^E \mathbf{v}_i^T (h) \right] \dot{q}_i \right) dh - YawBrMass {}^E \mathbf{v}_{Row}^O \cdot \left[ \sum_{i=4}^{10} \frac{d}{dt} \left( {}^E \mathbf{v}_i^O \right) \dot{q}_i \right] \quad (Row = 1,2,\ldots,10)\tag{4}
|
||||
$$
|
||||
这部分包含了科里奥利力和离心力等速度相关的非线性项。
|
||||
|
||||
2. **广义弹性力 ($F_{r \Big| ElasticT}$)**:
|
||||
由塔架的弹性变形引起,与广义坐标 $q_r$ 相关。
|
||||
$$
|
||||
F_{r \Big| ElasticT} = - \frac{\partial V'^T}{\partial q_r} \quad (r = 1,2,\ldots,22)\tag{5}
|
||||
$$
|
||||
具体形式为:
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Elastic}T} = \begin{Bmatrix}
|
||||
\vdots \\
|
||||
-k_{11}^{'TFA} q_{TFA1} - k_{12}^{'TFA} q_{TFA2} \\
|
||||
-k_{11}^{'TSS} q_{TSS1} - k_{12}^{'TSS} q_{TSS2} \\
|
||||
-k_{21}^{'TFA} q_{TFA1} - k_{22}^{'TFA} q_{TFA2} \\
|
||||
-k_{21}^{'TSS} q_{TSS1} - k_{22}^{'TSS} q_{TSS2} \\
|
||||
\vdots
|
||||
\end{Bmatrix}\tag{16}
|
||||
$$
|
||||
其中 $k_{ij}^{'TFA}$ 和 $k_{ij}^{'TSS}$ 是广义刚度系数。
|
||||
|
||||
3. **广义阻尼力 ($F_r |_{\text{Damp}T}$)**:
|
||||
假设阻尼与刚度成比例(瑞利阻尼),与广义速度 $\dot{q}_r$ 相关。
|
||||
$$
|
||||
F_r |_{\text{Damp}T} = \begin{cases}
|
||||
- \frac{\zeta_1^{TFA} k_{11}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{12}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} & \text{for } r=TFA1 \\
|
||||
\vdots
|
||||
\end{cases}\tag{11}
|
||||
$$
|
||||
具体形式为:
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Damp}T} = \begin{Bmatrix}
|
||||
\vdots \\
|
||||
- \frac{\zeta_1^{TFA} k_{11}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{12}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} \\
|
||||
\vdots
|
||||
\end{Bmatrix}\tag{18}
|
||||
$$
|
||||
|
||||
4. **广义重力 ($F_r |_{\text{Grav}T}$)**:
|
||||
由塔架自身质量和偏航轴承质量在重力场中的作用引起。
|
||||
$$
|
||||
F_r |_{\text{Grav}T} = \int_{0}^{\text{TwrFlexL}} \! {}^E \mathbf{v}_r^T(h) \cdot [-\mu^T(h) \mathbf{g}\mathbf{z}_2] \, dh + {}^E \mathbf{v}_r^O \cdot (-\text{YawBrMass} \cdot \mathbf{g}\mathbf{z}_2) \quad (r=3,4,...,10)\tag{19}
|
||||
$$
|
||||
对应的非线性惯性力项为:
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Grav}T} (\text{Row}) = - \int_{0}^{\text{TwrFlexL}} \! \mu^T(h) g {}^E \mathbf{v}_{\text{Row}}^T(h) \cdot \mathbf{z}_2 \, dh - \text{YawBrMass} \cdot g {}^E \mathbf{v}_{\text{Row}}^O \cdot \mathbf{z}_2 \quad (Row=3,4,...,10)\tag{21}
|
||||
$$
|
||||
|
||||
5. **广义气动力 ($F_r |_{\text{Aero}T}$)**:
|
||||
由作用在塔架上的气动力和气动弯矩引起。
|
||||
$$
|
||||
F_r |_{\text{Aero}T} = \int_{0}^{\text{TwrFlexL}} \! \left[ {}^E \mathbf{v}_r^T(h) \cdot \mathbf{F}_{\text{Aero}T}^T(h) + {}^E \boldsymbol{\omega}_r^F(h) \cdot \mathbf{M}_{\text{Aero}T}^F(h) \right] dh \quad (r=1,2,...,10)\tag{22}
|
||||
$$
|
||||
对应的非线性惯性力项为:
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Aero}T} (\text{Row}) = \int_{0}^{\text{TwrFlexL}} \! \left[ {}^E \mathbf{v}_{\text{Row}}^T(h) \cdot \mathbf{F}_{\text{Aero}T}^T(h) + {}^E \boldsymbol{\omega}_{\text{Row}}^F(h) \cdot \mathbf{M}_{\text{Aero}T}^F(h) \right] dh \quad (Row=1,2,...,10)\tag{24}
|
||||
$$
|
||||
|
||||
### 代码实现 (来自 [[FillAugmat]] 子程序)
|
||||
|
||||
`FillAugMat` 子程序的目标是构建增广矩阵 `AugMat`。这个矩阵的结构通常是左上角为质量矩阵 $[M]$,右侧为力向量 $[F]$,即 `[M | F]`。在OpenFAST中,它实际上是 `[C(q,t) | -f(qd,q,t)]` 的形式,其中 `C(q,t)` 是广义质量矩阵,`-f(qd,q,t)` 是广义力向量。
|
||||
|
||||
我们重点关注塔架相关的计算部分:
|
||||
|
||||
1. **初始化 `AugMat`**:
|
||||
```fortran
|
||||
AugMat = 0.0
|
||||
```
|
||||
在开始计算之前,`AugMat` 被初始化为零。
|
||||
|
||||
2. **偏航轴承质量效应 (Yaw Bearing Mass Effects)**:
|
||||
这部分对应于[[Tower]]笔记中公式 (3) 和 (4) 中与 `YawBrMass` 相关的项。
|
||||
```fortran
|
||||
DO L = 1,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O)
|
||||
DO I = L,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs greater than or equal to L
|
||||
AugMat(p%DOFs%PTTE(I),p%DOFs%PTTE(L)) = p%YawBrMass*DOT_PRODUCT( RtHSdat%PLinVelEO(p%DOFs%PTTE(I),0,:), & ! [C(q,t)]T of YawBrMass
|
||||
RtHSdat%PLinVelEO(p%DOFs%PTTE(L),0,:) )
|
||||
ENDDO ! I - All active (enabled) tower DOFs greater than or equal to L
|
||||
ENDDO ! L - All active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O)
|
||||
|
||||
TmpVec1 = -p%YawBrMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEOt ) ! The portion of FrcT0Trbt associated with the YawBrMass
|
||||
DO I = 1,p%DOFs%NPTTE ! Loop through all active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O)
|
||||
AugMat(p%DOFs%PTTE(I), p%NAug) = DOT_PRODUCT( RtHSdat%PLinVelEO(p%DOFs%PTTE(I),0,:), & ! {-f(qd,q,t)}T + {-f(qd,q,t)}GravT of YawBrMass
|
||||
TmpVec1 ) ! NOTE: TmpVec1 is still the portion of FrcT0Trbt associated with YawBrMass
|
||||
ENDDO ! I - All active (enabled) tower DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing (point O)
|
||||
```
|
||||
* `p%DOFs%NPTTE` 是塔架自由度的数量。
|
||||
* `p%YawBrMass` 是偏航轴承质量。
|
||||
* `RtHSdat%PLinVelEO` 是偏航轴承点 O 的广义速度偏导数,用于计算质量矩阵项。
|
||||
* `RtHSdat%LinAccEOt` 是偏航轴承点 O 的线性加速度,用于计算非线性惯性力项(包括重力)。
|
||||
* `p%NAug` 是增广矩阵的最后一列,用于存储力向量。
|
||||
* `TmpVec1` 包含了偏航轴承的重力 (`p%Gravity*CoordSys%z2`) 和非线性惯性力 (`RtHSdat%LinAccEOt`)。
|
||||
|
||||
3. **塔架分布式质量、重力、气动力和水动力效应**:
|
||||
这部分对应于[[Tower]]笔记中公式 (3), (4), (19), (21), (22), (24) 中与塔架分布式质量相关的积分项。
|
||||
```fortran
|
||||
DO J = 1,p%TwrNodes
|
||||
! ... (计算质量矩阵项)
|
||||
DO L = 1,p%DOFs%NPTTE
|
||||
DO I = L,p%DOFs%NPTTE
|
||||
AugMat(p%DOFs%PTTE(I),p%DOFs%PTTE(L)) = AugMat(p%DOFs%PTTE(I),p%DOFs%PTTE(L)) &
|
||||
+ p%TElmntMass(J) *DOT_PRODUCT( RtHSdat%PLinVelET(J,p%DOFs%PTTE(I),0,:), &
|
||||
RtHSdat%PLinVelET(J,p%DOFs%PTTE(L),0,:) ) & ! [C(q,t)]T + [C(q,t)]HydroT
|
||||
- abs(p%DHNodes(J))*DOT_PRODUCT( RtHSdat%PLinVelET(J,p%DOFs%PTTE(I),0,:), &
|
||||
RtHSdat%PFTHydro (:,J,p%DOFs%PTTE(L) ) ) &
|
||||
- abs(p%DHNodes(J))*DOT_PRODUCT( RtHSdat%PAngVelEF(J,p%DOFs%PTTE(I),0,:), &
|
||||
RtHSdat%PMFHydro (:,J,p%DOFs%PTTE(L) ) )
|
||||
ENDDO
|
||||
ENDDO
|
||||
|
||||
! ... (计算力向量项)
|
||||
TmpVec1 = ( RtHSdat%FTHydrot(:,J) )*abs(p%DHNodes(J)) &
|
||||
- p%TElmntMass(J)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccETt(:,J) ) ! The portion of FrcT0Trbt associated with tower element J
|
||||
TmpVec3 = ( RtHSdat%MFHydrot(:,J) )*abs(p%DHNodes(J)) ! The external moment applied to tower element J
|
||||
DO I = 1,p%DOFs%NPTTE
|
||||
AugMat(p%DOFs%PTTE(I), p%NAug) = AugMat(p%DOFs%PTTE(I), p%NAug) & ! {-f(qd,q,t)}T + {-f(qd,q,t)}GravT + {-f(qd,q,t)}AeroT + {-f(qd,q,t)}HydroT
|
||||
+ DOT_PRODUCT( RtHSdat%PLinVelET(J,p%DOFs%PTTE(I),0,:), TmpVec1 ) & ! NOTE: TmpVec1 is still the portion of FrcT0Trbt associated with tower element J
|
||||
+ DOT_PRODUCT( RtHSdat%PAngVelEF(J,p%DOFs%PTTE(I),0,:), TmpVec3 )
|
||||
ENDDO
|
||||
ENDDO
|
||||
```
|
||||
* `p%TwrNodes` 是塔架离散化的节点数量。
|
||||
* `p%TElmntMass(J)` 是第 `J` 个塔架单元的质量。
|
||||
* `RtHSdat%PLinVelET(J,...)` 和 `RtHSdat%PAngVelEF(J,...)` 是塔架单元 `J` 的广义速度偏导数,用于计算质量矩阵项。
|
||||
* `RtHSdat%FTHydrot(:,J)` 和 `RtHSdat%MFHydrot(:,J)` 是作用在塔架单元 `J` 上的水动力和水动弯矩。
|
||||
* `RtHSdat%LinAccETt(:,J)` 是塔架单元 `J` 的线性加速度,用于计算非线性惯性力项(包括重力)。
|
||||
* `TmpVec1` 包含了塔架单元的重力、非线性惯性力以及水动力。
|
||||
* `TmpVec3` 包含了水动弯矩。
|
||||
* 这里还包含了水动力学项 `[C(q,t)]HydroT` 和 `{-f(qd,q,t)}HydroT`,这在[[Tower]]笔记中没有直接列出,但在OpenFAST中是塔架受力的一部分。
|
||||
|
||||
4. **塔架弹性力和阻尼力**:
|
||||
这部分对应于[[Tower]]笔记中公式 (16) 和 (18) 中的弹性力和阻尼力项。
|
||||
```fortran
|
||||
IF ( p%DOF_Flag(DOF_TFA1) ) THEN
|
||||
AugMat( DOF_TFA1,p%NAug) = AugMat(DOF_TFA1,p%NAug) &
|
||||
- p%KTFA(1,1)*x%QT( DOF_TFA1) - p%KTFA(1,2)*x%QT( DOF_TFA2) & !
|
||||
- p%CTFA(1,1)*x%QDT(DOF_TFA1) - p%CTFA(1,2)*x%QDT(DOF_TFA2)
|
||||
ENDIF
|
||||
IF ( p%DOF_Flag(DOF_TSS1) ) THEN
|
||||
AugMat( DOF_TSS1,p%NAug) = AugMat(DOF_TSS1,p%NAug) &
|
||||
- p%KTSS(1,1)*x%QT( DOF_TSS1) - p%KTSS(1,2)*x%QT( DOF_TSS2) & ! {-f(qd,q,t)}ElasticT + {-f(qd,q,t)}DampT
|
||||
- p%CTSS(1,1)*x%QDT(DOF_TSS1) - p%CTSS(1,2)*x%QDT(DOF_TSS2)
|
||||
ENDIF
|
||||
IF ( p%DOF_Flag(DOF_TFA2) ) THEN
|
||||
AugMat( DOF_TFA2,p%NAug) = AugMat(DOF_TFA2,p%NAug) &
|
||||
- p%KTFA(2,1)*x%QT( DOF_TFA1) - p%KTFA(2,2)*x%QT( DOF_TFA2) & !
|
||||
- p%CTFA(2,1)*x%QDT(DOF_TFA1) - p%CTFA(2,2)*x%QDT(DOF_TFA2)
|
||||
ENDIF
|
||||
IF ( p%DOF_Flag(DOF_TSS2) ) THEN
|
||||
AugMat( DOF_TSS2,p%NAug) = AugMat(DOF_TSS2,p%NAug) &
|
||||
- p%KTSS(2,1)*x%QT( DOF_TSS1) - p%KTSS(2,2)*x%QT( DOF_TSS2) & !
|
||||
- p%CTSS(2,1)*x%QDT(DOF_TSS1) - p%CTSS(2,2)*x%QDT(DOF_TSS2)
|
||||
ENDIF
|
||||
```
|
||||
* `p%DOF_Flag(DOF_TFA1)` 等检查塔架前后 (TFA) 和侧向 (TSS) 模态的自由度是否启用。
|
||||
* `p%KTFA`, `p%KTSS` 是塔架的广义刚度矩阵,对应于[[Tower]]笔记中的 $k_{ij}^{'TFA}$ 和 $k_{ij}^{'TSS}$。
|
||||
* `p%CTFA`, `p%CTSS` 是塔架的广义阻尼矩阵,对应于[[Tower]]笔记中阻尼力公式中的系数。
|
||||
* `x%QT` 是广义坐标 $q$,`x%QDT` 是广义速度 $\dot{q}$。
|
||||
* 这些项直接添加到 `AugMat` 的力向量列 (`p%NAug`) 中。
|
||||
|
||||
5. **其他自由度与塔架的耦合**:
|
||||
在 `FillAugMat` 的后续部分,还有许多 `IF ( p%DOF_Flag (...) ) THEN ... ENDIF` 块,它们处理不同自由度(如平台运动 DOF_Sg, DOF_Sw, DOF_Hv, DOF_R, DOF_P, DOF_Y,以及偏航 DOF_Yaw 等)与塔架的耦合。这些耦合项通过 `DOT_PRODUCT` 广义速度偏导数和广义力/力矩偏导数来计算,并添加到 `AugMat` 中。例如:
|
||||
```fortran
|
||||
IF ( p%DOF_Flag (DOF_TFA1) ) THEN
|
||||
DO I = p%DOFs%Diag(DOF_TFA1),p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs on or below the diagonal
|
||||
AugMat(p%DOFs%SrtPS(I),DOF_TFA1) = AugMat(p%DOFs%SrtPS(I),DOF_TFA1) &
|
||||
- DOT_PRODUCT( RtHSdat%PLinVelEO(DOF_TFA1,0,:), &
|
||||
RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) & ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A
|
||||
- DOT_PRODUCT( RtHSdat%PAngVelEB(DOF_TFA1,0,:), &
|
||||
RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) )
|
||||
ENDDO
|
||||
! ... (力向量项)
|
||||
ENDIF
|
||||
```
|
||||
这部分代码计算了塔架自由度 (DOF_TFA1) 与其他自由度之间的耦合质量项和力项。`RtHSdat%PLinVelEO` 和 `RtHSdat%PAngVelEB` 是不同参考点(O点,B点)的广义速度偏导数,`RtHSdat%PFrcONcRt` 和 `RtHSdat%PMomBNcRt` 是广义力/力矩的偏导数。
|
||||
|
||||
6. **对称性填充**:
|
||||
```fortran
|
||||
DO L = 2,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs above the diagonal (columns)
|
||||
DO I = 1,L-1 ! Loop through all active (enabled) DOFs above the diagonal (rows)
|
||||
AugMat(p%DOFs%SrtPS(I),p%DOFs%SrtPS(L)) = AugMat(p%DOFs%SrtPS(L),p%DOFs%SrtPS(I))
|
||||
ENDDO ! I - All active (enabled) DOFs above the diagonal (rows)
|
||||
ENDDO ! L - All active (enabled) DOFs above the diagonal (columns)
|
||||
```
|
||||
由于质量矩阵在添加齿轮箱摩擦项之前是(或近似)对称的,这部分代码通过镜像对角线以下的元素来填充对角线以上的元素,从而提高计算效率。
|
||||
|
||||
### 总结
|
||||
|
||||
[[Tower]]笔记提供了塔架动力学建模的理论基础,通过凯恩方程推导了塔架在各种载荷下的广义力表达式。这些表达式包含了塔架的惯性、弹性、阻尼、重力和气动特性。
|
||||
|
||||
[[FillAugmat]]子程序则将这些理论公式转化为实际的数值计算。它通过遍历塔架的离散化单元和自由度,计算出对应的广义质量矩阵项和广义力向量项,并将它们组装到增广矩阵 `AugMat` 中。这个过程涉及对广义速度偏导数、广义加速度、质量密度、刚度、阻尼系数以及外部载荷(如重力、气动力、水动力)的数值积分和点积运算。最终形成的 `AugMat` 矩阵是求解整个风力机系统动力学方程的关键输入。
|
||||
[Timestamp: 2026/01/12 11:25:40]
|
||||
|
||||
**user**: [[Tower]][[CalculateForcesMoments]]结合理论和代码,解释塔架部分是如何计算的
|
||||
[Timestamp: 2026/01/12 16:16:07]
|
||||
|
||||
**ai**: 好的,我们来结合[[Tower]]笔记中的理论和[[CalculateForcesMoments]]子程序中的代码,解释塔架部分是如何计算的。
|
||||
|
||||
`CalculateForcesMoments` 子程序的主要目的是计算风力机各个部件(包括塔架)上的力和力矩,并将这些结果存储在 `RtHSdat` 结构体中。这些力和力矩包括广义惯性力、弹性力、阻尼力、重力、气动力和水动力等。这些计算结果随后会被 `FillAugmat` 子程序用来构建系统的增广矩阵。
|
||||
|
||||
### 理论回顾 (来自 [[Tower]] 笔记)
|
||||
|
||||
[[Tower]]笔记详细推导了塔架的广义惯性力、弹性力、阻尼力、重力和气动力。这些力通常表示为对广义坐标或广义速度的函数,并且在动力学方程中作为力向量的一部分。
|
||||
|
||||
* **广义惯性力 ($F_r^* \Big|_T$)**: 包含质量项和非线性惯性力项。在 `CalculateForcesMoments` 中,主要计算的是非线性惯性力项,即与加速度无关的速度相关项。
|
||||
* 非线性惯性力项:
|
||||
$$
|
||||
\left\{ - f(\dot{q},q,t) \right\} \Big|_T (Row) = - \int_0^{TwrFlexL} \mu^T (h) {}^E \mathbf{v}_{Row}^T (h) \cdot \left( \sum_{i=4}^{10} \frac{d}{dt} \left[ {}^E \mathbf{v}_i^T (h) \right] \dot{q}_i \right) dh - YawBrMass {}^E \mathbf{v}_{Row}^O \cdot \left[ \sum_{i=4}^{10} \frac{d}{dt} \left( {}^E \mathbf{v}_i^O \right) \dot{q}_i \right] \quad (Row = 1,2,\ldots,10)\tag{4}
|
||||
$$
|
||||
* **广义弹性力 ($F_{r \Big| ElasticT}$)**: 与广义坐标 $q_r$ 相关。
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Elastic}T} = \begin{Bmatrix}
|
||||
\vdots \\
|
||||
-k_{11}^{'TFA} q_{TFA1} - k_{12}^{'TFA} q_{TFA2} \\
|
||||
\vdots
|
||||
\end{Bmatrix}\tag{16}
|
||||
$$
|
||||
* **广义阻尼力 ($F_r |_{\text{Damp}T}$)**: 与广义速度 $\dot{q}_r$ 相关。
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Damp}T} = \begin{Bmatrix}
|
||||
\vdots \\
|
||||
- \frac{\zeta_1^{TFA} k_{11}^{'TFA}}{\pi f_1^{'TFA}} \dot{q}_{TFA1} - \frac{\zeta_2^{TFA} k_{12}^{'TFA}}{\pi f_2^{'TFA}} \dot{q}_{TFA2} \\
|
||||
\vdots
|
||||
\end{Bmatrix}\tag{18}
|
||||
$$
|
||||
* **广义重力 ($F_r |_{\text{Grav}T}$)**:
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Grav}T} (\text{Row}) = - \int_{0}^{\text{TwrFlexL}} \! \mu^T(h) g {}^E \mathbf{v}_{\text{Row}}^T(h) \cdot \mathbf{z}_2 \, dh - \text{YawBrMass} \cdot g {}^E \mathbf{v}_{\text{Row}}^O \cdot \mathbf{z}_2 \quad (Row=3,4,...,10)\tag{21}
|
||||
$$
|
||||
* **广义气动力 ($F_r |_{\text{Aero}T}$)**:
|
||||
$$
|
||||
\{-f(\dot{q},q,t)\}|_{\text{Aero}T} (\text{Row}) = \int_{0}^{\text{TwrFlexL}} \! \left[ {}^E \mathbf{v}_{\text{Row}}^T(h) \cdot \mathbf{F}_{\text{Aero}T}^T(h) + {}^E \boldsymbol{\omega}_{\text{Row}}^F(h) \cdot \mathbf{M}_{\text{Aero}T}^F(h) \right] dh \quad (Row=1,2,...,10)\tag{24}
|
||||
$$
|
||||
|
||||
### 代码实现 (来自 [[CalculateForcesMoments]] 子程序)
|
||||
|
||||
`CalculateForcesMoments` 子程序计算并存储了各种“部分力”和“总力”,这些力是用于后续组装增广矩阵的中间结果。对于塔架部分,主要涉及以下几个关键计算:
|
||||
|
||||
1. **塔架单元上的水动力和水动弯矩 (PFTHydro, PMFHydro, FTHydrot, MFHydrot)**:
|
||||
这部分计算了作用在塔架每个离散化单元上的水动力和水动弯矩。这些力不仅包括水动力学贡献,还可能包括基础刚度、阻尼或系泊线恢复力等。
|
||||
* **理论**: 这部分在[[Tower]]笔记中没有直接的公式,但在OpenFAST中,水动力学是塔架受力的重要组成部分,尤其对于浮式风力机。它通常通过附加质量、阻尼和恢复力矩阵来建模。
|
||||
* **代码**:
|
||||
```fortran
|
||||
DO J=1,p%TwrNodes
|
||||
RtHSdat%PFTHydro(:,J,:) = 0.0
|
||||
RtHSdat%PMFHydro(:,J,:) = 0.0
|
||||
DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower
|
||||
! ... (计算 PFTHydro 和 PMFHydro,涉及 u%TwrAddedMass 和广义速度偏导数)
|
||||
END DO
|
||||
END DO
|
||||
|
||||
DO J=1,p%TwrNodes
|
||||
! ... (计算 FTHydrot 和 MFHydrot,涉及 u%TowerPtLoads%Force/Moment, u%TwrAddedMass 和线/角加速度)
|
||||
END DO
|
||||
```
|
||||
* `p%TwrNodes` 是塔架的节点数量。
|
||||
* `u%TwrAddedMass` 是塔架的附加质量矩阵,用于计算水动力学惯性力。
|
||||
* `RtHSdat%PLinVelET` 和 `RtHSdat%PAngVelEF` 是塔架单元的广义线速度和角速度的偏导数,用于计算与广义加速度相关的部分力。
|
||||
* `RtHSdat%LinAccETt` 和 `RtHSdat%AngAccEFt` 是塔架单元的线加速度和角加速度,用于计算与广义速度相关的力(科里奥利力、离心力)以及重力。
|
||||
* `u%TowerPtLoads%Force/Moment` 是外部施加在塔架上的点载荷。
|
||||
* `PFTHydro` 和 `PMFHydro` 存储的是与广义加速度相关的部分力/力矩,用于构建质量矩阵。
|
||||
* `FTHydrot` 和 `MFHydrot` 存储的是与广义加速度无关的力/力矩(包括重力、水动力阻尼、恢复力、外部载荷以及非线性惯性力),用于构建力向量。
|
||||
|
||||
2. **偏航轴承处的力和力矩 (PFrcT0Trb, PMomX0Trb, FrcT0Trbt, MomX0Trbt)**:
|
||||
这部分计算了在塔架底部(点 T(0))的力和力矩,包括来自偏航轴承以上所有部件(转子、机舱、尾翼等)以及偏航轴承自身的贡献。
|
||||
* **理论**: 这对应于[[Tower]]笔记中公式 (19) 和 (21) 中与 `YawBrMass` 相关的项,以及来自上部结构的传递载荷。
|
||||
* **代码**:
|
||||
```fortran
|
||||
! ... (初始化 PFrcT0Trb 和 PMomX0Trb 为来自上部结构 (PFrcONcRt, PMomBNcRt) 的贡献)
|
||||
RtHSdat%PFrcT0Trb = RtHSdat%PFrcONcRt
|
||||
RtHSdat%PMomX0Trb = RtHSdat%PMomX0Trb
|
||||
|
||||
DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O)
|
||||
TmpVec1 = -p%YawBrMass*RtHSdat%PLinVelEO(p%DOFs%PTE(I),0,:) ! The portion of PFrcT0Trb associated with the YawBrMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0O, TmpVec1 ) ! The portion of PMomX0Trb associated with the YawBrMass
|
||||
RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I) ) = RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I) ) + TmpVec1
|
||||
RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I) ) = RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I) ) + TmpVec2
|
||||
END DO
|
||||
|
||||
TmpVec1 = -p%YawBrMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEOt ) ! The portion of FrcT0Trbt associated with the YawBrMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0O, TmpVec1 ) ! The portion of MomX0Trbt associated with the YawBrMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rT0O, RtHSdat%FrcONcRtt ) ! The portion of MomX0Trbt associated with the FrcONcRtt
|
||||
RtHSdat%FrcT0Trbt = RtHSdat%FrcONcRtt + TmpVec1
|
||||
RtHSdat%MomX0Trbt = RtHSdat%MomBNcRtt + TmpVec2 + TmpVec3
|
||||
|
||||
DO J=1,p%TwrNodes
|
||||
DO I = 1,p%DOFs%NPTE
|
||||
TmpVec1 = RtHSdat%PFTHydro(:,J,p%DOFs%PTE(I))*abs(p%DHNodes(J)) - p%TElmntMass(J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,:) ! The portion of PFrcT0Trb associated with tower element J
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0T(:,J), TmpVec1 ) ! The portion of PMomX0Trb associated with tower element J
|
||||
TmpVec3 = RtHSdat%PMFHydro(:,J,p%DOFs%PTE(I))*abs(p%DHNodes(J)) ! The added moment applied at tower element J
|
||||
RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I)) = RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I)) + TmpVec1
|
||||
RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I)) = RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I)) + TmpVec2 + TmpVec3
|
||||
END DO
|
||||
|
||||
TmpVec1 = ( RtHSdat%FTHydrot(:,J) )*abs(p%DHNodes(J)) &
|
||||
- p%TElmntMass(J)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccETt(:,J) ) ! The portion of FrcT0Trbt associated with tower element J
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0T(:,J), TmpVec1 ) ! The portion of MomX0Trbt associated with tower element J
|
||||
TmpVec3 = ( RtHSdat%MFHydrot(:,J) )*abs(p%DHNodes(J)) ! The external moment applied to tower element J
|
||||
RtHSdat%FrcT0Trbt = RtHSdat%FrcT0Trbt + TmpVec1
|
||||
RtHSdat%MomX0Trbt = RtHSdat%MomX0Trbt + TmpVec2 + TmpVec3
|
||||
END DO
|
||||
```
|
||||
* `p%YawBrMass` 是偏航轴承质量。
|
||||
* `RtHSdat%PLinVelEO` 是偏航轴承点 O 的广义线速度偏导数。
|
||||
* `RtHSdat%LinAccEOt` 是偏航轴承点 O 的线性加速度。
|
||||
* `RtHSdat%rT0O` 是从塔基 (T0) 到偏航轴承 (O) 的位置向量。
|
||||
* `RtHSdat%rT0T` 是从塔基 (T0) 到塔架单元 (T) 的位置向量。
|
||||
* `PFrcT0Trb` 和 `PMomX0Trb` 累加了来自偏航轴承和塔架单元的与广义加速度相关的部分力/力矩。
|
||||
* `FrcT0Trbt` 和 `MomX0Trbt` 累加了来自偏航轴承和塔架单元的与广义加速度无关的力/力矩(包括重力、水动力、气动力等)。
|
||||
|
||||
3. **平台参考点处的力和力矩 (PFrcZAll, PMomXAll, FrcZAllt, MomXAllt)**:
|
||||
这部分计算了在平台参考点 (Z) 处的总力和力矩,包括来自整个风力机(包括塔架)和平台自身的贡献。
|
||||
* **理论**: 这是整个系统在平台参考点处的总广义力和力矩。
|
||||
* **代码**:
|
||||
```fortran
|
||||
RtHSdat%PFrcZAll = RtHSdat%PFrcT0Trb
|
||||
RtHSdat%PMomXAll = RtHSdat%PFrcT0Trb
|
||||
|
||||
DO I = 1,p%DOFs%NActvDOF
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rZT0, RtHSdat%PFrcT0Trb(:,p%DOFs%SrtPS(I)) )
|
||||
RtHSdat%PMomXAll(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomXAll(:,p%DOFs%SrtPS(I)) + TmpVec
|
||||
END DO
|
||||
|
||||
DO I = 1,p%DOFs%NPYE
|
||||
TmpVec1 = -p%PtfmMass*RtHSdat%PLinVelEY(p%DOFs%PYE(I),0,:)
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rZY , TmpVec1 )
|
||||
RtHSdat%PFrcZAll(:,p%DOFs%PYE(I)) = RtHSdat%PFrcZAll(:,p%DOFs%PYE(I) ) + RtHSdat%PFZHydro(p%DOFs%PYE(I),:) + TmpVec1
|
||||
RtHSdat%PMomXAll(:,p%DOFs%PYE(I)) = RtHSdat%PMomXAll(:,p%DOFs%PYE(I) ) + RtHSdat%PMXHydro(p%DOFs%PYE(I),:) + TmpVec2 &
|
||||
- p%PtfmRIner*CoordSys%a1*DOT_PRODUCT( CoordSys%a1, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) &
|
||||
- p%PtfmYIner*CoordSys%a2*DOT_PRODUCT( CoordSys%a2, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) &
|
||||
- p%PtfmPIner*CoordSys%a3*DOT_PRODUCT( CoordSys%a3, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) )
|
||||
END DO
|
||||
|
||||
TmpVec1 = -p%PtfmMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEYt )
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rZY , TmpVec1 )
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rZT0 , RtHSdat%FrcT0Trbt )
|
||||
TmpVec = p%PtfmRIner*CoordSys%a1*DOT_PRODUCT( CoordSys%a1, RtHSdat%AngVelEX ) &
|
||||
+ p%PtfmYIner*CoordSys%a2*DOT_PRODUCT( CoordSys%a2, RtHSdat%AngVelEX ) &
|
||||
+ p%PtfmPIner*CoordSys%a3*DOT_PRODUCT( CoordSys%a3, RtHSdat%AngVelEX )
|
||||
TmpVec4 = CROSS_PRODUCT( -RtHSdat%AngVelEX, TmpVec )
|
||||
|
||||
RtHSdat%FrcZAllt = RtHSdat%FrcT0Trbt + RtHSdat%FZHydrot + TmpVec1
|
||||
RtHSdat%MomXAllt = RtHSdat%MomX0Trbt + RtHSdat%MXHydrot + TmpVec2 + TmpVec3 + TmpVec4
|
||||
```
|
||||
* `RtHSdat%rZT0` 是从平台参考点 (Z) 到塔基 (T0) 的位置向量。
|
||||
* `p%PtfmMass` 是平台质量。
|
||||
* `RtHSdat%PLinVelEY` 是平台质心 (Y) 的广义线速度偏导数。
|
||||
* `RtHSdat%LinAccEYt` 是平台质心 (Y) 的线性加速度。
|
||||
* `PFrcZAll` 和 `PMomXAll` 累加了来自塔架和平台自身的与广义加速度相关的部分力/力矩。
|
||||
* `FrcZAllt` 和 `MomXAllt` 累加了来自塔架和平台自身的与广义加速度无关的力/力矩。
|
||||
|
||||
### 总结
|
||||
|
||||
`CalculateForcesMoments` 子程序是OpenFAST动力学计算中的一个核心部分,它根据当前系统的状态(广义坐标 `x%QT` 和广义速度 `x%QDT`)、参数 `p`、坐标系信息 `CoordSys` 和外部输入 `u`,计算出作用在风力机各个部件上的力和力矩。
|
||||
|
||||
对于塔架部分,它主要完成了以下工作:
|
||||
1. **计算塔架单元上的水动力和水动弯矩**:这包括与广义加速度相关的部分(`PFTHydro`, `PMFHydro`)和与广义加速度无关的部分(`FTHydrot`, `MFHydrot`),后者包含了重力、水动力阻尼、恢复力以及外部点载荷和非线性惯性力。
|
||||
2. **自下而上累加力矩**:从叶片、轮毂、机舱、尾翼等部件开始,逐步向上累加力和力矩,直到塔基 (T0) 和平台参考点 (Z)。这个过程利用了力矩的传递原理,将各个部件的力和力矩转换到共同的参考点。
|
||||
3. **区分部分力/力矩和总力/力矩**:
|
||||
* 以 `PFrc...` 和 `PMom...` 开头的变量存储的是“部分力”和“部分力矩”,它们是广义加速度的系数,用于构建质量矩阵。
|
||||
* 以 `Frc...t` 和 `Mom...t` 结尾的变量存储的是“总力”和“总力矩”,它们是与广义加速度无关的项,用于构建力向量。
|
||||
|
||||
虽然[[Tower]]笔记提供了塔架广义力的理论表达式,但`CalculateForcesMoments`子程序通过数值方法,结合了OpenFAST中更全面的物理模型(如水动力学、外部载荷等),计算出这些力和力矩的具体数值,为后续的动力学方程求解提供了必要的输入。
|
||||
[Timestamp: 2026/01/12 16:16:33]
|
||||
|
||||
**user**: [[Tower]][[CalculateAngularPosVelPAcc]]结合理论和代码,解释塔架部分是如何计算的
|
||||
[Timestamp: 2026/01/12 16:20:19]
|
||||
|
||||
**ai**: `CalculateAngularPosVelPAcc` 子程序在OpenFAST动力学模型中扮演着关键角色,它负责计算风力机各个部件(包括塔架)的角位置、角速度以及部分角加速度。这些运动学量是后续计算广义力和组装动力学方程的基础。
|
||||
|
||||
### 理论回顾 (来自 [[Tower]] 笔记)
|
||||
|
||||
[[Tower]]笔记中,塔架被视为一个柔性体,其运动通过广义坐标 $q_i$ 及其时间导数 $\dot{q}_i$ 和 $\ddot{q}_i$ 来描述。塔架的柔性变形通过模态叠加原理来表示,即塔架上任意一点的位移、速度和加速度是刚体运动和各个柔性模态贡献的叠加。
|
||||
|
||||
* **广义速度和加速度**: 笔记中提到了塔架上点 T 的广义速度 ${}^E \mathbf{v}_r^T (h)$ 和广义加速度 ${}^E \mathbf{a}^T (h)$。这些向量包含了线性和角运动分量,并且与广义坐标及其导数相关。
|
||||
* **非线性惯性力**: 公式 (4) 中包含了 $\frac{d}{dt} \left( {}^E \mathbf{v}_i^T (h) \right) \dot{q}_i$ 这样的项,这表示了科里奥利力和离心力等非线性惯性效应,它们依赖于广义速度和广义速度的偏导数。为了计算这些项,需要知道部分角速度及其时间导数。
|
||||
|
||||
### 代码实现 (来自 [[CalculateAngularPosVelPAcc]] 子程序)
|
||||
|
||||
`CalculateAngularPosVelPAcc` 子程序通过自下而上的方式(从平台到塔架,再到机舱、轮毂和叶片)计算各个部件的运动学量。我们重点关注塔架相关的计算部分。
|
||||
|
||||
在代码中,塔架的计算位于 `!............... ! tower values: !...............` 注释块下。
|
||||
|
||||
1. **塔架单元的部分角速度 (`RtHSdat%PAngVelEF (J, :,0,:)`)**:
|
||||
这表示塔架上第 `J` 个节点(或单元,用 `F` 表示)在惯性坐标系 `E` 中的部分角速度。`0` 表示这是部分角速度本身(0阶导数)。
|
||||
```fortran
|
||||
RtHSdat%PAngVelEF (J, :,0,:) = RtHSdat%PAngVelEX(:,0,:)
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA1,0,:) = -p%TwrFASF(1,J,1)*CoordSys%a3
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS1,0,:) = p%TwrSSSF(1,J,1)*CoordSys%a1
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA2,0,:) = -p%TwrFASF(2,J,1)*CoordSys%a3
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS2,0,:) = p%TwrSSSF(2,J,1)*CoordSys%a1
|
||||
```
|
||||
* `RtHSdat%PAngVelEX(:,0,:)`:首先,塔架的部分角速度继承了平台(`X`)的部分角速度。这反映了塔架的刚体运动部分。
|
||||
* `p%TwrFASF` 和 `p%TwrSSSF`:这些是塔架在前后 (TFA) 和侧向 (TSS) 方向上的模态形状函数(Shape Functions)。`p%TwrFASF(1,J,1)` 表示第一个前后弯曲模态在第 `J` 个塔架节点处的形状函数值。
|
||||
* `CoordSys%a3` 和 `CoordSys%a1`:这些是机舱坐标系中的单位向量,分别代表了塔架前后弯曲和侧向弯曲的方向。
|
||||
* 通过将模态形状函数乘以相应的方向向量,并与平台的部分角速度叠加,计算出塔架每个柔性自由度对部分角速度的贡献。这直接体现了[[Tower]]笔记中柔性体运动的模态叠加原理。
|
||||
|
||||
2. **塔架单元的部分角速度的1阶导数 (`RtHSdat%PAngVelEF (J, :,1,:)`)**:
|
||||
这表示塔架上第 `J` 个节点的部分角速度的时间导数(1阶导数),即部分角加速度。
|
||||
```fortran
|
||||
RtHSdat%PAngVelEF (J, :,1,:) = RtHSdat%PAngVelEX(:,1,:)
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) )
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) )
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) )
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TSS2,0,:) )
|
||||
```
|
||||
* `RtHSdat%PAngVelEX(:,1,:)`:首先,继承平台的部分角加速度。
|
||||
* `CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) )`:这部分计算了科里奥利项。根据运动学原理,一个向量在旋转坐标系中的时间导数包含一个相对导数项和一个科里奥利项($\boldsymbol{\omega} \times \mathbf{v}$)。在这里,`RtHSdat%AngVelEX` 是平台(惯性系中的刚体部分)的角速度,`RtHSdat%PAngVelEF(J,DOF_TFA1,0,:)` 是塔架柔性模态的部分角速度。这个叉乘项正是由于平台旋转引起的塔架柔性模态部分角速度的变化率。这与[[Tower]]笔记中公式 (4) 的 $\frac{d}{dt} \left( {}^E \mathbf{v}_i^T (h) \right)$ 项直接相关。
|
||||
|
||||
3. **塔架单元的总角速度 (`RtHSdat%AngVelEF (:,J)`)**:
|
||||
这是塔架上第 `J` 个节点在惯性坐标系 `E` 中的总角速度。
|
||||
```fortran
|
||||
RtHSdat%AngVelEF (:,J) = RtHSdat%AngVelEX + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) &
|
||||
+ x%QDT(DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) &
|
||||
+ x%QDT(DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) &
|
||||
+ x%QDT(DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,0,:)
|
||||
```
|
||||
* `RtHSdat%AngVelEX`:平台在惯性系中的总角速度。
|
||||
* `x%QDT`:广义速度向量,例如 `x%QDT(DOF_TFA1)` 是第一个塔架前后弯曲模态的广义速度。
|
||||
* 通过将平台总角速度与每个塔架柔性模态的广义速度乘以其对应的部分角速度叠加,得到塔架节点的总角速度。这正是柔性体运动学中总速度的计算方式。
|
||||
|
||||
4. **塔架单元的相对角位置 (`RtHSdat%AngPosXF (:,J)`) 和总角位置 (`RtHSdat%AngPosEF (:,J)`)**:
|
||||
* `RtHSdat%AngPosXF (:,J)`:表示塔架第 `J` 个节点相对于平台(或其刚体部分)的角位置。它通过将每个塔架柔性模态的广义位置 `x%QT` 乘以其对应的部分角速度(注意这里是部分角速度,而不是部分角位置,因为在小角度假设下,角位置的偏导数近似等于部分角速度)来计算。
|
||||
* `RtHSdat%AngPosEF (:,J)`:塔架第 `J` 个节点在惯性系中的总角位置,是平台总角位置 `RtHSdat%AngPosEX` 和相对角位置 `RtHSdat%AngPosXF` 的叠加。
|
||||
|
||||
5. **塔架单元的部分角加速度 (`RtHSdat%AngAccEFt(:,J)`)**:
|
||||
这表示塔架上第 `J` 个节点在惯性坐标系 `E` 中的部分角加速度,即不包含 $\ddot{q}_i$ 项的角加速度。这部分包含了科里奥利力和离心力等非线性惯性效应。
|
||||
```fortran
|
||||
RtHSdat%AngAccEFt(:,J) = RtHSdat%AngAccEXt + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,1,:) &
|
||||
+ x%QDT(DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,1,:) &
|
||||
+ x%QDT(DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,1,:) &
|
||||
+ x%QDT(DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,1,:)
|
||||
```
|
||||
* `RtHSdat%AngAccEXt`:平台在惯性系中的部分角加速度。
|
||||
* 通过将每个塔架柔性模态的广义速度 `x%QDT` 乘以其对应的部分角速度的1阶导数 (`RtHSdat%PAngVelEF(J,DOF_TFA1,1,:)`),并与平台的部分角加速度叠加,得到塔架节点的总部分角加速度。这直接对应于[[Tower]]笔记中公式 (4) 的非线性惯性力项。
|
||||
|
||||
### 总结
|
||||
|
||||
`CalculateAngularPosVelPAcc` 子程序通过以下方式计算塔架的运动学量:
|
||||
|
||||
1. **模态叠加**: 利用塔架的模态形状函数 (`p%TwrFASF`, `p%TwrSSSF`) 和广义坐标 (`x%QT`, `x%QDT`) 来描述塔架的柔性变形。
|
||||
2. **分层计算**: 从平台开始,逐级向上计算各个部件的运动学量,塔架的运动学量是在平台运动的基础上叠加其自身柔性变形的贡献。
|
||||
3. **偏导数和时间导数**: 精确计算了部分角速度 (`PAngVelEF (J, :,0,:)`) 及其时间导数 (`PAngVelEF (J, :,1,:)`)。这些导数对于正确捕捉科里奥利力和离心力等非线性惯性效应至关重要,它们是[[Tower]]笔记中广义力公式(特别是惯性力部分)的直接输入。
|
||||
4. **总运动学量**: 结合刚体运动和柔性变形的贡献,计算出塔架节点的总角速度 (`AngVelEF`) 和总角位置 (`AngPosEF`)。
|
||||
|
||||
这些计算结果(特别是部分角速度及其导数,以及总角速度和部分角加速度)被存储在 `RtHSdat` 结构体中,供后续的 `CalculateForcesMoments` 和 `FillAugmat` 等子程序使用,以构建完整的动力学方程。
|
||||
[Timestamp: 2026/01/12 16:20:52]
|
||||
|
||||
**user**: [[Tower]][[CalculatePositions]]结合理论和代码,解释塔架部分是如何计算的
|
||||
[Timestamp: 2026/01/12 16:25:27]
|
||||
|
||||
**ai**: 好的,我们来结合[[Tower]]笔记中的理论和[[CalculatePositions]]子程序中的代码,解释塔架部分是如何计算的。
|
||||
|
||||
`CalculatePositions` 子程序在OpenFAST动力学模型中负责计算风力机各个部件(包括塔架)在惯性坐标系中的位置向量。这些位置信息是后续计算速度、加速度以及广义力和力矩的基础。
|
||||
|
||||
### 理论回顾 (来自 [[Tower]] 笔记)
|
||||
|
||||
[[Tower]]笔记中,塔架被视为一个柔性体,其变形通过模态叠加原理来描述。塔架上任意一点的位移是刚体运动和各个柔性模态贡献的叠加。
|
||||
|
||||
* **广义坐标 ($q_i$)**: 笔记中提到了塔架的前后 (TFA) 和侧向 (TSS) 弯曲模态的广义坐标 $q_{TFA1}, q_{TFA2}, q_{TSS1}, q_{TSS2}$。这些广义坐标代表了塔架柔性变形的程度。
|
||||
* **模态形状函数 ($\phi_i^{TFA}(h), \phi_i^{TSS}(h)$)**: 塔架的柔性变形通常通过模态形状函数来描述,这些函数定义了塔架沿其高度 $h$ 的变形模式。
|
||||
* **轴向缩短效应 (Axial Shortening)**: 柔性体的弯曲变形会导致其轴向长度的微小缩短,这是一种非线性效应,通常通过二次项来近似。
|
||||
|
||||
### 代码实现 (来自 [[CalculatePositions]] 子程序)
|
||||
|
||||
`CalculatePositions` 子程序通过自下而上的方式(从平台到塔架,再到机舱、轮毂和叶片)计算各个部件的位置向量。我们重点关注塔架相关的计算部分。
|
||||
|
||||
1. **塔顶/底板的位置向量 (`RtHSdat%rZO`)**:
|
||||
这部分计算了从平台参考点 (Z) 到塔顶/底板 (O) 的位置向量。这个向量包含了塔架的刚体高度以及由于塔架柔性变形引起的水平位移和轴向缩短。
|
||||
```fortran
|
||||
RtHSdat%rZO = ( x%QT(DOF_TFA1) + x%QT(DOF_TFA2) )*CoordSys%a1 & ! Position vector from platform reference (point Z) to tower-top / base plate (point O).
|
||||
+ ( p%RefTwrHt - 0.5*( p%AxRedTFA(1,1,p%TTopNode)*x%QT(DOF_TFA1)*x%QT(DOF_TFA1) &
|
||||
+ p%AxRedTFA(2,2,p%TTopNode)*x%QT(DOF_TFA2)*x%QT(DOF_TFA2) &
|
||||
+ 2.0*p%AxRedTFA(1,2,p%TTopNode)*x%QT(DOF_TFA1)*x%QT(DOF_TFA2) &
|
||||
+ p%AxRedTSS(1,1,p%TTopNode)*x%QT(DOF_TSS1)*x%QT(DOF_TSS1) &
|
||||
+ p%AxRedTSS(2,2,p%TTopNode)*x%QT(DOF_TSS2)*x%QT(DOF_TSS2) &
|
||||
+ 2.0*p%AxRedTSS(1,2,p%TTopNode)*x%QT(DOF_TSS1)*x%QT(DOF_TSS2) ) )*CoordSys%a2 &
|
||||
+ ( x%QT(DOF_TSS1) + x%QT(DOF_TSS2) )*CoordSys%a3
|
||||
```
|
||||
* `x%QT(DOF_TFA1)` 和 `x%QT(DOF_TFA2)`:塔架前后弯曲的两个模态的广义坐标。它们乘以 `CoordSys%a1`(机舱坐标系中的 x 方向单位向量)表示塔顶在前后方向的位移。
|
||||
* `x%QT(DOF_TSS1)` 和 `x%QT(DOF_TSS2)`:塔架侧向弯曲的两个模态的广义坐标。它们乘以 `CoordSys%a3`(机舱坐标系中的 z 方向单位向量,在OpenFAST中通常表示侧向)表示塔顶在侧向的位移。
|
||||
* `p%RefTwrHt`:塔架的参考高度。
|
||||
* `p%AxRedTFA` 和 `p%AxRedTSS`:这些是轴向缩短系数。当塔架弯曲时,其轴向长度会略微缩短。这部分通过广义坐标的二次项来近似,并乘以 `0.5`。这个缩短量从 `p%RefTwrHt` 中减去,表示塔顶在垂直方向(`CoordSys%a2`,机舱坐标系中的 y 方向单位向量,通常表示垂直)的实际高度。
|
||||
* `p%TTopNode`:表示塔顶所在的节点索引。
|
||||
|
||||
2. **塔基到塔顶的位置向量 (`RtHSdat%rT0O`)**:
|
||||
```fortran
|
||||
RtHSdat%rT0O = RtHSdat%rZO - RtHSdat%rZT0 ! Position vector from the tower base (point T(0)) to tower-top / base plate (point O).
|
||||
```
|
||||
* `RtHSdat%rZT0` 是从平台参考点 (Z) 到塔基 (T(0)) 的位置向量,它是一个常数,表示塔架的刚体部分。
|
||||
* `RtHSdat%rT0O` 是塔基到塔顶的相对位置向量,它包含了塔架的柔性变形。
|
||||
|
||||
3. **塔架单元的位置向量 (`RtHSdat%rT0T`, `RtHSdat%rZT`, `RtHSdat%rT`)**:
|
||||
这部分计算了塔架每个离散化节点(或单元,用 `T` 表示)的位置。
|
||||
```fortran
|
||||
RtHSdat%rZT (:,0) = RtHSdat%rZT0
|
||||
DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements
|
||||
! Calculate the position vector of the current node:
|
||||
RtHSdat%rT0T(:,J) = ( p%TwrFASF(1,J,0)*x%QT(DOF_TFA1) + p%TwrFASF(2,J,0)*x%QT(DOF_TFA2) )*CoordSys%a1 & ! Position vector from base of flexible portion of tower (point T(0)) to current node (point T(J)).
|
||||
+ ( p%HNodes(J) - 0.5*( p%AxRedTFA(1,1,J)*x%QT(DOF_TFA1)*x%QT(DOF_TFA1) &
|
||||
+ p%AxRedTFA(2,2,J)*x%QT(DOF_TFA2)*x%QT(DOF_TFA2) &
|
||||
+ 2.0*p%AxRedTFA(1,2,J)*x%QT(DOF_TFA1)*x%QT(DOF_TFA2) &
|
||||
+ p%AxRedTSS(1,1,J)*x%QT(DOF_TSS1)*x%QT(DOF_TSS1) &
|
||||
+ p%AxRedTSS(2,2,J)*x%QT(DOF_TSS2)*x%QT(DOF_TSS2) &
|
||||
+ 2.0*p%AxRedTSS(1,2,J)*x%QT(DOF_TSS1)*x%QT(DOF_TSS2) ) )*CoordSys%a2 &
|
||||
+ ( p%TwrSSSF(1,J,0)*x%QT(DOF_TSS1) + p%TwrSSSF(2,J,0)*x%QT(DOF_TSS2) )*CoordSys%a3
|
||||
RtHSdat%rZT (:,J) = RtHSdat%rZT0 + RtHSdat%rT0T(:,J) ! Position vector from platform reference (point Z) to the current node (point T(HNodes(J)).
|
||||
RtHSdat%rT(:,J) = RtHSdat%rZ + RtHSdat%rZT (:,J) ! Position vector from inertial frame origin to the current node (point T(HNodes(J)).
|
||||
END DO
|
||||
```
|
||||
* `p%TwrNodes`:塔架的节点数量。
|
||||
* `p%HNodes(J)`:第 `J` 个塔架节点在未变形状态下的高度。
|
||||
* `RtHSdat%rT0T(:,J)`:从塔基 (T(0)) 到第 `J` 个塔架节点 (T(J)) 的相对位置向量。其计算方式与 `RtHSdat%rZO` 类似,使用了塔架模态形状函数 (`p%TwrFASF`, `p%TwrSSSF`) 和轴向缩短系数 (`p%AxRedTFA`, `p%AxRedTSS`),但这些参数是针对每个节点 `J` 进行评估的。
|
||||
* `RtHSdat%rZT (:,J)`:从平台参考点 (Z) 到第 `J` 个塔架节点 (T(J)) 的相对位置向量,是 `RtHSdat%rZT0` 和 `RtHSdat%rT0T(:,J)` 的叠加。
|
||||
* `RtHSdat%rT(:,J)`:从惯性坐标系原点到第 `J` 个塔架节点 (T(J)) 的绝对位置向量,是平台在惯性系中的位置 `RtHSdat%rZ` 和相对位置 `RtHSdat%rZT (:,J)` 的叠加。
|
||||
|
||||
### 总结
|
||||
|
||||
`CalculatePositions` 子程序通过以下方式计算塔架的位置:
|
||||
|
||||
1. **模态叠加**: 塔架的柔性变形(前后弯曲和侧向弯曲)通过其广义坐标 (`x%QT`) 和模态形状函数 (`p%TwrFASF`, `p%TwrSSSF`) 来表示。
|
||||
2. **轴向缩短效应**: 考虑了塔架弯曲引起的轴向长度缩短这一非线性效应,通过广义坐标的二次项来近似。
|
||||
3. **分层计算**: 从平台参考点开始,逐步计算塔顶和塔架各个节点在惯性坐标系中的位置。每个节点的绝对位置都是其上层部件的绝对位置加上自身相对于上层部件的相对位置。
|
||||
4. **存储结果**: 计算出的所有位置向量都存储在 `RtHSdat` 结构体中,供后续的运动学(速度、加速度)和动力学(力和力矩)计算使用。
|
||||
|
||||
这些位置向量是OpenFAST中进行精确动力学分析的基础,它们直接影响了广义速度、广义加速度的计算,进而影响了广义惯性力、重力、气动力和水动力等各项力的计算。
|
||||
[Timestamp: 2026/01/12 16:25:42]
|
||||
|
||||
**user**: [[Tower]][[Coeff]]结合理论和代码,解释塔架部分是如何计算的
|
||||
[Timestamp: 2026/01/12 16:27:21]
|
||||
|
||||
**ai**: `Coeff` 子程序在OpenFAST动力学模型中负责计算风力机各个部件(包括塔架)的各种系数和属性。这些计算通常在模拟开始时进行一次,以设置系统的基本物理参数。[[Tower]]笔记提供了塔架动力学建模的理论基础,而`Coeff`子程序则将这些理论概念转化为具体的数值计算。
|
||||
|
||||
### 理论回顾 (来自 [[Tower]] 笔记)
|
||||
|
||||
[[Tower]]笔记详细推导了塔架的广义惯性力、弹性力、阻尼力、重力和气动力。这些力的计算依赖于以下关键参数:
|
||||
|
||||
* **质量密度 ($\mu^T(h)$)**: 塔架沿高度的质量分布,用于计算广义质量。
|
||||
$$
|
||||
\mu^T (h) = AdjTwMa \cdot TMassDen(h)\tag{1}
|
||||
$$
|
||||
* **广义质量 ($m_{ij}^{'TFA}$, $m_{ij}^{'TSS}$)**: 塔架在前后 (TFA) 和侧向 (TSS) 方向上的广义质量,通过质量密度和模态形状函数积分得到。
|
||||
$$
|
||||
m_{\ i j}^{\prime^{T F A}}=\int_{0}^{T w r F l e x L}\mu^{T}\left(h\right)\phi_{i}^{T F A}\left(h\right)\phi_{j}^{T F A}\left(h\right)d h\quad\left(i,j=1,2\right)\tag{13}
|
||||
$$
|
||||
* **广义刚度 ($k_{ij}^{'TFA}$, $k_{ij}^{'TSS}$)**: 塔架在前后和侧向方向上的广义刚度,通过弯曲刚度 ($EI$) 和模态形状函数的二阶导数积分得到。
|
||||
$$
|
||||
k_{ij}^{'TFA} = \sqrt{FAStTunr(i) FAStTunr(j)} \int_0^{TwrFlexL} EI^{TFA}(h) \frac{d^2 \phi_i^{TFA}(h)}{dh^2} \frac{d^2 \phi_j^{TFA}(h)}{dh^2} dh \quad (i, j = 1,2)\tag{7}
|
||||
$$
|
||||
* **固有频率 ($f_{i}^{'TFA}$, $f_{i}^{\prime T S S}$)**: 塔架的固有频率,由广义刚度和广义质量决定。
|
||||
$$
|
||||
f_{\;\;i}^{\;\prime^{T F A}}=\frac{1}{2\pi}\sqrt{\frac{k_{\;i i}^{\prime^{T F A}}}{m_{\;i i}^{\prime^{T F A}}}}\tag{12}
|
||||
$$
|
||||
* **阻尼比 ($\zeta_{i}^{T F A}$, $\zeta_{i}^{T S S}$)**: 塔架的结构阻尼比,用于计算广义阻尼。
|
||||
* **模态形状函数 ($\phi_i^{TFA}(h)$, $\phi_i^{TSS}(h)$)**: 描述塔架柔性变形的函数,及其一阶和二阶导数。
|
||||
* **轴向缩短效应**: 塔架弯曲时引起的轴向长度缩短,这是一种非线性几何效应。
|
||||
|
||||
### 代码实现 (来自 [[Coeff]] 子程序)
|
||||
|
||||
`Coeff` 子程序通过数值积分和参数设置来计算上述理论参数。以下是塔架部分的关键计算:
|
||||
|
||||
1. **初始化塔架相关参数**:
|
||||
```fortran
|
||||
p%TwrMass = 0.0
|
||||
p%KTFA = 0.0
|
||||
p%KTSS = 0.0
|
||||
KTFAGrav = 0.0
|
||||
KTSSGrav = 0.0
|
||||
```
|
||||
在计算开始前,塔架的总质量、广义刚度(前后和侧向)以及重力去刚化项都被初始化为零。
|
||||
|
||||
2. **计算塔顶总质量 (`p%TwrTpMass`)**:
|
||||
```fortran
|
||||
p%TwrTpMass = p%RotMass + p%RFrlMass + p%BoomMass + p%TFinMass + p%NacMass + p%YawBrMass
|
||||
```
|
||||
这计算了塔架顶部所有部件(转子、变桨结构、尾翼、机舱、偏航轴承等)的总质量。这个总质量在计算塔架的广义质量和固有频率时非常重要,因为它作为塔顶的集中质量效应。
|
||||
|
||||
3. **塔架单元质量和质量累加 (`p%TElmntMass`, `p%TwrMass`, `TMssAbvNd`)**:
|
||||
通过一个从塔顶向下遍历塔架节点的循环:
|
||||
```fortran
|
||||
DO J = p%TwrNodes,1,-1
|
||||
p%TElmntMass(J) = p%MassT(J)*abs(p%DHNodes(J)) ! 塔架单元J的质量
|
||||
p%TwrMass = p%TwrMass + p%TElmntMass(J) ! 累加塔架总质量
|
||||
TMssAbvNd(J) = 0.5*p%TElmntMass(J) ! 塔架单元J的质量贡献
|
||||
IF ( J == p%TwrNodes ) THEN
|
||||
TMssAbvNd(J) = TMssAbvNd(J) + p%TwrTpMass ! 最上层单元加上塔顶总质量
|
||||
ELSE
|
||||
TMssAbvNd(J) = 0.5*p%TElmntMass(J+1) + TMssAbvNd(J) + TMssAbvNd(J+1) ! 累加其上方所有质量
|
||||
ENDIF
|
||||
ENDDO
|
||||
```
|
||||
* `p%TElmntMass(J)`: 计算每个塔架单元的质量,对应于理论中的 $\mu^T(h)dh$。
|
||||
* `p%TwrMass`: 累加所有塔架单元的质量,得到柔性塔架的总质量。
|
||||
* `TMssAbvNd(J)`: 计算在节点 `J` 以上所有塔架单元和塔顶部件的总质量。这对于计算重力去刚化效应至关重要,因为重力载荷取决于其上方结构的质量。
|
||||
|
||||
4. **初始化广义塔架质量 (考虑塔顶质量)**:
|
||||
```fortran
|
||||
DO I = 1,2
|
||||
MTFA(I,I) = p%TwrTpMass
|
||||
MTSS(I,I) = p%TwrTpMass
|
||||
ENDDO
|
||||
```
|
||||
将塔顶总质量作为塔架广义质量矩阵对角线项的初始值,这反映了塔顶集中质量对塔架模态惯性的贡献。
|
||||
|
||||
5. **塔架模态形状函数 (`p%TwrFASF`, `p%TwrSSSF`)**:
|
||||
通过一个从塔基向上遍历塔架节点的循环,使用 `SHP` 函数计算塔架每个节点处的前后 (FAM) 和侧向 (SSM) 模态形状函数及其一阶和二阶导数。
|
||||
```fortran
|
||||
DO J = 1,p%TwrNodes
|
||||
p%TwrFASF(1,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 2, ErrStat, ErrMsg ) ! 二阶导数
|
||||
p%TwrFASF(1,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 1, ErrStat, ErrMsg ) ! 一阶导数
|
||||
p%TwrFASF(1,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 0, ErrStat, ErrMsg ) ! 零阶导数 (形状函数本身)
|
||||
! ... (类似地计算 TwrFASF(2,J,...) 和 TwrSSSF(...,J,...) )
|
||||
ENDDO
|
||||
```
|
||||
这些形状函数及其导数是计算广义质量、广义刚度和轴向缩短效应的基础,直接对应于理论中的 $\phi_i(h)$ 及其导数。
|
||||
|
||||
6. **广义质量积分 (`MTFA`, `MTSS`)**:
|
||||
在遍历塔架节点的循环中,累加每个单元的质量贡献。
|
||||
```fortran
|
||||
DO I = 1,2
|
||||
MTFA(I,I) = MTFA(I,I) + p%TElmntMass(J)*p%TwrFASF(I,J,0)**2
|
||||
MTSS(I,I) = MTSS(I,I) + p%TElmntMass(J)*p%TwrSSSF(I,J,0)**2
|
||||
ENDDO
|
||||
```
|
||||
这实现了理论中广义质量积分的数值近似,即 $\sum \mu^T(h) \phi_i(h)^2 \Delta h$。
|
||||
|
||||
7. **广义刚度积分 (`p%KTFA`, `p%KTSS`)**:
|
||||
同样在循环中,累加每个单元的刚度贡献。
|
||||
```fortran
|
||||
ElStffFA = p%StiffTFA(J)*abs(p%DHNodes(J)) ! 塔架单元J的前后刚度
|
||||
ElStffSS = p%StiffTSS(J)*abs(p%DHNodes(J)) ! 塔架单元J的侧向刚度
|
||||
DO I = 1,2
|
||||
DO L = 1,2
|
||||
p%KTFA(I,L) = p%KTFA(I,L) + ElStffFA *p%TwrFASF(I,J,2)*p%TwrFASF(L,J,2)
|
||||
p%KTSS(I,L) = p%KTSS(I,L) + ElStffSS *p%TwrSSSF(I,J,2)*p%TwrSSSF(L,J,2)
|
||||
ENDDO
|
||||
ENDDO
|
||||
```
|
||||
这实现了理论中广义刚度积分的数值近似,即 $\sum EI(h) \frac{d^2 \phi_i(h)}{dh^2} \frac{d^2 \phi_j(h)}{dh^2} \Delta h$。
|
||||
|
||||
8. **重力去刚化刚度 (`KTFAGrav`, `KTSSGrav`)**:
|
||||
```fortran
|
||||
ElmntStff = -TMssAbvNd(J)*abs(p%DHNodes(J))*p%Gravity ! 塔架单元J的重力刚度项
|
||||
DO I = 1,2
|
||||
KTFAGrav(I,I) = KTFAGrav(I,I) + ElmntStff*p%TwrFASF(I,J,1)**2
|
||||
KTSSGrav(I,I) = KTSSGrav(I,I) + ElmntStff*p%TwrSSSF(I,J,1)**2
|
||||
ENDDO
|
||||
```
|
||||
这计算了重力去刚化效应引起的刚度项,它与上方质量和模态形状函数的一阶导数(斜率)的平方有关。
|
||||
|
||||
9. **塔架轴向缩短形状函数 (`p%AxRedTFA`, `p%AxRedTSS`)**:
|
||||
```fortran
|
||||
DO I = 1,2
|
||||
DO L = 1,2
|
||||
AxRdTFA (I,L) = 0.5*p%DHNodes(J)*p%TwrFASF(I,J,1)*p%TwrFASF(L,J,1)
|
||||
p%AxRedTFA(I,L,J) = AxRdTFA(I,L)
|
||||
! ... (类似地计算 AxRedTSS)
|
||||
ENDDO
|
||||
ENDDO
|
||||
```
|
||||
这计算了塔架弯曲引起的轴向缩短系数,它与模态形状函数的一阶导数(斜率)的乘积有关。这些系数将在`CalculatePositions`子程序中用于计算塔架的实际位置。
|
||||
|
||||
10. **应用模态刚度调谐器**:
|
||||
```fortran
|
||||
DO I = 1,2
|
||||
DO L = 1,2
|
||||
p%KTFA(I,L) = SQRT( InputFileData%FAStTunr(I)*InputFileData%FAStTunr(L) )*p%KTFA(I,L)
|
||||
p%KTSS(I,L) = SQRT( InputFileData%SSStTunr(I)*InputFileData%SSStTunr(L) )*p%KTSS(I,L)
|
||||
ENDDO
|
||||
ENDDO
|
||||
```
|
||||
这实现了[[Tower]]笔记中提到的刚度调谐功能,允许用户通过输入参数调整塔架的固有频率。
|
||||
|
||||
11. **计算塔架固有频率 (`p%FreqTFA`, `p%FreqTSS`)**:
|
||||
```fortran
|
||||
DO I = 1,2
|
||||
p%FreqTFA(I,1) = Inv2Pi*SQRT( p%KTFA(I,I)/( MTFA(I,I) - p%TwrTpMass ) ) ! 不含重力去刚化和塔顶质量
|
||||
p%FreqTFA(I,2) = Inv2Pi*SQRT( ( p%KTFA(I,I) + KTFAGrav(I,I) )/MTFA(I,I) ) ! 含重力去刚化和塔顶质量
|
||||
! ... (类似地计算 FreqTSS)
|
||||
ENDDO
|
||||
```
|
||||
这直接实现了理论中的固有频率公式 $f = \frac{1}{2\pi}\sqrt{\frac{k}{m}}$,并考虑了不同情况下(是否包含重力去刚化和塔顶质量)的频率。
|
||||
|
||||
12. **计算广义阻尼 (`p%CTFA`, `p%CTSS`)**:
|
||||
```fortran
|
||||
DO I = 1,2
|
||||
DO L = 1,2
|
||||
p%CTFA(I,L) = ( 0.01*InputFileData%TwrFADmp(L) )*p%KTFA(I,L)/( Pi*p%FreqTFA(L,1) )
|
||||
p%CTSS(I,L) = ( 0.01*InputFileData%TwrSSDmp(L) )*p%KTSS(I,L)/( Pi*p%FreqTSS(L,1) )
|
||||
ENDDO
|
||||
ENDDO
|
||||
```
|
||||
这根据瑞利阻尼假设(阻尼与刚度成比例)计算广义阻尼系数,使用了输入的阻尼比和计算出的固有频率。这对应于[[Tower]]笔记中广义阻尼力公式的系数。
|
||||
|
||||
13. **计算塔架形状函数和轴向缩短函数在塔顶的值**:
|
||||
这部分与前面的循环类似,但专门针对塔顶节点,确保塔顶的形状函数和轴向缩短值被正确计算。
|
||||
|
||||
14. **计算总风力机质量 (`p%TurbMass`)**:
|
||||
```fortran
|
||||
p%TurbMass = p%TwrTpMass + p%TwrMass
|
||||
```
|
||||
将塔顶总质量和柔性塔架总质量相加,得到整个风力机的总质量。
|
||||
|
||||
### 总结
|
||||
|
||||
`Coeff` 子程序是OpenFAST中进行参数预处理的核心,它将用户在输入文件中定义的物理特性(如质量分布、刚度、模态形状函数等)转化为动力学模型所需的各种系数。对于塔架部分,它:
|
||||
|
||||
* **数值积分**: 通过离散化和求和的方式,数值近似地计算了塔架的广义质量和广义刚度,这与[[Tower]]笔记中的积分公式相对应。
|
||||
* **考虑非线性效应**: 计算了重力去刚化刚度项和轴向缩短系数,这些是柔性体动力学中重要的非线性效应。
|
||||
* **模态调谐**: 实现了塔架模态刚度调谐功能,允许用户调整塔架的固有频率。
|
||||
* **计算派生参数**: 根据基本参数计算了塔架的固有频率和广义阻尼系数。
|
||||
|
||||
这些在`Coeff`中计算出的参数(存储在 `p` 结构体中)随后会被其他子程序(如`CalculatePositions`、`CalculateAngularPosVelPAcc`、`CalculateForcesMoments`和`FillAugmat`)使用,以构建和求解风力机的完整动力学方程。
|
||||
[Timestamp: 2026/01/12 16:28:08]
|
||||
@ -0,0 +1,554 @@
|
||||
---
|
||||
epoch: 1768872772586
|
||||
modelKey: gemini-2.5-flash|google
|
||||
tags:
|
||||
- copilot-conversation
|
||||
---
|
||||
|
||||
**user**: [[meshmap]]分析SUBROUTINE MeshMapCreate的实现方法
|
||||
[Timestamp: 2026/01/20 09:32:52]
|
||||
|
||||
**ai**: The `SUBROUTINE MeshMapCreate` is a core routine within the `meshmap` module, designed to establish the necessary data structures for mapping information between two distinct meshes: a source mesh (`Src`) and a destination mesh (`Dest`). This mapping facilitates the transfer of data such as motions, scalars, and loads between these meshes.
|
||||
|
||||
Here's a detailed breakdown of its implementation:
|
||||
|
||||
**1. Purpose**
|
||||
The primary goal of `MeshMapCreate` is to:
|
||||
* Determine the required sizes for mapping data structures.
|
||||
* Allocate memory for these structures, specifically for motion/scalar mappings (`MeshMap%MapMotions`) and load mappings (`MeshMap%MapLoads`).
|
||||
* Initialize these mappings by calling specialized subroutines based on the element types of the source and destination meshes.
|
||||
* Allocate memory for `MeshMap%DisplacedPosition`.
|
||||
|
||||
**2. Input and Output Parameters**
|
||||
* `Src` (TYPE(MeshType), INTENT(IN)): The source mesh from which data will be mapped.
|
||||
* `Dest` (TYPE(MeshType), INTENT(IN)): The destination mesh to which data will be mapped.
|
||||
* `MeshMap` (TYPE(MeshMapType), INTENT(INOUT)): A data structure that will store all the mapping information.
|
||||
* `ErrStat` (INTEGER(IntKi), INTENT(OUT)): An error status code indicating the success or failure of the operation.
|
||||
* `ErrMsg` (CHARACTER(*), INTENT(OUT)): A descriptive error message if `ErrStat` indicates an error.
|
||||
|
||||
**3. Initial Checks**
|
||||
Before proceeding with any mapping, the subroutine performs a crucial check:
|
||||
* It verifies that both the `Dest` and `Src` meshes are `Committed`. If either mesh is not committed (meaning its definition is not finalized), a fatal error is set, and the subroutine returns, as mapping cannot occur on incomplete mesh definitions.
|
||||
|
||||
**4. Mapping for Motions and Scalars**
|
||||
This section handles the creation of mappings for motion and scalar fields:
|
||||
* **Condition**: The mapping is only attempted if both `Src` and `Dest` meshes possess motion fields (checked by `HasMotionFields(Src) .AND. HasMotionFields(Dest)`).
|
||||
* **Allocation**:
|
||||
* `PointsInMap` is determined by `Dest%Nnodes`, meaning the `MeshMap%MapMotions` array will have an entry for each node in the destination mesh.
|
||||
* `MeshMap%MapMotions` is then allocated. If allocation fails, a fatal error is reported.
|
||||
* **Initial Mapping Logic**: The subroutine uses a series of `IF` statements to select the appropriate mapping subroutine based on the element types of the destination and source meshes:
|
||||
* **Destination has Line2 elements (`Dest%ElemTable(ELEMENT_LINE2)%nelem > 0`)**:
|
||||
* If `Src` also has Line2 elements (`Src%ElemTable(ELEMENT_LINE2)%nelem > 0`), it calls `CreateMotionMap_L2_to_L2`. This subroutine, in turn, calls `CreateMapping_ProjectToLine2(Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ...)`, which projects destination Line2 nodes onto source Line2 elements.
|
||||
* If `Src` has Point elements (`Src%ElemTable(ELEMENT_POINT)%nelem > 0`), it calls `CreateMotionMap_P_to_L2`. This calls `CreateMapping_NearestNeighbor(Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ELEMENT_POINT, ...)`, finding the nearest source point for each destination Line2 node. It also negates the `couple_arm` vector for consistency.
|
||||
* **Destination has Point elements (`Dest%ElemTable(ELEMENT_POINT)%nelem > 0`)**:
|
||||
* If `Src` also has Point elements (`Src%ElemTable(ELEMENT_POINT)%nelem > 0`), it calls `CreateMotionMap_P_to_P`. This calls `CreateMapping_NearestNeighbor(Dest, Src, MeshMap%MapMotions, ELEMENT_POINT, ELEMENT_POINT, ...)`, finding the nearest source point for each destination point. It also negates the `couple_arm` vector.
|
||||
* If `Src` has Line2 elements (`Src%ElemTable(ELEMENT_LINE2)%nelem > 0`), it calls `CreateMotionMap_L2_to_P`. This calls `CreateMapping_ProjectToLine2(Dest, Src, MeshMap%MapMotions, ELEMENT_POINT, ...)`, projecting destination point nodes onto source Line2 elements.
|
||||
|
||||
**5. Mapping for Loads**
|
||||
This section handles the creation of mappings for load fields:
|
||||
* **Condition**: The mapping is only attempted if both `Src` and `Dest` meshes possess load fields (checked by `HasLoadFields(Src) .AND. HasLoadFields(Dest)`).
|
||||
* **Field Compatibility Checks**: It performs checks to ensure that the destination mesh can receive the loads from the source mesh. For example, if the source mesh has force fields, the destination mesh must have both force and moment fields.
|
||||
* **Allocation**:
|
||||
* `PointsInMap` is determined by `Src%Nnodes`, meaning the `MeshMap%MapLoads` array will have an entry for each node in the source mesh.
|
||||
* `MeshMap%MapLoads` is then allocated. If allocation fails, a fatal error is reported.
|
||||
* **Initial Mapping Logic**: Similar to motion mapping, it uses nested `IF` statements based on the element types of the destination and source meshes to call the appropriate `CreateLoadMap_` subroutines (e.g., `CreateLoadMap_L2_to_L2`, `CreateLoadMap_P_to_L2`, `CreateLoadMap_P_to_P`, `CreateLoadMap_L2_to_P`). While the implementations of these `CreateLoadMap_` subroutines are not provided in the context, they are expected to follow a similar logic to their `CreateMotionMap_` counterparts, potentially with adjusted roles for `Src` and `Dest` or specific considerations for load transfer.
|
||||
|
||||
**6. Allocation of `DisplacedPosition`**
|
||||
* After attempting to create motion and load mappings, the subroutine checks if `MeshMap%DisplacedPosition` has been allocated.
|
||||
* If not, it allocates a 3D array for `MeshMap%DisplacedPosition`. The size is determined by `PointsInTmpMap` (the maximum of `Dest%Nnodes` and `Src%Nnodes` to accommodate either mapping type) and `ElementNodes` (which is 1 for point elements, 2 for Line2 elements).
|
||||
|
||||
**7. Error Handling**
|
||||
* The subroutine uses `ErrStat` and `ErrMsg` to communicate the status and any issues.
|
||||
* `SetErrStat` is used to propagate errors from called subroutines or to set new errors within `MeshMapCreate`.
|
||||
* Fatal errors (`ErrID_Fatal`) cause an immediate return.
|
||||
* An informational message (`ErrID_Info`) is generated if a node is mapped to an element that is very close but not strictly "on" it (within a tolerance of 7.5mm), indicating a potential numerical precision issue.
|
||||
* If neither `MapMotions` nor `MapLoads` is successfully allocated, a fatal error is issued, indicating incompatible fields for mapping.
|
||||
|
||||
**Key Mapping Subroutines (Provided Implementations):**
|
||||
|
||||
* **`CreateMapping_ProjectToLine2(Mesh1, Mesh2, NodeMap, Mesh1_TYPE, ErrStat, ErrMsg)`**:
|
||||
* This routine projects nodes from `Mesh1` (e.g., destination nodes for motions) onto `Line2` elements of `Mesh2` (e.g., source Line2 elements).
|
||||
* For each node in `Mesh1`, it iterates through all `Line2` elements in `Mesh2`. It calculates the projection of the `Mesh1` node's position onto the line segment defined by the `Line2` element.
|
||||
* If the projection falls within the segment, it calculates the perpendicular distance. The `Line2` element with the minimum distance is chosen as the mapping target.
|
||||
* `NodeMap(i)%OtherMesh_Element` stores the index of the mapped `Line2` element, and `NodeMap(i)%shape_fn` stores the linear interpolation weights (0.0 to 1.0) along the element.
|
||||
* It includes logic to handle cases where a node is very close to the end of an element due to numerical precision. If a node cannot be mapped, a fatal error is reported, optionally with debug information.
|
||||
|
||||
* **`CreateMapping_NearestNeighbor(Mesh1, Mesh2, NodeMap, Mesh1_TYPE, Mesh2_TYPE, ErrStat, ErrMsg)`**:
|
||||
* This routine finds the nearest neighbor node in `Mesh2` (e.g., source nodes) for each node in `Mesh1` (e.g., destination nodes).
|
||||
* It first identifies which nodes in `Mesh2` are relevant for the mapping based on `Mesh2_TYPE`.
|
||||
* For each node in `Mesh1`, it iterates through the relevant nodes in `Mesh2`, calculating the Euclidean distance.
|
||||
* The `Mesh2` node with the minimum distance is selected as the mapping target.
|
||||
* `NodeMap(i)%OtherMesh_Element` stores the index of the nearest `Mesh2` node.
|
||||
* `NodeMap(i)%distance` stores the minimum distance.
|
||||
* `NodeMap(i)%couple_arm` stores the vector from the `Mesh1` node to the nearest `Mesh2` node.
|
||||
|
||||
In essence, `MeshMapCreate` acts as an orchestrator, dynamically selecting and invoking specialized geometric mapping algorithms to prepare the `MeshMap` data structure for subsequent data transfer operations between potentially different mesh types. The initial comment by `bjj` suggests a potential future enhancement to allow for dynamic reallocation if nodes are added during a simulation, indicating the current focus is on initial setup.
|
||||
[Timestamp: 2026/01/20 09:33:17]
|
||||
|
||||
**user**: 中文回复
|
||||
[Timestamp: 2026/01/20 09:33:23]
|
||||
|
||||
**ai**: `SUBROUTINE MeshMapCreate` 是 `meshmap` 模块中的一个核心子程序,旨在为两个不同的网格(源网格 `Src` 和目标网格 `Dest`)之间的数据映射建立必要的数据结构。这种映射有助于在这些网格之间传输运动、标量和载荷等数据。
|
||||
|
||||
以下是其实现的详细分析:
|
||||
|
||||
**1. 目的**
|
||||
`MeshMapCreate` 的主要目标是:
|
||||
* 确定映射数据结构所需的尺寸。
|
||||
* 为这些结构分配内存,特别是用于运动/标量映射 (`MeshMap%MapMotions`) 和载荷映射 (`MeshMap%MapLoads`)。
|
||||
* 根据源网格和目标网格的元素类型,通过调用专门的子程序来初始化这些映射。
|
||||
* 为 `MeshMap%DisplacedPosition` 分配内存。
|
||||
|
||||
**2. 输入和输出参数**
|
||||
* `Src` (TYPE(MeshType), INTENT(IN)):数据将从中映射的源网格。
|
||||
* `Dest` (TYPE(MeshType), INTENT(IN)):数据将映射到的目标网格。
|
||||
* `MeshMap` (TYPE(MeshMapType), INTENT(INOUT)):一个将存储所有映射信息的数据结构。
|
||||
* `ErrStat` (INTEGER(IntKi), INTENT(OUT)):指示操作成功或失败的错误状态码。
|
||||
* `ErrMsg` (CHARACTER(*), INTENT(OUT)):如果 `ErrStat` 指示错误,则为描述性错误消息。
|
||||
|
||||
**3. 初始检查**
|
||||
在进行任何映射之前,子程序会执行一个关键检查:
|
||||
* 它验证 `Dest` 和 `Src` 网格是否都已 `Committed`(即其定义已最终确定)。如果任一网格未提交,则会设置一个致命错误并返回子程序,因为无法对不完整的网格定义进行映射。
|
||||
|
||||
**4. 运动和标量映射**
|
||||
此部分处理运动和标量场的映射创建:
|
||||
* **条件**:仅当 `Src` 和 `Dest` 网格都具有运动场时才尝试映射(通过 `HasMotionFields(Src) .AND. HasMotionFields(Dest)` 检查)。
|
||||
* **分配**:
|
||||
* `PointsInMap` 由 `Dest%Nnodes` 确定,这意味着 `MeshMap%MapMotions` 数组将为目标网格中的每个节点分配一个条目。
|
||||
* 然后分配 `MeshMap%MapMotions`。如果分配失败,则报告致命错误。
|
||||
* **初始映射逻辑**:子程序使用一系列 `IF` 语句根据目标网格和源网格的元素类型选择适当的映射子程序:
|
||||
* **目标网格具有 Line2 元素 (`Dest%ElemTable(ELEMENT_LINE2)%nelem > 0`)**:
|
||||
* 如果 `Src` 也具有 Line2 元素 (`Src%ElemTable(ELEMENT_LINE2)%nelem > 0`),则调用 `CreateMotionMap_L2_to_L2`。此子程序又会调用 `CreateMapping_ProjectToLine2(Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ...)`,将目标 Line2 节点投影到源 Line2 元素上。
|
||||
* 如果 `Src` 具有 Point 元素 (`Src%ElemTable(ELEMENT_POINT)%nelem > 0`),则调用 `CreateMotionMap_P_to_L2`。此子程序调用 `CreateMapping_NearestNeighbor(Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ELEMENT_POINT, ...)`,为每个目标 Line2 节点找到最近的源点。它还会为了保持一致性而对 `couple_arm` 向量取反。
|
||||
* **目标网格具有 Point 元素 (`Dest%ElemTable(ELEMENT_POINT)%nelem > 0`)**:
|
||||
* 如果 `Src` 也具有 Point 元素 (`Src%ElemTable(ELEMENT_POINT)%nelem > 0`),则调用 `CreateMotionMap_P_to_P`。此子程序调用 `CreateMapping_NearestNeighbor(Dest, Src, MeshMap%MapMotions, ELEMENT_POINT, ELEMENT_POINT, ...)`,为每个目标点找到最近的源点。它还会对 `couple_arm` 向量取反。
|
||||
* 如果 `Src` 具有 Line2 元素 (`Src%ElemTable(ELEMENT_LINE2)%nelem > 0`),则调用 `CreateMotionMap_L2_to_P`。此子程序调用 `CreateMapping_ProjectToLine2(Dest, Src, MeshMap%MapMotions, ELEMENT_POINT, ...)`,将目标点节点投影到源 Line2 元素上。
|
||||
|
||||
**5. 载荷映射**
|
||||
此部分处理载荷场的映射创建:
|
||||
* **条件**:仅当 `Src` 和 `Dest` 网格都具有载荷场时才尝试映射(通过 `HasLoadFields(Src) .AND. HasLoadFields(Dest)` 检查)。
|
||||
* **字段兼容性检查**:它执行检查以确保目标网格可以接收来自源网格的载荷。例如,如果源网格具有力场,则目标网格必须同时具有力场和力矩场。
|
||||
* **分配**:
|
||||
* `PointsInMap` 由 `Src%Nnodes` 确定,这意味着 `MeshMap%MapLoads` 数组将为源网格中的每个节点分配一个条目。
|
||||
* 然后分配 `MeshMap%MapLoads`。如果分配失败,则报告致命错误。
|
||||
* **初始映射逻辑**:与运动映射类似,它根据目标网格和源网格的元素类型使用嵌套的 `IF` 语句来调用适当的 `CreateLoadMap_` 子程序(例如,`CreateLoadMap_L2_to_L2`、`CreateLoadMap_P_to_L2`、`CreateLoadMap_P_to_P`、`CreateLoadMap_L2_to_P`)。虽然这些 `CreateLoadMap_` 子程序的实现未在上下文中提供,但它们预计会遵循与其 `CreateMotionMap_` 对应子程序类似的逻辑,可能对 `Src` 和 `Dest` 的角色进行调整或对载荷传输进行特定考虑。
|
||||
|
||||
**6. `DisplacedPosition` 的分配**
|
||||
* 在尝试创建运动和载荷映射之后,子程序检查 `MeshMap%DisplacedPosition` 是否已分配。
|
||||
* 如果未分配,它会为 `MeshMap%DisplacedPosition` 分配一个 3D 数组。大小由 `PointsInTmpMap`(为适应任一映射类型,取 `Dest%Nnodes` 和 `Src%Nnodes` 的最大值)和 `ElementNodes`(点元素为 1,Line2 元素为 2)确定。
|
||||
|
||||
**7. 错误处理**
|
||||
* 子程序使用 `ErrStat` 和 `ErrMsg` 来传达状态和任何问题。
|
||||
* `SetErrStat` 用于传播来自被调用子程序的错误或在 `MeshMapCreate` 中设置新错误。
|
||||
* 致命错误 (`ErrID_Fatal`) 会导致立即返回。
|
||||
* 如果节点映射到非常接近但并非严格“在”其上的元素(在 7.5 毫米的容差范围内),则会生成一条信息性消息 (`ErrID_Info`),表明可能存在数值精度问题。
|
||||
* 如果 `MapMotions` 和 `MapLoads` 都未能成功分配,则会发出致命错误,表明映射的字段不兼容。
|
||||
|
||||
**关键映射子程序(已提供的实现):**
|
||||
|
||||
* **`CreateMapping_ProjectToLine2(Mesh1, Mesh2, NodeMap, Mesh1_TYPE, ErrStat, ErrMsg)`**:
|
||||
* 此例程将 `Mesh1` 中的节点(例如,运动的目标节点)投影到 `Mesh2` 中的 `Line2` 元素(例如,源 Line2 元素)上。
|
||||
* 对于 `Mesh1` 中的每个节点,它会遍历 `Mesh2` 中的所有 `Line2` 元素。它计算 `Mesh1` 节点位置到由 `Line2` 元素定义的线段的投影。
|
||||
* 如果投影落在该线段内,则计算垂直距离。选择距离最小的 `Line2` 元素作为映射目标。
|
||||
* `NodeMap(i)%OtherMesh_Element` 存储映射的 `Line2` 元素的索引,`NodeMap(i)%shape_fn` 存储沿元素的线性插值权重(0.0 到 1.0)。
|
||||
* 它包含处理由于数值精度问题导致节点非常接近元素末端的情况的逻辑。如果节点无法映射,则报告致命错误,并可选择提供调试信息。
|
||||
|
||||
* **`CreateMapping_NearestNeighbor(Mesh1, Mesh2, NodeMap, Mesh1_TYPE, Mesh2_TYPE, ErrStat, ErrMsg)`**:
|
||||
* 此例程为 `Mesh1` 中的每个节点(例如,目标节点)找到 `Mesh2` 中(例如,源节点)最近的邻居节点。
|
||||
* 它首先根据 `Mesh2_TYPE` 识别 `Mesh2` 中与映射相关的节点。
|
||||
* 对于 `Mesh1` 中的每个节点,它会遍历 `Mesh2` 中的相关节点,计算欧几里得距离。
|
||||
* 选择距离最小的 `Mesh2` 节点作为映射目标。
|
||||
* `NodeMap(i)%OtherMesh_Element` 存储最近的 `Mesh2` 节点的索引。
|
||||
* `NodeMap(i)%distance` 存储最小距离。
|
||||
* `NodeMap(i)%couple_arm` 存储从 `Mesh1` 节点到最近 `Mesh2` 节点的向量。
|
||||
|
||||
本质上,`MeshMapCreate` 充当协调器,动态选择和调用专门的几何映射算法,以准备 `MeshMap` 数据结构,用于在可能不同的网格类型之间进行后续数据传输操作。`bjj` 的初始注释表明未来可能会增强功能,以允许在模拟期间添加节点时进行动态重新分配,这表明当前重点是初始设置。
|
||||
[Timestamp: 2026/01/20 09:33:36]
|
||||
|
||||
**user**: 我现在有两套l2mesh,完整解释两套网格的载荷、运动映射方法
|
||||
[Timestamp: 2026/01/20 09:46:09]
|
||||
|
||||
**ai**: 好的,假设您有两套 Line2 类型的网格,我们称之为源网格 `Src` 和目标网格 `Dest`。我们将详细解释 `SUBROUTINE MeshMapCreate` 如何处理这两种网格之间的载荷和运动映射。
|
||||
|
||||
在 `MeshMapCreate` 子程序中,当 `Src` 和 `Dest` 都是 Line2 网格时,会触发特定的映射逻辑。
|
||||
|
||||
### 1. 运动和标量映射 (Motion and Scalar Mapping)
|
||||
|
||||
当 `Src` 和 `Dest` 都具有运动场 (`HasMotionFields(Src) .AND. HasMotionFields(Dest)`) 并且它们都是 Line2 元素网格时,`MeshMapCreate` 会执行以下步骤:
|
||||
|
||||
1. **确定映射大小**:
|
||||
* `PointsInMap` 将被设置为 `Dest%Nnodes`(目标网格的节点数)。这意味着 `MeshMap%MapMotions` 数组将为目标网格中的每个节点分配一个条目。
|
||||
* `ElementNodes` 将设置为 2,因为 Line2 元素有两个节点。
|
||||
|
||||
2. **分配 `MeshMap%MapMotions`**:
|
||||
* 子程序会尝试分配 `MeshMap%MapMotions(PointsInMap)`。如果分配失败,将报告致命错误。
|
||||
|
||||
3. **调用 `CreateMotionMap_L2_to_L2`**:
|
||||
* 由于 `Dest%ElemTable(ELEMENT_LINE2)%nelem > 0` (目标网格有 Line2 元素) 且 `Src%ElemTable(ELEMENT_LINE2)%nelem > 0` (源网格也有 Line2 元素),`MeshMapCreate` 会调用 `CreateMotionMap_L2_to_L2` 子程序。
|
||||
|
||||
4. **`CreateMotionMap_L2_to_L2` 的实现**:
|
||||
* 这个子程序的主要任务是调用 `CreateMapping_ProjectToLine2`。
|
||||
* 调用方式为:`CALL CreateMapping_ProjectToLine2(Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ErrStat2, ErrMsg2)`。
|
||||
* 这里,`Mesh1` 参数是 `Dest` 网格,`Mesh2` 参数是 `Src` 网格。
|
||||
* `NodeMap` 是 `MeshMap%MapMotions`。
|
||||
* `Mesh1_TYPE` 是 `ELEMENT_LINE2`。
|
||||
* `Mesh2_TYPE` 在 `CreateMapping_ProjectToLine2` 中被硬编码为 `ELEMENT_LINE2`。
|
||||
|
||||
5. **`CreateMapping_ProjectToLine2` 的实现 (L2-to-L2 运动映射)**:
|
||||
* 这个子程序的目标是将 `Mesh1` (即 `Dest` 网格) 的每个节点投影到 `Mesh2` (即 `Src` 网格) 的 Line2 元素上,以找到最佳的映射关系。
|
||||
* **初始化**: `NodeMap` 中的每个条目 `NodeMap(i)%OtherMesh_Element` 被初始化为 `NODE_NOT_MAPPED`,表示尚未映射。
|
||||
* **遍历目标网格节点**:
|
||||
* 它会遍历 `Mesh1` (目标网格 `Dest`) 中所有 `ELEMENT_LINE2` 类型的元素 (`iElem`)。
|
||||
* 对于每个元素,它会遍历该元素的所有节点 (`iNode`)。
|
||||
* 获取当前目标节点 `i` 的三维坐标 `Mesh1_xyz = Mesh1%Position(:, i)`。
|
||||
* **寻找最近的源 Line2 元素**:
|
||||
* 对于每个目标节点 `i`,它会遍历 `Mesh2` (源网格 `Src`) 中所有 `ELEMENT_LINE2` 类型的元素 (`jElem`)。
|
||||
* 对于每个源 Line2 元素 `jElem`,它会获取其两个节点 `n1` 和 `n2` 的坐标。
|
||||
* **投影计算**:
|
||||
* 计算从 `n1` 到 `n2` 的向量 `n1_n2_vector`。
|
||||
* 计算从 `n1` 到目标节点 `i` 的向量 `n1_Point_vector`。
|
||||
* 通过点积计算目标节点 `i` 在 `n1_n2_vector` 方向上的投影位置 `elem_position`。
|
||||
* `elem_position = DOT_PRODUCT(n1_n2_vector, n1_Point_vector) / DOT_PRODUCT(n1_n2_vector, n1_n2_vector)`。
|
||||
* **判断是否在元素上**:
|
||||
* 如果 `elem_position` 在 `[0.0, 1.0]` 之间(包括边界上的数值容差),则认为目标节点投影到了源 Line2 元素上。
|
||||
* 如果不在元素上,但非常接近元素端点(例如,小于 7.5 毫米),则会记录为“最近的元素”,并可能在后续作为映射目标。
|
||||
* **计算距离并选择最佳映射**:
|
||||
* 如果目标节点投影在源 Line2 元素上,则计算目标节点到该 Line2 元素的垂直距离(实际上是距离的平方)。
|
||||
* 如果当前 Line2 元素的距离小于之前找到的最小距离 `min_dist`,则更新 `min_dist`,并将当前源 Line2 元素 `jElem` 及其投影位置 `elem_position` 记录为最佳映射。
|
||||
* `NodeMap(i)%OtherMesh_Element` 存储源 Line2 元素的索引 `jElem`。
|
||||
* `NodeMap(i)%shape_fn(1)` 和 `NodeMap(i)%shape_fn(2)` 存储插值形函数值,分别为 `1.0 - elem_position` 和 `elem_position`。这些形函数用于在源 Line2 元素上进行线性插值,以获取目标节点处的运动值。
|
||||
* **错误处理**: 如果一个目标节点无法投影到任何源 Line2 元素上(即使考虑了数值容差),则会报告致命错误。
|
||||
|
||||
**总结 L2-to-L2 运动映射**: 对于目标网格 `Dest` 中的每个节点,系统会找到源网格 `Src` 中离它最近的 Line2 元素,并将目标节点映射到该源 Line2 元素上的一个投影点。映射信息包括源元素的索引和在该元素上的插值权重。
|
||||
|
||||
### 2. 载荷映射 (Load Mapping)
|
||||
|
||||
当 `Src` 和 `Dest` 都具有载荷场 (`HasLoadFields(Src) .AND. HasLoadFields(Dest)`) 并且它们都是 Line2 元素网格时,`MeshMapCreate` 会执行以下步骤:
|
||||
|
||||
1. **兼容性检查**:
|
||||
* 子程序会检查载荷场的兼容性。例如,如果源网格有力 (`Src%FieldMask(MASKID_Force)`),则目标网格必须有力 (`Dest%FieldMask(MASKID_Force)`) 和力矩 (`Dest%FieldMask(MASKID_Moment)`)。如果源网格有力矩 (`Src%FieldMask(MASKID_Moment)`),则目标网格必须有力矩。这些是确保载荷可以正确传输的必要条件。
|
||||
|
||||
2. **确定映射大小**:
|
||||
* `PointsInMap` 将被设置为 `Src%Nnodes`(源网格的节点数)。这意味着 `MeshMap%MapLoads` 数组将为源网格中的每个节点分配一个条目。
|
||||
* `ElementNodes` 将设置为 2,因为 Line2 元素有两个节点。
|
||||
|
||||
3. **分配 `MeshMap%MapLoads`**:
|
||||
* 子程序会尝试分配 `MeshMap%MapLoads(PointsInMap)`。如果分配失败,将报告致命错误。
|
||||
|
||||
4. **调用 `CreateLoadMap_L2_to_L2`**:
|
||||
* 由于 `Dest%ElemTable(ELEMENT_LINE2)%nelem > 0` (目标网格有 Line2 元素) 且 `Src%ElemTable(ELEMENT_LINE2)%nelem > 0` (源网格也有 Line2 元素),`MeshMapCreate` 会调用 `CreateLoadMap_L2_to_L2` 子程序。
|
||||
|
||||
5. **`CreateLoadMap_L2_to_L2` 的实现 (未在提供的代码中,但可推断)**:
|
||||
* 根据 `CreateMotionMap_L2_to_L2` 的模式,`CreateLoadMap_L2_to_L2` 也很可能会调用 `CreateMapping_ProjectToLine2`。
|
||||
* 然而,对于载荷映射,源和目标网格的角色通常是相反的。载荷是从源网格传递到目标网格。因此,在载荷映射中,我们通常需要将**源网格的节点**映射到**目标网格的元素**上。
|
||||
* 因此,推断的调用方式可能是:`CALL CreateMapping_ProjectToLine2(Src, Dest, MeshMap%MapLoads, ELEMENT_LINE2, ErrStat2, ErrMsg2)`。
|
||||
* 这里,`Mesh1` 参数是 `Src` 网格,`Mesh2` 参数是 `Dest` 网格。
|
||||
* `NodeMap` 是 `MeshMap%MapLoads`。
|
||||
* `Mesh1_TYPE` 是 `ELEMENT_LINE2`。
|
||||
* `Mesh2_TYPE` 在 `CreateMapping_ProjectToLine2` 中被硬编码为 `ELEMENT_LINE2`。
|
||||
|
||||
6. **`CreateMapping_ProjectToLine2` 的实现 (L2-to-L2 载荷映射)**:
|
||||
* 与运动映射类似,但角色互换。它将 `Mesh1` (即 `Src` 网格) 的每个节点投影到 `Mesh2` (即 `Dest` 网格) 的 Line2 元素上。
|
||||
* **遍历源网格节点**:
|
||||
* 它会遍历 `Mesh1` (源网格 `Src`) 中所有 `ELEMENT_LINE2` 类型的元素 (`iElem`)。
|
||||
* 对于每个元素,它会遍历该元素的所有节点 (`iNode`)。
|
||||
* 获取当前源节点 `i` 的三维坐标 `Mesh1_xyz = Mesh1%Position(:, i)`。
|
||||
* **寻找最近的目标 Line2 元素**:
|
||||
* 对于每个源节点 `i`,它会遍历 `Mesh2` (目标网格 `Dest`) 中所有 `ELEMENT_LINE2` 类型的元素 (`jElem`)。
|
||||
* 执行与运动映射中相同的投影计算和距离判断逻辑。
|
||||
* `NodeMap(i)%OtherMesh_Element` 存储目标 Line2 元素的索引 `jElem`。
|
||||
* `NodeMap(i)%shape_fn(1)` 和 `NodeMap(i)%shape_fn(2)` 存储插值形函数值,用于在目标 Line2 元素上进行线性插值,以确定源节点处的载荷如何分布到目标元素上。
|
||||
* **错误处理**: 同样,如果一个源节点无法投影到任何目标 Line2 元素上,则会报告致命错误。
|
||||
|
||||
**总结 L2-to-L2 载荷映射**: 对于源网格 `Src` 中的每个节点,系统会找到目标网格 `Dest` 中离它最近的 Line2 元素,并将源节点映射到该目标 Line2 元素上的一个投影点。映射信息包括目标元素的索引和在该元素上的插值权重。这些权重将用于将源节点上的载荷(力、力矩)分配到目标 Line2 元素的两个节点上。
|
||||
|
||||
### 3. `DisplacedPosition` 的分配
|
||||
|
||||
无论载荷或运动映射是否发生,如果 `MeshMap%DisplacedPosition` 尚未分配,它都会被分配。
|
||||
* `PointsInTmpMap` 在 Line2-to-Line2 情况下,对于运动映射是 `Dest%Nnodes`,对于载荷映射是 `Src%Nnodes`。因此,`PointsInTmpMap` 将取两者中的最大值。
|
||||
* `ElementNodes` 在 Line2 网格情况下为 2。
|
||||
* `MeshMap%DisplacedPosition` 将被分配为一个 `3 x PointsInTmpMap x ElementNodes` 的数组,用于存储位移后的位置信息。
|
||||
|
||||
### 总结
|
||||
|
||||
当您有两套 Line2 网格进行映射时:
|
||||
|
||||
* **运动映射 (L2-to-L2)**:目标网格 `Dest` 中的每个节点会被投影到源网格 `Src` 中最近的 Line2 元素上。映射结果存储在 `MeshMap%MapMotions` 中,包含源元素的索引和插值形函数,用于从源网格插值运动到目标网格节点。
|
||||
* **载荷映射 (L2-to-L2)**:源网格 `Src` 中的每个节点会被投影到目标网格 `Dest` 中最近的 Line2 元素上。映射结果存储在 `MeshMap%MapLoads` 中,包含目标元素的索引和插值形函数,用于将源网格节点上的载荷分配到目标网格元素节点。
|
||||
|
||||
这两种映射都依赖于 `CreateMapping_ProjectToLine2` 子程序,该子程序通过几何投影和距离计算来确定节点与 Line2 元素之间的对应关系。关键的区别在于 `CreateMapping_ProjectToLine2` 被调用的参数,特别是 `Mesh1` 和 `Mesh2` 的角色,这决定了是“目标节点找源元素”还是“源节点找目标元素”。
|
||||
[Timestamp: 2026/01/20 09:46:27]
|
||||
|
||||
**user**: [[meshmap]][[CalculatePositions]]我现在的两套网格,aero部分是有风电叶片预弯的网格,elast部分叶片网格是直的,两套网格是否可以匹配
|
||||
[Timestamp: 2026/01/20 10:11:20]
|
||||
|
||||
**ai**: 您提出的问题是关于两套网格的匹配性:一套是气动(aero)部分使用的**预弯叶片网格**,另一套是弹性(elast)部分使用的**直叶片网格**。在 `[[meshmap]]` 和 `[[CalculatePositions]]` 的上下文中,这两套网格是否可以匹配,以及如何匹配。
|
||||
|
||||
**核心观点:**
|
||||
|
||||
从 `MeshMapCreate` 的实现来看,它主要依赖于网格节点的**几何位置**来建立映射关系。因此,如果两套网格的节点在**初始(未变形)状态下**的几何位置差异很大,那么直接进行映射可能会导致不准确或失败。
|
||||
|
||||
然而,OpenFAST(以及类似的耦合仿真工具)通常会处理这种几何差异,通过在仿真过程中**动态更新网格位置**来实现匹配。
|
||||
|
||||
### `MeshMapCreate` 的作用和限制
|
||||
|
||||
`MeshMapCreate` 子程序负责在仿真开始时建立**初始的**网格映射关系。它会:
|
||||
|
||||
1. **检查网格是否已提交**: 确保网格定义完整。
|
||||
2. **分配映射数据结构**: 为运动和载荷分配 `MeshMap%MapMotions` 和 `MeshMap%MapLoads`。
|
||||
3. **调用映射算法**: 根据网格类型(例如,Line2-to-Line2)调用 `CreateMapping_ProjectToLine2` 或 `CreateMapping_NearestNeighbor`。
|
||||
|
||||
这些映射算法的核心是:
|
||||
|
||||
* **`CreateMapping_ProjectToLine2`**: 将一个网格的节点**投影**到另一个网格的 Line2 元素上,找到最近的投影点和插值权重。
|
||||
* **`CreateMapping_NearestNeighbor`**: 找到一个网格的节点在另一个网格中的**最近邻**节点。
|
||||
|
||||
**对于您的情况:**
|
||||
|
||||
* **Aero 网格 (预弯叶片)**:这代表了叶片的**初始几何形状**,包含了预弯信息。
|
||||
* **Elast 网格 (直叶片)**:这代表了叶片的**未变形参考构型**,通常是直的。
|
||||
|
||||
如果 `MeshMapCreate` 直接尝试将预弯网格的节点映射到直网格的节点或元素上,由于几何形状的显著差异(预弯与直),**初始映射的准确性会很差,甚至可能失败**。`CreateMapping_ProjectToLine2` 会寻找最近的投影点,但如果叶片形状差异太大,投影可能落在元素之外,或者找到的“最近”元素在物理上并不对应。
|
||||
|
||||
### `CalculatePositions` 的作用和动态匹配
|
||||
|
||||
`[[CalculatePositions]]` 子程序在 OpenFAST 的弹性动力学 (Elastodynamics) 模块中扮演着关键角色。它的主要功能是:
|
||||
|
||||
* **计算各个点的瞬时位置**: 根据系统的连续状态 `x`(包括位移和旋转)和参数 `p`,计算风力机各个部件(包括塔架和叶片)在**当前时刻**的瞬时位置。
|
||||
* **考虑变形**: 特别是对于叶片,`CalculatePositions` 会根据弹性变形状态 (`x%QT(DOF_BF(K,1))` 等) 计算叶片节点的实际位置 `RtHSdat%rS`。这意味着,即使弹性部分的**参考网格**是直的,在仿真过程中,`CalculatePositions` 会根据叶片的变形(包括预弯和柔性变形)计算出其**实际的、变形后的位置**。
|
||||
|
||||
**因此,匹配的关键在于:**
|
||||
|
||||
1. **初始几何差异**: `MeshMapCreate` 在建立初始映射时,会使用网格的**初始几何位置**。如果 aero 网格是预弯的,而 elast 网格是直的,那么在**初始时刻**,这两套网格的几何形状是不同的。
|
||||
2. **动态变形**: 在仿真过程中,弹性部分的直叶片网格会根据其变形状态(包括预弯效应,如果预弯被建模为一种初始变形)计算出其**实际的、变形后的位置**。
|
||||
3. **映射的更新**: 理想情况下,映射关系应该在每个时间步或在变形显著时进行更新,以反映网格的实际几何形状。`MeshMapCreate` 的注释 `bjj: maybe the MeshMapCreate routine shouldn't actually allocate arrays; allocate them in the "IF (RemapFlag)" sections so that if people add nodes during the simulation, the structures get reallocated to correct size?` 也暗示了这种动态更新的需求。
|
||||
|
||||
### 结论和建议
|
||||
|
||||
**两套网格是否可以匹配?**
|
||||
|
||||
* **直接匹配(基于初始几何)**: 如果 aero 网格是预弯的,而 elast 网格是直的,并且 `MeshMapCreate` 仅基于它们的**初始几何位置**进行映射,那么**匹配会非常困难,甚至可能失败**。`CreateMapping_ProjectToLine2` 可能会因为几何差异过大而找不到合适的投影点,或者找到的映射关系不准确。
|
||||
* **通过动态变形匹配**: 在 OpenFAST 这样的耦合仿真中,通常会通过以下方式处理:
|
||||
1. **弹性网格的参考构型**: 弹性部分的直叶片网格是其**未变形的参考构型**。
|
||||
2. **预弯的建模**: 预弯通常被建模为弹性叶片在**初始状态下的一个变形**,或者在坐标系定义中考虑。`CalculatePositions` 会将这种预弯效应(以及其他柔性变形)计算到叶片的实际位置中。
|
||||
3. **气动网格的变形**: 气动网格(预弯叶片)在仿真过程中也会根据弹性部分的变形进行更新,使其与弹性叶片的**实际变形形状**保持一致。
|
||||
4. **映射的动态更新**: 关键在于,在每个时间步,当弹性叶片发生变形时,气动网格的**实际位置**会根据弹性叶片的变形进行更新。然后,映射算法(或其后续的数据传输逻辑)会使用这些**更新后的、变形后的位置**来传递载荷和运动。
|
||||
|
||||
**为了实现准确的匹配,通常需要确保:**
|
||||
|
||||
1. **几何一致性**: 在进行映射时,两套网格的**实际几何形状**应该尽可能接近。这意味着,如果 aero 网格是预弯的,那么在进行映射时,elast 网格也应该被“变形”到预弯状态,或者 aero 网格的节点位置是基于 elast 网格的变形来计算的。
|
||||
2. **坐标系和参考点**: 确保两套网格的坐标系定义和参考点是一致的,或者有明确的转换关系。
|
||||
3. **映射算法的鲁棒性**: `CreateMapping_ProjectToLine2` 包含了一个 7.5 毫米的容差,用于处理节点非常接近元素端点的情况。这在一定程度上增加了鲁棒性,但如果初始几何差异过大,这个容差可能不足以解决问题。
|
||||
|
||||
**具体建议:**
|
||||
|
||||
* **检查 OpenFAST 的具体实现**: 了解 OpenFAST 如何处理预弯叶片的气动-弹性耦合。通常,气动网格的节点位置会根据弹性叶片的变形(包括预弯)进行更新。这意味着,在进行映射时,气动网格的节点位置实际上是**变形后的位置**。
|
||||
* **确保 `Src` 和 `Dest` 在映射时具有相似的几何**:
|
||||
* 如果 `Src` 是 aero 网格(预弯),`Dest` 是 elast 网格(直),那么在调用 `MeshMapCreate` 之前,可能需要将 `Dest` 网格的节点位置**预先变形**到与 `Src` 相似的预弯状态,或者 `Src` 网格的初始位置是基于 `Dest` 网格的参考构型加上预弯变形来定义的。
|
||||
* 更常见的情况是,在每个时间步,弹性模块会计算出叶片的**实际变形位置**(包括预弯),然后气动模块会使用这些位置来构建其气动网格。映射发生在这些**瞬时变形位置**之间。
|
||||
* **关注错误信息**: 如果 `MeshMapCreate` 报告致命错误,例如“Node ... does not project onto any line2 element”,这通常意味着几何差异过大,导致映射失败。
|
||||
|
||||
总之,虽然 `MeshMapCreate` 依赖于几何位置,但 OpenFAST 的整体框架会通过 `CalculatePositions` 等子程序在仿真过程中动态处理叶片的变形。因此,关键在于确保在进行网格映射时,所使用的网格位置(无论是源网格还是目标网格)能够准确反映叶片的**实际几何形状**,包括预弯效应。如果初始几何差异过大,直接的静态映射会存在问题,需要通过动态更新网格位置来解决。
|
||||
[Timestamp: 2026/01/20 10:11:36]
|
||||
|
||||
**user**: [[CalculatePositions]][[CalculateAngularPosVelPAcc]]如果我在结构上使用预弯的叶片模型和网格,如何使用模态计算叶片变形量
|
||||
[Timestamp: 2026/01/21 14:35:09]
|
||||
|
||||
**ai**: 您的问题是关于在结构上使用预弯叶片模型和网格时,如何使用模态计算叶片变形量,结合 `[[CalculatePositions]]` 和 `[[CalculateAngularPosVelPAcc]]` 子程序。
|
||||
|
||||
在 OpenFAST 这样的多体动力学仿真工具中,叶片的变形通常通过**模态叠加法**来表示。这意味着叶片的总变形是其各个振动模态乘以相应的模态坐标(或广义坐标)的线性组合。
|
||||
|
||||
### 1. 预弯叶片模型和网格的结构表示
|
||||
|
||||
当您说“结构上使用预弯的叶片模型和网格”时,这通常意味着:
|
||||
|
||||
* **初始几何**: 您的叶片网格在**未变形状态下**就已经包含了预弯的几何形状。这与之前讨论的“直叶片网格”作为参考构型不同。在这种情况下,叶片的“零变形”位置已经是预弯的。
|
||||
* **模态形状**: 弹性模态(如挥舞、摆振、扭转模态)是基于这个**预弯几何**来计算的。模态形状函数 `p%TwistedSF` 和 `p%AxRedBld` 包含了叶片沿展向的几何和结构特性,它们会反映预弯的影响。
|
||||
|
||||
### 2. `CalculatePositions` 如何计算叶片变形量
|
||||
|
||||
`CalculatePositions` 子程序的核心任务是计算风力机各个部件在**当前时刻**的瞬时位置。对于叶片,它通过模态叠加来计算其变形。
|
||||
|
||||
我们来看 `CalculatePositions` 中计算叶片节点位置的关键部分:
|
||||
|
||||
```fortran
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
...
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
! Calculate the position vector of the current node:
|
||||
|
||||
RtHSdat%rS0S(:,K,J) = ( p%TwistedSF(K,1,1,J,0)*x%QT( DOF_BF(K,1) ) & ! 展向位移分量 (j1方向)
|
||||
+ p%TwistedSF(K,1,2,J,0)*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%TwistedSF(K,1,3,J,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j1(K,:) &
|
||||
+ ( p%TwistedSF(K,2,1,J,0)*x%QT( DOF_BF(K,1) ) & ! 弦向位移分量 (j2方向)
|
||||
+ p%TwistedSF(K,2,2,J,0)*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%TwistedSF(K,2,3,J,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j2(K,:) &
|
||||
+ ( p%RNodes(J) - 0.5* & ! 展向位置分量 (j3方向)
|
||||
( p%AxRedBld(K,1,1,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,1) ) &
|
||||
+ p%AxRedBld(K,2,2,J)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%AxRedBld(K,3,3,J)*x%QT( DOF_BE(K,1) )*x%QT( DOF_BE(K,1) ) &
|
||||
+ 2.0*p%AxRedBld(K,1,2,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,2) ) &
|
||||
+ 2.0*p%AxRedBld(K,2,3,J)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BE(K,1) ) &
|
||||
+ 2.0*p%AxRedBld(K,1,3,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BE(K,1) ) ) )*CoordSys%j3(K,:)
|
||||
RtHSdat%rQS (:,K,J) = RtHSdat%rS0S(:,K,J) + p%HubRad*CoordSys%j3(K,:)
|
||||
RtHSdat%rS (:,K,J) = RtHSdat%rQS (:,K,J) + RtHSdat%rQ
|
||||
END DO
|
||||
END DO
|
||||
```
|
||||
|
||||
**解释:**
|
||||
|
||||
1. **`x%QT(...)`**: `x` 是连续状态变量,`x%QT` 包含了广义坐标(模态坐标)。
|
||||
* `DOF_BF(K,1)` 和 `DOF_BF(K,2)` 通常代表叶片 `K` 的第一和第二阶**挥舞 (Flapwise)** 模态的模态坐标。
|
||||
* `DOF_BE(K,1)` 通常代表叶片 `K` 的第一阶**摆振 (Edgewise)** 模态的模态坐标。
|
||||
* (注意:这里没有直接看到扭转模态的广义坐标,但通常也会有类似的表示,可能在 `DOF_BE` 中或通过其他方式处理。)
|
||||
2. **`p%TwistedSF(K,dim,mode,J,0)`**: 这是**模态形状函数 (Mode Shape Function)**。
|
||||
* `K`: 叶片编号。
|
||||
* `dim`: 位移分量方向(1代表 `j1` 方向,2代表 `j2` 方向)。
|
||||
* `mode`: 模态索引(例如,1代表第一阶挥舞,2代表第二阶挥舞,3代表第一阶摆振)。
|
||||
* `J`: 叶片沿展向的节点索引。
|
||||
* `0`: 表示位移形状函数(而不是旋转形状函数)。
|
||||
* 这些形状函数描述了在给定模态下,叶片沿展向不同位置的**单位变形量**。它们是预先通过有限元分析(FEA)等方法计算得到的,并且**已经包含了叶片的初始预弯几何**。
|
||||
3. **`CoordSys%j1(K,:)`, `CoordSys%j2(K,:)`, `CoordSys%j3(K,:)`**: 这些是叶片 `K` 局部坐标系的单位向量。`j3` 通常沿叶片展向,`j1` 和 `j2` 垂直于 `j3`,分别代表挥舞和摆振方向。
|
||||
4. **`p%RNodes(J)`**: 这是叶片节点 `J` 沿展向的**未变形径向位置**。
|
||||
5. **`p%AxRedBld(...)`**: 这些项是**轴向缩短 (Axial Shortening)** 效应的系数,表示由于大变形引起的展向长度缩短。它们是模态坐标的二次项,用于修正叶片沿展向的实际位置。
|
||||
|
||||
**如何使用模态计算叶片变形量:**
|
||||
|
||||
叶片上任意一点 `J` 的**变形位移**可以表示为:
|
||||
|
||||
$ \vec{u}_J = \sum_{m} q_m \vec{\phi}_{m,J} $
|
||||
|
||||
其中:
|
||||
* $ \vec{u}_J $ 是节点 `J` 的变形位移向量。
|
||||
* $ q_m $ 是第 $m$ 阶模态的模态坐标(即 `x%QT(DOF_BF(K,1))` 等)。
|
||||
* $ \vec{\phi}_{m,J} $ 是第 $m$ 阶模态在节点 `J` 处的模态形状向量。
|
||||
|
||||
在 `CalculatePositions` 中,`RtHSdat%rS0S(:,K,J)` 实际上计算的是从叶片根部 (S(0)) 到当前节点 (S(RNodes(J))) 的**相对位置向量**。这个向量包含了:
|
||||
|
||||
* **未变形的展向位置**: `p%RNodes(J)` 沿 `CoordSys%j3(K,:)` 方向。
|
||||
* **模态引起的变形位移**:
|
||||
* `j1` 方向的变形:`p%TwistedSF(K,1,mode,J,0) * x%QT(DOF_BF/BE)`
|
||||
* `j2` 方向的变形:`p%TwistedSF(K,2,mode,J,0) * x%QT(DOF_BF/BE)`
|
||||
* **轴向缩短效应**: `0.5 * (p%AxRedBld(...) * x%QT(...) * x%QT(...))` 沿 `CoordSys%j3(K,:)` 方向。
|
||||
|
||||
因此,**叶片变形量**就是当前计算出的位置与叶片在**初始预弯状态下**的未变形位置之间的差异。由于 `p%TwistedSF` 已经包含了预弯几何,所以 `x%QT` 乘以 `p%TwistedSF` 得到的位移就是**相对于预弯构型的柔性变形**。
|
||||
|
||||
### 3. `CalculateAngularPosVelPAcc` 的作用
|
||||
|
||||
`CalculateAngularPosVelPAcc` 子程序计算各个部件的**角位置、角速度和角加速度**。对于叶片,它也使用模态叠加来计算其**弹性旋转**。
|
||||
|
||||
关键部分如下:
|
||||
|
||||
```fortran
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
DO J = 0,p%TipNode ! Loop through the blade nodes / elements
|
||||
...
|
||||
RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) = - p%TwistedSF(K,2,1,J,1)*CoordSys%j1(K,:) &
|
||||
+ p%TwistedSF(K,1,1,J,1)*CoordSys%j2(K,:)
|
||||
RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) = - p%TwistedSF(K,2,2,J,1)*CoordSys%j1(K,:) &
|
||||
+ p%TwistedSF(K,1,2,J,1)*CoordSys%j2(K,:)
|
||||
RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:) = - p%TwistedSF(K,2,3,J,1)*CoordSys%j1(K,:) &
|
||||
+ p%TwistedSF(K,1,3,J,1)*CoordSys%j2(K,:)
|
||||
AngVelHM = x%QDT(DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) &
|
||||
+ x%QDT(DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) &
|
||||
+ x%QDT(DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:)
|
||||
RtHSdat%AngVelEM(:,J,K ) = RtHSdat%AngVelEH + AngVelHM
|
||||
RtHSdat%AngPosHM(:,K,J ) = x%QT (DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) &
|
||||
+ x%QT (DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) &
|
||||
+ x%QT (DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:)
|
||||
...
|
||||
END DO
|
||||
END DO
|
||||
```
|
||||
|
||||
**解释:**
|
||||
|
||||
1. **`p%TwistedSF(K,dim,mode,J,1)`**: 这里的 `TwistedSF` 带有 `1` 作为最后一个索引,表示这是**旋转形状函数**(或模态斜率/扭转形状函数),而不是位移形状函数。它描述了在给定模态下,叶片沿展向不同位置的**单位旋转量**。
|
||||
2. **`x%QDT(...)`**: `x%QDT` 包含了广义速度(模态坐标的时间导数)。
|
||||
3. **`AngVelHM`**: 这是叶片节点 `J` 相对于轮毂 (H) 的弹性角速度。它通过模态速度 `x%QDT` 乘以旋转形状函数来计算。
|
||||
4. **`AngPosHM`**: 这是叶片节点 `J` 相对于轮毂 (H) 的弹性角位置。它通过模态坐标 `x%QT` 乘以旋转形状函数来计算。
|
||||
|
||||
**叶片变形量(位移和旋转)的获取:**
|
||||
|
||||
如果您想获取叶片上某个节点 `J` 的**总变形位移**和**总变形旋转**,您需要:
|
||||
|
||||
1. **位移**:
|
||||
* 从 `RtHSdat%rS(:,K,J)` 中减去叶片 `K` 节点 `J` 的**初始预弯位置**(即在 `x%QT` 都为零时的位置)。
|
||||
* `RtHSdat%rS(:,K,J)` 已经是相对于惯性坐标系的总位置。
|
||||
* **相对变形位移**:`RtHSdat%rS0S(:,K,J)` 已经包含了相对于叶片根部的变形位移(包括柔性变形和轴向缩短)。如果您需要相对于**预弯构型**的纯柔性变形,那么 `RtHSdat%rS0S(:,K,J)` 的计算结果就是这个。
|
||||
2. **旋转**:
|
||||
* `RtHSdat%AngPosHM(:,K,J)` 直接提供了叶片节点 `J` 相对于轮毂的**弹性角位置**(即弹性旋转变形量)。这通常是相对于预弯构型的额外旋转。
|
||||
* `RtHSdat%AngVelEM(:,J,K)` 提供了叶片节点 `J` 在惯性坐标系中的总角速度,其中包含了轮毂的刚体运动和叶片的弹性变形引起的角速度。
|
||||
|
||||
**总结:**
|
||||
|
||||
当结构上使用预弯的叶片模型和网格时,OpenFAST 已经将预弯几何信息编码在模态形状函数 `p%TwistedSF` 和 `p%AxRedBld` 中。
|
||||
|
||||
* `CalculatePositions` 通过将模态坐标 `x%QT` 与位移模态形状函数 `p%TwistedSF(...,0)` 叠加,并考虑轴向缩短效应 `p%AxRedBld`,来计算叶片节点相对于其根部的**变形位移**。这个位移是相对于**预弯构型**的柔性变形。
|
||||
* `CalculateAngularPosVelPAcc` 通过将模态坐标 `x%QT` 与旋转模态形状函数 `p%TwistedSF(...,1)` 叠加,来计算叶片节点相对于轮毂的**弹性角位置(旋转变形量)**。
|
||||
|
||||
因此,您不需要额外处理预弯,因为模态形状函数已经包含了预弯的影响。`x%QT` 中的模态坐标直接驱动了相对于预弯构型的柔性变形。
|
||||
[Timestamp: 2026/01/21 14:35:31]
|
||||
|
||||
**user**: 我当前模态叠加的技术路线,支持叶片预弯变形,在模态形状的使用方法上是否有区别
|
||||
[Timestamp: 2026/01/21 14:42:16]
|
||||
|
||||
**ai**: 如果您当前的模态叠加技术路线支持叶片预弯变形,那么在模态形状的使用方法上,**核心原理没有区别,但模态形状的生成方式和物理含义会包含预弯信息**。
|
||||
|
||||
让我们详细分析一下:
|
||||
|
||||
### 1. 模态叠加法的核心原理
|
||||
|
||||
模态叠加法的基本思想是将结构的任意变形表示为一系列预定义的**模态形状**(或振型)的线性组合。每个模态形状乘以一个随时间变化的**模态坐标**(或广义坐标),然后将这些乘积相加,得到结构的瞬时变形。
|
||||
|
||||
$ \vec{u}(s, t) = \sum_{i=1}^{N} q_i(t) \vec{\phi}_i(s) $
|
||||
|
||||
其中:
|
||||
* $ \vec{u}(s, t) $ 是叶片沿展向位置 $s$ 在时间 $t$ 的变形位移。
|
||||
* $ q_i(t) $ 是第 $i$ 阶模态的模态坐标(广义坐标),由仿真求解得到。
|
||||
* $ \vec{\phi}_i(s) $ 是第 $i$ 阶模态在展向位置 $s$ 处的模态形状向量。
|
||||
|
||||
### 2. 模态形状中包含预弯信息
|
||||
|
||||
当您的结构模型(例如,用于有限元分析生成模态的几何模型)本身就包含了叶片的预弯几何时,生成的模态形状 $ \vec{\phi}_i(s) $ 会自然地反映这种预弯。
|
||||
|
||||
这意味着:
|
||||
|
||||
* **参考构型**: 此时,叶片的“未变形”或“零模态坐标”状态,就是其**预弯后的几何形状**。
|
||||
* **模态形状的物理含义**: 模态形状 $ \vec{\phi}_i(s) $ 描述的是叶片在**预弯构型基础上**的**柔性变形**。例如,第一阶挥舞模态描述的是叶片在预弯状态下,如何进一步向上或向下弯曲。
|
||||
* **`p%TwistedSF` 的作用**: 在 OpenFAST 的 `CalculatePositions` 子程序中,`p%TwistedSF` 数组就是这些模态形状函数。如果您的输入模型是预弯的,那么这些 `p%TwistedSF` 值就是从预弯叶片模型中提取或计算得到的。它们已经包含了预弯对模态形状的影响。
|
||||
|
||||
### 3. 模态形状使用方法的区别(概念上而非代码实现上)
|
||||
|
||||
从代码实现的角度来看,`CalculatePositions` 和 `CalculateAngularPosVelPAcc` 子程序中模态形状 (`p%TwistedSF`) 的使用方式**没有区别**。它们仍然是将模态坐标 (`x%QT`) 乘以相应的模态形状函数来计算位移和旋转。
|
||||
|
||||
**然而,在概念和数据准备上存在关键区别:**
|
||||
|
||||
* **传统直叶片模型**:
|
||||
* 模态形状 $ \vec{\phi}_i(s) $ 是基于**直叶片**的参考构型计算的。
|
||||
* 预弯效应通常需要通过**额外的几何变换**或**初始位移**来引入,或者在气动网格中直接使用预弯几何。
|
||||
* `x%QT` 乘以 $ \vec{\phi}_i(s) $ 得到的是相对于**直叶片构型**的变形。
|
||||
|
||||
* **预弯叶片模型**:
|
||||
* 模态形状 $ \vec{\phi}_i(s) $ 是基于**预弯叶片**的参考构型计算的。
|
||||
* 预弯效应**已经内嵌在模态形状中**,不需要额外的几何变换来引入预弯。
|
||||
* `x%QT` 乘以 $ \vec{\phi}_i(s) $ 得到的是相对于**预弯叶片构型**的**柔性变形**。
|
||||
|
||||
**这意味着:**
|
||||
|
||||
1. **模态形状的生成**: 您需要确保用于生成 `p%TwistedSF` 和 `p%AxRedBld` 等参数的有限元模型(或等效梁模型)本身就包含了叶片的预弯几何。这是最关键的一步。
|
||||
2. **“零变形”状态**: 当所有模态坐标 `x%QT` 都为零时,叶片的位置将是其**预弯后的初始几何形状**,而不是完全笔直的。
|
||||
3. **变形的解释**: 此时,通过模态叠加计算出的位移和旋转,是叶片在**预弯构型基础上**的**额外柔性变形**。
|
||||
|
||||
### 总结
|
||||
|
||||
如果您当前的模态叠加技术路线支持叶片预弯变形,并且您已经使用了包含预弯几何的结构模型来生成模态形状(`p%TwistedSF` 等),那么:
|
||||
|
||||
* **代码中的模态形状使用方法不变**:`CalculatePositions` 和 `CalculateAngularPosVelPAcc` 中的计算公式保持不变。
|
||||
* **模态形状的物理含义不同**:这些模态形状本身已经包含了预弯的影响,它们描述的是相对于预弯构型的柔性变形。
|
||||
* **数据准备是关键**:确保输入的模态形状数据 (`p%TwistedSF`, `p%AxRedBld`) 是从预弯叶片模型中正确提取的。
|
||||
|
||||
这种方法是处理预弯叶片的一种常见且有效的方式,因为它将预弯视为结构初始几何的一部分,从而简化了后续的动力学计算。
|
||||
[Timestamp: 2026/01/21 14:42:27]
|
||||
175
书籍/力学书籍/OpenFast/FASTKinetics/auto/Blade.md
Normal file
175
书籍/力学书籍/OpenFast/FASTKinetics/auto/Blade.md
Normal file
@ -0,0 +1,175 @@
|
||||
|
||||
|
||||
The distributed properties of blade 1 bring about generalized inertia forces and generalized active forces associated with blade elasticity, blade damping, blade weight, and blade aerodynamics.
|
||||
叶片1的分布式特性导致与叶片弹性、叶片阻尼、叶片重量及叶片气动力相关的广义惯性力和广义主动力。
|
||||
$$
|
||||
F_{r}^{*}\big|_{B1} = -\int_{0}^{BldFlexL} \mu^{B1}(r) \, {}^E \, \boldsymbol{v}_{r}^{S1}(r) \cdot {}^E \, \boldsymbol{a}^{S1}(r) \, dr - m^{BldTip} \, {}^E \, \boldsymbol{v}_{r}^{S1}(BldFlexL) \cdot {}^E \, \boldsymbol{a}^{S1}(BldFlexL) \quad (r = 1, 2, \ldots, 22) \tag{1}
|
||||
$$
|
||||
|
||||
其中
|
||||
$$
|
||||
\mu^{B1}(r) = AdjBlMs^{B1} \cdot BMassDen^{B1}(r) \tag{2}
|
||||
$$
|
||||
|
||||
$$
|
||||
m^{B1Tip} = TipMass(1) \tag{3}
|
||||
$$
|
||||
or,
|
||||
|
||||
$$
|
||||
F_{r}^{*}\big|_{B1} = -\int_{0}^{BldFlexL} \mu^{B1}(r) \, {}^E\boldsymbol{v}_{r}^{S1}(r) \cdot \left\{
|
||||
\begin{array}{l}
|
||||
\left( \sum_{i=1}^{14} {}^{E}\boldsymbol{v}_{i}^{S1}(r) \ddot{q}_{i} \right) + \left( \sum_{i=16}^{18} {}^{E}\boldsymbol{v}_{i}^{S1}(r) \ddot{q}_{i} \right) + {}^{E}\boldsymbol{v}_{Teet}^{S1}(r) \ddot{q}_{Teet} \\
|
||||
+ \left[ \sum_{i=4}^{14} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(r) \right) \dot{q}_{i} \right] + \left[ \sum_{i=16}^{18} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(r) \right) \dot{q}_{i} \right] + \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{Teet}^{S1}(r) \right) \dot{q}_{Teet}
|
||||
\end{array}
|
||||
\right\} dr \\
|
||||
- m^{B1Tip} {}^{E}\boldsymbol{v}_{r}^{S1}(BldFlexL) \cdot \left\{
|
||||
\begin{array}{l}
|
||||
\left( \sum_{i=1}^{14} {}^{E}\boldsymbol{v}_{i}^{S1}(BldFlexL) \ddot{q}_{i} \right) + \left( \sum_{i=16}^{18} {}^{E}\boldsymbol{v}_{i}^{S1}(BldFlexL) \ddot{q}_{i} \right) + {}^{E}\boldsymbol{v}_{Teet}^{S1}(BldFlexL) \ddot{q}_{Teet} \\
|
||||
+ \left[ \sum_{i=4}^{14} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(BldFlexL) \right) \dot{q}_{i} \right] + \left[ \sum_{i=16}^{18} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(BldFlexL) \right) \dot{q}_{i} \right] \\
|
||||
+ \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{Teet}^{S1}(BldFlexL) \right) \dot{q}_{Teet}
|
||||
\end{array}
|
||||
\right\} \quad (r = 1, 2, \ldots, 14; 16, 17, 18; Teet) \tag{4}
|
||||
$$
|
||||
|
||||
因此,
|
||||
|
||||
$$
|
||||
\left[C(q,t)\right]_{B1} (\text{Row,Col}) = \int_{0}^{BldFlexL} \mu^{B1}(r) \, {}^{E}\boldsymbol{v}_{\text{Row}}^{S1}(r) \cdot {}^{E}\boldsymbol{v}_{\text{Col}}^{S1}(r) \, dr + m^{B1Tip} {}^{E}\boldsymbol{v}_{\text{Row}}^{S1}(BldFlexL) \cdot {}^{E}\boldsymbol{v}_{\text{Col}}^{S1}(BldFlexL) \quad (\text{Row, Col} = 1,2,\ldots,14;16,17,18;22) \tag{5}
|
||||
$$
|
||||
|
||||
$$
|
||||
\left\{-f(\dot{q},q,t)\right\}_{B1} (\text{Row}) = -\int_{0}^{BldFlexL} \mu^{B1}(r) \, {}^{E}\boldsymbol{v}_{\text{Row}}^{S1}(r) \cdot \left\{ \left[ \sum_{i=4}^{14} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(r) \right) \dot{q}_{i} \right] + \left[ \sum_{i=16}^{18} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(r) \right) \dot{q}_{i} \right] + \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{Teet}^{S1}(r) \right) \dot{q}_{Teet} \right\} dr \\
|
||||
- m^{B1Tip} {}^{E}\boldsymbol{v}_{\text{Row}}^{S1}(BldFlexL) \cdot \left\{ \left[ \sum_{i=4}^{14} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(BldFlexL) \right) \dot{q}_{i} \right] + \left[ \sum_{i=16}^{18} \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{i}^{S1}(BldFlexL) \right) \dot{q}_{i} \right] + \frac{d}{dt} \left( {}^{E}\boldsymbol{v}_{Teet}^{S1}(BldFlexL) \right) \dot{q}_{Teet} \right\} \quad (\text{Row} = 1,2,\ldots,14;16,17,18;22) \tag{6}
|
||||
$$
|
||||
|
||||
|
||||
$$
|
||||
F_{r}\big|_{ElasticB1} = -\frac{\partial V'^{B1}}{\partial q_r} \quad (r = 1, 2, \ldots, 22) \tag{7}
|
||||
$$
|
||||
$$
|
||||
\left. F_{r} \right|_{ElasticB1} =
|
||||
\begin{cases}
|
||||
- {k'}_{11}^{B1F} q_{B1F1} - {k'}_{12}^{B1F} q_{B1F2}
|
||||
& \text{for } r = B1F1 \\
|
||||
- {k'}_{11}^{B1E} q_{B1E1}
|
||||
& \text{for } r = B1E1 \\
|
||||
- {k'}_{21}^{B1F} q_{B1F1} - {k'}_{22}^{B1F} q_{B1F2}
|
||||
& \text{for } r = B1F2 \\
|
||||
0
|
||||
& \text{otherwise}
|
||||
\end{cases} \tag{8}
|
||||
$$
|
||||
|
||||
where $k_{\ i j}^{\,\prime B I F}$ and $\boldsymbol{k\,}_{I I}^{\prime B I E}$ are the generalized stiffnesses of blade 1 in the local flap and local edge directions respectively when centrifugal-stiffening effects are not included as follows:
|
||||
其中,$k_{ij}^{\,\prime BIF}$ 和 $\boldsymbol{k}_{II}^{\prime BIE}$ 分别为未考虑离心刚化效应时,叶片1在局部挥舞方向和局部摆振方向的广义刚度,具体如下:
|
||||
$$
|
||||
{k'}_{ij}^{B1F} = \sqrt{FlStTunr^{B1}(i) \, FlStTunr^{B1}(j)} \int_{0}^{BldFlexL} EI^{B1F}(r) \frac{d^2 \phi_i^{B1F}(r)}{dr^2} \frac{d^2 \phi_j^{B1F}(r)}{dr^2} dr \quad (i, j = 1, 2) \tag{9}
|
||||
$$
|
||||
|
||||
其中,
|
||||
|
||||
$$
|
||||
EI^{B1F}(r) = AdjFlSt^{B1} \cdot FlpStff^{B1}(r) \tag{10}
|
||||
$$
|
||||
|
||||
|
||||
$$
|
||||
{k'}_{11}^{B1E} = \int_{0}^{BldFlexL} EI^{B1E}(r) \left[ \frac{d^2 \phi_{1}^{B1E}(r)}{dr^2} \right]^2 dr \tag{11}
|
||||
$$
|
||||
|
||||
其中,
|
||||
|
||||
$$
|
||||
EI^{B1E}(r) = AdjEdSt^{B1} \cdot EdgStff^{B1}(r) \tag{12}
|
||||
$$
|
||||
|
||||
Similarly, when using the Rayleigh damping technique where the damping is assumed proportional to the stiffness, then
|
||||
同样,在使用瑞利阻尼技术(假设阻尼与刚度成正比)时,则
|
||||
$$
|
||||
\left. F_r \right|_{DampB1} =
|
||||
\begin{cases}
|
||||
-\frac{\zeta_1^{B1F} {k'}_{11}^{B1F}}{\pi f^{\prime B 1 F}_1} \dot{q}_{B1F1} - \frac{\zeta_2^{B1F} {k'}_{12}^{B1F}}{\pi f^{\prime B 1 F}_2} \dot{q}_{B1F2} & \text{for } r = B1F1 \\
|
||||
-\frac{\zeta_1^{B1E} {k'}_{11}^{B1E}}{\pi f^{\prime B 1 E}_1} \dot{q}_{B1E1} & \text{for } r = B1E1 \\
|
||||
-\frac{\zeta_1^{B1F} {k'}_{21}^{B1F}}{\pi f^{\prime B 1 F}_1} \dot{q}_{B1F1} - \frac{\zeta_2^{B1F} {k'}_{22}^{B1F}}{\pi f^{\prime B 1 F}_2} \dot{q}_{B1F2} & \text{for } r = B1F2 \\
|
||||
0 & \text{otherwise}
|
||||
\end{cases} \tag{13}
|
||||
$$
|
||||
where $\zeta_{i}^{B I F}$ and $\zeta_{i}^{B I E}$ represent the structural damping ratio of blade 1 for the $i^{\mathrm{th}}$ mode in the local flap and edge directions, $B l d F l D m p^{B 1}(i)/100$ and $B l d E d D m p^{B 1}\left(i\right)/100$ respectively. Also, ${f^{\prime}}_{i}^{B I F}$ and $\boldsymbol{f}_{\ i}^{\prime B I E}$ represent the natural frequency of blade 1 for the $i^{\mathrm{th}}$ mode in the local flap and edge directions respectively without centrifugal-stiffening effects. That is,
|
||||
其中,$\zeta_{i}^{BIF}$ 和 $\zeta_{i}^{BIE}$ 分别代表叶片1在第 $i$ 阶模态下在**挥舞**方向和**摆振**方向的结构阻尼比,对应表达式为 $BldFlDmp^{B1}(i)/100$ 和 $BldEdDmp^{B1}(i)/100$。此外,${f^{\prime}}_{i}^{B I F}$ 和 $\boldsymbol{f}_{\ i}^{\prime B I E}$ 分别表示叶片1在第 $i$ 阶模态下,**不考虑离心刚度效应**时的**挥舞**方向和**摆振**方向的固有频率。也就是说,
|
||||
$$
|
||||
f_i^{\prime B1F} = \frac{1}{2\pi} \sqrt{\frac{k_{ii}^{\prime B1F}}{m_{ii}^{\prime B1F}}} \tag{14}
|
||||
$$
|
||||
|
||||
$$
|
||||
f_i^{\prime B1E} = \frac{1}{2\pi} \sqrt{\frac{k_{ii}^{\prime B1E}}{m_{ii}^{\prime B1E}}} \tag{15}
|
||||
$$
|
||||
|
||||
where $m_{\ i i}^{\prime B I F}$ and $m_{\ i i}^{\prime B I E}$ represent the generalized mass of blade 1 for the $i^{\mathrm{th}}$ mode in the local flap and edge directions respectively without centrifugal-stiffening and tip mass effects as follows:
|
||||
其中,$m_{ii}^{\prime BIF}$ 和 $m_{ii}^{\prime BIE}$ 分别表示在未考虑离心刚化和叶尖质量效应的情况下,第 $i$ 阶模态下叶片1在**挥舞方向**和**摆振方向**的广义质量,具体定义如下:
|
||||
$$
|
||||
m_{ij}^{\prime B1F} = \int_{0}^{BldFlexL} \mu^{B1}(r) \phi_i^{B1F}(r) \phi_j^{B1F}(r) \, dr \quad (i, j = 1, 2) \tag{16}
|
||||
$$
|
||||
$$
|
||||
m_{11}^{\prime B1E} = \int_{0}^{BldFlexL} \mu^{B1}(r) \left[ \phi_1^{B1E}(r) \right]^2 dr \tag{17}
|
||||
$$
|
||||
|
||||
Thus
|
||||
$$
|
||||
[C(q,t)]|_{ElasticB1} = 0 \quad \text{and} \quad [C(q,t)]|_{DampB1} = 0 \tag{18}
|
||||
$$
|
||||
|
||||
$$
|
||||
\left. \left\{ -f(\dot{q},q,t) \right\} \right|_{ElasticB1} =
|
||||
\begin{pmatrix}
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
-k_{11}^{\prime B1F} q_{B1F1} - k_{12}^{\prime B1F} q_{B1F2} \\
|
||||
-k_{11}^{\prime B1E} q_{B1E1} \\
|
||||
-k_{21}^{\prime B1F} q_{B1F1} - k_{22}^{\prime B1F} q_{B1F2} \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots
|
||||
\end{pmatrix} \tag{19}
|
||||
$$
|
||||
|
||||
$$
|
||||
\left. \left\{ -f(\dot{q},q,t) \right\} \right|_{DampB1} =
|
||||
\begin{pmatrix}
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
-\frac{\zeta_1^{B1F} k_{11}^{\prime B1F}}{\pi f_1^{\prime B1F}} \dot{q}_{B1F1} - \frac{\zeta_2^{B1F} k_{12}^{\prime B1F}}{\pi f_2^{\prime B1F}} \dot{q}_{B1F2} \\
|
||||
-\frac{\zeta_1^{B1E} k_{11}^{\prime B1E}}{\pi f_1^{\prime B1E}} \dot{q}_{B1E1} \\
|
||||
-\frac{\zeta_1^{B1F} k_{21}^{\prime B1F}}{\pi f_1^{\prime B1F}} \dot{q}_{B1F1} - \frac{\zeta_2^{B1F} k_{22}^{\prime B1F}}{\pi f_2^{\prime B1F}} \dot{q}_{B1F2} \\
|
||||
\vdots \\
|
||||
\vdots \\
|
||||
\vdots
|
||||
\end{pmatrix} \tag{20}
|
||||
$$$$
|
||||
F_{r}\big|_{GravB1} = -\int_{0}^{BldFlexL} \mu^{B1}(r) \, \boldsymbol{g}^{E}\boldsymbol{v}_{r}^{S1}(r) \cdot \boldsymbol{{z}}_2 \, dr - m^{B1Tip} \boldsymbol{g}^{E}\boldsymbol{v}_{r}^{S1}(BldFlexL) \cdot \boldsymbol{{z}}_2 \quad (r = 3,4,\ldots,14;16,17,18;Teet)\tag{21}
|
||||
$$
|
||||
|
||||
Thus,
|
||||
$$
|
||||
[C(q,t)]|_{GravB1} = 0\tag{22}
|
||||
$$
|
||||
$$
|
||||
\left\{ -f(\dot{q}, q, t) \right\}|_{GravB1} (\text{Row}) = -\int_{0}^{BldFlexL} \mu^{B1}(r) \, g \, {}^E\boldsymbol{v}_{Row}^{S1}(r) \cdot \boldsymbol{z}_2 \, dr - m^{B1Tip} \, g \, {}^E\boldsymbol{v}_{Row}^{S1}(BldFlexL) \cdot \boldsymbol{z}_2 \quad (\text{Row} = 3, 4, \ldots, 14; 16, 17, 18; 22)\tag{23}
|
||||
$$
|
||||
|
||||
|
||||
$$
|
||||
\boldsymbol{F}_r \big|_{AeroB1} = \int_{0}^{BldFlexL} \left[ {}^E\boldsymbol{v}_r^{S1}(r) \cdot \boldsymbol{F}_{AeroB1}^{S1}(r) + {}^E\boldsymbol{\omega}_r^{M1}(r) \cdot \boldsymbol{M}_{AeroB1}^{M1}(r) \right] dr + {}^E\boldsymbol{v}_r^{S1}(BldFlexL) \cdot \boldsymbol{F}_{TipDragB1}^{S1}(BldFlexL)(r = 1, 2, \ldots, 14; 16, 17, 18; Teet)\tag{24}
|
||||
$$
|
||||
|
||||
where $F_{A e r o B 1}^{S 1}(r)$ and $M_{A e r o B 1}^{M 1}\left(r\right)$ are aerodynamic forces and pitching moments applied to point S1 on blade 1 respectively expressed per unit span. Note that $M_{A e r o B 1}^{M 1}\left(r\right)$ can include effects of both direct aerodynamic pitching moments (i.e., $\mathrm{Cm})$ ) and aerodynamic pitching moments caused by an aerodynamic offset (i.e., moments due to aerodynamic lift and drag forces acting at a distance away from the center of mass of the blade element along the aerodynamic chord).
|
||||
其中,$F_{\text{AeroB1}}^{S1}(r)$ 和 $M_{\text{AeroB1}}^{M1}(r)$ 分别表示作用于叶片1上点S1处的单位展向长度上的气动力和气动俯仰力矩。需要注意的是,$M_{\text{AeroB1}}^{M1}(r)$ 可包含两部分气动俯仰力矩的影响:一是直接气动俯仰力矩(即 $\mathrm{Cm}$),二是由气动力(升力和阻力)在叶片元素气动弦线上相对于质心产生的偏移距离所引起的气动俯仰力矩。
|
||||
$$
|
||||
[C(q,t)]|_{AeroB1} = 0\tag{25}
|
||||
$$
|
||||
|
||||
$$
|
||||
\left\{ -f(\dot{q}, q, t) \right\}|_{AeroB1} (\text{Row}) = \int_{0}^{BldFlexL} \left[ {}^E\boldsymbol{v}_{Row}^{S1}(r) \cdot \boldsymbol{F}_{AeroB1}^{S1}(r) + {}^E\boldsymbol{\omega}_{Row}^{M1}(r) \cdot \boldsymbol{M}_{AeroB1}^{M1}(r) \right] dr + {}^E\boldsymbol{v}_{Row}^{S1}(BldFlexL) \cdot \boldsymbol{F}_{TipDragB1}^{S1}(BldFlexL) \quad (\text{Row} = 1, 2, \ldots, 14; 16, 17, 18; 22)\tag{26}
|
||||
$$
|
||||
222
书籍/力学书籍/OpenFast/FASTKinetics/auto/CalculateAngularPosVelPAcc.md
Normal file
222
书籍/力学书籍/OpenFast/FASTKinetics/auto/CalculateAngularPosVelPAcc.md
Normal file
@ -0,0 +1,222 @@
|
||||
|
||||
|
||||
```fortran
|
||||
SUBROUTINE CalculateAngularPosVelPAcc( p, x, CoordSys, RtHSdat )
|
||||
!..................................................................................................................................
|
||||
|
||||
! Passed variables
|
||||
TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters
|
||||
TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time
|
||||
TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time
|
||||
TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set)
|
||||
|
||||
!Local variables
|
||||
|
||||
REAL(ReKi) :: AngVelHM (3) ! Angular velocity of eleMent J of blade K (body M) in the hub (body H).
|
||||
! REAL(ReKi) :: AngVelEN (3) ! Angular velocity of the nacelle (body N) in the inertia frame (body E for earth).
|
||||
REAL(ReKi) :: AngAccELt (3) ! Portion of the angular acceleration of the low-speed shaft (body L) in the inertia frame (body E for earth) associated with everything but the QD2T()'s.
|
||||
INTEGER(IntKi) :: J ! Counter for elements
|
||||
INTEGER(IntKi) :: K ! Counter for blades
|
||||
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
! Angular and partial angular velocities
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
|
||||
! Define the angular and partial angular velocities of all of the rigid bodies in the inertia frame:
|
||||
! NOTE: PAngVelEN(I,D,:) = the Dth-derivative of the partial angular velocity of DOF I for body N in body E.
|
||||
|
||||
RtHSdat%PAngVelEX( :,0,:) = 0.0
|
||||
RtHSdat%PAngVelEX(DOF_R ,0,:) = CoordSys%z1
|
||||
RtHSdat%PAngVelEX(DOF_P ,0,:) = -CoordSys%z3
|
||||
RtHSdat%PAngVelEX(DOF_Y ,0,:) = CoordSys%z2
|
||||
RtHSdat%AngVelEX = x%QDT(DOF_R )*RtHSdat%PAngVelEX(DOF_R ,0,:) &
|
||||
+ x%QDT(DOF_P )*RtHSdat%PAngVelEX(DOF_P ,0,:) &
|
||||
+ x%QDT(DOF_Y )*RtHSdat%PAngVelEX(DOF_Y ,0,:)
|
||||
RtHSdat%AngPosEX = x%QT (DOF_R )*RtHSdat%PAngVelEX(DOF_R ,0,:) &
|
||||
+ x%QT (DOF_P )*RtHSdat%PAngVelEX(DOF_P ,0,:) &
|
||||
+ x%QT (DOF_Y )*RtHSdat%PAngVelEX(DOF_Y ,0,:)
|
||||
|
||||
RtHSdat%PAngVelEB( :,0,:) = RtHSdat%PAngVelEX(:,0,:)
|
||||
RtHSdat%PAngVelEB(DOF_TFA1,0,:) = -p%TwrFASF(1,p%TTopNode,1)*CoordSys%a3
|
||||
RtHSdat%PAngVelEB(DOF_TSS1,0,:) = p%TwrSSSF(1,p%TTopNode,1)*CoordSys%a1
|
||||
RtHSdat%PAngVelEB(DOF_TFA2,0,:) = -p%TwrFASF(2,p%TTopNode,1)*CoordSys%a3
|
||||
RtHSdat%PAngVelEB(DOF_TSS2,0,:) = p%TwrSSSF(2,p%TTopNode,1)*CoordSys%a1
|
||||
RtHSdat%AngVelEB = RtHSdat%AngVelEX + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEB(DOF_TFA1,0,:) &
|
||||
+ x%QDT(DOF_TSS1)*RtHSdat%PAngVelEB(DOF_TSS1,0,:) &
|
||||
+ x%QDT(DOF_TFA2)*RtHSdat%PAngVelEB(DOF_TFA2,0,:) &
|
||||
+ x%QDT(DOF_TSS2)*RtHSdat%PAngVelEB(DOF_TSS2,0,:)
|
||||
RtHSdat%AngPosXB = x%QT (DOF_TFA1)*RtHSdat%PAngVelEB(DOF_TFA1,0,:) &
|
||||
+ x%QT (DOF_TSS1)*RtHSdat%PAngVelEB(DOF_TSS1,0,:) &
|
||||
+ x%QT (DOF_TFA2)*RtHSdat%PAngVelEB(DOF_TFA2,0,:) &
|
||||
+ x%QT (DOF_TSS2)*RtHSdat%PAngVelEB(DOF_TSS2,0,:)
|
||||
|
||||
RtHSdat%PAngVelEN( :,0,:)= RtHSdat%PAngVelEB(:,0,:)
|
||||
RtHSdat%PAngVelEN(DOF_Yaw ,0,:)= CoordSys%d2
|
||||
RtHSdat%AngVelEN = RtHSdat%AngVelEB + x%QDT(DOF_Yaw )*RtHSdat%PAngVelEN(DOF_Yaw ,0,:)
|
||||
|
||||
RtHSdat%PAngVelER( :,0,:)= RtHSdat%PAngVelEN(:,0,:)
|
||||
RtHSdat%PAngVelER(DOF_RFrl,0,:)= CoordSys%rfa
|
||||
RtHSdat%AngVelER = RtHSdat%AngVelEN + x%QDT(DOF_RFrl)*RtHSdat%PAngVelER(DOF_RFrl,0,:)
|
||||
|
||||
RtHSdat%PAngVelEL( :,0,:)= RtHSdat%PAngVelER(:,0,:)
|
||||
RtHSdat%PAngVelEL(DOF_GeAz,0,:)= CoordSys%c1
|
||||
RtHSdat%PAngVelEL(DOF_DrTr,0,:)= CoordSys%c1
|
||||
RtHSdat%AngVelEL = RtHSdat%AngVelER + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEL(DOF_GeAz,0,:) &
|
||||
+ x%QDT(DOF_DrTr)*RtHSdat%PAngVelEL(DOF_DrTr,0,:)
|
||||
|
||||
RtHSdat%PAngVelEH( :,0,:)= RtHSdat%PAngVelEL(:,0,:)
|
||||
RtHSdat%AngVelEH = RtHSdat%AngVelEL
|
||||
IF ( p%NumBl == 2 ) THEN ! 2-blader
|
||||
RtHSdat%PAngVelEH(DOF_Teet,0,:)= CoordSys%f2
|
||||
RtHSdat%AngVelEH = RtHSdat%AngVelEH + x%QDT(DOF_Teet)*RtHSdat%PAngVelEH(DOF_Teet,0,:)
|
||||
ENDIF
|
||||
|
||||
RtHSdat%PAngVelEG( :,0,:) = RtHSdat%PAngVelER(:,0,:)
|
||||
RtHSdat%PAngVelEG(DOF_GeAz,0,:) = p%GBRatio*CoordSys%c1
|
||||
RtHSdat%AngVelEG = RtHSdat%AngVelER + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEG(DOF_GeAz,0,:)
|
||||
|
||||
RtHSdat%PAngVelEA( :,0,:) = RtHSdat%PAngVelEN(:,0,:)
|
||||
RtHSdat%PAngVelEA(DOF_TFrl,0,:) = CoordSys%tfa
|
||||
RtHSdat%AngVelEA = RtHSdat%AngVelEN + x%QDT(DOF_TFrl)*RtHSdat%PAngVelEA(DOF_TFrl,0,:)
|
||||
|
||||
|
||||
|
||||
! Define the 1st derivatives of the partial angular velocities of all
|
||||
! of the rigid bodies in the inertia frame and the portion of the angular
|
||||
! acceleration of the rigid bodies in the inertia frame associated with
|
||||
! everything but the QD2T()'s:
|
||||
|
||||
RtHSdat%PAngVelEX( :,1,:) = 0.0
|
||||
RtHSdat%AngAccEXt = 0.0
|
||||
|
||||
RtHSdat%PAngVelEB( :,1,:) = RtHSdat%PAngVelEX(:,1,:)
|
||||
RtHSdat%PAngVelEB(DOF_TFA1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TFA1,0,:) )
|
||||
RtHSdat%PAngVelEB(DOF_TSS1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TSS1,0,:) )
|
||||
RtHSdat%PAngVelEB(DOF_TFA2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TFA2,0,:) )
|
||||
RtHSdat%PAngVelEB(DOF_TSS2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX, RtHSdat%PAngVelEB(DOF_TSS2,0,:) )
|
||||
RtHSdat%AngAccEBt = RtHSdat%AngAccEXt + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEB(DOF_TFA1,1,:) &
|
||||
+ x%QDT(DOF_TSS1)*RtHSdat%PAngVelEB(DOF_TSS1,1,:) &
|
||||
+ x%QDT(DOF_TFA2)*RtHSdat%PAngVelEB(DOF_TFA2,1,:) &
|
||||
+ x%QDT(DOF_TSS2)*RtHSdat%PAngVelEB(DOF_TSS2,1,:)
|
||||
|
||||
RtHSdat%PAngVelEN( :,1,:) = RtHSdat%PAngVelEB(:,1,:)
|
||||
RtHSdat%PAngVelEN(DOF_Yaw ,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEB, RtHSdat%PAngVelEN(DOF_Yaw ,0,:) )
|
||||
RtHSdat%AngAccENt = RtHSdat%AngAccEBt + x%QDT(DOF_Yaw )*RtHSdat%PAngVelEN(DOF_Yaw ,1,:)
|
||||
|
||||
RtHSdat%PAngVelER( :,1,:) = RtHSdat%PAngVelEN(:,1,:)
|
||||
RtHSdat%PAngVelER(DOF_RFrl,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%PAngVelER(DOF_RFrl,0,:) )
|
||||
RtHSdat%AngAccERt = RtHSdat%AngAccENt + x%QDT(DOF_RFrl)*RtHSdat%PAngVelER(DOF_RFrl,1,:)
|
||||
|
||||
RtHSdat%PAngVelEL( :,1,:) = RtHSdat%PAngVelER(:,1,:)
|
||||
RtHSdat%PAngVelEL(DOF_GeAz,1,:) = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%PAngVelEL(DOF_GeAz,0,:) )
|
||||
RtHSdat%PAngVelEL(DOF_DrTr,1,:) = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%PAngVelEL(DOF_DrTr,0,:) )
|
||||
AngAccELt = RtHSdat%AngAccERt + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEL(DOF_GeAz,1,:) &
|
||||
+ x%QDT(DOF_DrTr)*RtHSdat%PAngVelEL(DOF_DrTr,1,:)
|
||||
|
||||
RtHSdat%PAngVelEH( :,1,:) = RtHSdat%PAngVelEL(:,1,:)
|
||||
RtHSdat%AngAccEHt = AngAccELt
|
||||
IF ( p%NumBl == 2 ) THEN ! 2-blader
|
||||
RtHSdat%PAngVelEH(DOF_Teet,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, RtHSdat%PAngVelEH(DOF_Teet,0,:) )
|
||||
RtHSdat%AngAccEHt = RtHSdat%AngAccEHt + x%QDT(DOF_Teet)*RtHSdat%PAngVelEH(DOF_Teet,1,:)
|
||||
ENDIF
|
||||
|
||||
RtHSdat%PAngVelEG( :,1,:) = RtHSdat%PAngVelER(:,1,:)
|
||||
RtHSdat%PAngVelEG(DOF_GeAz,1,:) = CROSS_PRODUCT( RtHSdat%AngVelER, RtHSdat%PAngVelEG(DOF_GeAz,0,:) )
|
||||
RtHSdat%AngAccEGt = RtHSdat%AngAccERt + x%QDT(DOF_GeAz)*RtHSdat%PAngVelEG(DOF_GeAz,1,:)
|
||||
|
||||
RtHSdat%PAngVelEA( :,1,:) = RtHSdat%PAngVelEN(:,1,:)
|
||||
RtHSdat%PAngVelEA(DOF_TFrl,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEN, RtHSdat%PAngVelEA(DOF_TFrl,0,:) )
|
||||
RtHSdat%AngAccEAt = RtHSdat%AngAccENt + x%QDT(DOF_TFrl)*RtHSdat%PAngVelEA(DOF_TFrl,1,:)
|
||||
|
||||
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
DO J = 0,p%TipNode ! Loop through the blade nodes / elements
|
||||
! Define the partial angular velocities of the current node (body M(RNodes(J))) in the inertia frame:
|
||||
! NOTE: PAngVelEM(K,J,I,D,:) = the Dth-derivative of the partial angular velocity
|
||||
! of DOF I for body M of blade K, element J in body E.
|
||||
|
||||
RtHSdat%PAngVelEM(K,J, :,0,:) = RtHSdat%PAngVelEH(:,0,:)
|
||||
RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) = - p%TwistedSF(K,2,1,J,1)*CoordSys%j1(K,:) &
|
||||
+ p%TwistedSF(K,1,1,J,1)*CoordSys%j2(K,:)
|
||||
RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) = - p%TwistedSF(K,2,2,J,1)*CoordSys%j1(K,:) &
|
||||
+ p%TwistedSF(K,1,2,J,1)*CoordSys%j2(K,:)
|
||||
RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:) = - p%TwistedSF(K,2,3,J,1)*CoordSys%j1(K,:) &
|
||||
+ p%TwistedSF(K,1,3,J,1)*CoordSys%j2(K,:)
|
||||
AngVelHM = x%QDT(DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) &
|
||||
+ x%QDT(DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) &
|
||||
+ x%QDT(DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:)
|
||||
RtHSdat%AngVelEM(:,J,K ) = RtHSdat%AngVelEH + AngVelHM
|
||||
RtHSdat%AngPosHM(:,K,J ) = x%QT (DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),0,:) &
|
||||
+ x%QT (DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),0,:) &
|
||||
+ x%QT (DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),0,:)
|
||||
RtHSdat%AngAccEKt(:,J ,K) = RtHSdat%AngAccEHt + x%QDT(DOF_BF(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),1,:) &
|
||||
+ x%QDT(DOF_BF(K,2))*RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),1,:) &
|
||||
+ x%QDT(DOF_BE(K,1))*RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),1,:)
|
||||
|
||||
! Define the 1st derivatives of the partial angular velocities of the current node (body M(RNodes(J))) in the inertia frame:
|
||||
|
||||
! NOTE: These are currently unused by the code, therefore, they need not
|
||||
! be calculated. Thus, they are currently commented out. If it
|
||||
! turns out that they are ever needed (i.e., if inertias of the
|
||||
! blade elements are ever added, etc...) simply uncomment out these computations:
|
||||
! RtHSdat%PAngVelEM(K,J, :,1,:) = RtHSdat%PAngVelEH(:,1,:)
|
||||
! RtHSdat%PAngVelEM(K,J,DOF_BF(K,1),1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, PAngVelEM(K,J,DOF_BF(K,1),0,:) )
|
||||
! RtHSdat%PAngVelEM(K,J,DOF_BF(K,2),1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, PAngVelEM(K,J,DOF_BF(K,2),0,:) )
|
||||
! RtHSdat%PAngVelEM(K,J,DOF_BE(K,1),1,:) = CROSS_PRODUCT( RtHSdat%AngVelEH, PAngVelEM(K,J,DOF_BE(K,1),0,:) )
|
||||
|
||||
|
||||
END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
END DO !K = 1,p%NumBl
|
||||
|
||||
|
||||
!...............
|
||||
! tower values:
|
||||
!...............
|
||||
|
||||
DO J = 0,p%TwrNodes ! Loop through the tower nodes / elements
|
||||
|
||||
! Define the partial angular velocities (and their 1st derivatives) of the
|
||||
! current node (body F(HNodes(J)) in the inertia frame.
|
||||
! Also define the overall angular velocity of the current node in the inertia frame.
|
||||
! Also, define the portion of the angular acceleration of the current node
|
||||
! in the inertia frame associated with everything but the QD2T()'s:
|
||||
|
||||
! NOTE: PAngVelEF(J,I,D,:) = the Dth-derivative of the partial angular velocity
|
||||
! of DOF I for body F of element J in body E.
|
||||
|
||||
RtHSdat%PAngVelEF (J, :,0,:) = RtHSdat%PAngVelEX(:,0,:)
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA1,0,:) = -p%TwrFASF(1,J,1)*CoordSys%a3
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS1,0,:) = p%TwrSSSF(1,J,1)*CoordSys%a1
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA2,0,:) = -p%TwrFASF(2,J,1)*CoordSys%a3
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS2,0,:) = p%TwrSSSF(2,J,1)*CoordSys%a1
|
||||
|
||||
RtHSdat%PAngVelEF (J, :,1,:) = RtHSdat%PAngVelEX(:,1,:)
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) )
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS1,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) )
|
||||
RtHSdat%PAngVelEF (J,DOF_TFA2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) )
|
||||
RtHSdat%PAngVelEF (J,DOF_TSS2,1,:) = CROSS_PRODUCT( RtHSdat%AngVelEX , RtHSdat%PAngVelEF(J,DOF_TSS2,0,:) )
|
||||
|
||||
|
||||
RtHSdat%AngVelEF (:,J) = RtHSdat%AngVelEX + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) &
|
||||
+ x%QDT(DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) &
|
||||
+ x%QDT(DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) &
|
||||
+ x%QDT(DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,0,:)
|
||||
|
||||
RtHSdat%AngPosXF (:,J) = x%QT (DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,0,:) &
|
||||
+ x%QT (DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,0,:) &
|
||||
+ x%QT (DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,0,:) &
|
||||
+ x%QT (DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,0,:)
|
||||
RtHSdat%AngPosEF (:,J) = RtHSdat%AngPosEX + RtHSdat%AngPosXF(:,J)
|
||||
RtHSdat%AngAccEFt(:,J) = RtHSdat%AngAccEXt + x%QDT(DOF_TFA1)*RtHSdat%PAngVelEF(J,DOF_TFA1,1,:) &
|
||||
+ x%QDT(DOF_TSS1)*RtHSdat%PAngVelEF(J,DOF_TSS1,1,:) &
|
||||
+ x%QDT(DOF_TFA2)*RtHSdat%PAngVelEF(J,DOF_TFA2,1,:) &
|
||||
+ x%QDT(DOF_TSS2)*RtHSdat%PAngVelEF(J,DOF_TSS2,1,:)
|
||||
|
||||
END DO ! J
|
||||
|
||||
|
||||
END SUBROUTINE CalculateAngularPosVelPAcc
|
||||
```
|
||||
634
书籍/力学书籍/OpenFast/FASTKinetics/auto/CalculateForcesMoments.md
Normal file
634
书籍/力学书籍/OpenFast/FASTKinetics/auto/CalculateForcesMoments.md
Normal file
@ -0,0 +1,634 @@
|
||||
|
||||
```fortran
|
||||
SUBROUTINE CalculateForcesMoments( p, x, CoordSys, u, RtHSdat )
|
||||
!..................................................................................................................................
|
||||
|
||||
! Passed variables
|
||||
TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters
|
||||
TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time
|
||||
TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time
|
||||
TYPE(ED_InputType), INTENT(IN ) :: u !< The aero (blade) & nacelle forces/moments
|
||||
TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set)
|
||||
|
||||
! Local variables
|
||||
REAL(ReKi) :: TmpVec (3) ! A temporary vector used in various computations.
|
||||
REAL(ReKi) :: TmpVec1 (3) ! A temporary vector used in various computations.
|
||||
REAL(ReKi) :: TmpVec2 (3) ! A temporary vector used in various computations.
|
||||
REAL(ReKi) :: TmpVec3 (3) ! A temporary vector used in various computations.
|
||||
REAL(ReKi) :: TmpVec4 (3) ! A temporary vector used in various computations.
|
||||
REAL(ReKi) :: TmpVec5 (3) ! A temporary vector used in various computations.
|
||||
REAL(ReKi) :: Force(3) ! External force (e.g. from AeroDyn)
|
||||
REAL(ReKi) :: Moment(3) ! External moment (e.g. from AeroDyn)
|
||||
INTEGER(IntKi) :: I ! Loops through some or all of the DOFs
|
||||
INTEGER(IntKi) :: J ! Counter for elements
|
||||
INTEGER(IntKi) :: K ! Counter for blades
|
||||
INTEGER(IntKi) :: NodeNum ! Node number for blade element (on a single mesh)
|
||||
|
||||
!.....................................
|
||||
! Compute forces and moments from properties related to Aero inputs
|
||||
!FSTipDrag
|
||||
!FSAero and MMAero
|
||||
!.....................................
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
! Calculate the tip drag forces if necessary:
|
||||
!bjj: add this back when we've figured out how to handle the tip brakes:
|
||||
!RtHSdat%FSTipDrag(:,K) = m%CoordSys%m2(K,p%BldNodes,:)*SIGN( 0.5*p%AirDens*(RtHSdat%LinVelESm2(K)**2)*u%TBDrCon(K), -1.*RtHSdat%LinVelESm2(K) )
|
||||
RtHSdat%FSTipDrag = 0.0_ReKi ! Calculate the tip drag forces if necessary
|
||||
|
||||
|
||||
! Calculate the normal and tangential aerodynamic forces and the aerodynamic
|
||||
! pitching moment at the current element per unit span by calling AeroDyn,
|
||||
! if necessary:
|
||||
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
|
||||
! Calculate the aerodynamic pitching moment arm (i.e., the position vector
|
||||
! from point S on the blade to the aerodynamic center of the element):
|
||||
|
||||
RtHSdat%rSAerCen(:,J,K) = p%rSAerCenn1(K,J)*CoordSys%n1(K,J,:) + p%rSAerCenn2(K,J)*CoordSys%n2(K,J,:)
|
||||
|
||||
! rPAerCen = m%RtHS%rPQ + m%RtHS%rQS(:,K,J) + m%RtHS%rSAerCen(:,J,K) ! Position vector from teeter pin (point P) to blade analysis node aerodynamic center.
|
||||
! rAerCen = m%RtHS%rS (:,K,J) + m%RtHS%rSAerCen(:,J,K) ! Position vector from inertial frame origin to blade analysis node aerodynamic center.
|
||||
|
||||
|
||||
! fill FSAero() and MMAero() with the forces resulting from inputs u%BladeLn2Mesh(K)%Force(1:2,:) and u%BladeLn2Mesh(K)%Moment(3,:):
|
||||
! [except, we're ignoring the additional nodes we added on the mesh end points]
|
||||
|
||||
NodeNum = J ! we're ignoring the root and tip
|
||||
|
||||
if (p%UseAD14) then
|
||||
RtHSdat%FSAero(:,K,J) = ( u%BladePtLoads(K)%Force(1,NodeNum) * CoordSys%te1(K,J,:) &
|
||||
+ u%BladePtLoads(K)%Force(2,NodeNum) * CoordSys%te2(K,J,:) ) / p%DRNodes(J)
|
||||
|
||||
RtHSdat%MMAero(:,K,J) = CROSS_PRODUCT( RtHSdat%rSAerCen(:,J,K), RtHSdat%FSAero(:,K,J) )&
|
||||
+ u%BladePtLoads(K)%Moment(3,NodeNum)/p%DRNodes(J) * CoordSys%te3(K,J,:)
|
||||
else
|
||||
RtHSdat%FSAero(1,K,J) = u%BladePtLoads(K)%Force(1,NodeNum) / p%DRNodes(J)
|
||||
RtHSdat%FSAero(2,K,J) = u%BladePtLoads(K)%Force(3,NodeNum) / p%DRNodes(J)
|
||||
RtHSdat%FSAero(3,K,J) = -u%BladePtLoads(K)%Force(2,NodeNum) / p%DRNodes(J)
|
||||
|
||||
RtHSdat%MMAero(1,K,J) = u%BladePtLoads(K)%Moment(1,NodeNum) / p%DRNodes(J)
|
||||
RtHSdat%MMAero(2,K,J) = u%BladePtLoads(K)%Moment(3,NodeNum) / p%DRNodes(J)
|
||||
RtHSdat%MMAero(3,K,J) = -u%BladePtLoads(K)%Moment(2,NodeNum) / p%DRNodes(J)
|
||||
end if
|
||||
|
||||
|
||||
END DO !J
|
||||
END DO ! K
|
||||
|
||||
|
||||
!.....................................
|
||||
! PFrcS0B and PMomH0B
|
||||
!.....................................
|
||||
! RtHSdat%PFrcS0B = 0.0
|
||||
! RtHSdat%PMomH0B = 0.0
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
! Initialize the partial forces and moments (including those associated
|
||||
! with the QD2T()'s and those that are not) at the blade root (point S(0))
|
||||
! using the tip brake effects:
|
||||
|
||||
RtHSdat%PFrcS0B(:,K,:) = 0.0 ! Initialize these partial
|
||||
RtHSdat%PMomH0B(:,K,:) = 0.0 ! forces and moments to zero
|
||||
DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K
|
||||
|
||||
TmpVec1 = -p%TipMass(K)*RtHSdat%PLinVelES(K,p%TipNode,p%DOFs%PSE(K,I),0,:) ! The portion of PFrcS0B associated with the tip brake
|
||||
|
||||
RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) = TmpVec1
|
||||
RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I)) = CROSS_PRODUCT( RtHSdat%rS0S(:,K,p%TipNode), TmpVec1 ) ! The portion of PMomH0B associated with the tip brake
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K
|
||||
|
||||
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
! Integrate to find the partial forces and moments (including those associated
|
||||
! with the QD2T()'s and those that are not) at the blade root (point S(0)):
|
||||
|
||||
DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K
|
||||
|
||||
TmpVec1 = -p%BElmntMass(J,K)*RtHSdat%PLinVelES(K,J,p%DOFs%PSE(K,I),0,:) ! The portion of PFrcS0B associated with blade element J
|
||||
|
||||
RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) = RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) + TmpVec1
|
||||
RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I)) = RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I)) + &
|
||||
CROSS_PRODUCT( RtHSdat%rS0S(:,K,J), TmpVec1 ) ! The portion of PMomH0B associated with blade element J
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K
|
||||
END DO
|
||||
|
||||
|
||||
END DO
|
||||
|
||||
|
||||
!.....................................
|
||||
! FrcS0Bt and MomH0Bt
|
||||
!.....................................
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
TmpVec1 = RtHSdat%FSTipDrag(:,K) - p%TipMass(K)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccESt(:,K,p%TipNode) ) ! The portion of FrcS0Bt associated with the tip brake
|
||||
RtHSdat%FrcS0Bt(:,K) = TmpVec1
|
||||
RtHSdat%MomH0Bt(:,K) = CROSS_PRODUCT( RtHSdat%rS0S(:,K,p%TipNode), TmpVec1 ) ! The portion of MomH0Bt associated with the tip brake
|
||||
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
TmpVec1 = RtHSdat%FSAero(:,K,J)*p%DRNodes(J) - p%BElmntMass(J,K)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccESt(:,K,J) ) ! The portion of FrcS0Bt associated with blade element J
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rS0S(:,K,J), TmpVec1 ) ! The portion of MomH0Bt associated with blade element J
|
||||
TmpVec3 = RtHSdat%MMAero(:,K,J)*p%DRNodes(J) ! The total external moment applied to blade element J
|
||||
|
||||
RtHSdat%FrcS0Bt(:,K) = RtHSdat%FrcS0Bt(:,K) + TmpVec1
|
||||
RtHSdat%MomH0Bt(:,K) = RtHSdat%MomH0Bt(:,K) + TmpVec2 + TmpVec3
|
||||
|
||||
END DO !J
|
||||
|
||||
END DO !K
|
||||
|
||||
|
||||
!.....................................
|
||||
! PFrcPRot AND PMomLPRot:
|
||||
! ( requires PFrcS0B and PMomH0B)
|
||||
!.....................................
|
||||
! Initialize the partial forces and moments (including those associated
|
||||
! with the QD2T()'s and those that are not) at the teeter pin (point P) using the hub mass effects:
|
||||
|
||||
RtHSdat%PFrcPRot = 0.0 ! Initialize these partial
|
||||
RtHSdat%PMomLPRot = 0.0 ! forces and moments to zero
|
||||
DO I = 1,p%DOFs%NPCE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the hub center of mass (point C)
|
||||
|
||||
TmpVec1 = -p%HubMass*RtHSdat%PLinVelEC(p%DOFs%PCE(I),0,:) ! The portion of PFrcPRot associated with the HubMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rPC, TmpVec1 ) ! The portion of PMomLPRot associated with the HubMass
|
||||
|
||||
RtHSdat%PFrcPRot (:,p%DOFs%PCE(I)) = TmpVec1
|
||||
RtHSdat%PMomLPRot(:,p%DOFs%PCE(I)) = TmpVec2 - p%Hubg1Iner*CoordSys%g1*DOT_PRODUCT( CoordSys%g1, RtHSdat%PAngVelEH(p%DOFs%PCE(I),0,:) ) &
|
||||
- p%Hubg2Iner*CoordSys%g2*DOT_PRODUCT( CoordSys%g2, RtHSdat%PAngVelEH(p%DOFs%PCE(I),0,:) )
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the hub center of mass (point C)
|
||||
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
! Calculate the position vector from the teeter pin to the blade root:
|
||||
|
||||
!rPS0(:,K) = RtHSdat%rPQ + p%HubRad*CoordSys%j3(K,:) ! Position vector from teeter pin (point P) to blade root (point S(0)).
|
||||
|
||||
! Add the blade effects to the partial forces and moments (including those associated with the QD2T()'s and those that are
|
||||
! not) at the teeter pin (point P):
|
||||
|
||||
DO I = 1,p%DOFs%NPSE(K) ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rPS0(:,K), RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I)) ) ! The portion of PMomLPRot associated with PFrcS0B.
|
||||
|
||||
RtHSdat%PFrcPRot (:,p%DOFs%PSE(K,I)) = RtHSdat%PFrcPRot (:,p%DOFs%PSE(K,I)) + RtHSdat%PFrcS0B(:,K,p%DOFs%PSE(K,I))
|
||||
RtHSdat%PMomLPRot(:,p%DOFs%PSE(K,I)) = RtHSdat%PMomLPRot(:,p%DOFs%PSE(K,I)) + RtHSdat%PMomH0B(:,K,p%DOFs%PSE(K,I))+TmpVec
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of blade K
|
||||
|
||||
|
||||
END DO ! K
|
||||
!PRINT '(F30.20)', RtHSdat%PMomLPRot(:,11)
|
||||
!.....................................
|
||||
! FrcPRott and MomLPRott:
|
||||
! (requires FrcS0Bt and MomH0Bt)
|
||||
!.....................................
|
||||
|
||||
TmpVec1 = -p%HubMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccECt ) ! The portion of FrcPRott associated with the HubMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rPC, TmpVec1 ) ! The portion of MomLPRott associated with the HubMass
|
||||
TmpVec = p%Hubg1Iner*CoordSys%g1*DOT_PRODUCT( CoordSys%g1, RtHSdat%AngVelEH ) & ! = ( Hub inertia dyadic ) dot ( angular velocity of hub in the inertia frame )
|
||||
+ p%Hubg2Iner*CoordSys%g2*DOT_PRODUCT( CoordSys%g2, RtHSdat%AngVelEH )
|
||||
TmpVec3 = CROSS_PRODUCT( -RtHSdat%AngVelEH, TmpVec ) ! = ( -angular velocity of hub in the inertia frame ) cross ( TmpVec )
|
||||
|
||||
RtHSdat%FrcPRott(1) = TmpVec1(1) + u%HubPtLoad%Force(1,1)
|
||||
RtHSdat%FrcPRott(2) = TmpVec1(2) + u%HubPtLoad%Force(3,1)
|
||||
RtHSdat%FrcPRott(3) = TmpVec1(3) - u%HubPtLoad%Force(2,1)
|
||||
|
||||
RtHSdat%MomLPRott = TmpVec2 + TmpVec3 - p%Hubg1Iner*CoordSys%g1*DOT_PRODUCT( CoordSys%g1, RtHSdat%AngAccEHt ) &
|
||||
- p%Hubg2Iner*CoordSys%g2*DOT_PRODUCT( CoordSys%g2, RtHSdat%AngAccEHt )
|
||||
|
||||
RtHSdat%MomLPRott(1) = RtHSdat%MomLPRott(1) + u%HubPtLoad%Moment(1,1)
|
||||
RtHSdat%MomLPRott(2) = RtHSdat%MomLPRott(2) + u%HubPtLoad%Moment(3,1)
|
||||
RtHSdat%MomLPRott(3) = RtHSdat%MomLPRott(3) - u%HubPtLoad%Moment(2,1)
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
! Calculate the position vector from the teeter pin to the blade root:
|
||||
|
||||
!rPS0 = RtHSdat%rPQ + p%HubRad*m%CoordSys%j3(K,:) ! Position vector from teeter pin (point P) to blade root (point S(0)).
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rPS0(:,K), RtHSdat%FrcS0Bt(:,K) ) ! The portion of MomLPRott associated with FrcS0Bt.
|
||||
|
||||
RtHSdat%FrcPRott = RtHSdat%FrcPRott + RtHSdat%FrcS0Bt(:,K)
|
||||
RtHSdat%MomLPRott = RtHSdat%MomLPRott + RtHSdat%MomH0Bt(:,K) + TmpVec
|
||||
|
||||
END DO ! K
|
||||
|
||||
|
||||
! Define the partial forces and moments (including those associated with
|
||||
! the QD2T()'s and those that are not) at the specified point on the
|
||||
! rotor-furl axis (point V) / nacelle (body N) using the structure that
|
||||
! furls with the rotor, generator, and rotor effects.
|
||||
|
||||
!.....................................
|
||||
! PMomNGnRt and PFrcVGnRt
|
||||
! (requires PMomLPRot and PFrcPRot)
|
||||
!.....................................
|
||||
RtHSdat%PFrcVGnRt = RtHSdat%PFrcPRot ! Initialize these partial forces and
|
||||
RtHSdat%PMomNGnRt = RtHSdat%PMomLPRot ! moments using the rotor effects
|
||||
DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rVP, RtHSdat%PFrcPRot(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomNGnRt associated with the PFrcPRot
|
||||
|
||||
RtHSdat%PMomNGnRt(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomNGnRt(:,p%DOFs%SrtPS(I)) + TmpVec
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs
|
||||
DO I = 1,p%DOFs%NPDE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D)
|
||||
|
||||
TmpVec1 = -p%RFrlMass*RtHSdat%PLinVelED(p%DOFs%PDE(I) ,0,:) ! The portion of PFrcVGnRt associated with the RFrlMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rVD, TmpVec1 ) ! The portion of PMomNGnRt associated with the RFrlMass
|
||||
|
||||
RtHSdat%PFrcVGnRt(:,p%DOFs%PDE(I) ) = RtHSdat%PFrcVGnRt(:,p%DOFs%PDE(I) ) + TmpVec1
|
||||
|
||||
RtHSdat%PMomNGnRt(:,p%DOFs%PDE(I) ) = RtHSdat%PMomNGnRt(:,p%DOFs%PDE(I) ) + TmpVec2 &
|
||||
- p%RrfaIner*CoordSys%rfa*DOT_PRODUCT( CoordSys%rfa, RtHSdat%PAngVelER(p%DOFs%PDE(I) ,0,:) ) &
|
||||
- p%GenIner*CoordSys%c1 *DOT_PRODUCT( CoordSys%c1 , RtHSdat%PAngVelEG(p%DOFs%PDE(I) ,0,:) )
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the center of mass of the structure that furls with the rotor (not including rotor) (point D)
|
||||
IF ( p%DOF_Flag(DOF_GeAz) ) THEN
|
||||
|
||||
RtHSdat%PMomNGnRt(:,DOF_GeAz) = RtHSdat%PMomNGnRt(:,DOF_GeAz) & ! The previous loop (DO I = 1,NPDE) misses the DOF_GeAz-contribution to: ( Generator inertia dyadic ) dot ( partial angular velocity of the generator in the inertia frame )
|
||||
- p%GenIner*CoordSys%c1 *DOT_PRODUCT( CoordSys%c1, RtHSdat%PAngVelEG(DOF_GeAz,0,:) ) ! Thus, add this contribution if necessary.
|
||||
|
||||
ENDIF
|
||||
|
||||
!.....................................
|
||||
! FrcVGnRtt and MomNGnRtt
|
||||
! (requires FrcPRott and MomLPRott)
|
||||
!.....................................
|
||||
TmpVec1 = -p%RFrlMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEDt ) ! The portion of FrcVGnRtt associated with the RFrlMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rVD , TmpVec1 ) ! The portion of MomNGnRtt associated with the RFrlMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rVP , RtHSdat%FrcPRott ) ! The portion of MomNGnRtt associated with the FrcPRott
|
||||
TmpVec = p%RrfaIner*CoordSys%rfa*DOT_PRODUCT( CoordSys%rfa, RtHSdat%AngVelER ) ! = ( R inertia dyadic ) dot ( angular velocity of structure that furls with the rotor in the inertia frame )
|
||||
TmpVec4 = CROSS_PRODUCT( -RtHSdat%AngVelER, TmpVec ) ! = ( -angular velocity of structure that furls with the rotor in the inertia frame ) cross ( TmpVec )
|
||||
TmpVec = p%GenIner*CoordSys%c1* DOT_PRODUCT( CoordSys%c1 , RtHSdat%AngVelEG ) ! = ( Generator inertia dyadic ) dot ( angular velocity of generator in the inertia frame )
|
||||
TmpVec5 = CROSS_PRODUCT( -RtHSdat%AngVelEG, TmpVec ) ! = ( -angular velocity of generator in the inertia frame ) cross ( TmpVec )
|
||||
|
||||
RtHSdat%FrcVGnRtt = RtHSdat%FrcPRott + TmpVec1
|
||||
RtHSdat%MomNGnRtt = RtHSdat%MomLPRott + TmpVec2 + TmpVec3 + TmpVec4 + TmpVec5 &
|
||||
- p%RrfaIner*CoordSys%rfa*DOT_PRODUCT( CoordSys%rfa, RtHSdat%AngAccERt ) &
|
||||
- p%GenIner*CoordSys%c1 *DOT_PRODUCT( CoordSys%c1 , RtHSdat%AngAccEGt )
|
||||
|
||||
|
||||
!.....................................
|
||||
! PFrcWTail and PMomNTail
|
||||
!.....................................
|
||||
! Define the partial forces and moments (including those associated with the QD2T()'s and
|
||||
! those that are not) at the specified point on the tail-furl axis (point W) / nacelle (body N) using the tail effects.
|
||||
|
||||
RtHSdat%PFrcWTail = 0.0 ! Initialize these partial
|
||||
RtHSdat%PMomNTail = 0.0 ! forces and moments to zero
|
||||
DO I = 1,p%DOFs%NPIE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I)
|
||||
|
||||
TmpVec1 = -p%BoomMass*RtHSdat%PLinVelEI(p%DOFs%PIE(I),0,:) ! The portion of PFrcWTail associated with the BoomMass
|
||||
TmpVec2 = -p%TFinMass*RtHSdat%PLinVelEJ(p%DOFs%PIE(I),0,:) ! The portion of PFrcWTail associated with the TFinMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rWI, TmpVec1 ) ! The portion of PMomNTail associated with the BoomMass
|
||||
TmpVec4 = CROSS_PRODUCT( RtHSdat%rWJ, TmpVec2 ) ! The portion of PMomNTail associated with the TFinMass
|
||||
|
||||
RtHSdat%PFrcWTail(:,p%DOFs%PIE(I)) = TmpVec1 + TmpVec2
|
||||
RtHSdat%PMomNTail(:,p%DOFs%PIE(I)) = TmpVec3 + TmpVec4 - p%AtfaIner*CoordSys%tfa* &
|
||||
DOT_PRODUCT( CoordSys%tfa, RtHSdat%PAngVelEA(p%DOFs%PIE(I),0,:) )
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I)
|
||||
|
||||
!.....................................
|
||||
! FrcWTailt and MomNTailt - Forces on the tailfin
|
||||
!.....................................
|
||||
! Aerodynamic loads on TailFin CM (point K), with change of coordinate system
|
||||
Force(1:3) = (/ u%TFinCMLoads%Force (1,1), u%TFinCMLoads%Force (3,1), -u%TFinCMLoads%Force (2,1) /)
|
||||
Moment(1:3) = (/ u%TFinCMLoads%Moment(1,1), u%TFinCMLoads%Moment(3,1), -u%TFinCMLoads%Moment(2,1) /)
|
||||
|
||||
TmpVec1 = -p%BoomMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEIt ) ! The portion of FrcWTailt associated with the BoomMass
|
||||
TmpVec2 = -p%TFinMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEJt ) ! The portion of FrcWTailt associated with the TFinMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rWI , TmpVec1 ) ! The portion of MomNTailt associated with the BoomMass
|
||||
TmpVec4 = CROSS_PRODUCT( RtHSdat%rWJ , TmpVec2 ) ! The portion of MomNTailt associated with the TFinMass
|
||||
TmpVec = p%AtfaIner*CoordSys%tfa*DOT_PRODUCT( CoordSys%tfa, RtHSdat%AngVelEA ) ! = ( A inertia dyadic ) dot ( angular velocity of the tail in the inertia frame )
|
||||
TmpVec5 = CROSS_PRODUCT( -RtHSdat%AngVelEA, TmpVec ) ! = ( -angular velocity of the tail in the inertia frame ) cross ( TmpVec )
|
||||
|
||||
RtHSdat%FrcWTailt = Force + TmpVec1 + TmpVec2
|
||||
RtHSdat%MomNTailt = Moment + TmpVec3 + TmpVec4 + TmpVec5 &
|
||||
+ CROSS_PRODUCT( RtHSdat%rWJ , Force ) & ! The portion of MomNTailt associated with Force with lever arm WK
|
||||
- p%AtfaIner*CoordSys%tfa*DOT_PRODUCT( CoordSys%tfa, RtHSdat%AngAccEAt )
|
||||
|
||||
!.....................................
|
||||
! PFrcONcRt and PMomBNcRt
|
||||
! (requires PFrcVGnRt, PMomNGnRt, PFrcWTail, PMomNTail, )
|
||||
!.....................................
|
||||
|
||||
! Define the partial forces and moments (including those associated with
|
||||
! the QD2T()'s and those that are not) at the yaw bearing (point O) /
|
||||
! base plate (body B) using the nacelle, generator, rotor, and tail effects.
|
||||
|
||||
RtHSdat%PFrcONcRt = RtHSdat%PFrcVGnRt + RtHSdat%PFrcWTail ! Initialize these partial forces and moments using
|
||||
RtHSdat%PMomBNcRt = RtHSdat%PMomNGnRt + RtHSdat%PMomNTail ! the rotor, rotor-furl, generator, and tail effects
|
||||
DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rOV, RtHSdat%PFrcVGnRt(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomBNcRt associated with the PFrcVGnRt
|
||||
|
||||
RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) + TmpVec
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs
|
||||
DO I = 1,p%DOFs%NPIE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I)
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rOW, RtHSdat%PFrcWTail(:,p%DOFs%PIE(I) ) ) ! The portion of PMomBNcRt associated with the PFrcWTail
|
||||
|
||||
RtHSdat%PMomBNcRt(:,p%DOFs%PIE(I) ) = RtHSdat%PMomBNcRt(:,p%DOFs%PIE(I) ) + TmpVec
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tail boom center of mass (point I)
|
||||
DO I = 1,p%DOFs%NPUE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U)
|
||||
|
||||
TmpVec1 = -p%NacMass*RtHSdat%PLinVelEU(p%DOFs%PUE(I),0,:) ! The portion of PFrcONcRt associated with the NacMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rOU, TmpVec1 ) ! The portion of PMomBNcRt associated with the NacMass
|
||||
|
||||
RtHSdat%PFrcONcRt(:,p%DOFs%PUE(I) ) = RtHSdat%PFrcONcRt(:,p%DOFs%PUE(I) ) + TmpVec1
|
||||
RtHSdat%PMomBNcRt(:,p%DOFs%PUE(I) ) = RtHSdat%PMomBNcRt(:,p%DOFs%PUE(I) ) + TmpVec2 - p%Nacd2Iner*CoordSys%d2* &
|
||||
DOT_PRODUCT( CoordSys%d2, RtHSdat%PAngVelEN(p%DOFs%PUE(I),0,:) )
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the nacelle center of mass (point U)
|
||||
|
||||
|
||||
!.....................................
|
||||
! FrcONcRtt and MomBNcRtt
|
||||
! (requires FrcVGnRtt, MomNGnRtt, FrcWTailt, MomNTailt)
|
||||
!.....................................
|
||||
|
||||
TmpVec1 = -p%NacMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEUt ) ! The portion of FrcONcRtt associated with the NacMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rOU, TmpVec1 ) ! The portion of MomBNcRtt associated with the NacMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rOV, RtHSdat%FrcVGnRtt ) ! The portion of MomBNcRtt associated with the FrcVGnRtt
|
||||
TmpVec4 = CROSS_PRODUCT( RtHSdat%rOW, RtHSdat%FrcWTailt ) ! The portion of MomBNcRtt associated with the FrcWTailt
|
||||
TmpVec = p%Nacd2Iner*CoordSys%d2*DOT_PRODUCT( CoordSys%d2, RtHSdat%AngVelEN ) ! = ( Nacelle inertia dyadic ) dot ( angular velocity of nacelle in the inertia frame )
|
||||
|
||||
RtHSdat%FrcONcRtt = RtHSdat%FrcVGnRtt + RtHSdat%FrcWTailt + TmpVec1 + (/ u%NacelleLoads%Force(1,1), u%NacelleLoads%Force(3,1), -u%NacelleLoads%Force(2,1) /)
|
||||
|
||||
RtHSdat%MomBNcRtt = RtHSdat%MomNGnRtt + RtHSdat%MomNTailt + TmpVec2 + TmpVec3 + TmpVec4 &
|
||||
+ CROSS_PRODUCT( -RtHSdat%AngVelEN, TmpVec ) & ! = ( -angular velocity of nacelle in the inertia frame ) cross ( TmpVec ) &
|
||||
- p%Nacd2Iner*CoordSys%d2*DOT_PRODUCT( CoordSys%d2, RtHSdat%AngAccENt ) &
|
||||
+ (/ u%NacelleLoads%Moment(1,1), u%NacelleLoads%Moment(3,1), -u%NacelleLoads%Moment(2,1) /)
|
||||
|
||||
!.....................................
|
||||
! PFTHydro and PMFHydro
|
||||
! (requires TwrAddedMass)
|
||||
!.....................................
|
||||
|
||||
! Compute the partial hydrodynamic forces and moments per unit length
|
||||
! (including those associated with the QD2T()'s and those that are not) at the current tower element (point T) / (body F):
|
||||
|
||||
! NOTE: These forces are named PFTHydro, PMFHydro, FTHydrot, and MFHydrot. However, the names should not imply that the
|
||||
! forces are a result of hydrodynamic contributions only. These tower forces contain contributions from any external
|
||||
! load acting on the tower other than loads transmitted from aerodynamics. For example, these tower forces contain
|
||||
! contributions from foundation stiffness and damping [not floating] or mooring line restoring and damping,
|
||||
! as well as hydrostatic and hydrodynamic contributions [offshore].
|
||||
|
||||
DO J=1,p%TwrNodes
|
||||
|
||||
RtHSdat%PFTHydro(:,J,:) = 0.0
|
||||
RtHSdat%PMFHydro(:,J,:) = 0.0
|
||||
DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower
|
||||
|
||||
RtHSdat%PFTHydro(:,J,p%DOFs%PTE(I)) = &
|
||||
CoordSys%z1*( - u%TwrAddedMass(DOF_Sg,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Sg,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Sg,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) &
|
||||
- CoordSys%z3*( - u%TwrAddedMass(DOF_Sw,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Sw,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Sw,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) &
|
||||
+ CoordSys%z2*( - u%TwrAddedMass(DOF_Hv,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Hv,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Hv,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) )
|
||||
RtHSdat%PMFHydro(:,J,p%DOFs%PTE(I)) = &
|
||||
CoordSys%z1*( - u%TwrAddedMass(DOF_R ,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_R ,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_R ,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) &
|
||||
- CoordSys%z3*( - u%TwrAddedMass(DOF_P ,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_P ,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_P ,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) ) &
|
||||
+ CoordSys%z2*( - u%TwrAddedMass(DOF_Y ,DOF_Sg,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Y ,DOF_Sw,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_Hv,J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,2) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_R ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,1) &
|
||||
+ u%TwrAddedMass(DOF_Y ,DOF_P ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,3) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_Y ,J)*RtHSdat%PAngVelEF(J,p%DOFs%PTE(I),0,2) )
|
||||
|
||||
END DO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower
|
||||
END DO !J
|
||||
|
||||
!.....................................
|
||||
! FTHydrot and MFHydrot
|
||||
! (requires TwrAddedMass)
|
||||
!.....................................
|
||||
|
||||
DO J=1,p%TwrNodes
|
||||
RtHSdat%FTHydrot(:,J) = CoordSys%z1*( u%TowerPtLoads%Force(DOF_Sg,J)/abs(p%DHNodes(J)) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Sg,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Sg,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Sg,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) &
|
||||
- CoordSys%z3*( u%TowerPtLoads%Force(DOF_Sw,J)/abs(p%DHNodes(J)) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Sw,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Sw,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Sw,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) &
|
||||
+ CoordSys%z2*( u%TowerPtLoads%Force(DOF_Hv,J)/abs(p%DHNodes(J)) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Hv,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Hv,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Hv,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) )
|
||||
RtHSdat%MFHydrot(:,J) = CoordSys%z1*( u%TowerPtLoads%Moment(DOF_R-3,J)/abs(p%DHNodes(J)) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_R ,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_R ,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) &
|
||||
- u%TwrAddedMass(DOF_R ,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) &
|
||||
- CoordSys%z3*( u%TowerPtLoads%Moment(DOF_P-3 ,J)/abs(p%DHNodes(J)) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_P ,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_P ,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) &
|
||||
- u%TwrAddedMass(DOF_P ,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) ) &
|
||||
+ CoordSys%z2*( u%TowerPtLoads%Moment(DOF_Y-3 ,J)/abs(p%DHNodes(J)) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_Sg,J)*RtHSdat%LinAccETt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Y ,DOF_Sw,J)*RtHSdat%LinAccETt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_Hv,J)*RtHSdat%LinAccETt(2,J) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_R ,J)*RtHSdat%AngAccEFt(1,J) &
|
||||
+ u%TwrAddedMass(DOF_Y ,DOF_P ,J)*RtHSdat%AngAccEFt(3,J) &
|
||||
- u%TwrAddedMass(DOF_Y ,DOF_Y ,J)*RtHSdat%AngAccEFt(2,J) )
|
||||
|
||||
END DO !J
|
||||
|
||||
!.....................................
|
||||
! PFrcT0Trb and PMomX0Trb
|
||||
! (requires PFrcONcRt, PMomBNcRt, PFrcT0Trb, PMomX0Trb, PFTHydro, PMFHydro)
|
||||
!.....................................
|
||||
|
||||
! Initialize the partial forces and moments (including those associated
|
||||
! with the QD2T()'s and those that are not) at the tower base (point T(0)) using everything but the tower:
|
||||
|
||||
RtHSdat%PFrcT0Trb = RtHSdat%PFrcONcRt ! Initialize these partial forces and moments
|
||||
RtHSdat%PMomX0Trb = RtHSdat%PMomBNcRt ! using all of the effects above the yaw bearing
|
||||
DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rT0O, RtHSdat%PFrcONcRt(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomX0Trb associated with the PFrcONcRt
|
||||
|
||||
RtHSdat%PMomX0Trb(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomX0Trb(:,p%DOFs%SrtPS(I)) + TmpVec
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs
|
||||
DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O)
|
||||
|
||||
TmpVec1 = -p%YawBrMass*RtHSdat%PLinVelEO(p%DOFs%PTE(I),0,:) ! The portion of PFrcT0Trb associated with the YawBrMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0O, TmpVec1 ) ! The portion of PMomX0Trb associated with the YawBrMass
|
||||
|
||||
RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I) ) = RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I) ) + TmpVec1
|
||||
RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I) ) = RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I) ) + TmpVec2
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the yaw bearing center of mass (point O)
|
||||
|
||||
TmpVec1 = -p%YawBrMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEOt ) ! The portion of FrcT0Trbt associated with the YawBrMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0O, TmpVec1 ) ! The portion of MomX0Trbt associated with the YawBrMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rT0O, RtHSdat%FrcONcRtt ) ! The portion of MomX0Trbt associated with the FrcONcRtt
|
||||
|
||||
RtHSdat%FrcT0Trbt = RtHSdat%FrcONcRtt + TmpVec1
|
||||
RtHSdat%MomX0Trbt = RtHSdat%MomBNcRtt + TmpVec2 + TmpVec3
|
||||
|
||||
! Integrate to find the total partial forces and moments (including those
|
||||
! associated with the QD2T()'s and those that are not) at the tower base (point T(0)):
|
||||
DO J=1,p%TwrNodes
|
||||
|
||||
DO I = 1,p%DOFs%NPTE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower
|
||||
|
||||
TmpVec1 = RtHSdat%PFTHydro(:,J,p%DOFs%PTE(I))*abs(p%DHNodes(J)) - p%TElmntMass(J)*RtHSdat%PLinVelET(J,p%DOFs%PTE(I),0,:) ! The portion of PFrcT0Trb associated with tower element J
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0T(:,J), TmpVec1 ) ! The portion of PMomX0Trb associated with tower element J
|
||||
TmpVec3 = RtHSdat%PMFHydro(:,J,p%DOFs%PTE(I))*abs(p%DHNodes(J)) ! The added moment applied at tower element J
|
||||
|
||||
RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I)) = RtHSdat%PFrcT0Trb(:,p%DOFs%PTE(I)) + TmpVec1
|
||||
RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I)) = RtHSdat%PMomX0Trb(:,p%DOFs%PTE(I)) + TmpVec2 + TmpVec3
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the tower
|
||||
|
||||
TmpVec1 = ( RtHSdat%FTHydrot(:,J) )*abs(p%DHNodes(J)) &
|
||||
- p%TElmntMass(J)*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccETt(:,J) ) ! The portion of FrcT0Trbt associated with tower element J
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rT0T(:,J), TmpVec1 ) ! The portion of MomX0Trbt associated with tower element J
|
||||
TmpVec3 = ( RtHSdat%MFHydrot(:,J) )*abs(p%DHNodes(J)) ! The external moment applied to tower element J
|
||||
|
||||
RtHSdat%FrcT0Trbt = RtHSdat%FrcT0Trbt + TmpVec1
|
||||
|
||||
RtHSdat%MomX0Trbt = RtHSdat%MomX0Trbt + TmpVec2 + TmpVec3
|
||||
|
||||
END DO !J
|
||||
|
||||
!.....................................
|
||||
! PFZHydro and PMXHydro
|
||||
! ( requires PtfmAddedMass )
|
||||
!.....................................
|
||||
|
||||
!..................................................................................................................................
|
||||
! Compute the partial platform forces and moments (including those associated with the QD2T()'s and those that are not) at the
|
||||
! platform reference (point Z) / (body X).
|
||||
!
|
||||
! NOTE: These forces are named PFZHydro, PMXHydro, FZHydrot, and MXHydrot. However, the names should not imply that the forces
|
||||
! are a result of hydrodynamic contributions only. These platform forces contain contributions from any external load acting
|
||||
! on the platform other than loads transmitted from the wind turbine. For example, these platform forces contain contributions
|
||||
! from foundation stiffness and damping [not floating] or mooring line restoring and damping [floating], as well as hydrostatic
|
||||
! and hydrodynamic contributions [offshore].
|
||||
!bjj: m%RtHS%PFZHydro, %PMXHydro, %FZHydrot, and %MXHydrot are not used in the output routine anymore
|
||||
! (because of their dependence on inputs, u)
|
||||
|
||||
RtHSdat%PFZHydro = 0.0
|
||||
RtHSdat%PMXHydro = 0.0
|
||||
DO I = 1,p%DOFs%NPYE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y)
|
||||
|
||||
RtHSdat%PFZHydro(p%DOFs%PYE(I),:) = - u%PtfmAddedMass(DOF_Sg,p%DOFs%PYE(I))*RtHSdat%PLinVelEZ(DOF_Sg,0,:) &
|
||||
- u%PtfmAddedMass(DOF_Sw,p%DOFs%PYE(I))*RtHSdat%PLinVelEZ(DOF_Sw,0,:) &
|
||||
- u%PtfmAddedMass(DOF_Hv,p%DOFs%PYE(I))*RtHSdat%PLinVelEZ(DOF_Hv,0,:)
|
||||
RtHSdat%PMXHydro(p%DOFs%PYE(I),:) = - u%PtfmAddedMass(DOF_R ,p%DOFs%PYE(I))*RtHSdat%PAngVelEX(DOF_R ,0,:) &
|
||||
- u%PtfmAddedMass(DOF_P ,p%DOFs%PYE(I))*RtHSdat%PAngVelEX(DOF_P ,0,:) &
|
||||
- u%PtfmAddedMass(DOF_Y ,p%DOFs%PYE(I))*RtHSdat%PAngVelEX(DOF_Y ,0,:)
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y)
|
||||
|
||||
RtHSdat%FZHydrot = u%PlatformPtMesh%Force(DOF_Sg,1)*RtHSdat%PLinVelEZ(DOF_Sg,0,:) &
|
||||
+ u%PlatformPtMesh%Force(DOF_Sw,1)*RtHSdat%PLinVelEZ(DOF_Sw,0,:) &
|
||||
+ u%PlatformPtMesh%Force(DOF_Hv,1)*RtHSdat%PLinVelEZ(DOF_Hv,0,:)
|
||||
RtHSdat%MXHydrot = u%PlatformPtMesh%Moment(DOF_R-3,1)*RtHSdat%PAngVelEX(DOF_R ,0,:) &
|
||||
+ u%PlatformPtMesh%Moment(DOF_P-3,1)*RtHSdat%PAngVelEX(DOF_P ,0,:) &
|
||||
+ u%PlatformPtMesh%Moment(DOF_Y-3,1)*RtHSdat%PAngVelEX(DOF_Y ,0,:)
|
||||
|
||||
!.....................................
|
||||
! PFrcZAll and PMomXAll
|
||||
! (requires PFrcT0Trb, PMomX0Trb, PFZHydro, PMXHydro )
|
||||
!.....................................
|
||||
|
||||
! Define the partial forces and moments (including those associated with the QD2T()'s and those that are not) at the
|
||||
! platform reference (point Z) / (body X) using the turbine and platform effects:
|
||||
|
||||
RtHSdat%PFrcZAll = RtHSdat%PFrcT0Trb ! Initialize these partial forces and moments
|
||||
RtHSdat%PMomXAll = RtHSdat%PMomX0Trb ! using the effects from the wind turbine
|
||||
DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs
|
||||
|
||||
TmpVec = CROSS_PRODUCT( RtHSdat%rZT0, RtHSdat%PFrcT0Trb(:,p%DOFs%SrtPS(I)) ) ! The portion of PMomXAll associated with the PFrcT0Trb
|
||||
|
||||
RtHSdat%PMomXAll(:,p%DOFs%SrtPS(I)) = RtHSdat%PMomXAll(:,p%DOFs%SrtPS(I)) + TmpVec
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs
|
||||
DO I = 1,p%DOFs%NPYE ! Loop through all active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y)
|
||||
|
||||
TmpVec1 = -p%PtfmMass*RtHSdat%PLinVelEY(p%DOFs%PYE(I),0,:) ! The portion of PFrcZAll associated with the PtfmMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rZY , TmpVec1 ) ! The portion of PMomXAll associated with the PtfmMass
|
||||
|
||||
RtHSdat%PFrcZAll(:,p%DOFs%PYE(I)) = RtHSdat%PFrcZAll(:,p%DOFs%PYE(I) ) + RtHSdat%PFZHydro(p%DOFs%PYE(I),:) + TmpVec1
|
||||
RtHSdat%PMomXAll(:,p%DOFs%PYE(I)) = RtHSdat%PMomXAll(:,p%DOFs%PYE(I) ) + RtHSdat%PMXHydro(p%DOFs%PYE(I),:) + TmpVec2 &
|
||||
- p%PtfmRIner*CoordSys%a1*DOT_PRODUCT( CoordSys%a1, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) &
|
||||
- p%PtfmYIner*CoordSys%a2*DOT_PRODUCT( CoordSys%a2, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) ) &
|
||||
- p%PtfmPIner*CoordSys%a3*DOT_PRODUCT( CoordSys%a3, RtHSdat%PAngVelEX(p%DOFs%PYE(I),0,:) )
|
||||
|
||||
ENDDO ! I - All active (enabled) DOFs that contribute to the QD2T-related linear accelerations of the platform center of mass (point Y)
|
||||
|
||||
!.....................................
|
||||
! FrcZAllt and MomXAllt
|
||||
! (requires FrcT0Trbt, MomX0Trbt)
|
||||
!.....................................
|
||||
|
||||
TmpVec1 = -p%PtfmMass*( p%Gravity*CoordSys%z2 + RtHSdat%LinAccEYt ) ! The portion of FrcZAllt associated with the PtfmMass
|
||||
TmpVec2 = CROSS_PRODUCT( RtHSdat%rZY , TmpVec1 ) ! The portion of MomXAllt associated with the PtfmMass
|
||||
TmpVec3 = CROSS_PRODUCT( RtHSdat%rZT0 , RtHSdat%FrcT0Trbt ) ! The portion of MomXAllt associated with the FrcT0Trbt
|
||||
TmpVec = p%PtfmRIner*CoordSys%a1*DOT_PRODUCT( CoordSys%a1, RtHSdat%AngVelEX ) & ! = ( Platform inertia dyadic ) dot ( angular velocity of platform in the inertia frame )
|
||||
+ p%PtfmYIner*CoordSys%a2*DOT_PRODUCT( CoordSys%a2, RtHSdat%AngVelEX ) &
|
||||
+ p%PtfmPIner*CoordSys%a3*DOT_PRODUCT( CoordSys%a3, RtHSdat%AngVelEX )
|
||||
TmpVec4 = CROSS_PRODUCT( -RtHSdat%AngVelEX, TmpVec ) ! = ( -angular velocity of platform in the inertia frame ) cross ( TmpVec )
|
||||
|
||||
RtHSdat%FrcZAllt = RtHSdat%FrcT0Trbt + RtHSdat%FZHydrot + TmpVec1
|
||||
RtHSdat%MomXAllt = RtHSdat%MomX0Trbt + RtHSdat%MXHydrot + TmpVec2 + TmpVec3 + TmpVec4
|
||||
|
||||
|
||||
END SUBROUTINE CalculateForcesMoments
|
||||
```
|
||||
143
书籍/力学书籍/OpenFast/FASTKinetics/auto/CalculatePositions.md
Normal file
143
书籍/力学书籍/OpenFast/FASTKinetics/auto/CalculatePositions.md
Normal file
@ -0,0 +1,143 @@
|
||||
|
||||
```fortran
|
||||
SUBROUTINE CalculatePositions( p, x, CoordSys, RtHSdat )
|
||||
!..................................................................................................................................
|
||||
|
||||
! Passed variables
|
||||
TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters
|
||||
TYPE(ED_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time
|
||||
TYPE(ED_CoordSys), INTENT(IN ) :: CoordSys !< The coordinate systems that have been set for these states/time
|
||||
TYPE(ED_RtHndSide), INTENT(INOUT) :: RtHSdat !< data from the RtHndSid module (contains positions to be set)
|
||||
|
||||
!Local variables
|
||||
!REAL(R8Ki) :: rQ (3) ! Position vector from inertial frame origin to apex of rotation (point Q).
|
||||
|
||||
INTEGER(IntKi) :: J ! Counter for elements
|
||||
INTEGER(IntKi) :: K ! Counter for blades
|
||||
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
! Positions
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
|
||||
! Define the position vectors between the various points on the wind turbine
|
||||
! that are not dependent on the distributed tower or blade parameters:
|
||||
|
||||
RtHSdat%rZ = x%QT(DOF_Sg)* CoordSys%z1 + x%QT(DOF_Hv)* CoordSys%z2 - x%QT(DOF_Sw)* CoordSys%z3 ! Position vector from inertia frame origin to platform reference (point Z).
|
||||
RtHSdat%rZY = p%rZYzt* CoordSys%a2 + p%PtfmCMxt*CoordSys%a1 - p%PtfmCMyt*CoordSys%a3 ! Position vector from platform reference (point Z) to platform mass center (point Y).
|
||||
RtHSdat%rZT0 = p%rZT0zt* CoordSys%a2 ! Position vector from platform reference (point Z) to tower base (point T(0))
|
||||
RtHSdat%rZO = ( x%QT(DOF_TFA1) + x%QT(DOF_TFA2) )*CoordSys%a1 & ! Position vector from platform reference (point Z) to tower-top / base plate (point O).
|
||||
+ ( p%RefTwrHt - 0.5*( p%AxRedTFA(1,1,p%TTopNode)*x%QT(DOF_TFA1)*x%QT(DOF_TFA1) &
|
||||
+ p%AxRedTFA(2,2,p%TTopNode)*x%QT(DOF_TFA2)*x%QT(DOF_TFA2) &
|
||||
+ 2.0*p%AxRedTFA(1,2,p%TTopNode)*x%QT(DOF_TFA1)*x%QT(DOF_TFA2) &
|
||||
+ p%AxRedTSS(1,1,p%TTopNode)*x%QT(DOF_TSS1)*x%QT(DOF_TSS1) &
|
||||
+ p%AxRedTSS(2,2,p%TTopNode)*x%QT(DOF_TSS2)*x%QT(DOF_TSS2) &
|
||||
+ 2.0*p%AxRedTSS(1,2,p%TTopNode)*x%QT(DOF_TSS1)*x%QT(DOF_TSS2) ) )*CoordSys%a2 &
|
||||
+ ( x%QT(DOF_TSS1) + x%QT(DOF_TSS2) )*CoordSys%a3
|
||||
RtHSdat%rOU = p%NacCMxn*CoordSys%d1 + p%NacCMzn *CoordSys%d2 - p%NacCMyn *CoordSys%d3 ! Position vector from tower-top / base plate (point O) to nacelle center of mass (point U).
|
||||
RtHSdat%rOV = p%RFrlPnt_n(1)*CoordSys%d1 + p%RFrlPnt_n(3)*CoordSys%d2 - p%RFrlPnt_n(2)*CoordSys%d3 ! Position vector from tower-top / base plate (point O) to specified point on rotor-furl axis (point V).
|
||||
RtHSdat%rVIMU = p%rVIMUxn*CoordSys%rf1 + p%rVIMUzn *CoordSys%rf2 - p%rVIMUyn *CoordSys%rf3 ! Position vector from specified point on rotor-furl axis (point V) to nacelle IMU (point IMU).
|
||||
RtHSdat%rVD = p%rVDxn*CoordSys%rf1 + p%rVDzn *CoordSys%rf2 - p%rVDyn *CoordSys%rf3 ! Position vector from specified point on rotor-furl axis (point V) to center of mass of structure that furls with the rotor (not including rotor) (point D).
|
||||
RtHSdat%rVP = p%rVPxn*CoordSys%rf1 + p%rVPzn *CoordSys%rf2 - p%rVPyn *CoordSys%rf3 + p%OverHang*CoordSys%c1 ! Position vector from specified point on rotor-furl axis (point V) to teeter pin (point P).
|
||||
RtHSdat%rPQ = -p%UndSling*CoordSys%g1 ! Position vector from teeter pin (point P) to apex of rotation (point Q).
|
||||
RtHSdat%rQC = p%HubCM*CoordSys%g1 ! Position vector from apex of rotation (point Q) to hub center of mass (point C).
|
||||
RtHSdat%rOW = p%TFrlPnt_n(1)*CoordSys%d1 + p%TFrlPnt_n(3) *CoordSys%d2 - p%TFrlPnt_n(2)*CoordSys%d3 ! Position vector from tower-top / base plate (point O) to specified point on tail-furl axis (point W).
|
||||
RtHSdat%rWI = p%rWIxn*CoordSys%tf1 + p%rWIzn*CoordSys%tf2 - p%rWIyn*CoordSys%tf3 ! Position vector from specified point on tail-furl axis (point W) to tail boom center of mass (point I).
|
||||
RtHSdat%rWJ = p%rWJxn*CoordSys%tf1 + p%rWJzn*CoordSys%tf2 - p%rWJyn*CoordSys%tf3 ! Position vector from specified point on tail-furl axis (point W) to tail fin center of mass (point J).
|
||||
RtHSdat%rPC = RtHSdat%rPQ + RtHSdat%rQC ! Position vector from teeter pin (point P) to hub center of mass (point C).
|
||||
RtHSdat%rT0O = RtHSdat%rZO - RtHSdat%rZT0 ! Position vector from the tower base (point T(0)) to tower-top / base plate (point O).
|
||||
RtHSdat%rO = RtHSdat%rZ + RtHSdat%rZO ! Position vector from inertial frame origin to tower-top / base plate (point O).
|
||||
RtHSdat%rV = RtHSdat%rO + RtHSdat%rOV ! Position vector from inertial frame origin to specified point on rotor-furl axis (point V)
|
||||
!RtHSdat%rP = RtHSdat%rO + RtHSdat%rOV + RtHSdat%rVP ! Position vector from inertial frame origin to teeter pin (point P).
|
||||
RtHSdat%rP = RtHSdat%rV + RtHSdat%rVP ! Position vector from inertial frame origin to teeter pin (point P).
|
||||
RtHSdat%rQ = RtHSdat%rP + RtHSdat%rPQ ! Position vector from inertial frame origin to apex of rotation (point Q).
|
||||
RtHSdat%rJ = RtHSdat%rO + RtHSdat%rOW + RtHSdat%rWJ ! Position vector from inertial frame origin to tail fin center of mass (point J).
|
||||
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through all blades
|
||||
|
||||
! Calculate the position vector of the tip:
|
||||
RtHSdat%rS0S(:,K,p%TipNode) = ( p%TwistedSF(K,1,1,p%TipNode,0)*x%QT( DOF_BF(K,1) ) & ! Position vector from the blade root (point S(0)) to the blade tip (point S(p%BldFlexL)).
|
||||
+ p%TwistedSF(K,1,2,p%TipNode,0)*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%TwistedSF(K,1,3,p%TipNode,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j1(K,:) &
|
||||
+ ( p%TwistedSF(K,2,1,p%TipNode,0)*x%QT( DOF_BF(K,1) ) &
|
||||
+ p%TwistedSF(K,2,2,p%TipNode,0)*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%TwistedSF(K,2,3,p%TipNode,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j2(K,:) &
|
||||
+ ( p%BldFlexL - 0.5* &
|
||||
( p%AxRedBld(K,1,1,p%TipNode)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,1) ) &
|
||||
+ p%AxRedBld(K,2,2,p%TipNode)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%AxRedBld(K,3,3,p%TipNode)*x%QT( DOF_BE(K,1) )*x%QT( DOF_BE(K,1) ) &
|
||||
+ 2.*p%AxRedBld(K,1,2,p%TipNode)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,2) ) &
|
||||
+ 2.*p%AxRedBld(K,2,3,p%TipNode)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BE(K,1) ) &
|
||||
+ 2.*p%AxRedBld(K,1,3,p%TipNode)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BE(K,1) ) ) )*CoordSys%j3(K,:)
|
||||
RtHSdat%rQS (:,K,p%TipNode) = RtHSdat%rS0S(:,K,p%TipNode) + p%HubRad*CoordSys%j3(K,:) ! Position vector from apex of rotation (point Q) to the blade tip (point S(p%BldFlexL)).
|
||||
RtHSdat%rS (:,K,p%TipNode) = RtHSdat%rQS (:,K,p%TipNode) + RtHSdat%rQ ! Position vector from inertial frame origin to the blade tip (point S(p%BldFlexL)).
|
||||
|
||||
! position vectors for blade root node:
|
||||
RtHSdat%rQS (:,K,0) = p%HubRad*CoordSys%j3(K,:)
|
||||
RtHSdat%rS (:,K,0) = p%HubRad*CoordSys%j3(K,:) + RtHSdat%rQ
|
||||
|
||||
|
||||
! Calculate the position vector from the teeter pin to the blade root:
|
||||
|
||||
RtHSdat%rPS0(:,K) = RtHSdat%rPQ + p%HubRad*CoordSys%j3(K,:) ! Position vector from teeter pin (point P) to blade root (point S(0)).
|
||||
|
||||
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
|
||||
! Calculate the position vector of the current node:
|
||||
|
||||
RtHSdat%rS0S(:,K,J) = ( p%TwistedSF(K,1,1,J,0)*x%QT( DOF_BF(K,1) ) & ! Position vector from the blade root (point S(0)) to the current node (point S(RNodes(J)).
|
||||
+ p%TwistedSF(K,1,2,J,0)*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%TwistedSF(K,1,3,J,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j1(K,:) &
|
||||
+ ( p%TwistedSF(K,2,1,J,0)*x%QT( DOF_BF(K,1) ) &
|
||||
+ p%TwistedSF(K,2,2,J,0)*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%TwistedSF(K,2,3,J,0)*x%QT( DOF_BE(K,1) ) )*CoordSys%j2(K,:) &
|
||||
+ ( p%RNodes(J) - 0.5* &
|
||||
( p%AxRedBld(K,1,1,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,1) ) &
|
||||
+ p%AxRedBld(K,2,2,J)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BF(K,2) ) &
|
||||
+ p%AxRedBld(K,3,3,J)*x%QT( DOF_BE(K,1) )*x%QT( DOF_BE(K,1) ) &
|
||||
+ 2.0*p%AxRedBld(K,1,2,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BF(K,2) ) &
|
||||
+ 2.0*p%AxRedBld(K,2,3,J)*x%QT( DOF_BF(K,2) )*x%QT( DOF_BE(K,1) ) &
|
||||
+ 2.0*p%AxRedBld(K,1,3,J)*x%QT( DOF_BF(K,1) )*x%QT( DOF_BE(K,1) ) ) )*CoordSys%j3(K,:)
|
||||
RtHSdat%rQS (:,K,J) = RtHSdat%rS0S(:,K,J) + p%HubRad*CoordSys%j3(K,:) ! Position vector from apex of rotation (point Q) to the current node (point S(RNodes(J)).
|
||||
RtHSdat%rS (:,K,J) = RtHSdat%rQS (:,K,J) + RtHSdat%rQ ! Position vector from inertial frame origin to the current node (point S(RNodes(J)).
|
||||
|
||||
|
||||
END DO !J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
|
||||
|
||||
END DO !K = 1,p%NumBl
|
||||
|
||||
|
||||
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! Get the tower element positions
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
RtHSdat%rZT (:,0) = RtHSdat%rZT0
|
||||
DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements
|
||||
|
||||
|
||||
! Calculate the position vector of the current node:
|
||||
|
||||
RtHSdat%rT0T(:,J) = ( p%TwrFASF(1,J,0)*x%QT(DOF_TFA1) + p%TwrFASF(2,J,0)*x%QT(DOF_TFA2) )*CoordSys%a1 & ! Position vector from base of flexible portion of tower (point T(0)) to current node (point T(J)).
|
||||
+ ( p%HNodes(J) - 0.5*( p%AxRedTFA(1,1,J)*x%QT(DOF_TFA1)*x%QT(DOF_TFA1) &
|
||||
+ p%AxRedTFA(2,2,J)*x%QT(DOF_TFA2)*x%QT(DOF_TFA2) &
|
||||
+ 2.0*p%AxRedTFA(1,2,J)*x%QT(DOF_TFA1)*x%QT(DOF_TFA2) &
|
||||
+ p%AxRedTSS(1,1,J)*x%QT(DOF_TSS1)*x%QT(DOF_TSS1) &
|
||||
+ p%AxRedTSS(2,2,J)*x%QT(DOF_TSS2)*x%QT(DOF_TSS2) &
|
||||
+ 2.0*p%AxRedTSS(1,2,J)*x%QT(DOF_TSS1)*x%QT(DOF_TSS2) ) )*CoordSys%a2 &
|
||||
+ ( p%TwrSSSF(1,J,0)*x%QT(DOF_TSS1) + p%TwrSSSF(2,J,0)*x%QT(DOF_TSS2) )*CoordSys%a3
|
||||
RtHSdat%rZT (:,J) = RtHSdat%rZT0 + RtHSdat%rT0T(:,J) ! Position vector from platform reference (point Z) to the current node (point T(HNodes(J)).
|
||||
|
||||
|
||||
RtHSdat%rT(:,J) = RtHSdat%rZ + RtHSdat%rZT (:,J) ! Position vector from inertial frame origin to the current node (point T(HNodes(J)).
|
||||
|
||||
END DO
|
||||
|
||||
|
||||
END SUBROUTINE CalculatePositions
|
||||
|
||||
```
|
||||
678
书籍/力学书籍/OpenFast/FASTKinetics/auto/Coeff.md
Normal file
678
书籍/力学书籍/OpenFast/FASTKinetics/auto/Coeff.md
Normal file
@ -0,0 +1,678 @@
|
||||
|
||||
```fortran
|
||||
SUBROUTINE Coeff(p,InputFileData, ErrStat, ErrMsg)
|
||||
!..................................................................................................................................
|
||||
|
||||
! Passed variables
|
||||
|
||||
TYPE(ED_ParameterType), INTENT(INOUT) :: p !< Parameters of the structural dynamics module
|
||||
TYPE(ED_InputFile), INTENT(IN) :: InputFileData !< all the data in the ElastoDyn input file
|
||||
INTEGER(IntKi), INTENT(OUT) :: ErrStat !< Error status
|
||||
CHARACTER(*), INTENT(OUT) :: ErrMsg !< Error message when ErrStat =/ ErrID_None
|
||||
|
||||
|
||||
! Local variables.
|
||||
|
||||
REAL(ReKi) :: AxRdBld (3,3) ! Temporary result holding the current addition to the p%AxRedBld() array.
|
||||
REAL(ReKi) :: AxRdBldOld(3,3) ! Previous AxRdBld (i.e., AxRdBld from the previous node)
|
||||
REAL(ReKi) :: AxRdTFA (2,2) ! Temporary result holding the current addition to the AxRedTFA() array.
|
||||
REAL(ReKi) :: AxRdTFAOld(2,2) ! Previous AxRdTFA (i.e., AxRdTFA from the previous node)
|
||||
REAL(ReKi) :: AxRdTSS (2,2) ! Temporary result holding the current addition to the AxRedTSS() array.
|
||||
REAL(ReKi) :: AxRdTSSOld(2,2) ! Previous AxRdTSS (i.e., AxRdTSS from the previous node)
|
||||
REAL(ReKi) :: TmpDist ! Temporary distance used in the calculation of the aero center locations.
|
||||
REAL(ReKi) :: TmpDistj1 ! Temporary distance used in the calculation of the aero center locations.
|
||||
REAL(ReKi) :: TmpDistj2 ! Temporary distance used in the calculation of the aero center locations.
|
||||
REAL(ReKi) :: ElmntStff ! (Temporary) stiffness of an element.
|
||||
REAL(ReKi) :: ElStffFA ! (Temporary) tower fore-aft stiffness of an element
|
||||
REAL(ReKi) :: ElStffSS ! (Temporary) tower side-to-side stiffness of an element
|
||||
REAL(ReKi) :: FMomAbvNd (p%NumBl,p%BldNodes) ! FMomAbvNd(K,J) = portion of the first moment of blade K about the rotor centerline (not root, like FirstMom(K)) associated with everything above node J (including tip brake masses).
|
||||
REAL(ReKi) :: KBECent (p%NumBl,1,1) ! Centrifugal-term of generalized edgewise stiffness of the blades.
|
||||
REAL(ReKi) :: KBFCent (p%NumBl,2,2) ! Centrifugal-term of generalized flapwise stiffness of the blades.
|
||||
REAL(ReKi) :: KTFAGrav (2,2) ! Gravitational-term of generalized fore-aft stiffness of the tower.
|
||||
REAL(ReKi) :: KTSSGrav (2,2) ! Gravitational-term of generalized side-to-side stiffness of the tower.
|
||||
REAL(ReKi) :: MBE (p%NumBl,1,1) ! Generalized edgewise mass of the blades.
|
||||
REAL(ReKi) :: MBF (p%NumBl,2,2) ! Generalized flapwise mass of the blades.
|
||||
REAL(ReKi) :: MTFA (2,2) ! Generalized fore-aft mass of the tower.
|
||||
REAL(ReKi) :: MTSS (2,2) ! Generalized side-to-side mass of the tower.
|
||||
REAL(ReKi) :: Shape ! Temporary result holding a value from the SHP function
|
||||
REAL(ReKi) :: Shape1 ! Temporary result holding a value from the SHP function
|
||||
REAL(ReKi) :: Shape2 ! Temporary result holding a value from the SHP function
|
||||
REAL(ReKi) :: TMssAbvNd (p%TwrNodes) ! Portion of the tower mass associated with everything above node J (including tower-top effects)
|
||||
REAL(ReKi) :: TwstdSF (2,3,0:1) ! Temperory result holding the current addition to the TwistedSF() array.
|
||||
REAL(ReKi) :: TwstdSFOld(2,3,0:1) ! Previous TwstdSF (i.e., TwstdSF from the previous node)
|
||||
|
||||
INTEGER(IntKi) :: I ! Generic index.
|
||||
INTEGER(IntKi) :: J ! Loops through nodes / elements.
|
||||
INTEGER(IntKi) :: K ! Loops through blades.
|
||||
INTEGER(IntKi) :: L ! Generic index
|
||||
|
||||
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ''
|
||||
|
||||
!...............................................................................................................................
|
||||
! Calculate the distances from point S on a blade to the aerodynamic center in the j1 and j2 directions:
|
||||
!...............................................................................................................................
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through the blades
|
||||
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
TmpDist = ( 0.25 - p%PitchAxis(K,J) )*p%Chord(J) ! Distance along the chordline from point S (25% chord) to the aerodynamic center of the blade element J--positive towards the trailing edge.
|
||||
TmpDistj1 = TmpDist*p%SAeroTwst(J) ! Distance along the j1-axis from point S (25% chord) to the aerodynamic center of the blade element J
|
||||
TmpDistj2 = TmpDist*p%CAeroTwst(J) ! Distance along the j2-axis from point S (25% chord) to the aerodynamic center of the blade element J
|
||||
p%rSAerCenn1(K,J) = TmpDistj1*p%CThetaS(K,J) - TmpDistj2*p%SThetaS(K,J)
|
||||
p%rSAerCenn2(K,J) = TmpDistj1*p%SThetaS(K,J) + TmpDistj2*p%CThetaS(K,J)
|
||||
|
||||
ENDDO ! J - Blade nodes / elements
|
||||
|
||||
ENDDO ! K - Blades
|
||||
|
||||
|
||||
!...............................................................................................................................
|
||||
! Calculate the structure that furls with the rotor inertia term:
|
||||
!...............................................................................................................................
|
||||
|
||||
p%RrfaIner = InputFileData%RFrlIner - p%RFrlMass*( (p%rVDxn**2 )*( 1.0 - p%CRFrlSkw2*p%CRFrlTlt2 ) &
|
||||
+ (p%rVDzn**2 )* p%CRFrlTlt2 &
|
||||
+ (p%rVDyn**2 )*( 1.0 - p%SRFrlSkw2*p%CRFrlTlt2 ) &
|
||||
- 2.0*p%rVDxn*p%rVDzn* p%CRFrlSkew*p%CSRFrlTlt &
|
||||
- 2.0*p%rVDxn*p%rVDyn* p%CSRFrlSkw*p%CRFrlTlt2 &
|
||||
- 2.0*p%rVDzn*p%rVDyn* p%SRFrlSkew*p%CSRFrlTlt )
|
||||
IF ( p%RrfaIner < 0.0 ) THEN
|
||||
ErrStat = ErrID_Fatal
|
||||
ErrMsg = ' RFrlIner must not be less than RFrlMass*( perpendicular distance between rotor-furl'// &
|
||||
' axis and CM of the structure that furls with the rotor [not including rotor] )^2.'
|
||||
RETURN
|
||||
END IF
|
||||
|
||||
!...............................................................................................................................
|
||||
! Calculate the tail boom inertia term:
|
||||
!...............................................................................................................................
|
||||
|
||||
p%AtfaIner = p%TFrlIner - p%BoomMass*( p%rWIxn*p%rWIxn*( 1.0 - p%CTFrlSkw2*p%CTFrlTlt2 ) &
|
||||
+ p%rWIzn*p%rWIzn* p%CTFrlTlt2 &
|
||||
+ p%rWIyn*p%rWIyn*( 1.0 - p%STFrlSkw2*p%CTFrlTlt2 ) &
|
||||
- 2.0*p%rWIxn*p%rWIzn* p%CTFrlSkew*p%CSTFrlTlt &
|
||||
- 2.0*p%rWIxn*p%rWIyn* p%CSTFrlSkw*p%CTFrlTlt2 &
|
||||
- 2.0*p%rWIzn*p%rWIyn* p%STFrlSkew*p%CSTFrlTlt )
|
||||
IF ( p%AtfaIner < 0.0 ) THEN
|
||||
ErrStat = ErrID_Fatal
|
||||
ErrMsg = ' TFrlIner must not be less than BoomMass*( perpendicular distance between tail-furl'// &
|
||||
' axis and tail boom CM )^2.'
|
||||
RETURN
|
||||
ENDIF
|
||||
|
||||
!...............................................................................................................................
|
||||
! Calculate the nacelle inertia terms:
|
||||
!...............................................................................................................................
|
||||
|
||||
p%Nacd2Iner = InputFileData%NacYIner - p%NacMass*( p%NacCMxn**2 + p%NacCMyn**2 ) ! Nacelle inertia about the d2-axis
|
||||
IF ( p%Nacd2Iner < 0.0 ) THEN
|
||||
ErrStat = ErrID_Fatal
|
||||
ErrMsg = ' NacYIner must not be less than NacMass*( NacCMxn^2 + NacCMyn^2 ).'
|
||||
RETURN
|
||||
END IF
|
||||
|
||||
! Calculate hub inertia about its centerline passing through its c.g..
|
||||
! This calculation assumes that the hub for a 2-blader is essentially
|
||||
! a uniform cylinder whose centerline is transverse through the cylinder
|
||||
! passing through its c.g.. That is, for a 2-blader, Hubg1Iner =
|
||||
! Hubg2Iner is the inertia of the hub about both the g1- and g2- axes. For
|
||||
! 3-bladers, Hubg1Iner is simply equal to HubIner and Hubg2Iner is zero.
|
||||
! Also, Initialize RotMass and RotIner to associated hub properties:
|
||||
|
||||
IF ( p%NumBl == 2 ) THEN ! 2-blader
|
||||
p%Hubg1Iner = ( InputFileData%HubIner - p%HubMass*( ( p%UndSling - p%HubCM )**2 ) )/( p%CosDel3**2 )
|
||||
p%Hubg2Iner = p%Hubg1Iner
|
||||
IF ( p%Hubg1Iner < 0.0 ) THEN
|
||||
ErrStat = ErrID_Fatal
|
||||
ErrMsg = ' HubIner must not be less than HubMass*( UndSling - HubCM )^2 for 2-blader.'
|
||||
RETURN
|
||||
END IF
|
||||
ELSE ! 3-blader
|
||||
p%Hubg1Iner = InputFileData%HubIner
|
||||
p%Hubg2Iner = 0.0
|
||||
ENDIF
|
||||
|
||||
p%RotMass = p%HubMass
|
||||
p%RotIner = p%Hubg1Iner
|
||||
|
||||
|
||||
!...............................................................................................................................
|
||||
|
||||
! Initialize several variables to 0.0:
|
||||
|
||||
p%KBF = 0.0
|
||||
p%KBE = 0.0
|
||||
KBFCent = 0.0
|
||||
KBECent = 0.0
|
||||
|
||||
p%TwrMass = 0.0
|
||||
p%KTFA = 0.0
|
||||
p%KTSS = 0.0
|
||||
KTFAGrav = 0.0
|
||||
KTSSGrav = 0.0
|
||||
|
||||
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through the blades
|
||||
|
||||
|
||||
! Initialize BldMass(), FirstMom(), and SecondMom() using TipMass() effects:
|
||||
|
||||
p%BldMass (K) = p%TipMass(K)
|
||||
p%FirstMom (K) = p%TipMass(K)*p%BldFlexL
|
||||
p%SecondMom(K) = p%TipMass(K)*p%BldFlexL*p%BldFlexL
|
||||
|
||||
|
||||
DO J = p%BldNodes,1,-1 ! Loop through the blade nodes / elements in reverse
|
||||
|
||||
|
||||
! Calculate the mass of the current element
|
||||
|
||||
p%BElmntMass(J,K) = p%MassB(K,J)*p%DRNodes(J) ! Mass of blade element J
|
||||
|
||||
|
||||
! Integrate to find some blade properties which will be output in .fsm
|
||||
|
||||
p%BldMass (K) = p%BldMass (K) + p%BElmntMass(J,K)
|
||||
p%FirstMom (K) = p%FirstMom (K) + p%BElmntMass(J,K)*p%RNodes(J)
|
||||
p%SecondMom(K) = p%SecondMom(K) + p%BElmntMass(J,K)*p%RNodes(J)*p%RNodes(J)
|
||||
|
||||
|
||||
! Integrate to find FMomAbvNd:
|
||||
|
||||
FMomAbvNd (K,J) = ( 0.5*p%BElmntMass(J,K) )*( p%HubRad + p%RNodes(J ) + 0.5*p%DRNodes(J ) )
|
||||
|
||||
IF ( J == p%BldNodes ) THEN ! Outermost blade element
|
||||
! Add the TipMass() effects:
|
||||
|
||||
FMomAbvNd(K,J) = FmomAbvNd(K,J) + p%TipMass(K)*p%TipRad
|
||||
ELSE ! All other blade elements
|
||||
! Add to FMomAbvNd(K,J) the effects from the (not yet used) portion of element J+1
|
||||
|
||||
FMomAbvNd(K,J) = FMomAbvNd(K,J) + FMomAbvNd(K,J+1) &
|
||||
+ ( 0.5*p%BElmntMass(J+1,K) )*( p%HubRad + p%RNodes(J+1) - 0.5*p%DRNodes(J+1) )
|
||||
ENDIF
|
||||
|
||||
|
||||
ENDDO ! J - Blade nodes / elements in reverse
|
||||
|
||||
IF (.NOT. p%BD4Blades) THEN
|
||||
! Calculate BldCG() using FirstMom() and BldMass(); and calculate
|
||||
! RotMass and RotIner:
|
||||
|
||||
p%BldCG (K) = p%FirstMom (K) / p%BldMass (K)
|
||||
p%RotMass = p%RotMass + p%BldMass (K)
|
||||
p%RotIner = p%RotIner + ( p%SecondMom(K) + p%BldMass (K)*p%HubRad*( 2.0*p%BldCG(K) + p%HubRad ) )*( p%CosPreC(K)**2 )
|
||||
END IF
|
||||
|
||||
ENDDO ! K - Blades
|
||||
|
||||
|
||||
|
||||
DO K = 1,p%NumBl ! Loop through the blades
|
||||
|
||||
|
||||
! Initialize the generalized blade masses using tip mass effects:
|
||||
|
||||
MBF(K,1,1) = p%TipMass(K)
|
||||
MBF(K,2,2) = p%TipMass(K)
|
||||
MBE(K,1,1) = p%TipMass(K)
|
||||
|
||||
|
||||
DO J = 1,p%BldNodes ! Loop through the blade nodes / elements
|
||||
|
||||
|
||||
! Integrate to find the generalized mass of the blade (including tip mass effects).
|
||||
! Ignore the cross-correlation terms of MBF (i.e. MBF(i,j) where i /= j) since
|
||||
! these terms will never be used.
|
||||
|
||||
Shape1 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 0, ErrStat, ErrMsg )
|
||||
Shape2 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 0, ErrStat, ErrMsg )
|
||||
MBF (K,1,1) = MBF (K,1,1) + p%BElmntMass(J,K)*Shape1*Shape1
|
||||
MBF (K,2,2) = MBF (K,2,2) + p%BElmntMass(J,K)*Shape2*Shape2
|
||||
|
||||
Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 0, ErrStat, ErrMsg )
|
||||
MBE (K,1,1) = MBE (K,1,1) + p%BElmntMass(J,K)*Shape *Shape
|
||||
|
||||
|
||||
! Integrate to find the generalized stiffness of the blade (not including centrifugal
|
||||
! effects).
|
||||
|
||||
ElmntStff = p%StiffBF(K,J)*p%DRNodes(J) ! Flapwise stiffness of blade element J
|
||||
Shape1 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
Shape2 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%KBF (K,1,1) = p%KBF (K,1,1) + ElmntStff*Shape1*Shape1
|
||||
p%KBF (K,1,2) = p%KBF (K,1,2) + ElmntStff*Shape1*Shape2
|
||||
p%KBF (K,2,1) = p%KBF (K,2,1) + ElmntStff*Shape2*Shape1
|
||||
p%KBF (K,2,2) = p%KBF (K,2,2) + ElmntStff*Shape2*Shape2
|
||||
|
||||
ElmntStff = p%StiffBE(K,J)*p%DRNodes(J) ! Edgewise stiffness of blade element J
|
||||
Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%KBE (K,1,1) = p%KBE (K,1,1) + ElmntStff*Shape *Shape
|
||||
|
||||
|
||||
! Integrate to find the centrifugal-term of the generalized flapwise and edgewise
|
||||
! stiffness of the blades. Ignore the cross-correlation terms of KBFCent (i.e.
|
||||
! KBFCent(i,j) where i /= j) since these terms will never be used.
|
||||
|
||||
ElmntStff = FMomAbvNd(K,J)*p%DRNodes(J)*p%RotSpeed**2 ! Centrifugal stiffness of blade element J
|
||||
|
||||
Shape1 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 1, ErrStat, ErrMsg )
|
||||
Shape2 = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 1, ErrStat, ErrMsg )
|
||||
KBFCent(K,1,1) = KBFCent(K,1,1) + ElmntStff*Shape1*Shape1
|
||||
KBFCent(K,2,2) = KBFCent(K,2,2) + ElmntStff*Shape2*Shape2
|
||||
|
||||
Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 1, ErrStat, ErrMsg )
|
||||
KBECent(K,1,1) = KBECent(K,1,1) + ElmntStff*Shape *Shape
|
||||
|
||||
|
||||
! Calculate the 2nd derivatives of the twisted shape functions:
|
||||
|
||||
Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,1,J,2) = Shape*p%CThetaS(K,J) ! 2nd deriv. of Phi1(J) for blade K
|
||||
p%TwistedSF(K,2,1,J,2) = -Shape*p%SThetaS(K,J) ! 2nd deriv. of Psi1(J) for blade K
|
||||
|
||||
Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,2,J,2) = Shape*p%CThetaS(K,J) ! 2nd deriv. of Phi2(J) for blade K
|
||||
p%TwistedSF(K,2,2,J,2) = -Shape*p%SThetaS(K,J) ! 2nd deriv. of Psi2(J) for blade K
|
||||
|
||||
Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,3,J,2) = Shape*p%SThetaS(K,J) ! 2nd deriv. of Phi3(J) for blade K
|
||||
p%TwistedSF(K,2,3,J,2) = Shape*p%CThetaS(K,J) ! 2nd deriv. of Psi3(J) for blade K
|
||||
|
||||
|
||||
! Integrate to find the 1st derivatives of the twisted shape functions:
|
||||
|
||||
DO I = 1,2 ! Loop through Phi and Psi
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
TwstdSF ( I,L, 1) = p%TwistedSF(K,I,L,J,2)*0.5*p%DRNodes(J)
|
||||
p%TwistedSF (K,I,L,J,1) = TwstdSF ( I,L, 1)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - Phi and Psi
|
||||
|
||||
IF ( J /= 1 ) THEN ! All but the innermost blade element
|
||||
! Add the effects from the (not yet used) portion of element J-1
|
||||
|
||||
DO I = 1,2 ! Loop through Phi and Psi
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
p%TwistedSF(K,I,L,J,1) = p%TwistedSF(K,I,L,J,1) + p%TwistedSF(K,I,L,J-1,1) &
|
||||
+ TwstdSFOld( I,L, 1)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - Phi and Psi
|
||||
ENDIF
|
||||
|
||||
|
||||
! Integrate to find the twisted shape functions themselves (i.e., their zeroeth derivative):
|
||||
|
||||
DO I = 1,2 ! Loop through Phi and Psi
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
TwstdSF ( I,L, 0) = p%TwistedSF(K,I,L,J,1)*0.5*p%DRNodes(J)
|
||||
p%TwistedSF (K,I,L,J,0) = TwstdSF ( I,L, 0)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - Phi and Psi
|
||||
|
||||
IF ( J /= 1 ) THEN ! All but the innermost blade element
|
||||
! Add the effects from the (not yet used) portion of element J-1
|
||||
|
||||
DO I = 1,2 ! Loop through Phi and Psi
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
p%TwistedSF(K,I,L,J,0) = p%TwistedSF(K,I,L,J,0) + p%TwistedSF(K,I,L,J-1,0) &
|
||||
+ TwstdSFOld( I,L, 0)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - Phi and Psi
|
||||
ENDIF
|
||||
|
||||
|
||||
! Integrate to find the blade axial reduction shape functions:
|
||||
|
||||
DO I = 1,3 ! Loop through all blade DOFs
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
AxRdBld ( I,L ) = 0.5*p%DRNodes(J)*( &
|
||||
p%TwistedSF(K,1,I,J,1)*p%TwistedSF(K,1,L,J,1) &
|
||||
+ p%TwistedSF(K,2,I,J,1)*p%TwistedSF(K,2,L,J,1) )
|
||||
p%AxRedBld (K,I,L,J) = AxRdBld(I,L)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - All blade DOFs
|
||||
|
||||
IF ( J /= 1 ) THEN ! All but the innermost blade element
|
||||
! Add the effects from the (not yet used) portion of element J-1
|
||||
|
||||
DO I = 1,3 ! Loop through all blade DOFs
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
p%AxRedBld(K,I,L,J) = p%AxRedBld(K,I,L,J) + p%AxRedBld(K,I,L,J-1) &
|
||||
+ AxRdBldOld(I,L)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - All blade DOFs
|
||||
ENDIF
|
||||
|
||||
|
||||
! Store the TwstdSF and AxRdBld terms of the current element (these will be used for the next element)
|
||||
|
||||
TwstdSFOld = TwstdSF
|
||||
AxRdBldOld = AxRdBld
|
||||
|
||||
|
||||
ENDDO ! J - Blade nodes / elements
|
||||
|
||||
|
||||
|
||||
|
||||
IF (p%BD4Blades) THEN
|
||||
|
||||
!p%KBF ( K,:,: ) = 0.0_ReKi
|
||||
|
||||
! the 1st and zeroeth derivatives of the twisted shape functions at the blade root:
|
||||
p%TwistedSF(K,:,:,:,1) = 0.0_ReKi
|
||||
p%TwistedSF(K,:,:,:,0) = 0.0_ReKi
|
||||
p%AxRedBld( K,:,:,: ) = 0.0_ReKi
|
||||
ELSE
|
||||
|
||||
! Apply the flapwise modal stiffness tuners of the blades to KBF():
|
||||
|
||||
DO I = 1,2 ! Loop through flap DOFs
|
||||
DO L = 1,2 ! Loop through flap DOFs
|
||||
p%KBF(K,I,L) = SQRT( p%FStTunr(K,I)*p%FStTunr(K,L) )*p%KBF(K,I,L)
|
||||
ENDDO ! L - Flap DOFs
|
||||
ENDDO ! I - Flap DOFs
|
||||
|
||||
! Calculate the blade natural frequencies:
|
||||
|
||||
DO I = 1,NumBF ! Loop through flap DOFs
|
||||
p%FreqBF(K,I,1) = Inv2Pi*SQRT( p%KBF(K,I,I) /( MBF(K,I,I) - p%TipMass(K) ) ) ! Natural blade I-flap frequency w/o centrifugal stiffening nor tip mass effects
|
||||
p%FreqBF(K,I,2) = Inv2Pi*SQRT( p%KBF(K,I,I) / MBF(K,I,I) ) ! Natural blade I-flap frequency w/o centrifugal stiffening, but w/ tip mass effects
|
||||
p%FreqBF(K,I,3) = Inv2Pi*SQRT( ( p%KBF(K,I,I) + KBFCent(K,I,I) )/ MBF(K,I,I) ) ! Natural blade I-flap frequency w/ centrifugal stiffening and tip mass effects
|
||||
ENDDO ! I - Flap DOFs
|
||||
|
||||
p%FreqBE (K,1,1) = Inv2Pi*SQRT( p%KBE(K,1,1) /( MBE(K,1,1) - p%TipMass(K) ) ) ! Natural blade 1-edge frequency w/o centrifugal stiffening nor tip mass effects
|
||||
p%FreqBE (K,1,2) = Inv2Pi*SQRT( p%KBE(K,1,1) / MBE(K,1,1) ) ! Natural Blade 1-edge frequency w/o centrifugal stiffening, but w/ tip mass effects
|
||||
p%FreqBE (K,1,3) = Inv2Pi*SQRT( ( p%KBE(K,1,1) + KBECent(K,1,1) )/ MBE(K,1,1) ) ! Natural Blade 1-edge frequency w/ centrifugal stiffening and tip mass effects
|
||||
|
||||
|
||||
! Calculate the generalized damping of the blades:
|
||||
|
||||
DO I = 1,NumBF ! Loop through flap DOFs
|
||||
DO L = 1,NumBF ! Loop through flap DOFs
|
||||
p%CBF(K,I,L) = ( 0.01*p%BldFDamp(K,L) )*p%KBF(K,I,L)/( Pi*p%FreqBF(K,L,1) )
|
||||
ENDDO ! L - Flap DOFs
|
||||
ENDDO ! I - Flap DOFs
|
||||
|
||||
p%CBE (K,1,1) = ( 0.01*p%BldEDamp(K,1) )*p%KBE(K,1,1)/( Pi*p%FreqBE(K,1,1) )
|
||||
|
||||
|
||||
! Calculate the 2nd derivatives of the twisted shape functions at the blade root:
|
||||
|
||||
Shape = SHP( 0.0_ReKi, p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,1,0,2) = Shape*p%CThetaS(K,0) ! 2nd deriv. of Phi1(0) for blade K
|
||||
p%TwistedSF(K,2,1,0,2) = -Shape*p%SThetaS(K,0) ! 2nd deriv. of Psi1(0) for blade K
|
||||
|
||||
Shape = SHP( 0.0_ReKi, p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,2,0,2) = Shape*p%CThetaS(K,0) ! 2nd deriv. of Phi2(0) for blade K
|
||||
p%TwistedSF(K,2,2,0,2) = -Shape*p%SThetaS(K,0) ! 2nd deriv. of Psi2(0) for blade K
|
||||
|
||||
Shape = SHP( 0.0_ReKi, p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,3,0,2) = Shape*p%SThetaS(K,0) ! 2nd deriv. of Phi3(0) for blade K
|
||||
p%TwistedSF(K,2,3,0,2) = Shape*p%CThetaS(K,0) ! 2nd deriv. of Psi3(0) for blade K
|
||||
|
||||
|
||||
! Calculate the 2nd derivatives of the twisted shape functions at the tip:
|
||||
|
||||
Shape = SHP( 1.0_ReKi, p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,1,p%TipNode,2) = Shape*p%CThetaS(K,p%TipNode) ! 2nd deriv. of Phi1(p%TipNode) for blade K
|
||||
p%TwistedSF(K,2,1,p%TipNode,2) = -Shape*p%SThetaS(K,p%TipNode) ! 2nd deriv. of Psi1(p%TipNode) for blade K
|
||||
|
||||
Shape = SHP( 1.0_ReKi, p%BldFlexL, p%BldFl2Sh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,2,p%TipNode,2) = Shape*p%CThetaS(K,p%TipNode) ! 2nd deriv. of Phi2(p%TipNode) for blade K
|
||||
p%TwistedSF(K,2,2,p%TipNode,2) = -Shape*p%SThetaS(K,p%TipNode) ! 2nd deriv. of Psi2(p%TipNode) for blade K
|
||||
|
||||
Shape = SHP( 1.0_ReKi, p%BldFlexL, p%BldEdgSh(:,K), 2, ErrStat, ErrMsg )
|
||||
p%TwistedSF(K,1,3,p%TipNode,2) = Shape*p%SThetaS(K,p%TipNode) ! 2nd deriv. of Phi3(p%TipNode) for blade K
|
||||
p%TwistedSF(K,2,3,p%TipNode,2) = Shape*p%CThetaS(K,p%TipNode) ! 2nd deriv. of Psi3(p%TipNode) for blade K
|
||||
|
||||
|
||||
! Integrate to find the 1st and zeroeth derivatives of the twisted shape functions
|
||||
! at the tip:
|
||||
|
||||
DO I = 1,2 ! Loop through Phi and Psi
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
p%TwistedSF(K,I,L,p%TipNode,1) = p%TwistedSF(K,I,L,p%BldNodes,1) + TwstdSFOld(I,L,1)
|
||||
p%TwistedSF(K,I,L,p%TipNode,0) = p%TwistedSF(K,I,L,p%BldNodes,0) + TwstdSFOld(I,L,0)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - Phi and Psi
|
||||
|
||||
! the 1st and zeroeth derivatives of the twisted shape functions at the blade root:
|
||||
p%TwistedSF(K,:,:,0,1) = 0.0_ReKi
|
||||
p%TwistedSF(K,:,:,0,0) = 0.0_ReKi
|
||||
p%AxRedBld( K,:,:,0 ) = 0.0_ReKi
|
||||
|
||||
! Integrate to find the blade axial reduction shape functions at the tip:
|
||||
|
||||
DO I = 1,3 ! Loop through all blade DOFs
|
||||
DO L = 1,3 ! Loop through all blade DOFs
|
||||
p%AxRedBld(K,I,L,p%TipNode) = p%AxRedBld(K,I,L,p%BldNodes) + AxRdBldOld(I,L)
|
||||
ENDDO ! L - All blade DOFs
|
||||
ENDDO ! I - All blade DOFs
|
||||
END IF ! p%BD4Blades
|
||||
|
||||
|
||||
ENDDO ! K - Blades
|
||||
|
||||
|
||||
|
||||
! Calculate the tower-top mass:
|
||||
|
||||
p%TwrTpMass = p%RotMass + p%RFrlMass + p%BoomMass + p%TFinMass + p%NacMass + p%YawBrMass
|
||||
|
||||
|
||||
DO J = p%TwrNodes,1,-1 ! Loop through the tower nodes / elements in reverse
|
||||
|
||||
|
||||
! Calculate the mass of the current element
|
||||
|
||||
p%TElmntMass(J) = p%MassT(J)*abs(p%DHNodes(J)) ! Mass of tower element J
|
||||
|
||||
|
||||
! Integrate to find the tower mass which will be output in .fsm
|
||||
|
||||
p%TwrMass = p%TwrMass + p%TElmntMass(J)
|
||||
|
||||
|
||||
! Integrate to find TMssAbvNd:
|
||||
|
||||
TMssAbvNd (J) = 0.5*p%TElmntMass(J)
|
||||
|
||||
IF ( J == p%TwrNodes ) THEN ! Uppermost tower element
|
||||
! Add the TwrTpMass effects:
|
||||
|
||||
TMssAbvNd(J) = TMssAbvNd(J) + p%TwrTpMass
|
||||
ELSE ! All other tower elements
|
||||
! Add to TMssAbvNd(J) the effects from the (not yet used) portion of element J+1
|
||||
|
||||
TMssAbvNd(J) = 0.5*p%TElmntMass(J+1) + TMssAbvNd(J) + TMssAbvNd(J+1)
|
||||
ENDIF
|
||||
|
||||
|
||||
ENDDO ! J - Tower nodes / elements in reverse
|
||||
|
||||
|
||||
|
||||
! Initialize the generalized tower masses using tower-top mass effects:
|
||||
|
||||
DO I = 1,2 ! Loop through all tower modes in a single direction
|
||||
MTFA(I,I) = p%TwrTpMass
|
||||
MTSS(I,I) = p%TwrTpMass
|
||||
ENDDO ! I - All tower modes in a single direction
|
||||
|
||||
! set values for tower base (note that we haven't corrctly defined the values for (:,0,2) in the arrays below):
|
||||
p%TwrFASF( :,0,0:1) = 0.0_ReKi
|
||||
p%TwrSSSF( :,0,0:1) = 0.0_ReKi
|
||||
p%AxRedTFA(:,:,0) = 0.0_ReKi
|
||||
p%AxRedTSS(:,:,0) = 0.0_ReKi
|
||||
|
||||
DO J = 1,p%TwrNodes ! Loop through the tower nodes / elements
|
||||
|
||||
|
||||
! Calculate the tower shape functions (all derivatives):
|
||||
|
||||
p%TwrFASF(1,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrFASF(2,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM2Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrFASF(1,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrFASF(2,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM2Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrFASF(1,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM1Sh(:), 0, ErrStat, ErrMsg )
|
||||
p%TwrFASF(2,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwFAM2Sh(:), 0, ErrStat, ErrMsg )
|
||||
|
||||
p%TwrSSSF(1,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM1Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(2,J,2) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM2Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(1,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM1Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(2,J,1) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM2Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(1,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM1Sh(:), 0, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(2,J,0) = SHP( p%HNodesNorm(J), p%TwrFlexL, InputFileData%TwSSM2Sh(:), 0, ErrStat, ErrMsg )
|
||||
|
||||
|
||||
! Integrate to find the generalized mass of the tower (including tower-top mass effects).
|
||||
! Ignore the cross-correlation terms of MTFA (i.e. MTFA(i,j) where i /= j) and MTSS
|
||||
! since these terms will never be used.
|
||||
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
MTFA (I,I) = MTFA (I,I) + p%TElmntMass(J)*p%TwrFASF(I,J,0)**2
|
||||
MTSS (I,I) = MTSS (I,I) + p%TElmntMass(J)*p%TwrSSSF(I,J,0)**2
|
||||
ENDDO ! I - through all tower DOFs in one direction
|
||||
|
||||
|
||||
! Integrate to find the generalized stiffness of the tower (not including gravitational
|
||||
! effects).
|
||||
|
||||
ElStffFA = p%StiffTFA(J)*abs(p%DHNodes(J)) ! Fore-aft stiffness of tower element J
|
||||
ElStffSS = p%StiffTSS(J)*abs(p%DHNodes(J)) ! Side-to-side stiffness of tower element J
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
DO L = 1,2 ! Loop through all tower DOFs in one direction
|
||||
p%KTFA (I,L) = p%KTFA (I,L) + ElStffFA *p%TwrFASF(I,J,2)*p%TwrFASF(L,J,2)
|
||||
p%KTSS (I,L) = p%KTSS (I,L) + ElStffSS *p%TwrSSSF(I,J,2)*p%TwrSSSF(L,J,2)
|
||||
ENDDO ! L - All tower DOFs in one direction
|
||||
ENDDO ! I - through all tower DOFs in one direction
|
||||
|
||||
|
||||
! Integrate to find the gravitational-term of the generalized stiffness of the tower.
|
||||
! Ignore the cross-correlation terms of KTFAGrav (i.e. KTFAGrav(i,j) where i /= j)
|
||||
! and KTSSGrav since these terms will never be used.
|
||||
|
||||
ElmntStff = -TMssAbvNd(J)*abs(p%DHNodes(J))*p%Gravity ! Gravitational stiffness of tower element J
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
KTFAGrav(I,I) = KTFAGrav(I,I) + ElmntStff*p%TwrFASF(I,J,1)**2
|
||||
KTSSGrav(I,I) = KTSSGrav(I,I) + ElmntStff*p%TwrSSSF(I,J,1)**2
|
||||
ENDDO
|
||||
|
||||
|
||||
! Integrate to find the tower axial reduction shape functions:
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
DO L = 1,2 ! Loop through all tower DOFs in one direction
|
||||
AxRdTFA (I,L) = 0.5*p%DHNodes(J)*p%TwrFASF(I,J,1)*p%TwrFASF(L,J,1)
|
||||
AxRdTSS (I,L) = 0.5*p%DHNodes(J)*p%TwrSSSF(I,J,1)*p%TwrSSSF(L,J,1)
|
||||
|
||||
p%AxRedTFA(I,L,J) = AxRdTFA(I,L)
|
||||
p%AxRedTSS(I,L,J) = AxRdTSS(I,L)
|
||||
ENDDO ! L - All tower DOFs in one direction
|
||||
ENDDO
|
||||
|
||||
IF ( J /= 1 ) THEN ! All but the lowermost tower element
|
||||
! Add the effects from the (not yet used) portion of element J-1
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
DO L = 1,2 ! Loop through all tower DOFs in one direction
|
||||
p%AxRedTFA(I,L,J) = p%AxRedTFA(I,L,J) + p%AxRedTFA(I,L,J-1)+ AxRdTFAOld(I,L)
|
||||
p%AxRedTSS(I,L,J) = p%AxRedTSS(I,L,J) + p%AxRedTSS(I,L,J-1)+ AxRdTSSOld(I,L)
|
||||
ENDDO ! L - All tower DOFs in one direction
|
||||
ENDDO
|
||||
ENDIF
|
||||
|
||||
|
||||
! Store the AxRdTFA and AxRdTSS terms of the current element (these will be used for the next element)
|
||||
|
||||
AxRdTFAOld = AxRdTFA
|
||||
AxRdTSSOld = AxRdTSS
|
||||
|
||||
|
||||
ENDDO ! J - Tower nodes / elements
|
||||
|
||||
|
||||
! Apply the modal stiffness tuners of the tower to KTFA() and KTSS():
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
DO L = 1,2 ! Loop through all tower DOFs in one direction
|
||||
p%KTFA(I,L) = SQRT( InputFileData%FAStTunr(I)*InputFileData%FAStTunr(L) )*p%KTFA(I,L)
|
||||
|
||||
p%KTSS(I,L) = SQRT( InputFileData%SSStTunr(I)*InputFileData%SSStTunr(L) )*p%KTSS(I,L)
|
||||
ENDDO ! L - All tower DOFs in one direction
|
||||
ENDDO ! I - through all tower DOFs in one direction
|
||||
|
||||
|
||||
! Calculate the tower natural frequencies:
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
if ( EqualRealNos(( MTFA(I,I) - p%TwrTpMass ), 0.0_ReKi) ) then
|
||||
p%FreqTFA(I,1) = NaN ! Avoid creating a divide by zero signal, but set p%FreqTFA(I,1) = NaN
|
||||
else
|
||||
p%FreqTFA(I,1) = Inv2Pi*SQRT( p%KTFA(I,I)/( MTFA(I,I) - p%TwrTpMass ) ) ! Natural tower I-fore-aft frequency w/o gravitational destiffening nor tower-top mass effects
|
||||
end if
|
||||
if ( EqualRealNos(( MTSS(I,I) - p%TwrTpMass ), 0.0_ReKi) ) then
|
||||
p%FreqTSS(I,1) = NaN ! Avoid creating a divide by zero signal, but set p%FreqTFS(I,1) = NaN
|
||||
else
|
||||
p%FreqTSS(I,1) = Inv2Pi*SQRT( p%KTSS(I,I)/( MTSS(I,I) - p%TwrTpMass ) ) ! Natural tower I-side-to-side frequency w/o gravitational destiffening nor tower-top mass effects
|
||||
end if
|
||||
p%FreqTFA(I,2) = Inv2Pi*SQRT( ( p%KTFA(I,I) + KTFAGrav(I,I) )/MTFA(I,I) ) ! Natural tower I-fore-aft frequency w/ gravitational destiffening and tower-top mass effects
|
||||
p%FreqTSS(I,2) = Inv2Pi*SQRT( ( p%KTSS(I,I) + KTSSGrav(I,I) )/MTSS(I,I) ) ! Natural tower I-side-to-side frequency w/ gravitational destiffening and tower-top mass effects
|
||||
ENDDO ! I - All tower DOFs in one direction
|
||||
|
||||
|
||||
! Calculate the generalized damping of the tower:
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
DO L = 1,2 ! Loop through all tower DOFs in one direction
|
||||
p%CTFA(I,L) = ( 0.01*InputFileData%TwrFADmp(L) )*p%KTFA(I,L)/( Pi*p%FreqTFA(L,1) )
|
||||
|
||||
p%CTSS(I,L) = ( 0.01*InputFileData%TwrSSDmp(L) )*p%KTSS(I,L)/( Pi*p%FreqTSS(L,1) )
|
||||
ENDDO ! L - All tower DOFs in one direction
|
||||
ENDDO ! I - All tower DOFs in one direction
|
||||
|
||||
|
||||
! Calculate the tower shape functions (all derivatives) at the tower-top:
|
||||
|
||||
p%TwrFASF(1,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM1Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrFASF(2,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM2Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrFASF(1,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM1Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrFASF(2,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM2Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrFASF(1,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM1Sh(:), 0, ErrStat, ErrMsg )
|
||||
p%TwrFASF(2,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwFAM2Sh(:), 0, ErrStat, ErrMsg )
|
||||
|
||||
p%TwrSSSF(1,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM1Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(2,p%TTopNode,2) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM2Sh(:), 2, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(1,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM1Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(2,p%TTopNode,1) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM2Sh(:), 1, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(1,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM1Sh(:), 0, ErrStat, ErrMsg )
|
||||
p%TwrSSSF(2,p%TTopNode,0) = SHP( 1.0_ReKi, p%TwrFlexL, InputFileData%TwSSM2Sh(:), 0, ErrStat, ErrMsg )
|
||||
|
||||
|
||||
! Integrate to find the tower axial reduction shape functions at the tower-top:
|
||||
|
||||
DO I = 1,2 ! Loop through all tower DOFs in one direction
|
||||
DO L = 1,2 ! Loop through all tower DOFs in one direction
|
||||
p%AxRedTFA(I,L,p%TTopNode) = p%AxRedTFA(I,L,p%TwrNodes)+ AxRdTFAOld(I,L)
|
||||
p%AxRedTSS(I,L,p%TTopNode) = p%AxRedTSS(I,L,p%TwrNodes)+ AxRdTSSOld(I,L)
|
||||
ENDDO ! L - All tower DOFs in one direction
|
||||
ENDDO
|
||||
|
||||
|
||||
! Calculate the turbine mass:
|
||||
|
||||
p%TurbMass = p%TwrTpMass + p%TwrMass
|
||||
|
||||
|
||||
RETURN
|
||||
END SUBROUTINE Coeff
|
||||
```
|
||||
622
书籍/力学书籍/OpenFast/FASTKinetics/auto/meshmap.md
Normal file
622
书籍/力学书籍/OpenFast/FASTKinetics/auto/meshmap.md
Normal file
@ -0,0 +1,622 @@
|
||||
|
||||
```fortran
|
||||
|
||||
!----------------------------------------------------------------------------------------------------------------------------------
|
||||
!bjj: maybe the MeshMapCreate routine shouldn't actually allocate arrays; allocate them in
|
||||
! the "IF (RemapFlag)" sections so that if people add nodes during the simulation, the structures get reallocated to correct
|
||||
! size? MeshMapCreate should maybe be MeshMapping_Init() and only check that fields are compatible, etc.
|
||||
!----------------------------------------------------------------------------------------------------------------------------------
|
||||
!> This subroutine takes two meshes, determines the sizes required for the mapping data structure, and then
|
||||
!! allocates the mappings (different for loads and motions/scalars).
|
||||
SUBROUTINE MeshMapCreate( Src, Dest, MeshMap, ErrStat, ErrMsg )
|
||||
|
||||
! note that MeshMap%MapSrcToAugmt is allocated in Create_Augmented_Ln2_Src_Mesh() along with the Augmented_Ln2_Src Mesh
|
||||
|
||||
TYPE(MeshType), INTENT(IN) :: Src !< source mesh
|
||||
TYPE(MeshType), INTENT(IN) :: Dest !< destination mesh
|
||||
|
||||
TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data structure
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None
|
||||
|
||||
! local variables:
|
||||
|
||||
INTEGER(IntKi) :: PointsInMap, PointsInTmpMap
|
||||
INTEGER(IntKi) :: ElementNodes
|
||||
LOGICAL :: MapCreated
|
||||
INTEGER(IntKi) :: ErrStat2
|
||||
CHARACTER(ErrMsgLen) :: ErrMsg2
|
||||
CHARACTER(*), PARAMETER :: RoutineName = 'MeshMapCreate'
|
||||
|
||||
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ''
|
||||
|
||||
MapCreated = .FALSE.
|
||||
|
||||
|
||||
IF ( .NOT. Dest%Committed .OR. .NOT. Src%Committed ) THEN
|
||||
ErrStat = ErrID_Fatal
|
||||
ErrMsg = " Both meshes must be committed before they can be mapped."
|
||||
RETURN
|
||||
END IF
|
||||
|
||||
|
||||
ElementNodes = 1
|
||||
PointsInTmpMap = 0
|
||||
|
||||
!................................................
|
||||
! Allocate the mapping for Motions and Scalars (if both meshes have some):
|
||||
!................................................
|
||||
IF ( HasMotionFields(Src) .AND. HasMotionFields(Dest) ) THEN
|
||||
|
||||
IF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN !Line2-to-Point and Line2-to-Line2 motion mapping
|
||||
ElementNodes = 2
|
||||
END IF
|
||||
|
||||
|
||||
! for motion fields, every destination node is mapped to a source element or node
|
||||
|
||||
PointsInMap = Dest%Nnodes
|
||||
PointsInTmpMap = MAX(PointsInTmpMap,PointsInMap)
|
||||
|
||||
IF ( PointsInMap < 1 ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'MeshMap%MapMotions not allocated because no nodes were found to map.', ErrStat, ErrMsg, RoutineName)
|
||||
ELSE
|
||||
|
||||
! Allocate the mapping structure:
|
||||
ALLOCATE( MeshMap%MapMotions(PointsInMap), STAT=ErrStat2 )
|
||||
IF ( ErrStat2 /= 0 ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Error trying to allocate MeshMap%MapMotions.', ErrStat, ErrMsg, RoutineName)
|
||||
ELSE
|
||||
MapCreated = .TRUE.
|
||||
|
||||
! set up the initial mappings so that we don't necessarially have to do this multiple times on the first time step (if calculating Jacobians)
|
||||
IF ( Dest%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! point-to-Line2 or Line2-to-Line2
|
||||
|
||||
IF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-Line2
|
||||
CALL CreateMotionMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
ELSEIF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-Line2
|
||||
CALL CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
|
||||
ELSEIF ( Dest%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point or Line2-to-point
|
||||
|
||||
IF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point
|
||||
CALL CreateMotionMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
ELSEIF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-point
|
||||
CALL CreateMotionMap_L2_to_P(Src, Dest, MeshMap, ErrStat2, ErrMsg2)
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
|
||||
END IF ! create initial mapping based on mesh element type
|
||||
|
||||
END IF ! MapMotions created
|
||||
|
||||
END IF ! Dest has nodes to map
|
||||
|
||||
END IF !HasMotionFields
|
||||
|
||||
|
||||
!................................................
|
||||
! Allocate the mapping for Loads:
|
||||
!................................................
|
||||
IF ( HasLoadFields(Src) .AND. HasLoadFields(Dest) ) THEN
|
||||
|
||||
! check that the appropriate combinations of source/destination force/moments exist:
|
||||
IF ( Src%FieldMask(MASKID_Force) ) THEN
|
||||
IF (.NOT. Dest%FieldMask(MASKID_Force) ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Destination mesh does not contain force but source mesh does.', ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
IF (.NOT. Dest%FieldMask(MASKID_Moment) ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Destination mesh must contain moment when source mesh contains force.', ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
END IF
|
||||
IF ( Src%FieldMask(MASKID_Moment) ) THEN
|
||||
IF (.NOT. Dest%FieldMask(MASKID_Moment) ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Destination mesh does not contain moment but source mesh does.', ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
END IF
|
||||
|
||||
|
||||
! get size of mapping:
|
||||
PointsInMap = Src%Nnodes
|
||||
|
||||
IF ( PointsInMap < 1 ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'MeshMap%MapLoads not allocated because no nodes were found to map.', ErrStat, ErrMsg, RoutineName)
|
||||
ELSE
|
||||
|
||||
! Allocate the mapping structure:
|
||||
ALLOCATE( MeshMap%MapLoads(PointsInMap), STAT=ErrStat2 )
|
||||
IF ( ErrStat2 /= 0 ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Error trying to allocate MeshMap%MapLoads.', ErrStat, ErrMsg, RoutineName)
|
||||
ELSE
|
||||
MapCreated = .TRUE.
|
||||
|
||||
! set up the initial mappings so that we don't necessarially have to do this multiple times on the first time step (if calculating Jacobians)
|
||||
IF ( Dest%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! point-to-Line2 or Line2-to-Line2
|
||||
|
||||
ElementNodes = 2
|
||||
|
||||
IF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-Line2
|
||||
CALL CreateLoadMap_L2_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
ELSEIF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-Line2
|
||||
CALL CreateLoadMap_P_to_L2( Src, Dest, MeshMap, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
|
||||
ELSEIF ( Dest%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point or Line2-to-point
|
||||
|
||||
IF ( Src%ElemTable(ELEMENT_POINT)%nelem > 0 ) THEN ! point-to-point
|
||||
CALL CreateLoadMap_P_to_P( Src, Dest, MeshMap, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
ELSEIF ( Src%ElemTable(ELEMENT_LINE2)%nelem > 0 ) THEN ! Line2-to-point
|
||||
CALL CreateLoadMap_L2_to_P(Src, Dest, MeshMap, ErrStat2, ErrMsg2)
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
|
||||
END IF ! create initial mapping based on mesh element type
|
||||
|
||||
END IF ! MapLoads allocated
|
||||
|
||||
END IF ! Src has nodes to transfer
|
||||
|
||||
END IF ! HasLoadFields
|
||||
|
||||
IF ( .NOT. MapCreated ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Neither MapMotions or MapLoads was allocated. Meshes may not have compatible fields for mapping.', ErrStat, ErrMsg, RoutineName)
|
||||
RETURN
|
||||
END IF
|
||||
|
||||
|
||||
!................................................
|
||||
! Allocate the DisplacedPosition field:
|
||||
!................................................
|
||||
|
||||
IF (.NOT. ALLOCATED (MeshMap%DisplacedPosition)) THEN
|
||||
CALL AllocAry( MeshMap%DisplacedPosition, 3, PointsInTmpMap, ElementNodes, 'MeshMap%DisplacedPosition', ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
|
||||
END IF
|
||||
|
||||
|
||||
END SUBROUTINE MeshMapCreate
|
||||
```
|
||||
|
||||
|
||||
```fortran
|
||||
!> This routine creates the mapping of motions between two meshes
|
||||
SUBROUTINE CreateMotionMap_L2_to_L2( Src, Dest, MeshMap, ErrStat, ErrMsg )
|
||||
|
||||
TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh
|
||||
TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh
|
||||
TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< structure that contains data necessary to map these two meshes
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None
|
||||
|
||||
! Local variables:
|
||||
INTEGER(IntKi) :: ErrStat2
|
||||
CHARACTER(ErrMsgLen) :: ErrMsg2
|
||||
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ""
|
||||
|
||||
|
||||
CALL CreateMapping_ProjectToLine2(Dest,Src, MeshMap%MapMotions, ELEMENT_LINE2, ErrStat2, ErrMsg2)
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_L2_to_L2')
|
||||
IF (ErrStat >= AbortErrLev) RETURN
|
||||
|
||||
END SUBROUTINE CreateMotionMap_L2_to_L2
|
||||
```
|
||||
|
||||
```fortran
|
||||
!> This routine projects Mesh1 onto a Line2 mesh (Mesh2) to find the element mappings between the two meshes.
|
||||
SUBROUTINE CreateMapping_ProjectToLine2(Mesh1, Mesh2, NodeMap, Mesh1_TYPE, ErrStat, ErrMsg)
|
||||
|
||||
TYPE(MeshType), INTENT(IN ) :: Mesh1 !< The mesh in the outer mapping loop (Dest for Motions/Scalars; Src for Loads)
|
||||
TYPE(MeshType), INTENT(IN ) :: Mesh2 !< The mesh in the inner mapping loop (Src for Motions/Scalars; Dest for Loads)
|
||||
|
||||
TYPE(MapType), INTENT(INOUT) :: NodeMap(:) !< The mapping from Src to Dest
|
||||
|
||||
INTEGER(IntKi), INTENT(IN ) :: Mesh1_TYPE !< Type of Mesh1 elements to map
|
||||
INTEGER(IntKi), PARAMETER :: Mesh2_TYPE = ELEMENT_LINE2 !< Type of Mesh2 elements on map (MUST BE ELEMENT_LINE2)
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None
|
||||
|
||||
|
||||
! local variables
|
||||
|
||||
! INTEGER(IntKi) :: ErrStat2 ! Error status of the operation
|
||||
! CHARACTER(ErrMsgLen) :: ErrMsg2 ! Error message if ErrStat2 /= ErrID_None
|
||||
#ifdef DEBUG_MESHMAPPING
|
||||
CHARACTER(200) :: DebugFileName ! File name for debugging file
|
||||
#endif
|
||||
CHARACTER(*), PARAMETER :: RoutineName = 'CreateMapping_ProjectToLine2'
|
||||
|
||||
|
||||
REAL(ReKi) :: denom
|
||||
REAL(ReKi) :: dist
|
||||
REAL(ReKi) :: min_dist
|
||||
REAL(ReKi) :: elem_position
|
||||
REAL(SiKi) :: elem_position_SiKi
|
||||
|
||||
REAL(ReKi) :: Mesh1_xyz(3)
|
||||
|
||||
REAL(ReKi) :: n1_n2_vector(3) ! vector going from node 1 to node 2 in Line2 element
|
||||
REAL(ReKi) :: n1_Point_vector(3) ! vector going from node 1 in Line 2 element to Destination Point
|
||||
REAL(ReKi) :: tmp(3) ! temporary vector for cross product calculation
|
||||
|
||||
|
||||
INTEGER(IntKi) :: iElem, iNode, i ! do-loop counter for elements on Mesh1, associated node(S)
|
||||
INTEGER(IntKi) :: jElem ! do-loop counter for elements on Mesh2, associated node
|
||||
|
||||
INTEGER(IntKi) :: n1, n2 ! nodes associated with an element
|
||||
|
||||
LOGICAL :: found
|
||||
LOGICAL :: on_element
|
||||
REAL(ReKi) :: closest_elem_position
|
||||
INTEGER(IntKi) :: closest_elem
|
||||
REAL(ReKi) :: closest_elem_diff
|
||||
REAL(ReKi) :: closest_elem_distance
|
||||
|
||||
#ifdef DEBUG_MESHMAPPING
|
||||
INTEGER(IntKi) :: Un ! unit number for debugging
|
||||
INTEGER(IntKi) :: ErrStat2
|
||||
CHARACTER(ErrMsgLen) :: ErrMsg2
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
! initialization
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ""
|
||||
|
||||
|
||||
! Map the source nodes to destination nodes:
|
||||
do n1=1,size(NodeMap)
|
||||
NodeMap(n1)%OtherMesh_Element = NODE_NOT_MAPPED ! initialize this so we know if we've mapped this node already (done only because we may have different elements)
|
||||
end do !n1
|
||||
|
||||
|
||||
|
||||
do iElem = 1, Mesh1%ElemTable(Mesh1_TYPE)%nelem ! number of Mesh1_TYPE elements on Mesh1
|
||||
do iNode = 1, SIZE( Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes )
|
||||
i = Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes(iNode) ! the nodes on element iElem
|
||||
IF ( NodeMap(i)%OtherMesh_Element > 0 ) CYCLE ! we already mapped this node; let's move on to the next iNode (or iElem)
|
||||
|
||||
! destination point
|
||||
Mesh1_xyz = Mesh1%Position(:, i)
|
||||
|
||||
found = .false.
|
||||
min_dist = HUGE(min_dist)
|
||||
|
||||
! some values for finding mapping if there are some numerical issues
|
||||
closest_elem_diff = HUGE(min_dist)
|
||||
closest_elem = 0
|
||||
|
||||
do jElem = 1, Mesh2%ElemTable(Mesh2_TYPE)%nelem ! ELEMENT_LINE2 = Mesh2_TYPE
|
||||
|
||||
! write(*,*) 'i,jElem = ', i,jElem, 'found = ', found
|
||||
|
||||
! grab node numbers associated with the jElem_th element
|
||||
n1 = Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes(1)
|
||||
n2 = Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes(2)
|
||||
|
||||
! Calculate vectors used in projection operation
|
||||
|
||||
n1_n2_vector = Mesh2%Position(:,n2) - Mesh2%Position(:,n1)
|
||||
n1_Point_vector = Mesh1_xyz - Mesh2%Position(:,n1)
|
||||
|
||||
denom = DOT_PRODUCT( n1_n2_vector, n1_n2_vector )
|
||||
IF ( EqualRealNos( denom, 0.0_ReKi ) ) THEN
|
||||
CALL SetErrStat( ErrID_Fatal, 'Division by zero because Line2 element nodes are in same position.', ErrStat, ErrMsg, RoutineName)
|
||||
RETURN
|
||||
END IF
|
||||
|
||||
! project point onto line defined by n1 and n2
|
||||
|
||||
elem_position = DOT_PRODUCT(n1_n2_vector,n1_Point_vector) / denom
|
||||
|
||||
! note: i forumlated it this way because Fortran doesn't necessarially do shortcutting and I don't want to call EqualRealNos if we don't need it:
|
||||
if ( elem_position .ge. 0.0_ReKi .and. elem_position .le. 1.0_ReKi ) then !we're ON the element (between the two nodes)
|
||||
on_element = .true.
|
||||
else
|
||||
elem_position_SiKi = REAL( elem_position, SiKi )
|
||||
if (EqualRealNos( elem_position_SiKi, 1.0_SiKi )) then !we're ON the element (at a node)
|
||||
on_element = .true.
|
||||
elem_position = 1.0_ReKi
|
||||
elseif (EqualRealNos( elem_position_SiKi, 0.0_SiKi )) then !we're ON the element (at a node)
|
||||
on_element = .true.
|
||||
elem_position = 0.0_ReKi
|
||||
else !we're not on the element
|
||||
on_element = .false.
|
||||
|
||||
if (.not. found) then ! see if we have are very close to the end of an element (numerical roundoff?)
|
||||
if ( elem_position_SiKi < 0.0_SiKi ) then
|
||||
if ( -elem_position_SiKi < closest_elem_diff ) then
|
||||
closest_elem_diff = -elem_position_SiKi
|
||||
closest_elem = jElem
|
||||
closest_elem_position = 0.0_ReKi
|
||||
closest_elem_distance = sqrt(denom) * closest_elem_diff ! distance from end of element, in meters
|
||||
end if
|
||||
else
|
||||
if ( elem_position_SiKi-1.0_SiKi < closest_elem_diff ) then
|
||||
closest_elem_diff = elem_position_SiKi-1.0_SiKi
|
||||
closest_elem = jElem
|
||||
closest_elem_position = 1.0_ReKi
|
||||
closest_elem_distance = sqrt(denom) * closest_elem_diff ! distance from end of element, in meters
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
|
||||
end if
|
||||
end if
|
||||
|
||||
if (on_element) then
|
||||
|
||||
! calculate distance between point and line (note: this is actually the distance squared);
|
||||
! will only store information once we have determined the closest element
|
||||
tmp = cross_product( n1_n2_vector, n1_Point_vector )
|
||||
dist = DOT_PRODUCT(tmp,tmp) / denom
|
||||
|
||||
if (dist .lt. min_dist) then
|
||||
found = .true.
|
||||
min_dist = dist
|
||||
|
||||
NodeMap(i)%OtherMesh_Element = jElem
|
||||
NodeMap(i)%shape_fn(1) = 1.0_ReKi - elem_position
|
||||
NodeMap(i)%shape_fn(2) = elem_position
|
||||
|
||||
!NodeMap(i)%couple_arm = n1_Point_vector
|
||||
|
||||
end if !the point is closest to this line2 element
|
||||
|
||||
endif
|
||||
|
||||
end do !jElem
|
||||
|
||||
! if failed to find an element that the Point projected into, throw an error
|
||||
if (.not. found) then
|
||||
if ( closest_elem_distance <= 7.5e-3 ) then ! if it is within 7.5mm of the end of an element, we'll accept it
|
||||
NodeMap(i)%OtherMesh_Element = closest_elem
|
||||
NodeMap(i)%shape_fn(1) = 1.0_ReKi - closest_elem_position
|
||||
NodeMap(i)%shape_fn(2) = closest_elem_position
|
||||
CALL SetErrStat( ErrID_Info, 'Found close value for node '//trim(num2Lstr(i))//'. ('//trim(num2lstr(closest_elem_distance))//' m)', ErrStat, ErrMsg, RoutineName)
|
||||
end if
|
||||
|
||||
if (NodeMap(i)%OtherMesh_Element .lt. 1 ) then
|
||||
CALL SetErrStat( ErrID_Fatal, 'Node '//trim(num2Lstr(i))//' does not project onto any line2 element.' &
|
||||
//' Closest distance is '//trim(num2lstr(closest_elem_distance))//' m.', ErrStat, ErrMsg, RoutineName)
|
||||
|
||||
#ifdef DEBUG_MESHMAPPING
|
||||
! output some mesh information for debugging
|
||||
CALL GetNewUnit(Un,ErrStat2,ErrMsg2)
|
||||
DebugFileName='FAST_Meshes.'//trim(num2Lstr(Un))//'.dbg'
|
||||
CALL OpenFOutFile(Un,DebugFileName,ErrStat2,ErrMsg2)
|
||||
IF (ErrStat2 >= AbortErrLev) RETURN
|
||||
|
||||
CALL SetErrStat( ErrID_Info, 'See '//trim(DebugFileName)//' for mesh debug information.', ErrStat, ErrMsg, RoutineName)
|
||||
WRITE( Un, '(A,I5,A,I5,A,ES15.5,A)' ) 'Element ', closest_elem, ' is closest to node ', i, &
|
||||
'. It has a relative position of ', closest_elem_diff, '.'
|
||||
|
||||
WRITE( Un, '(A)') '************************************************** Mesh1 ***************************************************'
|
||||
WRITE( Un, '(A)') 'Mesh1 is the destination mesh for transfer of motions/scalars; it is the source mesh for transfer of loads.'
|
||||
WRITE( Un, '(A)') '************************************************************************************************************'
|
||||
CALL MeshPrintInfo ( Un, Mesh1 )
|
||||
WRITE( Un, '(A)') '************************************************** Mesh2 ***************************************************'
|
||||
WRITE( Un, '(A)') 'Mesh2 is the source mesh for transfer of motions/scalars; it is the destination mesh for transfer of loads.'
|
||||
WRITE( Un, '(A)') '************************************************************************************************************'
|
||||
CALL MeshPrintInfo ( Un, Mesh2 )
|
||||
! CLOSE(Un) ! by not closing this, I can ensure unique file names.
|
||||
#endif
|
||||
|
||||
RETURN
|
||||
endif
|
||||
|
||||
end if !not found on projection to element
|
||||
|
||||
end do !iNode
|
||||
end do !iElem
|
||||
|
||||
END SUBROUTINE CreateMapping_ProjectToLine2
|
||||
```
|
||||
|
||||
```fortran
|
||||
SUBROUTINE CreateMotionMap_P_to_L2( Src, Dest, MeshMap, ErrStat, ErrMsg )
|
||||
|
||||
TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh
|
||||
TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh
|
||||
TYPE(MeshMapType), INTENT(INOUT) :: MeshMap
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None
|
||||
|
||||
! Local variables:
|
||||
INTEGER(IntKi) :: i
|
||||
INTEGER(IntKi) :: ErrStat2
|
||||
CHARACTER(ErrMsgLen) :: ErrMsg2
|
||||
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ""
|
||||
|
||||
|
||||
! Each destination node (on a LINE2 mesh) needs a source
|
||||
! in following call, Dest is mesh to looped over, finding a corresponding point for each point in Src
|
||||
CALL CreateMapping_NearestNeighbor( Dest, Src, MeshMap%MapMotions, ELEMENT_LINE2, ELEMENT_POINT, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_P_to_L2')
|
||||
IF (ErrStat >= AbortErrLev) RETURN
|
||||
|
||||
! bjj: for consistant definition of couple_arm (i.e. p_ODR-p_OSR), let's multiply by -1
|
||||
do i=1,SIZE(MeshMap%MapMotions)
|
||||
MeshMap%MapMotions(i)%couple_arm = -1._ReKi*MeshMap%MapMotions(i)%couple_arm
|
||||
end do
|
||||
|
||||
|
||||
END SUBROUTINE CreateMotionMap_P_to_L2
|
||||
```
|
||||
|
||||
```fortran
|
||||
|
||||
!> This routine creates the node-to-node (nearest neighbor). We map FROM Mesh1 to Mesh2
|
||||
SUBROUTINE CreateMapping_NearestNeighbor( Mesh1, Mesh2, NodeMap, Mesh1_TYPE, Mesh2_TYPE, ErrStat, ErrMsg )
|
||||
!.......................................................................................
|
||||
TYPE(MeshType), INTENT(IN ) :: Mesh1 !< The mesh in the outer mapping loop (Dest for Motions/Scalars; Src for Loads)
|
||||
TYPE(MeshType), INTENT(IN ) :: Mesh2 !< The mesh in the inner mapping loop (Src for Motions/Scalars; Dest for Loads)
|
||||
|
||||
TYPE(MapType), INTENT(INOUT) :: NodeMap(:) !< The mapping from Src to Dest
|
||||
|
||||
INTEGER(IntKi), INTENT(IN ) :: Mesh1_TYPE !< Type of Mesh1 elements to map
|
||||
INTEGER(IntKi), INTENT(IN ) :: Mesh2_TYPE !< Type of Mesh2 elements on map
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None
|
||||
|
||||
! local variables
|
||||
|
||||
REAL(ReKi) :: dist
|
||||
REAL(ReKi) :: min_dist
|
||||
|
||||
REAL(ReKi) :: Mesh1_xyz(3)
|
||||
REAL(ReKi) :: Mesh2_xyz(3)
|
||||
|
||||
INTEGER(IntKi) :: point_with_min_dist
|
||||
INTEGER(IntKi) :: iElem, iNode, i ! do-loop counter for elements on Mesh1, associated node(S)
|
||||
INTEGER(IntKi) :: jElem, jNode, j ! do-loop counter for elements on Mesh2, associated node
|
||||
|
||||
LOGICAL :: UseMesh2Node(Mesh2%NNodes) ! determines if the node on the second mesh is part of the mapping (i.e., contained in an element of the appropriate type)
|
||||
|
||||
|
||||
! initialization
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ""
|
||||
|
||||
! Determine which nodes on mesh2 are going to be in the mapping
|
||||
UseMesh2Node = .FALSE.
|
||||
do jElem = 1, Mesh2%ElemTable(Mesh2_TYPE)%nelem ! number of point elements on Mesh2
|
||||
do jNode = 1, SIZE( Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes )
|
||||
UseMesh2Node( Mesh2%ElemTable(Mesh2_TYPE)%Elements(jElem)%ElemNodes(jNode) ) = .TRUE.
|
||||
end do
|
||||
end do
|
||||
|
||||
! Map the source nodes to destination nodes:
|
||||
do i=1,size(NodeMap)
|
||||
NodeMap(i)%OtherMesh_Element = NODE_NOT_MAPPED ! initialize this so we know if we've mapped this node already (done only because we may have different elements)
|
||||
end do !n1
|
||||
|
||||
|
||||
do iElem = 1, Mesh1%ElemTable(Mesh1_TYPE)%nelem ! number of Mesh1_TYPE elements on Mesh1 = number of points on Mesh1
|
||||
do iNode = 1, SIZE( Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes )
|
||||
i = Mesh1%ElemTable(Mesh1_TYPE)%Elements(iElem)%ElemNodes(iNode) ! the nodes on element iElem
|
||||
IF ( NodeMap(i)%OtherMesh_Element > 0 ) CYCLE ! we already mapped this node; let's move on
|
||||
|
||||
|
||||
! Find the nearest neighbor node for this particular node
|
||||
|
||||
! initialize minimum distance marker at some huge number
|
||||
min_dist = HUGE(min_dist)
|
||||
point_with_min_dist = 0
|
||||
|
||||
Mesh1_xyz = Mesh1%Position(:, i)
|
||||
|
||||
do j = 1, Mesh2%NNodes
|
||||
IF ( .NOT. UseMesh2Node(j) ) CYCLE !This node isn't part of the elements we're mapping
|
||||
|
||||
! destination point
|
||||
Mesh2_xyz = Mesh2%Position(:, j)
|
||||
|
||||
! calculate distance between source and desination; will only store information once we have determined
|
||||
! the closest point
|
||||
dist = sqrt( (Mesh1_xyz(1) - Mesh2_xyz(1))**2 &
|
||||
+ (Mesh1_xyz(2) - Mesh2_xyz(2))**2 &
|
||||
+ (Mesh1_xyz(3) - Mesh2_xyz(3))**2 )
|
||||
|
||||
if (dist .lt. min_dist) then
|
||||
|
||||
min_dist = dist
|
||||
point_with_min_dist = j
|
||||
|
||||
!if (EqualRealNos(dist), 0.0_ReKi)) EXIT !we have an exact match so let's just stop looking
|
||||
|
||||
endif
|
||||
|
||||
end do !j
|
||||
|
||||
if (point_with_min_dist .lt. 1 ) then
|
||||
CALL SetErrStat( ErrID_Fatal, 'Failed to find destination point associated with source point.', ErrStat, ErrMsg, 'CreateMapping_NearestNeighbor')
|
||||
RETURN
|
||||
endif
|
||||
|
||||
NodeMap(i)%OtherMesh_Element = point_with_min_dist !bjj: For consistency, I really wish we had used element numbers here instead....
|
||||
|
||||
NodeMap(i)%distance = min_dist
|
||||
|
||||
NodeMap(i)%couple_arm = Mesh2%Position(:, point_with_min_dist) - Mesh1_xyz
|
||||
!bjj: this is the negative of the case where it's Mesh2=src, so we'll have to multiply by -1 outside this routine if that's the case
|
||||
|
||||
end do !iNode
|
||||
end do !iElem
|
||||
|
||||
|
||||
END SUBROUTINE CreateMapping_NearestNeighbor
|
||||
```
|
||||
|
||||
```fortran
|
||||
SUBROUTINE CreateMotionMap_P_to_P( Src, Dest, MeshMap, ErrStat, ErrMsg )
|
||||
|
||||
TYPE(MeshType), INTENT(IN ) :: Src ! The source mesh
|
||||
TYPE(MeshType), INTENT(IN ) :: Dest ! The destination mesh
|
||||
TYPE(MeshMapType), INTENT(INOUT) :: MeshMap
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None
|
||||
|
||||
! Local variables:
|
||||
INTEGER(IntKi) :: i
|
||||
INTEGER(IntKi) :: ErrStat2
|
||||
CHARACTER(ErrMsgLen) :: ErrMsg2
|
||||
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ""
|
||||
|
||||
! in following call, Dest is mesh to looped over, finding a corresponding point for each point in Src
|
||||
CALL CreateMapping_NearestNeighbor( Dest, Src, MeshMap%MapMotions, ELEMENT_POINT, ELEMENT_POINT, ErrStat2, ErrMsg2 )
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_P_to_P')
|
||||
IF (ErrStat >= AbortErrLev) RETURN
|
||||
|
||||
! bjj: for consistant definition of couple_arm (i.e. p_ODR-p_OSR), let's multiply by -1
|
||||
do i=1,SIZE(MeshMap%MapMotions)
|
||||
MeshMap%MapMotions(i)%couple_arm = -1.0_ReKi*MeshMap%MapMotions(i)%couple_arm
|
||||
end do
|
||||
|
||||
END SUBROUTINE CreateMotionMap_P_to_P
|
||||
```
|
||||
|
||||
```fortran
|
||||
SUBROUTINE CreateMotionMap_L2_to_P( Src, Dest, MeshMap, ErrStat, ErrMsg )
|
||||
|
||||
TYPE(MeshType), INTENT(IN ) :: Src !< The source mesh
|
||||
TYPE(MeshType), INTENT(IN ) :: Dest !< The destination mesh
|
||||
TYPE(MeshMapType), INTENT(INOUT) :: MeshMap !< mapping data structure
|
||||
|
||||
INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation
|
||||
CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None
|
||||
|
||||
! Local variables:
|
||||
INTEGER(IntKi) :: ErrStat2
|
||||
CHARACTER(ErrMsgLen) :: ErrMsg2
|
||||
|
||||
ErrStat = ErrID_None
|
||||
ErrMsg = ""
|
||||
|
||||
CALL CreateMapping_ProjectToLine2(Dest,Src, MeshMap%MapMotions, ELEMENT_POINT, ErrStat2, ErrMsg2)
|
||||
CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'CreateMotionMap_L2_to_P')
|
||||
!IF (ErrStat >= AbortErrLev) RETURN
|
||||
|
||||
END SUBROUTINE CreateMotionMap_L2_to_P
|
||||
```
|
||||
@ -345,7 +345,7 @@ in which there are as many terms as there are degrees of freedom. The off-diagon
|
||||
If more than one translational degree of freedom is specified at any nodal point, the same point mass will be associated with each degree of freedom. On the other hand, the mass associated with any rotational degree of freedom will be zero because of the assumption that the mass is lumped in points which have no rotational inertia. (Of course, if a rigid mass having a finite rotational inertia is associated with a rotational degree of freedom, the diagonal mass coefficient for that degree of freedom would be the rotational inertia of the mass.) Thus the lumped-mass matrix is a diagonal matrix which will include zero diagonal elements for the rotational degrees of freedom, in general.
|
||||
其中项数与自由度数相同。该矩阵的非对角项 $m_{i j}$ 为零,因为任何质点的加速度仅在该点产生惯性力。点 $i$ 处由于点 $i$ 的单位加速度产生的惯性力显然等于集中在该点的质量;因此,在集中质量系统中,质量影响系数 $m_{i i}=m_{i}$。
|
||||
|
||||
如果在任何节点处指定了多个平移自由度,则相同的质点质量将与每个自由度相关联。另一方面,与任何旋转自由度相关联的质量将为零,因为假设质量集中在没有转动惯量的点上。(当然,如果一个具有有限转动惯量的刚性质量与一个旋转自由度相关联,那么该自由度的对角质量系数将是该质量的转动惯量。)因此,集中质量矩阵是一个对角矩阵,通常会包含旋转自由度的零对角元素。
|
||||
**如果在任何节点处指定了多个平移自由度,则相同的质点质量将与每个自由度相关联。另一方面,与任何旋转自由度相关联的质量将为零,因为假设质量集中在没有转动惯量的点上。(当然,如果一个具有有限转动惯量的刚性质量与一个旋转自由度相关联,那么该自由度的对角质量系数将是该质量的转动惯量。)因此,集中质量矩阵是一个对角矩阵,通常会包含旋转自由度的零对角元素。** ?
|
||||
## Consistent-Mass Matrix一致质量矩阵
|
||||
|
||||
Making use of the finite-element concept, it is possible to evaluate mass influence coefficients for each element of a structure by a procedure similar to the analysis of element stiffness coefficients. Consider, for example, the nonuniform beam segment shown in Fig. 10-7, which may be assumed to be the same as that of Fig. 10-4. The degrees of freedom of the segment are the translation and rotation at each end, and it will be assumed that the displacements within the span are defined by the same interpolation functions $\psi_{i}(x)$ used in deriving the element stiffness.
|
||||
|
||||
12
多体+耦合求解器/ElastoDyn问题 NREL Forum.md
Normal file
12
多体+耦合求解器/ElastoDyn问题 NREL Forum.md
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
不支持prebend
|
||||
# [Out-of-plane tip displacements](https://forums.nrel.gov/t/out-of-plane-tip-displacements/7037)
|
||||
[[20260120_093252__[[meshmap]]分析SUBROUTINE_MeshMapCreate的实现方法and预弯]]
|
||||
|
||||
# [Comparing ElastoDyn with BeamDyn for blade tip deformations](https://forums.nrel.gov/t/comparing-elastodyn-with-beamdyn-for-blade-tip-deformations/4774)
|
||||
|
||||
|
||||
|
||||
|
||||
# [Deflection of ElastoDyn](https://forums.nrel.gov/t/deflection-of-elastodyn/2233)
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
{
|
||||
"nodes":[
|
||||
{"id":"9461f7dd96103316","type":"text","text":"Kane方法","x":-120,"y":-280,"width":250,"height":50},
|
||||
{"id":"0c8534c8ba68c9a6","type":"text","text":"**广义**主动力","x":-280,"y":-140,"width":250,"height":50},
|
||||
{"id":"5eaa425c204bf600","type":"text","text":"**广义**惯性力","x":40,"y":-140,"width":250,"height":50},
|
||||
{"id":"e398416e55019686","type":"text","text":"运动学","x":-210,"y":220,"width":250,"height":60},
|
||||
{"id":"38d3d1a313c094ee","type":"text","text":"广义坐标","x":-280,"y":340,"width":250,"height":60},
|
||||
{"id":"8ec17237cebe7433","type":"text","text":"广义速率","x":60,"y":340,"width":250,"height":60},
|
||||
{"id":"7351d2bbb065d539","type":"text","text":"动力学 ","x":-210,"y":110,"width":250,"height":60},
|
||||
{"id":"da500b2b12ed0901","type":"text","text":"填充augmat矩阵","x":290,"y":-30,"width":250,"height":60},
|
||||
{"id":"20ce8d75f0f35588","type":"text","text":"解出来q_dot ---u","x":580,"y":-30,"width":250,"height":60},
|
||||
{"id":"6094c53caf966263","type":"text","text":"由F + F^* 的形式转换到 [C(q,t)],{-f(qd,q,t)}形式 ","x":-165,"y":-40,"width":340,"height":80},
|
||||
{"id":"c20eeff7484d8a39","type":"text","text":"叠加法","x":-275,"y":560,"width":250,"height":60},
|
||||
{"id":"a729b7930412f0b1","type":"text","text":"需要保持边界条件一致","x":60,"y":560,"width":250,"height":60},
|
||||
{"id":"d405163cb9ecd804","type":"text","text":"叶片多段拆分,小段做模态叠加?","x":60,"y":670,"width":250,"height":60},
|
||||
{"id":"4a08e20366911d68","type":"text","text":"v1pt_theory","x":290,"y":140,"width":250,"height":60},
|
||||
{"id":"6e5a6a3cdd47bd52","type":"text","text":"v2pt_theory","x":290,"y":207,"width":250,"height":60},
|
||||
{"id":"4bfacdf3ddedbdec","type":"text","text":"柔性体 / 连续体","x":-340,"y":960,"width":250,"height":60},
|
||||
{"id":"ae48e80ccd92bffa","type":"text","text":"连续体振动","x":60,"y":960,"width":250,"height":60},
|
||||
{"id":"ed5a265dc4b72aaa","type":"text","text":"连续体动力学","x":420,"y":960,"width":250,"height":60},
|
||||
{"id":"fc13b731983ac384","type":"text","text":"浮动坐标系","x":-340,"y":1181,"width":250,"height":60},
|
||||
{"id":"df8e8a93ea4af203","x":984,"y":-235,"width":250,"height":60,"type":"text","text":"叶片"},
|
||||
{"id":"7dc483819d8b527b","x":1280,"y":-235,"width":250,"height":60,"type":"text","text":"轮毂"},
|
||||
{"id":"c02c22667637367f","x":1580,"y":-235,"width":250,"height":60,"type":"text","text":"机舱"},
|
||||
{"id":"623ac90ce5bad160","x":1580,"y":-60,"width":250,"height":60,"type":"text","text":"塔架"},
|
||||
{"id":"0324f23e7dc78d68","x":1580,"y":55,"width":250,"height":60,"type":"text","text":"机舱"},
|
||||
{"id":"ba5c15a27611709c","x":1580,"y":-150,"width":250,"height":60,"type":"text","text":"偏航轴承"},
|
||||
{"id":"6c3a6982a53e7df9","x":984,"y":177,"width":250,"height":60,"type":"text","text":"刚体部件:"},
|
||||
{"id":"f3c36900dd3ed9d1","x":1280,"y":177,"width":250,"height":60,"type":"text","text":"刚体的广义主动力、惯性力公式"},
|
||||
{"id":"b624e8c6302b9a1c","x":984,"y":310,"width":250,"height":60,"type":"text","text":"叶片、塔架"},
|
||||
{"id":"1054909d642ce071","x":1280,"y":310,"width":250,"height":60,"type":"text","text":"广义惯性力:质点广义惯性力公式 积分"},
|
||||
{"id":"1e1a1a0d67920443","x":1280,"y":420,"width":250,"height":60,"type":"text","text":"广义主动力:由势能dV/dq_r"},
|
||||
{"id":"092cf6719d47d01d","x":1280,"y":530,"width":250,"height":60,"type":"text","text":"弹性恢复力、阻尼、重力、气动力"},
|
||||
{"id":"32b762bd2a4b0d66","x":984,"y":640,"width":250,"height":60,"type":"text","text":"传动链、偏航"},
|
||||
{"id":"14a4450243ca9953","x":1620,"y":530,"width":250,"height":60,"type":"text","text":"原理呢?"}
|
||||
],
|
||||
"edges":[
|
||||
{"id":"647c1b45edc92b02","fromNode":"9461f7dd96103316","fromSide":"bottom","toNode":"0c8534c8ba68c9a6","toSide":"top"},
|
||||
{"id":"e3d4293dd3262f2d","fromNode":"9461f7dd96103316","fromSide":"bottom","toNode":"5eaa425c204bf600","toSide":"top"},
|
||||
{"id":"9a803fcaec81414e","fromNode":"38d3d1a313c094ee","fromSide":"right","toNode":"8ec17237cebe7433","toSide":"left"},
|
||||
{"id":"7ff52c30a0b0347d","fromNode":"a729b7930412f0b1","fromSide":"bottom","toNode":"d405163cb9ecd804","toSide":"top"},
|
||||
{"id":"d97ef554530b15b5","fromNode":"c20eeff7484d8a39","fromSide":"right","toNode":"a729b7930412f0b1","toSide":"left"},
|
||||
{"id":"034d145edd7cfce0","fromNode":"0c8534c8ba68c9a6","fromSide":"bottom","toNode":"6094c53caf966263","toSide":"top"},
|
||||
{"id":"da18b7fa4859fa6f","fromNode":"5eaa425c204bf600","fromSide":"bottom","toNode":"6094c53caf966263","toSide":"top"},
|
||||
{"id":"5d5f4fef281a656e","fromNode":"6094c53caf966263","fromSide":"right","toNode":"da500b2b12ed0901","toSide":"left"},
|
||||
{"id":"5573fa12a3a02ee0","fromNode":"da500b2b12ed0901","fromSide":"right","toNode":"20ce8d75f0f35588","toSide":"left"},
|
||||
{"id":"c4828432b71fd99a","fromNode":"4bfacdf3ddedbdec","fromSide":"right","toNode":"ae48e80ccd92bffa","toSide":"left"},
|
||||
{"id":"8ded09c7902a30b6","fromNode":"ae48e80ccd92bffa","fromSide":"right","toNode":"ed5a265dc4b72aaa","toSide":"left"},
|
||||
{"id":"4818c7bc8aa99b57","fromNode":"b624e8c6302b9a1c","fromSide":"right","toNode":"1054909d642ce071","toSide":"left"},
|
||||
{"id":"d58b296db32dc932","fromNode":"1054909d642ce071","fromSide":"bottom","toNode":"1e1a1a0d67920443","toSide":"top"},
|
||||
{"id":"f88001eedfed69b8","fromNode":"1e1a1a0d67920443","fromSide":"bottom","toNode":"092cf6719d47d01d","toSide":"top"},
|
||||
{"id":"d0bfe0faa41e4e2f","fromNode":"6c3a6982a53e7df9","fromSide":"right","toNode":"f3c36900dd3ed9d1","toSide":"left"},
|
||||
{"id":"14130329273bf6fc","fromNode":"092cf6719d47d01d","fromSide":"right","toNode":"14a4450243ca9953","toSide":"left"}
|
||||
]
|
||||
}
|
||||
160
多体+耦合求解器/多体理论框架及ED求解方法.canvas
Normal file
160
多体+耦合求解器/多体理论框架及ED求解方法.canvas
Normal file
@ -0,0 +1,160 @@
|
||||
{
|
||||
"nodes":[
|
||||
{"id":"9461f7dd96103316","type":"text","text":"Kane方法","x":-120,"y":-280,"width":250,"height":50},
|
||||
{"id":"0c8534c8ba68c9a6","type":"text","text":"**广义**主动力","x":-280,"y":-140,"width":250,"height":50},
|
||||
{"id":"5eaa425c204bf600","type":"text","text":"**广义**惯性力","x":40,"y":-140,"width":250,"height":50},
|
||||
{"id":"e398416e55019686","type":"text","text":"运动学","x":-210,"y":220,"width":250,"height":60},
|
||||
{"id":"38d3d1a313c094ee","type":"text","text":"广义坐标","x":-280,"y":340,"width":250,"height":60},
|
||||
{"id":"8ec17237cebe7433","type":"text","text":"广义速率","x":60,"y":340,"width":250,"height":60},
|
||||
{"id":"7351d2bbb065d539","type":"text","text":"动力学 ","x":-210,"y":110,"width":250,"height":60},
|
||||
{"id":"da500b2b12ed0901","type":"text","text":"填充augmat矩阵","x":290,"y":-30,"width":250,"height":60},
|
||||
{"id":"20ce8d75f0f35588","type":"text","text":"解出来q_dot ---u","x":580,"y":-30,"width":250,"height":60},
|
||||
{"id":"6094c53caf966263","type":"text","text":"由F + F* 的形式转换到 [C(q,t)],{-f(qd,q,t)}形式 ","x":-165,"y":-40,"width":340,"height":80},
|
||||
{"id":"c20eeff7484d8a39","type":"text","text":"叠加法","x":-275,"y":560,"width":250,"height":60},
|
||||
{"id":"a729b7930412f0b1","type":"text","text":"需要保持边界条件一致","x":60,"y":560,"width":250,"height":60},
|
||||
{"id":"d405163cb9ecd804","type":"text","text":"叶片多段拆分,小段做模态叠加?","x":60,"y":670,"width":250,"height":60},
|
||||
{"id":"4a08e20366911d68","type":"text","text":"v1pt_theory","x":290,"y":140,"width":250,"height":60},
|
||||
{"id":"6e5a6a3cdd47bd52","type":"text","text":"v2pt_theory","x":290,"y":207,"width":250,"height":60},
|
||||
{"id":"4bfacdf3ddedbdec","type":"text","text":"柔性体 / 连续体","x":-340,"y":960,"width":250,"height":60},
|
||||
{"id":"ae48e80ccd92bffa","type":"text","text":"连续体振动","x":60,"y":960,"width":250,"height":60},
|
||||
{"id":"ed5a265dc4b72aaa","type":"text","text":"连续体动力学","x":420,"y":960,"width":250,"height":60},
|
||||
{"id":"fc13b731983ac384","type":"text","text":"浮动坐标系","x":-340,"y":1181,"width":250,"height":60},
|
||||
{"id":"df8e8a93ea4af203","type":"text","text":"叶片","x":984,"y":-235,"width":250,"height":60},
|
||||
{"id":"7dc483819d8b527b","type":"text","text":"轮毂","x":1280,"y":-235,"width":250,"height":60},
|
||||
{"id":"c02c22667637367f","type":"text","text":"机舱","x":1580,"y":-235,"width":250,"height":60},
|
||||
{"id":"623ac90ce5bad160","type":"text","text":"塔架","x":1580,"y":-60,"width":250,"height":60},
|
||||
{"id":"0324f23e7dc78d68","type":"text","text":"机舱","x":1580,"y":55,"width":250,"height":60},
|
||||
{"id":"ba5c15a27611709c","type":"text","text":"偏航轴承","x":1580,"y":-150,"width":250,"height":60},
|
||||
{"id":"6c3a6982a53e7df9","type":"text","text":"刚体部件:","x":984,"y":177,"width":250,"height":60},
|
||||
{"id":"f3c36900dd3ed9d1","type":"text","text":"刚体的广义主动力、惯性力公式","x":1280,"y":177,"width":250,"height":60},
|
||||
{"id":"b624e8c6302b9a1c","type":"text","text":"叶片、塔架","x":984,"y":310,"width":250,"height":60},
|
||||
{"id":"1054909d642ce071","type":"text","text":"广义惯性力:质点广义惯性力公式 积分","x":1280,"y":310,"width":250,"height":60},
|
||||
{"id":"1e1a1a0d67920443","type":"text","text":"广义主动力:由势能dV/dq_r","x":1280,"y":420,"width":250,"height":60},
|
||||
{"id":"092cf6719d47d01d","type":"text","text":"弹性恢复力、阻尼、重力、气动力","x":1280,"y":530,"width":250,"height":60},
|
||||
{"id":"32b762bd2a4b0d66","type":"text","text":"传动链、偏航","x":984,"y":640,"width":250,"height":60},
|
||||
{"id":"14a4450243ca9953","type":"text","text":"原理呢?","x":1620,"y":530,"width":250,"height":60},
|
||||
{"id":"5ed3765756616b02","type":"text","text":"叶片","x":-936,"y":1420,"width":250,"height":60},
|
||||
{"id":"9a7256948b4e439c","type":"text","text":"轮毂","x":-640,"y":1420,"width":250,"height":60},
|
||||
{"id":"db5161e16a8e2c3f","type":"text","text":"机舱","x":-340,"y":1420,"width":250,"height":60},
|
||||
{"id":"95eb99b9b0299f2f","type":"text","text":"塔架","x":-340,"y":1595,"width":250,"height":60},
|
||||
{"id":"a2e90c49290ecb52","type":"text","text":"偏航轴承","x":-340,"y":1505,"width":250,"height":60},
|
||||
{"id":"cccd4482e817fca4","type":"text","text":"$$\n{k'}_{ij}^{B1F} = \\sqrt{FlStTunr^{B1}(i) \\, FlStTunr^{B1}(j)} \\int_{0}^{BldFlexL} EI^{B1F}(r) \\frac{d^2 \\phi_i^{B1F}(r)}{dr^2} \\frac{d^2 \\phi_j^{B1F}(r)}{dr^2} dr \\quad (i, j = 1, 2) \\tag{9}\n$$","x":-180,"y":1855,"width":980,"height":130},
|
||||
{"id":"722e4b9c310e6d2a","type":"text","text":"$$\nEI^{B1F}(r) = AdjFlSt^{B1} \\cdot FlpStff^{B1}(r) \\tag{10}\n$$","x":-180,"y":2050,"width":980,"height":80},
|
||||
{"id":"50e241bef2144ea1","type":"text","text":"$$\n\\frac{d^2 \\phi_i^{B1F}(r)}{dr^2} \\frac{d^2 \\phi_j^{B1F}(r)}{dr^2}\n$$","x":200,"y":2190,"width":220,"height":120},
|
||||
{"id":"f65edb48b74e18d7","type":"text","text":"叶片广义挥舞刚度","x":-540,"y":1904,"width":250,"height":32,"color":"2"},
|
||||
{"id":"e0d016f4bb106554","type":"text","text":"- 需要叶片挥舞刚度","x":-540,"y":2072,"width":250,"height":36},
|
||||
{"id":"a9889437875a9263","type":"text","text":"- 模态形状二阶导","x":-540,"y":2232,"width":250,"height":36},
|
||||
{"id":"da8b0f86919e99d9","type":"text","text":"$$\n\\left[ \\frac{d^2 \\phi_{1}^{B1E}(r)}{dr^2} \\right]^2\n$$","x":10,"y":2710,"width":220,"height":120},
|
||||
{"id":"6454ea0b5f37aafa","type":"text","text":"- 模态形状二阶导","x":-540,"y":2752,"width":250,"height":36},
|
||||
{"id":"36c9ab3fd7a0a402","type":"text","text":"- 需要叶片挥舞刚度","x":-540,"y":2592,"width":250,"height":36},
|
||||
{"id":"ab5c75b7401fb031","type":"text","text":"叶片广义摆振刚度","x":-540,"y":2424,"width":250,"height":32,"color":"2"},
|
||||
{"id":"da00f9548457388f","type":"text","text":"$$\n{k'}_{11}^{B1E} = \\int_{0}^{BldFlexL} EI^{B1E}(r) \\left[ \\frac{d^2 \\phi_{1}^{B1E}(r)}{dr^2} \\right]^2 dr \\tag{11}\n$$","x":-180,"y":2380,"width":600,"height":120},
|
||||
{"id":"a20bd9b934093730","type":"text","text":"$$\nEI^{B1E}(r) = AdjEdSt^{B1} \\cdot EdgStff^{B1}(r) \\tag{12}\n$$","x":-180,"y":2570,"width":560,"height":80},
|
||||
{"id":"c477cd2a76cd46fb","x":-540,"y":3101,"width":250,"height":60,"type":"text","text":"- 模态形状一阶导"},
|
||||
{"id":"2ee598faf0603188","x":-540,"y":2921,"width":250,"height":83,"color":"2","type":"text","text":"离心刚化效应引起的刚度项"},
|
||||
{"id":"dcd9236bd7c84bd4","type":"text","text":"叶片质量属性","x":-540,"y":3356,"width":250,"height":32,"color":"2"},
|
||||
{"id":"ebc5c6d7451acc3b","type":"text","text":"- 叶片质量","x":-540,"y":3454,"width":250,"height":36},
|
||||
{"id":"a49465d6a6a3c3c2","type":"text","text":"- 叶片一阶矩","x":-540,"y":3534,"width":250,"height":36},
|
||||
{"id":"11e198e842aadec4","type":"text","text":"- 叶片质心","x":-540,"y":3853,"width":250,"height":36},
|
||||
{"id":"7f6f9185b340d930","type":"text","text":"- 风轮质量","x":-540,"y":3954,"width":250,"height":36},
|
||||
{"id":"5a48574ff6eeda7e","type":"text","text":"- 风轮惯性","x":-540,"y":4054,"width":250,"height":36},
|
||||
{"id":"987e81ef1f1995b3","type":"text","text":"- 叶片二阶矩","x":-540,"y":3614,"width":250,"height":36},
|
||||
{"id":"c4978e46cf739ba4","x":-180,"y":2885,"width":820,"height":346,"type":"text","text":"```rust\nelmnt_stff = f_mom_abv_nd[[k, j]] * p.dr_nodes[j] * p.rot_speed.powi(2);\n\nshape1 = shp_array(p.r_nodes_norm[j], p.bld_flex_l, &p.bld_fl1_sh.slice(s![.., k]).to_owned(), 1);\n\nshape2 = shp_array(p.r_nodes_norm[j], p.bld_flex_l, &p.bld_fl2_sh.slice(s![.., k]).to_owned(), 1);\n\nk_bf_cent[[k, 0, 0]] += elmnt_stff * shape1 * shape1;\n\nk_bf_cent[[k, 1, 1]] += elmnt_stff * shape2 * shape2;\n\nshape = shp_array(p.r_nodes_norm[j], p.bld_flex_l, &p.bld_edg_sh.slice(s![.., k]).to_owned(), 1);\n\nk_be_cent[[k, 0, 0]] += elmnt_stff * shape * shape;\n```"},
|
||||
{"id":"c29809ca3c70881b","type":"text","text":" ```fortran\n p%BldMass (K) = p%TipMass(K)\n p%FirstMom (K) = p%TipMass(K)*p%BldFlexL\n p%SecondMom(K) = p%TipMass(K)*p%BldFlexL*p%BldFlexL\n ...\n p%BElmntMass(J,K) = p%MassB(K,J)*p%DRNodes(J)\n ...\n p%BldMass (K) = p%BldMass (K) + p%BElmntMass(J,K)\n p%FirstMom (K) = p%FirstMom (K) + p%BElmntMass(J,K)*p%RNodes(J)\n p%SecondMom(K) = p%SecondMom(K) + p%BElmntMass(J,K)*p%RNodes(J)*p%RNodes(J)\n \n ```","x":-180,"y":3320,"width":789,"height":460},
|
||||
{"id":"253044dc6cebe206","type":"text","text":"```rust\np.bld_cg[k] = p.first_mom[k] / p.bld_mass[k];\n\np.rot_mass += p.bld_mass[k];\n\np.rot_iner += (p.second_mom[k] + p.bld_mass[k] * p.hub_rad * (2.0 * p.bld_cg[k] + p.hub_rad)) * p.cos_pre_c[k].powi(2);\n```\n","x":-156,"y":3853,"width":796,"height":237},
|
||||
{"id":"9a824939bad661d2","x":-2120,"y":2252,"width":250,"height":36,"type":"text","text":"- 摆振广义质量"},
|
||||
{"id":"8fa04043b651b57e","x":-2120,"y":2394,"width":250,"height":36,"type":"text","text":"- 模态形状0阶导"},
|
||||
{"id":"34fed438f96dfa4c","x":-2120,"y":2540,"width":250,"height":60,"color":"2","type":"text","text":"固有频率"},
|
||||
{"id":"9005abbfdd8f3246","x":-2120,"y":2660,"width":250,"height":60,"type":"text","text":"挥舞固有频率"},
|
||||
{"id":"8944328366cdad0c","x":-2120,"y":2780,"width":250,"height":69,"type":"text","text":"考虑叶尖质量、离心刚化"},
|
||||
{"id":"a96110788e264552","x":-2120,"y":3180,"width":250,"height":60,"type":"text","text":"摆振固有频率"},
|
||||
{"id":"6f03c475fcf16a01","type":"text","text":"考虑叶尖质量、离心刚化","x":-2120,"y":3320,"width":250,"height":69},
|
||||
{"id":"f1cd43613a1fdfa5","type":"text","text":"广义质量","x":-2120,"y":1996,"width":250,"height":32,"color":"2"},
|
||||
{"id":"5b82d2f5eb26eefc","type":"text","text":"- 挥舞广义质量","x":-2120,"y":2094,"width":250,"height":36},
|
||||
{"id":"5d4daed7f83a3fa5","x":-2938,"y":2057,"width":640,"height":110,"type":"text","text":"$$\nm_{ij}^{\\prime B1F} = \\int_{0}^{BldFlexL} \\mu^{B1}(r) \\phi_i^{B1F}(r) \\phi_j^{B1F}(r) \\, dr \\quad (i, j = 1, 2) \\tag{16}\n$$"},
|
||||
{"id":"44300ab8ae0139cc","x":-2618,"y":2630,"width":320,"height":120,"type":"text","text":"$$\nf_i^{\\prime B1F} = \\frac{1}{2\\pi} \\sqrt{\\frac{k_{ii}^{\\prime B1F}}{m_{ii}^{\\prime B1F}}} \\tag{14}\n$$"},
|
||||
{"id":"0bc6d2d448f012fd","x":-3014,"y":2780,"width":716,"height":315,"type":"text","text":"```rust\n// Natural blade I-flap frequency w/o centrifugal stiffening nor tip mass effects\n\np.freq_bf[[k, i, 0]] = INV2PI * (p.kbf[[k, i, i]] / (m_bf[[k, i, i]] - p.tip_mass[k])).sqrt();\n\n// Natural blade I-flap frequency w/o centrifugal stiffening, but w/ tip mass effects\n\np.freq_bf[[k, i, 1]] = INV2PI * (p.kbf[[k, i, i]] / m_bf[[k, i, i]]).sqrt();\n\n// Natural blade I-flap frequency w/ centrifugal stiffening and tip mass effects\n\np.freq_bf[[k, i, 2]] = INV2PI * ((p.kbf[[k, i, i]] + k_bf_cent[[k, i, i]]) / m_bf[[k, i, i]]).sqrt();\n```"},
|
||||
{"id":"5047212eb42c9e69","type":"text","text":"$$\nf_i^{\\prime B1E} = \\frac{1}{2\\pi} \\sqrt{\\frac{k_{ii}^{\\prime B1E}}{m_{ii}^{\\prime B1E}}} \\tag{15}\n$$","x":-2618,"y":3150,"width":320,"height":120},
|
||||
{"id":"f5ccbef2e5e250b9","type":"text","text":"```rust\n// Natural blade 1-edge frequency w/o centrifugal stiffening nor tip mass effects\n\np.freq_be[[k, 0, 0]] = INV2PI * (p.kbe[[k, 0, 0]] / (m_be[[k, 0, 0]] - p.tip_mass[k])).sqrt();\n\n// Natural Blade 1-edge frequency w/o centrifugal stiffening, but w/ tip mass effects\n\np.freq_be[[k, 0, 1]] = INV2PI * (p.kbe[[k, 0, 0]] / m_be[[k, 0, 0]]).sqrt();\n\n// Natural Blade 1-edge frequency w/ centrifugal stiffening and tip mass effects\n\np.freq_be[[k, 0, 2]] = INV2PI * ((p.kbe[[k, 0, 0]] + k_be_cent[[k, 0, 0]]) / m_be[[k, 0, 0]]).sqrt();\n```","x":-3014,"y":3320,"width":716,"height":315},
|
||||
{"id":"b5bee6a3e7c29d31","type":"text","text":"**叶片广义参数计算**","x":-1440,"y":2916,"width":250,"height":93,"color":"1"},
|
||||
{"id":"d89b6477389b9a45","x":-2774,"y":2196,"width":476,"height":112,"type":"text","text":"$$\nm_{11}^{\\prime B1E} = \\int_{0}^{BldFlexL} \\mu^{B1}(r) \\left[ \\phi_1^{B1E}(r) \\right]^2 dr \\tag{17}\n$$"},
|
||||
{"id":"d1cb8d99b00c07c8","x":-3022,"y":3699,"width":724,"height":203,"type":"text","text":"$$\n\\left. F_r \\right|_{DampB1} =\n\\begin{cases}\n-\\frac{\\zeta_1^{B1F} {k'}_{11}^{B1F}}{\\pi f^{\\prime B 1 F}_1} \\dot{q}_{B1F1} - \\frac{\\zeta_2^{B1F} {k'}_{12}^{B1F}}{\\pi f^{\\prime B 1 F}_2} \\dot{q}_{B1F2} & \\text{for } r = B1F1 \\\\\n-\\frac{\\zeta_1^{B1E} {k'}_{11}^{B1E}}{\\pi f^{\\prime B 1 E}_1} \\dot{q}_{B1E1} & \\text{for } r = B1E1 \\\\\n-\\frac{\\zeta_1^{B1F} {k'}_{21}^{B1F}}{\\pi f^{\\prime B 1 F}_1} \\dot{q}_{B1F1} - \\frac{\\zeta_2^{B1F} {k'}_{22}^{B1F}}{\\pi f^{\\prime B 1 F}_2} \\dot{q}_{B1F2} & \\text{for } r = B1F2 \\\\\n0 & \\text{otherwise}\n\\end{cases} \\tag{13}\n$$"},
|
||||
{"id":"204d6c2f3ec03ac0","x":-2120,"y":3771,"width":250,"height":60,"color":"2","type":"text","text":"广义阻尼"},
|
||||
{"id":"1684e3f8b6f17829","type":"text","text":"挥舞和摆振方向结构阻尼比","x":-2120,"y":3980,"width":250,"height":69},
|
||||
{"id":"b1dddd3ed142c348","x":-2600,"y":3973,"width":302,"height":84,"type":"text","text":"$\\zeta_{i}^{BIF} = BldFlDmp^{B1}(i)/100$\n$\\zeta_{i}^{BIE} = BldEdDmp^{B1}(i)/100$"},
|
||||
{"id":"c328cec51da1530b","x":-2963,"y":4080,"width":665,"height":230,"type":"text","text":" ```fortran\n\tp%CBF(K,I,L) = ( 0.01*p%BldFDamp(K,L) )*p%KBF(K,I,L)/( Pi*p%FreqBF(K,L,1) )\n\tp%CBE(K,1,1) = ( 0.01*p%BldEDamp(K,1) )*p%KBE(K,1,1)/( Pi*p%FreqBE(K,1,1) )\n ``` "},
|
||||
{"id":"169bd99d304f6f85","x":-2120,"y":4165,"width":250,"height":60,"type":"text","text":"广义阻尼系数"},
|
||||
{"id":"cd865939df274ef7","x":-3291,"y":4420,"width":993,"height":623,"type":"text","text":" ```fortran\n ! Calculate the 2nd derivatives of the twisted shape functions:\n Shape = SHP( p%RNodesNorm(J), p%BldFlexL, p%BldFl1Sh(:,K), 2, ErrStat, ErrMsg )\n p%TwistedSF(K,1,1,J,2) = Shape*p%CThetaS(K,J)\n ...\n ! Integrate to find the 1st derivatives of the twisted shape functions:\n TwstdSF ( I,L, 1) = p%TwistedSF(K,I,L,J,2)*0.5*p%DRNodes(J)\n p%TwistedSF (K,I,L,J,1) = TwstdSF ( I,L, 1)\n ...\n ! Integrate to find the twisted shape functions themselves (i.e., their zeroeth derivative):\n TwstdSF ( I,L, 0) = p%TwistedSF(K,I,L,J,1)*0.5*p%DRNodes(J)\n p%TwistedSF (K,I,L,J,0) = TwstdSF ( I,L, 0)\n ...\n ! Integrate to find the blade axial reduction shape functions:\n AxRdBld ( I,L ) = 0.5*p%DRNodes(J)*( &\n p%TwistedSF(K,1,I,L,1)*p%TwistedSF(K,1,L,J,1) &\n + p%TwistedSF(K,2,I,L,1)*p%TwistedSF(K,2,L,J,1) )\n p%AxRedBld (K,I,L,J) = AxRdBld(I,L)\n ```"},
|
||||
{"id":"43c52f1d3f4f4337","x":-2120,"y":4580,"width":250,"height":60,"color":"4","type":"text","text":"扭转形状函数和轴向缩短系数"}
|
||||
],
|
||||
"edges":[
|
||||
{"id":"647c1b45edc92b02","fromNode":"9461f7dd96103316","fromSide":"bottom","toNode":"0c8534c8ba68c9a6","toSide":"top"},
|
||||
{"id":"e3d4293dd3262f2d","fromNode":"9461f7dd96103316","fromSide":"bottom","toNode":"5eaa425c204bf600","toSide":"top"},
|
||||
{"id":"9a803fcaec81414e","fromNode":"38d3d1a313c094ee","fromSide":"right","toNode":"8ec17237cebe7433","toSide":"left"},
|
||||
{"id":"7ff52c30a0b0347d","fromNode":"a729b7930412f0b1","fromSide":"bottom","toNode":"d405163cb9ecd804","toSide":"top"},
|
||||
{"id":"d97ef554530b15b5","fromNode":"c20eeff7484d8a39","fromSide":"right","toNode":"a729b7930412f0b1","toSide":"left"},
|
||||
{"id":"034d145edd7cfce0","fromNode":"0c8534c8ba68c9a6","fromSide":"bottom","toNode":"6094c53caf966263","toSide":"top"},
|
||||
{"id":"da18b7fa4859fa6f","fromNode":"5eaa425c204bf600","fromSide":"bottom","toNode":"6094c53caf966263","toSide":"top"},
|
||||
{"id":"5d5f4fef281a656e","fromNode":"6094c53caf966263","fromSide":"right","toNode":"da500b2b12ed0901","toSide":"left"},
|
||||
{"id":"5573fa12a3a02ee0","fromNode":"da500b2b12ed0901","fromSide":"right","toNode":"20ce8d75f0f35588","toSide":"left"},
|
||||
{"id":"c4828432b71fd99a","fromNode":"4bfacdf3ddedbdec","fromSide":"right","toNode":"ae48e80ccd92bffa","toSide":"left"},
|
||||
{"id":"8ded09c7902a30b6","fromNode":"ae48e80ccd92bffa","fromSide":"right","toNode":"ed5a265dc4b72aaa","toSide":"left"},
|
||||
{"id":"4818c7bc8aa99b57","fromNode":"b624e8c6302b9a1c","fromSide":"right","toNode":"1054909d642ce071","toSide":"left"},
|
||||
{"id":"d58b296db32dc932","fromNode":"1054909d642ce071","fromSide":"bottom","toNode":"1e1a1a0d67920443","toSide":"top"},
|
||||
{"id":"f88001eedfed69b8","fromNode":"1e1a1a0d67920443","fromSide":"bottom","toNode":"092cf6719d47d01d","toSide":"top"},
|
||||
{"id":"d0bfe0faa41e4e2f","fromNode":"6c3a6982a53e7df9","fromSide":"right","toNode":"f3c36900dd3ed9d1","toSide":"left"},
|
||||
{"id":"14130329273bf6fc","fromNode":"092cf6719d47d01d","fromSide":"right","toNode":"14a4450243ca9953","toSide":"left"},
|
||||
{"id":"4d588dd609ceeb1e","fromNode":"f65edb48b74e18d7","fromSide":"right","toNode":"cccd4482e817fca4","toSide":"left"},
|
||||
{"id":"2e2be072d2f0e10f","fromNode":"e0d016f4bb106554","fromSide":"right","toNode":"722e4b9c310e6d2a","toSide":"left"},
|
||||
{"id":"8c75af2dfe500f7c","fromNode":"f65edb48b74e18d7","fromSide":"left","toNode":"e0d016f4bb106554","toSide":"left"},
|
||||
{"id":"ffb790d799b2ad82","fromNode":"f65edb48b74e18d7","fromSide":"left","toNode":"a9889437875a9263","toSide":"left"},
|
||||
{"id":"cdc9289e799ecaaf","fromNode":"a9889437875a9263","fromSide":"right","toNode":"50e241bef2144ea1","toSide":"left"},
|
||||
{"id":"7f1bc02337b44a20","fromNode":"36c9ab3fd7a0a402","fromSide":"right","toNode":"a20bd9b934093730","toSide":"left"},
|
||||
{"id":"8785ed74e88adf4e","fromNode":"6454ea0b5f37aafa","fromSide":"right","toNode":"da8b0f86919e99d9","toSide":"left"},
|
||||
{"id":"7ed2af81de878d33","fromNode":"ab5c75b7401fb031","fromSide":"right","toNode":"da00f9548457388f","toSide":"left"},
|
||||
{"id":"b9462798dc7ea087","fromNode":"ab5c75b7401fb031","fromSide":"left","toNode":"36c9ab3fd7a0a402","toSide":"left"},
|
||||
{"id":"6e6a4a6a3c31137f","fromNode":"ab5c75b7401fb031","fromSide":"left","toNode":"6454ea0b5f37aafa","toSide":"left"},
|
||||
{"id":"c23bb251830336d5","fromNode":"b5bee6a3e7c29d31","fromSide":"right","toNode":"f65edb48b74e18d7","toSide":"left"},
|
||||
{"id":"9ab29f4b57e27b0d","fromNode":"b5bee6a3e7c29d31","fromSide":"right","toNode":"ab5c75b7401fb031","toSide":"left"},
|
||||
{"id":"f54ee3299cbf7265","fromNode":"b5bee6a3e7c29d31","fromSide":"right","toNode":"dcd9236bd7c84bd4","toSide":"left"},
|
||||
{"id":"61aa378205c46b26","fromNode":"dcd9236bd7c84bd4","fromSide":"left","toNode":"ebc5c6d7451acc3b","toSide":"left"},
|
||||
{"id":"28f6e87b0c7eea26","fromNode":"dcd9236bd7c84bd4","fromSide":"left","toNode":"a49465d6a6a3c3c2","toSide":"left"},
|
||||
{"id":"ff4d8f82fdfdb90d","fromNode":"dcd9236bd7c84bd4","fromSide":"left","toNode":"987e81ef1f1995b3","toSide":"left"},
|
||||
{"id":"92f9ed21804f53e2","fromNode":"987e81ef1f1995b3","fromSide":"bottom","toNode":"11e198e842aadec4","toSide":"top"},
|
||||
{"id":"b3ec4450d2d0a73b","fromNode":"11e198e842aadec4","fromSide":"top","toNode":"7f6f9185b340d930","toSide":"top"},
|
||||
{"id":"dffde18030232f37","fromNode":"7f6f9185b340d930","fromSide":"bottom","toNode":"5a48574ff6eeda7e","toSide":"top"},
|
||||
{"id":"257676f063ba93a2","fromNode":"ebc5c6d7451acc3b","fromSide":"right","toNode":"c29809ca3c70881b","toSide":"left"},
|
||||
{"id":"a19f6c3e9df6f3c6","fromNode":"a49465d6a6a3c3c2","fromSide":"right","toNode":"c29809ca3c70881b","toSide":"left"},
|
||||
{"id":"9b20ae7ad0081184","fromNode":"987e81ef1f1995b3","fromSide":"right","toNode":"c29809ca3c70881b","toSide":"left"},
|
||||
{"id":"f093013ff0a96dd0","fromNode":"11e198e842aadec4","fromSide":"right","toNode":"253044dc6cebe206","toSide":"left"},
|
||||
{"id":"02244e836b50d487","fromNode":"7f6f9185b340d930","fromSide":"right","toNode":"253044dc6cebe206","toSide":"left"},
|
||||
{"id":"99cf66af0f6ec6d3","fromNode":"5a48574ff6eeda7e","fromSide":"right","toNode":"253044dc6cebe206","toSide":"left"},
|
||||
{"id":"3f71b0b7e384a8be","fromNode":"b5bee6a3e7c29d31","fromSide":"right","toNode":"2ee598faf0603188","toSide":"left"},
|
||||
{"id":"56f5f551d20be422","fromNode":"2ee598faf0603188","fromSide":"left","toNode":"c477cd2a76cd46fb","toSide":"left"},
|
||||
{"id":"cc3407d414603eb8","fromNode":"2ee598faf0603188","fromSide":"right","toNode":"c4978e46cf739ba4","toSide":"left"},
|
||||
{"id":"b6160496e46a4eae","fromNode":"c477cd2a76cd46fb","fromSide":"right","toNode":"c4978e46cf739ba4","toSide":"left"},
|
||||
{"id":"3368bcd74ba9e4fb","fromNode":"9005abbfdd8f3246","fromSide":"bottom","toNode":"8944328366cdad0c","toSide":"top"},
|
||||
{"id":"6909067532cb91bc","fromNode":"a96110788e264552","fromSide":"bottom","toNode":"6f03c475fcf16a01","toSide":"top"},
|
||||
{"id":"321843e8dd3be858","fromNode":"5b82d2f5eb26eefc","fromSide":"left","toNode":"5d4daed7f83a3fa5","toSide":"right"},
|
||||
{"id":"3925cae98ff11bdc","fromNode":"9a824939bad661d2","fromSide":"left","toNode":"d89b6477389b9a45","toSide":"right"},
|
||||
{"id":"88b616e16f0fd305","fromNode":"f1cd43613a1fdfa5","fromSide":"right","toNode":"5b82d2f5eb26eefc","toSide":"right"},
|
||||
{"id":"68f5cf5a18a17801","fromNode":"f1cd43613a1fdfa5","fromSide":"right","toNode":"9a824939bad661d2","toSide":"right"},
|
||||
{"id":"ebac050a172817ba","fromNode":"f1cd43613a1fdfa5","fromSide":"right","toNode":"8fa04043b651b57e","toSide":"right"},
|
||||
{"id":"c6940f9a6f6ed020","fromNode":"9005abbfdd8f3246","fromSide":"left","toNode":"44300ab8ae0139cc","toSide":"right"},
|
||||
{"id":"90f4d6c4e8f93b32","fromNode":"8944328366cdad0c","fromSide":"left","toNode":"0bc6d2d448f012fd","toSide":"right"},
|
||||
{"id":"9854bbe1c5c3932e","fromNode":"a96110788e264552","fromSide":"left","toNode":"5047212eb42c9e69","toSide":"right"},
|
||||
{"id":"16d9a0e220097480","fromNode":"6f03c475fcf16a01","fromSide":"left","toNode":"f5ccbef2e5e250b9","toSide":"right"},
|
||||
{"id":"d52e7f0275237844","fromNode":"34fed438f96dfa4c","fromSide":"right","toNode":"9005abbfdd8f3246","toSide":"right"},
|
||||
{"id":"63ad29914f63862d","fromNode":"34fed438f96dfa4c","fromSide":"right","toNode":"a96110788e264552","toSide":"right"},
|
||||
{"id":"c58c7b2bd323e581","fromNode":"b5bee6a3e7c29d31","fromSide":"left","toNode":"f1cd43613a1fdfa5","toSide":"right"},
|
||||
{"id":"b427c81d66172385","fromNode":"b5bee6a3e7c29d31","fromSide":"left","toNode":"34fed438f96dfa4c","toSide":"right"},
|
||||
{"id":"eaf4a6506bae5f72","fromNode":"b5bee6a3e7c29d31","fromSide":"left","toNode":"204d6c2f3ec03ac0","toSide":"right"},
|
||||
{"id":"ed232ba50bf6c970","fromNode":"1684e3f8b6f17829","fromSide":"left","toNode":"b1dddd3ed142c348","toSide":"right"},
|
||||
{"id":"a0f82a31cbffe766","fromNode":"204d6c2f3ec03ac0","fromSide":"left","toNode":"d1cb8d99b00c07c8","toSide":"right"},
|
||||
{"id":"0f934757be6b10ed","fromNode":"204d6c2f3ec03ac0","fromSide":"right","toNode":"1684e3f8b6f17829","toSide":"right"},
|
||||
{"id":"eb49e3a35fec607d","fromNode":"204d6c2f3ec03ac0","fromSide":"right","toNode":"169bd99d304f6f85","toSide":"right"},
|
||||
{"id":"4165dc7658a3b437","fromNode":"169bd99d304f6f85","fromSide":"left","toNode":"c328cec51da1530b","toSide":"right"},
|
||||
{"id":"711a31af774553f9","fromNode":"43c52f1d3f4f4337","fromSide":"left","toNode":"cd865939df274ef7","toSide":"right"},
|
||||
{"id":"55cbfdf0e50ce7f1","fromNode":"b5bee6a3e7c29d31","fromSide":"left","toNode":"43c52f1d3f4f4337","toSide":"right"}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,3 +5,15 @@
|
||||
|
||||
|
||||
思路: 判断是否由于叶片变形量为负导致转速发散,尝试从叶片方程探究为什么变形量为负
|
||||
|
||||
|
||||
p.kbf
|
||||
p.cbf
|
||||
数太大了
|
||||
明阳机型是nrel 5mw的100倍
|
||||
|
||||
p.ktfa
|
||||
p.ctfa
|
||||
p.ktss
|
||||
p.ctss
|
||||
明阳机型是nrel 5mw的1000倍
|
||||
|
||||
54
多体求解器debug/误差较大的载荷.md
Normal file
54
多体求解器debug/误差较大的载荷.md
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
- foundation fz
|
||||
- Foundation Fy
|
||||
- Foundation Mz
|
||||
- Nacelle fore-aft displacement
|
||||
- Blade root 1 Mz
|
||||
- Blade root 1 Fy
|
||||
|
||||
|
||||
# foundation fz
|
||||
|
||||
```rust
|
||||
dot_product(&frc_t0_trb, &m.coord_sys.a2) * 1000.0;
|
||||
```
|
||||
|
||||
`m.coord_sys.a2` --- Z
|
||||
|
||||
`frc_t0_trb` Total force at the base of flexible portion of the tower (point T(0)) due to the entire wind turbine
|
||||
|
||||
`PFrcT0Trb` Partial force at the tower base (point T(0)) due to the turbine
|
||||
`PMomX0Trb` Partial moment at the platform (body X) / tower base (point T(0)) due to the turbine
|
||||
`FrcT0Trbt` Portion of the force at tower base (point T(0)) due to the turbine associated with everything but the QD2T()'s
|
||||
`MomX0Trbt` Portion of the moment at the platform (body X) / tower base (point T(0)) due to the turbine associated with everything but the QD2T()'s
|
||||
|
||||
# Foundation Fy
|
||||
|
||||
```rust
|
||||
-dot_product(&frc_t0_trb, &m.coord_sys.a3) * 1000.0;
|
||||
```
|
||||
|
||||
# Foundation Mz
|
||||
|
||||
```rust
|
||||
dot_product(&mom_x0_trb, &m.coord_sys.a2) * 1000.0;
|
||||
```
|
||||
|
||||
# Nacelle fore-aft displacement
|
||||
|
||||
```rust
|
||||
m.rt_hs.r_o[0] - y.tower_ln2_mesh.position[[0, j-1]];
|
||||
```
|
||||
|
||||
# Blade root 1 Mz
|
||||
|
||||
```rust
|
||||
dot_product(&mom_h0_b.slice(s![.., k]).to_owned(), &m.coord_sys.i3.slice(s![k, ..]).to_owned()) * 1000.0;
|
||||
```
|
||||
|
||||
# Blade root 1 Fy
|
||||
|
||||
```rust
|
||||
dot_product(&frc_s0_b.slice(s![.., k]).to_owned(), &m.coord_sys.i2.slice(s![k, ..]).to_owned()) * 1000.0;
|
||||
```
|
||||
@ -1,14 +1,12 @@
|
||||
{
|
||||
"nodes":[
|
||||
{"id":"8359617e1edc48ba","type":"text","text":"状态指标:\n推进OKR的时候也要关注这些事情,它们是完成OKR的保障。\n\n\n效率状态 green","x":-76,"y":-306,"width":456,"height":347},
|
||||
{"id":"a4eaccbbfadaaf17","type":"text","text":"# 目标:\n多体模块完善 线性化模块开发\n### 每周盘点一下它们\n\n\n关键结果:多体动力学建模原理、建模方法、线性化原理掌握 (9/10)\n\n关键结果:风机多体动力学文献调研情况完成 (5.5/10)\n关键结果:目标工况测试、稳态工况对比 (9/10)","x":-76,"y":-803,"width":456,"height":457},
|
||||
{"id":"a4eaccbbfadaaf17","type":"text","text":"# 目标:\n多体模块完善 线性化模块开发\n### 每周盘点一下它们\n\n\n关键结果:机组整机线性化模块开发 (6/10)\n\n关键结果:叶片、塔架station结果输出功能开发 (0/10)\n关键结果:整机瞬态仿真初始化功能改进 (0/10)\n关键结果:dlc2.x剩余故障工况建模及开发(0/10)\n关键结果:针对软件认证所需输出变量完善输出功能(0/10)\n","x":-76,"y":-803,"width":456,"height":457},
|
||||
{"id":"d2c5e076ba6cf7d7","type":"text","text":"# 推进计划\n未来四周计划推进的重要事情\n\n文献调研启动\n\n建模重新推导\n\n\n","x":-600,"y":-306,"width":456,"height":347},
|
||||
{"id":"82708a439812fdc7","type":"text","text":"# 1月已完成\n\n\n\n","x":-220,"y":134,"width":440,"height":560},
|
||||
{"id":"82708a439812fdc7","type":"text","text":"# 1月已完成\n\n\n\nP1 检查有没有塔筒上所有部件合并计算质量、质心、惯性参数 -- done仅有合并质量\n\nP1 明阳机型验证 \n- 叶片发散 叶片往前位移 原因查找 done -- 刘\n\nP1 明阳机型验证 \n\n- 商业机型模型验证 气动建模有问题\n- 中性轴问题 ED当前不支持预弯叶片计算\n\nP1 机型测试\n- 模型对齐讨论 done\n- 1.4aaa 工况设置问题\n- 明阳、NREL 5MW跑一轮计算\n\nP1 给方方姐回电话 done\n- 商业机型测试有结果后再见面\n- 建议双向了解情况\n\n- 过程+结果,年前 建立信任 现在是副总师了,站位上跟实验室对齐,计划增加王老师从技术角度汇报的渠道\n\nP1 服务器 ing\n- 机架 - 浪潮确定\n- 电源 - 电工给方案\n","x":-220,"y":134,"width":440,"height":560},
|
||||
{"id":"505acb3e6b119076","type":"text","text":"# 12月已完成\n\nP1 明阳机型验证\n\n- 商业机型建模 done\n- 正常发电工况对故障工况支持 故障建模 done\n\t- 超速n4 普通超速 多体设fault结构体 \n\t- 卡桨、 控制设fault结构体\n\n- 故障工况检查 done\n- 批量计算更新配置文件,风文件,程序版本,再计算 done\n\nP1 稳态工况init_with_yaml检查 done\n\nP1 前端\n- 所有simulation功能测试及对接 done\n\nP1 演示ppt补充内容 再补充\n- 补充steady operational loads / steady parked loads 缺结果 done\n- 6个算例的跑通 找一个与bladed对比 缺结果 done \n- 内部控制器 pass\n- batch 并行计算 单个工况是否快 多工况并行 暂时不做\n\nP1 前端\n- steady输出的名字改掉 done\n- 批量计算 改成并行计算 功能界面\n- 瞬态计算更新控制器 测试 done\n- 简单内控\n- 比较Bladed与正常发电工况速度,总时间短一点 multicase done\n- 是否需要增加相对路径问题 done\n\nP1 dlc 71 done\n\nP1 输出量更新到Bladed相同命名 done\n\nP1 专利 done\n- 做出solidworks模型,写专利\n\n","x":-700,"y":134,"width":440,"height":560},
|
||||
{"id":"30cb7486dc4e224c","type":"text","text":"# 2月已完成\n\n\n","x":260,"y":134,"width":440,"height":560},
|
||||
{"id":"c18d25521d773705","type":"text","text":"# 计划\n这周要做的3~5件重要的事情,这些事情能有效推进实现OKR。\n\nP1 必须做。P2 应该做\n\n\nP2 柔性部件 叶片、塔架变形算法 主线\n- 变形体动力学 简略看看ing\n- 柔性梁弯曲变形振动学习,主线 \n\t- 广义质量 刚度矩阵及含义\n\t\n- 梳理bladed动力学框架\n\t- 子结构文献阅读\n\t- 叶片模型建模 done\n- 共旋方法学习\n- DTU 变形量计算方法学习\n\n\nP1 线性化方法编写 ing\n\n- 开始编写扰动代码\n- 形成系统矩阵-输出矩阵\n\n\nP1 明阳机型验证 \n\n- 商业机型模型验证 气动建模有问题\n- 动态失速计算慢\n- 叶片发散\n\n\nP2 气动、多体、控制、水动联调\n\n\n\nP1 服务器网络申请 ing\nP1 报告更新到0.6版本 ing\n\nP2 bladed对比--稳态运行载荷,产出报告\n- 气动参与模块对比\n- 模态对比 两种描述方法不同,bladed方向更多,x y z deflection, x y z rotation,不好对比\n- 气动对比 aerodynamic info 轴向切向诱导因子,根部,尖部差距较大\n\nP2 yaw 自由度再bug确认 已知原理了\n","x":-597,"y":-803,"width":453,"height":457},
|
||||
{"id":"86ab96a25a3bf82e","type":"text","text":" 湍流风+ 控制的联调,bladed也算一个算例\n- 加水动的联调\n- 8月份底完成这两个\n- 9月份完成停机等工况测试\n- 10月份明阳实际机型测试","x":580,"y":-803,"width":480,"height":220},
|
||||
{"id":"e355f33c92cf18ea","type":"text","text":"9月份定常计算对接前端\n非定常测试完也对接前端","x":580,"y":-500,"width":480,"height":100},
|
||||
{"id":"c18d25521d773705","type":"text","text":"# 计划\n这周要做的3~5件重要的事情,这些事情能有效推进实现OKR。\n\nP1 必须做。P2 应该做\n\n\nP2 柔性部件 叶片、塔架变形算法 主线\n- 变形体动力学 简略看看ing\n- 柔性梁弯曲变形振动学习,主线 \n\t- 广义质量 刚度矩阵及含义\n\t\n- 梳理bladed动力学框架\n\t- 子结构文献阅读\n\t- 叶片模型建模 done\n- 共旋方法学习\n- DTU 变形量计算方法学习\n\n\nP1 线性化方法编写 ing\n\n- 开始编写扰动代码\n- 形成系统矩阵-输出矩阵\n\n\n\n\nP1 检查误差较大的载荷,首先确保与Bladed同坐标系输出\n- foundation fz - PFrcT0Trb\n- Foundation Fy\n- Foundation Mz\n- Nacelle fore-aft displacement\n- Blade root 1 Mz\n- Blade root 1 Fy\n\nP1 叶素、塔架station输出结果\n\n\n\n\nP1 服务器 ing\n- 电源 - 让电工给接线\n- 超聚变 - 装系统done\n\n\n\nP2 初始化方法,找到稳态结果开始\n\n\n\n\nP1 报告更新到0.6版本 ing\n\nP2 bladed对比--稳态运行载荷,产出报告\n- 气动参与模块对比\n- 模态对比 两种描述方法不同,bladed方向更多,x y z deflection, x y z rotation,不好对比\n- 气动对比 aerodynamic info 轴向切向诱导因子,根部,尖部差距较大\n\nP2 yaw 自由度再bug确认 已知原理了\n","x":-597,"y":-803,"width":453,"height":457},
|
||||
{"id":"859e6853b7f1b92b","type":"text","text":"年底考核:\n专利\n线性化模块","x":1200,"y":-803,"width":320,"height":110},
|
||||
{"id":"a850b2f46fa52de7","type":"text","text":"# 25年开发工作\n\n- 对标bladed中steady calculation,开发steady operational loads,steady parked loads任务流程序\n- 设计并开发 YAML 配置文件模块,实现了对 YAML 格式模型文件与配置文件的读取、解析\n- 开发控制模块,并与其他模块耦合,实现对32位、64位dll文件支持,完成变桨与变流器执行器的传递函数模型算法开发\n- 对标bladed中simulations,集成控制模块开发正常发电工况、启机、正常停机、紧急停机、空转、停机功能\n- 开发批量计算模块\n\n","x":800,"y":134,"width":440,"height":560}
|
||||
],
|
||||
|
||||
BIN
工作总结/周报/周报110-郭翼泽.docx
Normal file
BIN
工作总结/周报/周报110-郭翼泽.docx
Normal file
Binary file not shown.
BIN
工作总结/周报/周报111-郭翼泽.docx
Normal file
BIN
工作总结/周报/周报111-郭翼泽.docx
Normal file
Binary file not shown.
BIN
工作总结/周报/周报112-郭翼泽.docx
Normal file
BIN
工作总结/周报/周报112-郭翼泽.docx
Normal file
Binary file not shown.
12
生活OKRs/25.12-26.02 OKR.canvas
Normal file
12
生活OKRs/25.12-26.02 OKR.canvas
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"nodes":[
|
||||
{"id":"04da78b746646560","type":"text","text":"状态指标:\n推进OKR的时候也要关注这些事情,它们是完成OKR的保障。\n\n\n","x":34,"y":-186,"width":456,"height":347},
|
||||
{"id":"85cce24e1132f21f","type":"text","text":"# 目标:海龟 短剧 AI项目推进\n### 每周盘点一下它们\n\n\n关键结果:海龟系统现在版本测试 (9/10)\n\n关键结果:公众号系统实现(10/10)\n\n关键结果:文献调研智能体搭建 (5/10)","x":34,"y":-573,"width":456,"height":347},
|
||||
{"id":"52c483d4870680c3","type":"text","text":"# 推进计划\nRag系统、agent系统调研\n新闻 公众号\n小说推广系统 可能容易实现一些\n","x":-490,"y":-186,"width":456,"height":347},
|
||||
{"id":"0b25ceb1c28f6da1","type":"text","text":"# 十二月已完成\n\n\nP2 短剧流程串起来 部分逻辑更新\n\n- 拆分发布流程 done","x":-482,"y":240,"width":440,"height":340},
|
||||
{"id":"b79f3a0f35402ec1","type":"text","text":"# 一月已完成\n\nP1 海龟交易法 \n- 数据爬虫bug解决 切换成单一标底获取\n- 选股部分 xq done\n","x":34,"y":240,"width":440,"height":340},
|
||||
{"id":"1597ad15730745ea","type":"text","text":"# 十一月已完成\n\nP1 suno youtube视频\n- 生成音频\n- 动画 done\n- 音频有什么特征\n- 控制音乐时长","x":540,"y":240,"width":440,"height":340},
|
||||
{"id":"5aac58c184e57887","type":"text","text":"# 计划\n这周要做的3~5件重要的事情,这些事情能有效推进实现OKR。\n\nP1 必须做。P2 应该做\n\n\nP1 海龟交易法 \n\n- 9点28-29分开始检测价格,做出预备\n- 突破价格似乎不对-以及突破但是没有提示\n\nP1 商业保险调研\n\nP1 新号1000粉丝\n\nP2 短剧流程串起来 部分逻辑更新\n- 如当天收集任务,剪辑前一天任务,拆分收集与剪辑任务数据库\n- 拆分发布流程 done\n\n","x":-490,"y":-573,"width":450,"height":347}
|
||||
],
|
||||
"edges":[]
|
||||
}
|
||||
34
软件组工作讨论/2026.1.6 26年工作.md
Normal file
34
软件组工作讨论/2026.1.6 26年工作.md
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
### 任务
|
||||
|
||||
整机线性化模型
|
||||
|
||||
newmark-β
|
||||
|
||||
综合误差小于8%,内控所有的误差都应小于8%
|
||||
|
||||
暂定20号组内评审,对比的报告和误差大的地方排除一下,如果通过评审,1月底找时间团队过一下。
|
||||
|
||||
|
||||
模型和算法排期
|
||||
|
||||
其他任务:
|
||||
- 双风轮功能 董+郭 天成号,9月份之前完成,最好+认证
|
||||
- 批量计算功能继续推进,大批量测试1000-2000工况
|
||||
- 界面
|
||||
|
||||
额外提:
|
||||
|
||||
- 坐标系与bladed对标,任务要列出来
|
||||
- 共旋先排上
|
||||
|
||||
batch python转化成rust集成
|
||||
与批处理共用一个 yaml class
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 节点
|
||||
|
||||
1月底前形成excel
|
||||
Loading…
x
Reference in New Issue
Block a user