Coverage for src / sdynpy / demo / beam_airplane.py: 100%
51 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-11 16:22 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-11 16:22 +0000
1# -*- coding: utf-8 -*-
2"""
3Demonstration system for a simple airplane made of beams
4"""
5"""
6Copyright 2022 National Technology & Engineering Solutions of Sandia,
7LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
8Government retains certain rights in this software.
10This program is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 3 of the License, or
13(at your option) any later version.
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
20You should have received a copy of the GNU General Public License
21along with this program. If not, see <https://www.gnu.org/licenses/>.
22"""
24import numpy as _np
25from ..fem.sdynpy_beam import beamkm as _beamkm
26from ..core.sdynpy_geometry import (Geometry as _Geometry,
27 node_array as _node_array,
28 traceline_array as _traceline_array,
29 coordinate_system_array as _coordinate_system_array)
30from ..core.sdynpy_coordinate import (from_nodelist as _from_nodelist,
31 coordinate_array as _coordinate_array)
32from ..core.sdynpy_system import (System as _System,
33 substructure_by_position as _substructure_by_position)
36def create_models():
37 """
38 Creates models for the demonstration airplane.
40 Returns
41 -------
42 full_system : System
43 `System` containing all the airplane degrees of freedom
44 full_geometry : Geometry
45 `Geometry` containing the full airplane model
46 transmission_system : System
47 `System` containing a shorter wing that can be used as a transmission
48 simulator
49 transmission_geometry : Geometry
50 `Geometry` containing a shorter wing that can be used as a transmission
51 simulator
52 all_systems : dict[System]
53 A dictionary containing component `System` objects for use in
54 substructuring
55 all_geometries : dict[Geometry]
56 A dictionary containing component `Geometry` objects for use in
57 substructuring
59 """
60 # Fuselage coords
61 fuselage_coords = _np.array([_np.linspace(0, 10, 21),
62 _np.zeros(21),
63 _np.zeros(21)]).T
65 # Wing coords
66 wing_coords = _np.array([[x, y, 0] for x in [2, 3] for y in _np.linspace(-10, 10, 41)])
68 # Transmission simulator
69 transmission_simulator_coords = _np.array(
70 [[x, y, 0] for x in [2, 3] for y in _np.linspace(-2.5, 2.5, 11)])
72 # Tail Coords
73 tail_coords = _np.array([[9, 2, 2], [9, 1, 1], [9, 0, 0], [9, -1, 1],
74 [9, -2, 2], [10, 2, 2], [10, 1, 1], [10, 0, 0], [10, -1, 1], [10, -2, 2]])
76 # Create element connectivity
77 fuselage_connectivity = _np.array(
78 [_np.arange(0, fuselage_coords.shape[0] - 1), _np.arange(1, fuselage_coords.shape[0])]).T
79 wing_connectivity = _np.concatenate((
80 _np.array([_np.arange(0, wing_coords.shape[0] // 2 - 1),
81 _np.arange(1, wing_coords.shape[0] // 2)]).T, # Front stringer
82 _np.array([_np.arange(wing_coords.shape[0] // 2, wing_coords.shape[0] - 1),
83 _np.arange(wing_coords.shape[0] // 2 + 1, wing_coords.shape[0])]).T, # Back stringer
84 _np.array([_np.arange(0, wing_coords.shape[0] // 2),
85 _np.arange(wing_coords.shape[0] // 2, wing_coords.shape[0])]).T # Spars
86 ), axis=0)
87 transmission_simulator_connectivity = _np.concatenate((
88 _np.array([_np.arange(0, transmission_simulator_coords.shape[0] // 2 - 1),
89 _np.arange(1, transmission_simulator_coords.shape[0] // 2)]).T, # Front stringer
90 _np.array([_np.arange(transmission_simulator_coords.shape[0] // 2, transmission_simulator_coords.shape[0] - 1),
91 _np.arange(transmission_simulator_coords.shape[0] // 2 + 1, transmission_simulator_coords.shape[0])]).T, # Back stringer
92 _np.array([_np.arange(0, transmission_simulator_coords.shape[0] // 2),
93 _np.arange(transmission_simulator_coords.shape[0] // 2, transmission_simulator_coords.shape[0])]).T # Spars
94 ), axis=0)
95 tail_connectivity = _np.concatenate((
96 _np.array([_np.arange(0, tail_coords.shape[0] // 2 - 1),
97 _np.arange(1, tail_coords.shape[0] // 2)]).T, # Front stringer
98 _np.array([_np.arange(tail_coords.shape[0] // 2, tail_coords.shape[0] - 1),
99 _np.arange(tail_coords.shape[0] // 2 + 1, tail_coords.shape[0])]).T, # Back stringer
100 _np.array([_np.arange(0, tail_coords.shape[0] // 2),
101 _np.arange(tail_coords.shape[0] // 2, tail_coords.shape[0])]).T # Spars
102 ), axis=0)
104 # Create the bending directions, we will do positive z for all
105 fuselage_bend_direction_1 = _np.array(
106 [_np.zeros(fuselage_connectivity.shape[0]),
107 _np.zeros(fuselage_connectivity.shape[0]),
108 _np.ones(fuselage_connectivity.shape[0])]
109 ).T
110 wing_bend_direction_1 = _np.array(
111 [_np.zeros(wing_connectivity.shape[0]),
112 _np.zeros(wing_connectivity.shape[0]),
113 _np.ones(wing_connectivity.shape[0])]
114 ).T
115 transmission_simulator_bend_direction_1 = _np.array(
116 [_np.zeros(transmission_simulator_connectivity.shape[0]),
117 _np.zeros(transmission_simulator_connectivity.shape[0]),
118 _np.ones(transmission_simulator_connectivity.shape[0])]
119 ).T
120 tail_bend_direction_1 = _np.array(
121 [_np.zeros(tail_connectivity.shape[0]),
122 _np.zeros(tail_connectivity.shape[0]),
123 _np.ones(tail_connectivity.shape[0])]
124 ).T
126 # Define beam parameters
127 beam_width = 0.1
128 beam_height = 0.15
129 E = 69e9
130 nu = 0.33
131 rho = 2830
132 I1 = beam_width * beam_height**3 / 12
133 I2 = beam_width**3 * beam_height / 12
134 G = E / (2 * (1 - nu))
135 J = I1 + I2
136 Ixx_per_L = (1 / 12) * rho * beam_width * beam_height * (beam_width**2 + beam_height**2)
138 # Rather than doing all the math to create matrices 3 times, let's just do it once in a for loop.
139 # Let's use dictionaries to store the matrices
140 all_systems = {}
141 all_geometries = {}
142 names = ['fuselage', 'wing', 'tail', 'transmission_simulator']
143 colors = [1, 7, 11, 13]
145 for coord, conn, bend_direction, name, color in zip([fuselage_coords, wing_coords, tail_coords, transmission_simulator_coords],
146 [fuselage_connectivity, wing_connectivity,
147 tail_connectivity, transmission_simulator_connectivity],
148 [fuselage_bend_direction_1, wing_bend_direction_1,
149 tail_bend_direction_1, transmission_simulator_bend_direction_1],
150 names, colors):
151 # Create arguments for the beamkm function
152 ae = beam_width * beam_height * E * _np.ones(conn.shape[0])
153 jg = J * G * _np.ones(conn.shape[0])
154 ei1 = E * I1 * _np.ones(conn.shape[0])
155 ei2 = E * I2 * _np.ones(conn.shape[0])
156 mass_per_length = rho * beam_width * beam_height * _np.ones(conn.shape[0])
157 tmmi_per_length = Ixx_per_L * _np.ones(conn.shape[0])
159 # Compute K and M via beamkm
160 this_K, this_M = _beamkm(coord, conn, bend_direction, ae, jg, ei1,
161 ei2, mass_per_length, tmmi_per_length)
163 # Create objects
164 # Create geometry
165 all_geometries[name] = _Geometry(
166 _node_array(_np.arange(coord.shape[0]) + 1, coord, color),
167 _coordinate_system_array(),
168 _traceline_array(_np.arange(conn.shape[0]) + 1, color=color, connectivity=conn + 1)
169 )
170 # Create system
171 all_systems[name] = _System(
172 _from_nodelist(all_geometries[name].node.id, [1, 2, 3, 4, 5, 6]),
173 this_M, this_K
174 )
176 # Now let's create the full airplane
177 systems = [all_systems[name] for name in names if name not in ['transmission_simulator']]
178 geometries = [all_geometries[name] for name in names if name not in ['transmission_simulator']]
180 full_system, full_geometry = _substructure_by_position(systems, geometries)
182 # Now let's create the stubby airplane
183 systems = [all_systems[name] for name in names if name not in ['wing']]
184 geometries = [all_geometries[name] for name in names if name not in ['wing']]
186 transmission_system, transmission_geometry = _substructure_by_position(systems, geometries)
188 return full_system, full_geometry, transmission_system, transmission_geometry, all_systems, all_geometries
191(system, geometry, transmission_system, transmission_geometry,
192 component_systems, component_geometries) = create_models()