February 28, 2025

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 study by seeing their document (https://framat.readthedocs.io/en/latest/theory/fem.html), and update soon…