
About
There are many free structural analysis tools available.
FreeFEM++, OpenSees, salome-meca… However, they are surprisingly difficult to use.
FreeFEM++ uses its own unique language, which comes with a steep learning curve, and errors can be hard to understand.
OpenSees has the advantage of being callable from Python, but it feels a bit complex.
Salome-meca looks promising, but I can’t even download it properly at the moment—probably because they are throttling the bandwidth.
Of course, the best choice depends on the purpose, but right now, there doesn’t seem to be a truly good option.
Among these, OpenSees might be the best choice since it is educationally clear about how computations are processed.
That being said, I recently found a somewhat simpler option—FramAT.
You’ve never heard of it, have you?
FramAT
This tool is an Apache-2 licensed software developed by a Scottish company.
It doesn’t have any particularly impressive features, but it allows for structural analysis of beam elements. Beam element analysis involves relatively simple calculations, making it a great educational tool as well.
Moreover, they have included the theoretical aspects in their documentation, which is extremely helpful.
I immediately tried out the tutorial.
Tutorial
from framat import Model
model = Model()
mat = model.add_feature('material', uid='dummy')
mat.set('E', 1)
mat.set('G', 1)
mat.set('rho', 1)
cs = model.add_feature('cross_section', uid='dummy')
cs.set('A', 1)
cs.set('Iy', 1)
cs.set('Iz', 1)
cs.set('J', 1)
beam = model.add_feature('beam')
beam.add('node', [0, 0, 0], uid='root')
beam.add('node', [1, 0, 0], uid='corner')
beam.add('node', [1, 1, 0], uid='tip')
beam.set('nelem', 10)
beam.add('material', {'from': 'root', 'to': 'tip', 'uid': 'dummy'})
beam.add('cross_section', {'from': 'root', 'to': 'tip', 'uid': 'dummy'})
beam.add('orientation', {'from': 'root', 'to': 'tip', 'up': [0, 0, 1]})
beam.add('point_load', {'at': 'corner', 'load': [0, 0, -1, 0, 0, 0]})
bc = model.set_feature('bc')
bc.add('fix', {'node': 'root', 'fix': ['all']})
pp = model.set_feature('post_proc')
pp.add('plot', ['undeformed', 'deformed', 'nodes'])
model.run()
Theory
I will gradually study by seeing their document (https://framat.readthedocs.io/en/latest/theory/fem.html), and update soon…
What this tries to solve is an equation that represents Equilibrium of Forces and Constraints of Node (location).
Equilibrium of Forces and Constraints of Node (location)
\begin{align} \begin{bmatrix} K & B^T(x) \\ B(x) & 0 \end{bmatrix} \begin{bmatrix} U(x) \\ \lambda(x) \end{bmatrix} = \begin{bmatrix} F \\ 0 \end{bmatrix} \end{align}
where K is stiffness matrix, B is the boundary conditions, and U is the displacement, F is force and \lambda is lagrange multipliers. So if we solve the equation (1), we will get the solution when force is balanced.
\begin{bmatrix} U(x) \\ \lambda(x) \end{bmatrix} = \begin{bmatrix} K & B^T(x) \\ B(x) & 0 \end{bmatrix} ^{-1} \begin{bmatrix} F \\ 0 \end{bmatrix}
the \lambda represents reaction forces on fixed points, actually.
So what is important here is to define stiffness matrix K, constraints B and force F.
Disadvantage of this tool?
It seems that this tool only allows us to put nodes in order. So, probably we cannot set grid nodes which has more than 3 nodes connected. I am not pretty sure, it just says that a beam has nodes as list. It can have infinite number of beams, we should check out it can have shared nodes from other beams.