Skip to content

Commit 545acbc

Browse files
committed
initial push
1 parent 97d02c3 commit 545acbc

File tree

8,995 files changed

+108401
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

8,995 files changed

+108401
-1
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
*.lvbitx
3+
*.aliases

LICENSE.txt

+427
Large diffs are not rendered by default.

README.md

+62-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,62 @@
1-
# LabVIEW-FPGA-Array-Based-Linear-Algebra
1+
# LabVIEW-FPGA-Array-Based-Linear-Algebra
2+
A library of array-based linear algebra solvers for LabVIEW FPGA designed for ease of use over efficiency or timing.
3+
4+
The provided palette has functions for
5+
- Matrix-matrix multiply
6+
- Vector-matrix multiply
7+
- Matrix-vector multiply
8+
- Dot-product
9+
- Matrix inverse
10+
- Matrix transpose
11+
- Cholesky Decomposition
12+
- Eigenvalue
13+
14+
All functions except the eigenvalue are polymorphic and can take both single precisions floating data type and fixed-point data points up to a word length of 12 and integer word length of 32. Note that the eigenvalue function only supports single precisions floating point.
15+
16+
<p align="center">
17+
<img src="palette.png" alt="drawing" width="450"/>
18+
</p>
19+
<p align="center">
20+
</p>
21+
22+
These functions enable array-based deployment of algorithms to FPGAs. Arrays are stored in the look-up tables (LUT) for ease of implementation.
23+
24+
<p align="center">
25+
<img src="code.png" alt="drawing" width="800"/>
26+
</p>
27+
<p align="center">
28+
</p>
29+
30+
## How do I install this?
31+
Click [Releases](https://github.com/ARTS-Laboratory/LabVIEW-FPGA-Array-Based-Linear-Algebra/releases) on the right-hand side of the screen and download the latest release. The .vip file is what you want and is called "arts_lab_lib_array_based_linear_algebra-x.x.x.x.vip". You can install .vip files through NI's VIPM Browser.
32+
33+
## [Development workspace](development_workspace)
34+
Houses all the code used in building and developing the functions, including test deployments to FPGAs.
35+
36+
## [Package](package)
37+
Houses the published packages.
38+
39+
40+
## Licensing and Citation
41+
42+
[![CC BY-SA 4.0][cc-by-sa-shield]][cc-by-sa]
43+
44+
This work is licensed under a
45+
[Creative Commons Attribution-ShareAlike 4.0 International License][cc-by-sa].
46+
47+
[cc-by-sa]: http://creativecommons.org/licenses/by-sa/4.0/
48+
[cc-by-sa-image]: https://licensebuttons.net/l/by-sa/4.0/88x31.png
49+
[cc-by-sa-shield]: https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg
50+
51+
52+
Cite as:
53+
54+
@Misc{Downey2021LabVIEWFPGAArray,
55+
author = {Austin Downey},
56+
howpublished = {GitHub},
57+
title = {Lab{VIEW} {FPGA} Array-based Linear Algebra},
58+
year = {2021},
59+
groups = {{ARTS-L}ab},
60+
url = {https://github.com/ARTS-Laboratory/LabVIEW-FPGA-Array-Based-Linear-Algebra},
61+
}
62+

code.png

12.3 KB
Loading
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[ProjectWindow_Data]
2+
ProjectExplorer.ClassicPosition[String] = "136,184,1142,1142"
3+

development_workspace/Cholesky_decomposition_v1.1/Cholesky_decomposition/Cholesky_FPGA/Cholesky_FPGA_V1/Cholesky_FPGA_V1.lvproj

+3,087
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"M": [[0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.012937500000000003, 0.0001557291666666667, 0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [-0.0001557291666666667, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.012937500000000003, 0.0001557291666666667, 0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.012937500000000003, 0.0001557291666666667, 0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.012937500000000003, 0.0001557291666666667, 0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.012937500000000003, 0.0001557291666666667, 0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.012937500000000003, 0.0001557291666666667, 0.07475000000000001, 0.0, -0.0001557291666666667, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, -1.7968750000000007e-06, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0001557291666666667, 0.07475000000000001, 0.0, 0.012937500000000003, -0.0001557291666666667], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.7968750000000007e-06, 0.0, 4.7916666666666685e-06, 0.0001557291666666667, -1.7968750000000007e-06], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.012937500000000003, 0.0001557291666666667, 0.037375000000000005, -0.00026354166666666675], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0001557291666666667, -1.7968750000000007e-06, -0.00026354166666666675, 2.3958333333333343e-06]], "K": [[20000000.0, 0.0, -10000000.0, 250000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 16666.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [-10000000.0, -250000.0, 20000000.0, 0.0, -10000000.0, 250000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [250000.0, 4166.666666666667, 0.0, 16666.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, -10000000.0, -250000.0, 20000000.0, 0.0, -10000000.0, 250000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 250000.0, 4166.666666666667, 0.0, 16666.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, -10000000.0, -250000.0, 20000000.0, 0.0, -10000000.0, 250000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 250000.0, 4166.666666666667, 0.0, 16666.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -10000000.0, -250000.0, 20000000.0, 0.0, -10000000.0, 250000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 250000.0, 4166.666666666667, 0.0, 16666.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -10000000.0, -250000.0, 20000000.0, 0.0, -10000000.0, 250000.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 250000.0, 4166.666666666667, 0.0, 16666.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -10000000.0, -250000.0, 20000000.0, 0.0, 250000.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 250000.0, 4166.666666666667, 0.0, 16666.666666666668, 4166.666666666667, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 250000.0, 4166.666666666667, 17566.666666666668, -250000.0, 4166.666666666667, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -250000.0, 20000000.0, 0.0, -10000000.0, 250000.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4166.666666666667, 0.0, 16666.666666666668, -250000.0, 4166.666666666667], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -10000000.0, -250000.0, 10000000.0, -250000.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 250000.0, 4166.666666666667, -250000.0, 8333.333333333334]]}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Spyder Editor
4+
5+
This is a temporary script file.
6+
"""
7+
8+
#%%
9+
import matplotlib.pyplot as plt
10+
import matplotlib as mpl
11+
from mpl_toolkits.mplot3d import Axes3D
12+
import os as os
13+
import numpy as np
14+
import scipy as sp
15+
from scipy.interpolate import griddata
16+
from matplotlib import cm
17+
import time
18+
import subprocess
19+
import pickle
20+
import scipy.io as sio
21+
import sympy as sym
22+
from matplotlib import cm
23+
import re as re
24+
from scipy import signal
25+
26+
plt.close('all')
27+
28+
cc = plt.rcParams['axes.prop_cycle'].by_key()['color']
29+
30+
#%% Load the data
31+
32+
# considering a cantilever beam with nodal coordinates defined by the length of the beam
33+
# and fixed at the left_hand side
34+
35+
36+
def make_M_K(beam_node_num = 5):
37+
#beam_node_num = 5 # number of nodes, this must be at least 3
38+
pin_location = 0.85#25 # The pin locaion in terms of L
39+
mass_location = 1.0 # The mass location in terms of L
40+
mass_width = 0.025 # The 1-D width of the mass
41+
mass = 0.259 # the weight of the mass in kg
42+
pin_node_rotation_spring = 900 # set the value of the spring at the pinned connection
43+
pin_node = int((beam_node_num*pin_location)-1) # set the pin location in terms of matrix location
44+
beam_length = 0.500 # length of the beam in meters
45+
beam_width = 0.05 # width of the beamin meters
46+
beam_height = 0.005 # thickness of the beam in meters
47+
beam_element = beam_node_num-1 # calculate the number of elements in the beam
48+
beam_el_length = beam_length/beam_element # calculate the element lengths of the beam
49+
mass_el_number = int(mass_width/beam_el_length) # defines the number of elements with added mass
50+
# define the mass of the elements as a function of the dropped mass
51+
if mass_width/beam_el_length <= 2:
52+
mass_el = mass
53+
else:
54+
mass_el = mass/mass_el_number
55+
# define what nodes these masses are attached to
56+
mass_node = np.zeros((beam_node_num),dtype=bool)
57+
ss1 = int(int(beam_node_num*mass_location)-(mass_el_number-1)/2)
58+
ss2 = ss1+mass_el_number
59+
if ss2 > beam_node_num:
60+
ss2 = beam_node_num
61+
ss1 = beam_node_num - mass_el_number
62+
mass_node[ss1:ss2+1]=True
63+
beam_E = 200*1e9 # Youngs modules of steel in Pa
64+
beam_density = 8050 # density of steel in kg/m^3
65+
beam_I = (beam_width*beam_height**3)/12 # caclulated moment of inertia
66+
beam_area = beam_width*beam_height
67+
dt = 0.0005 # Time step.
68+
steps = 10000 # Number of steps for loop below.
69+
C_alpha = 0
70+
C_beta = 0.00003 # was 0.00003
71+
gravity = -9.807 # gravity in m/s^2
72+
tt = np.arange(0,dt*steps,dt) # Time vector.
73+
74+
analytical_tip_load = (mass*gravity*beam_length**3)/(3*beam_E*beam_I)
75+
analytical_distubted_load = (beam_density*beam_area*9.81*beam_length**4)/(8*beam_E*beam_I)
76+
analytical = analytical_tip_load+analytical_distubted_load
77+
78+
# build a list of displacement and rotations
79+
DOF = []
80+
for i in range(beam_node_num):
81+
DOF.append('displacement')
82+
DOF.append('rotation')
83+
DOF = np.asarray(DOF)
84+
85+
# define the mass matrix of a Euler-Bernoulli beam
86+
M_el = (beam_density*beam_area*beam_el_length)/420* \
87+
np.matrix([[156,22*beam_el_length,54,-13*beam_el_length], \
88+
[22*beam_el_length,4*beam_el_length**2,13*beam_el_length,-3*beam_el_length**2], \
89+
[54,13*beam_el_length,156,-22*beam_el_length], \
90+
[-13*beam_el_length,-3*beam_el_length**2,-22*beam_el_length,4*beam_el_length**2]])
91+
92+
M_mass_el = mass_el/420* \
93+
np.matrix([[156,22*beam_el_length,54,-13*beam_el_length], \
94+
[22*beam_el_length,4*beam_el_length**2,13*beam_el_length,-3*beam_el_length**2], \
95+
[54,13*beam_el_length,156,-22*beam_el_length], \
96+
[-13*beam_el_length,-3*beam_el_length**2,-22*beam_el_length,4*beam_el_length**2]])
97+
98+
# define the stiffness matrix of a Euler-Bernoulli beam
99+
K_el = (beam_E*beam_I)/beam_el_length**3* \
100+
np.matrix([[12,6*beam_el_length,-12,6*beam_el_length], \
101+
[6*beam_el_length,4*beam_el_length**2,-6*beam_el_length,2*beam_el_length**2], \
102+
[-12,-6*beam_el_length,12,-6*beam_el_length], \
103+
[6*beam_el_length,2*beam_el_length**2,-6*beam_el_length,4*beam_el_length**2]])
104+
105+
matrix_size = (beam_node_num)*2
106+
M = np.zeros((matrix_size,matrix_size))
107+
M_mass = np.zeros((matrix_size,matrix_size))
108+
F_static_mass = np.zeros((matrix_size))
109+
K = np.zeros((matrix_size,matrix_size))
110+
111+
# for each element, add the element matrix into the global matirx
112+
for elem_num in range(0,beam_element):
113+
n = (elem_num)*2
114+
M[n:n+4,n:n+4] = np.add(M[n:n+4,n:n+4],M_el)
115+
K[n:n+4,n:n+4] = np.add(K[n:n+4,n:n+4],K_el)
116+
117+
# add the stffness from the pin roller
118+
node_rotation_cell = pin_node*2+1
119+
K[node_rotation_cell,node_rotation_cell] = K[node_rotation_cell,node_rotation_cell] +pin_node_rotation_spring
120+
121+
M_no_BC = np.copy(M)
122+
K_no_BC = np.copy(K)
123+
124+
for elem_num in range(0,beam_element):
125+
if mass_node[elem_num] == True:
126+
n = (elem_num)*2
127+
M_mass[n:n+4,n:n+4] = np.add(M_mass[n:n+4,n:n+4],M_mass_el)
128+
129+
M = np.add(M_mass,M)
130+
131+
# add the froce from gravity on the beam
132+
F_static = np.zeros((matrix_size))
133+
F_static[DOF=='displacement'] = 1
134+
F_static[0] = 0.5
135+
F_static[-2] = 0.5
136+
F_static = F_static*beam_density*beam_area*beam_el_length*gravity
137+
138+
# add the drop mass to the F static vector
139+
for elem_num in range(0,beam_element):
140+
if mass_node[elem_num] == True:
141+
n = (elem_num)*2
142+
F_static_mass[n:n+4] = np.add(F_static_mass[n:n+4],np.matrix([1,0,1,0])*0.5)
143+
F_static_mass = F_static_mass*mass_el*gravity
144+
145+
# rebuild the F_static vector
146+
F_static = np.add(F_static,F_static_mass)
147+
148+
# remove the row and column associated with the pin location.
149+
M = np.delete(np.delete(M,(pin_node*2),axis=0),(pin_node*2),axis=1)
150+
K = np.delete(np.delete(K,(pin_node*2),axis=0),(pin_node*2),axis=1)
151+
F_static = np.delete(F_static,(pin_node*2),axis=0)
152+
DOF = np.delete(DOF,(pin_node*2),axis=0)
153+
154+
# for the fixed end on the left side, u_1 and u_2 = 0, so we can remove these columns
155+
# and rows form the matrixes.
156+
# apply the boundary conditions
157+
M = np.delete(np.delete(M,(0,1),axis=0),(0,1),axis=1)
158+
K = np.delete(np.delete(K,(0,1),axis=0),(0,1),axis=1)
159+
F_static = np.delete(F_static,(0,1),axis=0)
160+
DOF = np.delete(DOF,(0,1),axis=0)
161+
162+
# define the damping coefficent
163+
C = C_alpha*M+C_beta*K
164+
165+
zeros_matrix = np.zeros((M.shape[0],M.shape[0]))
166+
identity_matrix = np.eye(M.shape[0])
167+
168+
A00 = np.zeros((M.shape[0],M.shape[0]))
169+
A01 = np.eye(M.shape[0])
170+
A10 = np.matmul(np.linalg.inv(M),-K)
171+
A11 = np.matmul(np.linalg.inv(M),-C)
172+
A = np.vstack((np.hstack((A00,A01)),np.hstack((A10,A11))))
173+
174+
B_p = np.vstack((zeros_matrix,np.linalg.inv(M))) # define the B matrix that considers the applied force
175+
B_g = np.vstack((zeros_matrix,identity_matrix)) # define the B matrix that considers gravity
176+
177+
DOF_displacement = DOF=='displacement'
178+
179+
#%% Static solution
180+
181+
X_static = np.matmul(F_static,np.linalg.inv(K))
182+
#X_static = np.matmul(np.linalg.inv(K),F_static)
183+
X_static_displacement = X_static[0:DOF_displacement.shape[0]][DOF_displacement]
184+
185+
# Build a list of the non zero displacements and map this onto the empty zeros matrix
186+
displacements_static = np.zeros((beam_node_num))
187+
displacements_non_zero = np.ones((beam_node_num),dtype=bool)
188+
displacements_non_zero[0] = False
189+
displacements_non_zero[pin_node] = False
190+
displacements_static[displacements_non_zero] = X_static_displacement
191+
192+
# plt.figure()
193+
# plt.plot(displacements_static*1000)
194+
# plt.grid('on')
195+
# plt.xlabel('nodes (#)')
196+
# plt.ylabel('displacement (mm)')
197+
# plt.title('Static displacement over the length of the beam')
198+
# plt.savefig('figures/discrete_static_solution_displacement',dpi=300)
199+
# plt.legend()
200+
# plt.tight_layout()
201+
202+
#%% discrete solution
203+
204+
X = np.zeros((A.shape[0],steps))
205+
X[0:X_static.shape[0],0] = np.copy(X_static)# set the initial X to the static displacement values
206+
P_p = np.zeros((B_p.shape[1],steps))# Initialize the force vector.
207+
P_g = np.ones((B_g.shape[1]))*gravity# Initialize the force vector.
208+
P_p[-1,0]=-100 # define the location of the input loading. -1 is the tip
209+
210+
# Solve the state space equations.
211+
# solve these out-side the loop to increase speed
212+
aa = sp.linalg.expm(A*dt)
213+
aaa = np.matmul(np.linalg.inv(A),np.subtract(aa,np.eye(A.shape[0])))
214+
tt_in=time.time()
215+
for i in range(0,steps-1):
216+
b_p = np.matmul(B_p,P_p[:,i])
217+
b_g = np.matmul(B_g,P_g)
218+
bbb = np.add(b_p,b_g)
219+
X[:,i+1] = np.matmul(aa,X[:,i]) + np.matmul(aaa,bbb)
220+
tt_out=time.time()
221+
#print('run time = '+str((tt_out-tt_in)*100)+' ms')
222+
displacements = np.zeros((beam_node_num,steps))
223+
X_displacement = X[0:DOF_displacement.shape[0],:][DOF_displacement,:]
224+
225+
# Build a list of the non zero displacements and map this onto the empty zeros matrix
226+
displacements[displacements_non_zero,:] = X_displacement
227+
228+
# # Plot the displacement at the tip
229+
# plt.figure()
230+
# plt.plot(displacements[:,-1]*1000,label='time step '+str(i))
231+
# plt.grid('on')
232+
# plt.xlabel('nodes (#)')
233+
# plt.ylabel('displacement (mm)')
234+
# plt.title('dynamic displacement over the lenght of the beam')
235+
# plt.savefig('figures/dynamic_discrete_solution_displacement',dpi=300)
236+
# plt.legend()
237+
# plt.tight_layout()
238+
#
239+
# # polt selected beam displacements
240+
# displacement_times = [0,2,4,6]
241+
# plt.figure()
242+
# for i in displacement_times:
243+
# plt.plot(displacements[:,i]*1000,label='time step '+str(np.round(i*dt,4)*1000)+' ms')
244+
# plt.grid('on')
245+
# plt.xlabel('nodes (#)')
246+
# plt.ylabel('displacement (mm)')
247+
# plt.title('displacement over the length of the beam')
248+
# plt.legend(framealpha=1)
249+
# plt.savefig('figures/discrete_solution_displacement',dpi=300)
250+
# plt.tight_layout()
251+
#
252+
# # plot the final displaced shape
253+
# plt.figure()
254+
# plt.plot(tt,displacements[-1,:]*1000)
255+
# plt.grid('on')
256+
# plt.xlabel('time (s)')
257+
# plt.ylabel('displacement (mm)')
258+
# plt.title('displacement at last node')
259+
# plt.savefig('figures/discrete_solution_tip',dpi=300)
260+
# plt.tight_layout()
261+
# #plt.xlim([0,3.7])
262+
# #plt.savefig('figures/discrete_solution',dpi=300)
263+
264+
# Calculation of the natural frequencies.
265+
tt_in=time.time()
266+
eigvals,eigvects = sp.linalg.eig(K,M)
267+
eigvals=np.expand_dims(np.real(eigvals), axis=0)
268+
FEA_wn = np.sort(np.real(np.squeeze(np.sqrt(eigvals)))) # Natural frequencies, rad/s
269+
Frequencies = np.expand_dims(FEA_wn/(2*np.pi),axis=1) # Natural freq in Hz
270+
# print(np.round(Frequencies[0:5].T))
271+
# tt_out=time.time()
272+
# print('run time = '+str((tt_out-tt_in)*100)+' ms')
273+
274+
return(M,K)
275+
276+
277+
278+
279+
280+
281+
282+
283+
284+
285+
286+
287+
288+
289+

0 commit comments

Comments
 (0)